From fae542e2055d9dd9e82217c6bf27107d1bb4ce97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Sun, 3 Aug 2025 17:02:27 +0800 Subject: [PATCH 001/104] =?UTF-8?q?:recycle:=20=E5=90=8D=E7=A7=B0=E9=87=8D?= =?UTF-8?q?=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../netty/ProtocolFrameLengthCodec.java | 2 +- .../transport/netty/client/package-info.java | 2 +- .../netty/server/CloseableChannel.java | 25 +--- .../transport/netty/server/package-info.java | 2 +- .../remoting/integration/KeepaliveTests.java | 22 ++-- ...ctoryNettyTransportFragmentationTests.java | 8 +- .../transport/netty/SetupRejectionTests.java | 6 +- .../transport/netty/TcpPingTests.java | 6 +- .../transport/netty/TcpPongServer.java | 4 +- .../WebSocketTransportIntegrationTests.java | 4 +- .../src/test/resources/logback-test.xml | 4 +- today-remoting/Protocol.md | 12 +- today-remoting/README.md | 2 +- .../src/main/java/infra/remoting/Channel.java | 2 +- .../java/infra/remoting/ChannelAcceptor.java | 4 +- .../main/java/infra/remoting/Closeable.java | 6 +- .../java/infra/remoting/DuplexConnection.java | 2 +- .../remoting/ProtocolErrorException.java | 4 +- .../infra/remoting/core/ChannelConnector.java | 94 +++++++------- .../infra/remoting/core/ChannelRequester.java | 2 +- .../infra/remoting/core/ChannelResponder.java | 4 +- .../core/DefaultConnectionSetupPayload.java | 2 +- .../remoting/core/DefaultRemotingClient.java | 18 +-- .../infra/remoting/core/RemotingClient.java | 64 +++++---- .../remoting/core/RemotingClientAdapter.java | 28 ++-- .../infra/remoting/core/RemotingServer.java | 34 ++--- .../remoting/core/ResolvingOperator.java | 2 - .../main/java/infra/remoting/core/Resume.java | 2 +- .../java/infra/remoting/core/ServerSetup.java | 18 +-- .../infra/remoting/core/package-info.java | 8 +- .../remoting/exceptions/SetupException.java | 2 +- .../remoting/exceptions/package-info.java | 2 +- .../remoting/frame/FrameHeaderCodec.java | 2 +- .../remoting/frame/decoder/package-info.java | 2 +- .../infra/remoting/frame/package-info.java | 2 +- .../java/infra/remoting/lb/ChannelPool.java | 36 +++--- .../lb/LoadBalanceRemotingClient.java | 12 +- .../java/infra/remoting/lb/PooledChannel.java | 8 +- .../lb/RoundRobinLoadBalanceStrategy.java | 2 +- .../lb/WeightedLoadBalanceStrategy.java | 16 +-- .../main/java/infra/remoting/lease/Lease.java | 2 +- .../infra/remoting/lease/package-info.java | 2 +- .../plugins/ChannelAcceptorInterceptor.java | 2 +- .../plugins/ConnectionInterceptor.java | 2 +- .../InitializingInterceptorRegistry.java | 12 +- .../plugins/RateLimitInterceptor.java | 8 +- .../remoting/plugins/RequestInterceptor.java | 2 +- .../infra/remoting/plugins/package-info.java | 2 +- .../remoting/resume/ResumableFramesStore.java | 6 +- .../infra/remoting/resume/package-info.java | 2 +- .../remoting/transport/ClientTransport.java | 2 +- .../remoting/transport/ServerTransport.java | 2 +- .../infra/remoting/transport/Transport.java | 6 +- .../test/java/infra/remoting/FrameTest.java | 54 -------- .../infra/remoting/RaceTestConstants.java | 2 +- .../remoting/core/AbstractSocketRule.java | 4 +- .../remoting/core/ChannelConnectorTests.java | 2 +- .../remoting/core/ChannelLeaseTests.java | 42 +++--- .../remoting/core/ChannelReconnectTests.java | 36 +++--- .../ChannelRequesterSubscribersTests.java | 12 +- .../ChannelRequesterTerminationTests.java | 29 ++--- .../remoting/core/ChannelRequesterTests.java | 6 +- .../remoting/core/ChannelResponderTests.java | 2 +- .../infra/remoting/core/ChannelTests.java | 2 +- .../core/DefaultChannelClientTests.java | 8 +- .../core/FireAndForgetRequesterMonoTest.java | 4 +- .../infra/remoting/core/KeepAliveTest.java | 121 +++++++++--------- .../core/RequestStreamRequesterFluxTest.java | 2 +- .../remoting/core/SetupRejectionTest.java | 20 +-- .../remoting/exceptions/ExceptionsTests.java | 7 +- .../infra/remoting/lb/LoadbalanceTests.java | 34 ++--- .../lb/WeightedLoadBalanceStrategyTests.java | 24 ++-- .../plugins/RequestInterceptorTests.java | 20 +-- .../test/util/TestDuplexConnection.java | 2 +- .../src/test/resources/logback-test.xml | 2 +- .../remoting/test/BaseClientServerTest.java | 34 ++--- .../infra/remoting/test/ClientSetupRule.java | 4 +- .../java/infra/remoting/test/PingClient.java | 10 +- .../infra/remoting/test/package-info.java | 2 +- ...g.assertj.core.presentation.Representation | 2 +- 80 files changed, 460 insertions(+), 554 deletions(-) delete mode 100644 today-remoting/src/test/java/infra/remoting/FrameTest.java diff --git a/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/ProtocolFrameLengthCodec.java b/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/ProtocolFrameLengthCodec.java index 85f62d8..eff6036 100644 --- a/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/ProtocolFrameLengthCodec.java +++ b/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/ProtocolFrameLengthCodec.java @@ -38,7 +38,7 @@ public ProtocolFrameLengthCodec() { } /** - * Creates a new instance of the decoder, specifying the RSocket frame length header size. + * Creates a new instance of the decoder, specifying the Protocol frame length header size. * * @param maxFrameLength maximum allowed frame length for incoming protocol frames */ diff --git a/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/client/package-info.java b/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/client/package-info.java index eff2e01..7772b94 100644 --- a/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/client/package-info.java +++ b/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/client/package-info.java @@ -15,7 +15,7 @@ * along with this program. If not, see [http://www.gnu.org/licenses/] */ -/** The Netty-based RSocket client transport implementations. */ +/** The Netty-based client transport implementations. */ @NonNullApi package infra.remoting.transport.netty.client; diff --git a/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/server/CloseableChannel.java b/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/server/CloseableChannel.java index 2c3d306..8aa8f53 100644 --- a/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/server/CloseableChannel.java +++ b/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/server/CloseableChannel.java @@ -17,7 +17,6 @@ package infra.remoting.transport.netty.server; -import java.lang.reflect.Method; import java.net.InetSocketAddress; import java.util.Objects; @@ -35,18 +34,6 @@ */ public final class CloseableChannel implements Closeable { - /** For forward compatibility: remove when RSocket compiles against Reactor 1.0. */ - private static final Method channelAddressMethod; - - static { - try { - channelAddressMethod = DisposableChannel.class.getMethod("address"); - } - catch (NoSuchMethodException ex) { - throw new IllegalStateException("Expected address method", ex); - } - } - private final Channel channel; /** @@ -76,17 +63,7 @@ public CloseableChannel(Channel channel) { * @see DisposableChannel#address() */ public InetSocketAddress address() { - try { - return (InetSocketAddress) channel.localAddress(); - } - catch (ClassCastException | NoSuchMethodError e) { - try { - return (InetSocketAddress) channelAddressMethod.invoke(this.channel); - } - catch (Exception ex) { - throw new IllegalStateException("Unable to obtain address", ex); - } - } + return (InetSocketAddress) channel.localAddress(); } @Override diff --git a/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/server/package-info.java b/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/server/package-info.java index ede97a7..5da875a 100644 --- a/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/server/package-info.java +++ b/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/server/package-info.java @@ -15,7 +15,7 @@ * along with this program. If not, see [http://www.gnu.org/licenses/] */ -/** The Netty-based RSocket server transport implementations. */ +/** The Netty-based server transport implementations. */ @NonNullApi package infra.remoting.transport.netty.server; diff --git a/today-remoting-transport-tcp/src/test/java/infra/remoting/integration/KeepaliveTests.java b/today-remoting-transport-tcp/src/test/java/infra/remoting/integration/KeepaliveTests.java index 6b22928..0a22525 100644 --- a/today-remoting-transport-tcp/src/test/java/infra/remoting/integration/KeepaliveTests.java +++ b/today-remoting-transport-tcp/src/test/java/infra/remoting/integration/KeepaliveTests.java @@ -65,13 +65,13 @@ void tearDown() { @Test void keepAliveTest() { - RemotingClient rsocketClient = createClient(); + RemotingClient client = createClient(); int expectedCount = 4; AtomicBoolean sleepOnce = new AtomicBoolean(true); StepVerifier.create(Flux.range(0, expectedCount) .delayElements(Duration.ofMillis(2000)) - .concatMap(i -> rsocketClient + .concatMap(i -> client .requestResponse(Mono.just(DefaultPayload.create(""))) .doOnNext(__ -> { if (sleepOnce.getAndSet(false)) { @@ -94,13 +94,13 @@ void keepAliveTest() { @Test void keepAliveTestLazy() { - Mono rsocketMono = createClientLazy(); + Mono channelMono = createClientLazy(); int expectedCount = 4; AtomicBoolean sleepOnce = new AtomicBoolean(true); StepVerifier.create(Flux.range(0, expectedCount) .delayElements(Duration.ofMillis(2000)) - .concatMap(i -> rsocketMono.flatMap(rsocket -> rsocket + .concatMap(i -> channelMono.flatMap(channel -> channel .requestResponse(DefaultPayload.create("")) .doOnNext(__ -> { if (sleepOnce.getAndSet(false)) { @@ -126,18 +126,18 @@ private static Mono createServer() { TcpServer tcpServer = TcpServer.create().host("localhost").port(PORT); - return RemotingServer.create((setupPayload, rSocket) -> { - rSocket + return RemotingServer.create((setupPayload, channel) -> { + channel .onClose() .doFirst(() -> LOG.info("Connected on server side.")) .doOnTerminate(() -> LOG.info("Connection closed on server side.")) .subscribe(); - return Mono.just(new MyServerRsocket()); + return Mono.just(new MyServerChannel()); }) .payloadDecoder(PayloadDecoder.ZERO_COPY) .bind(TcpServerTransport.create(tcpServer)) - .doOnNext(closeableChannel -> LOG.info("RSocket server started.")); + .doOnNext(closeableChannel -> LOG.info("server started.")); } private static RemotingClient createClient() { @@ -147,14 +147,14 @@ private static RemotingClient createClient() { Retry.backoff(Long.MAX_VALUE, Duration.ofSeconds(10L)) .doBeforeRetry(retrySignal -> LOG.info("Reconnecting. Reason: {}", reason)); - Mono rsocketMono = + Mono channelMono = ChannelConnector.create() .fragment(16384) .reconnect(reconnectSpec.apply("connector-close")) .keepAlive(Duration.ofMillis(100L), Duration.ofMillis(900L)) .connect(TcpClientTransport.create(TcpClient.create().host("localhost").port(PORT))); - RemotingClient client = RemotingClient.from(rsocketMono); + RemotingClient client = RemotingClient.from(channelMono); client.source() .doOnNext(r -> LOG.info("Got")) @@ -184,7 +184,7 @@ private static Mono createClientLazy() { .connect(TcpClientTransport.create(TcpClient.create().host("localhost").port(PORT))); } - public static class MyServerRsocket implements Channel { + public static class MyServerChannel implements Channel { @Override public Mono requestResponse(Payload payload) { diff --git a/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/ChannelFactoryNettyTransportFragmentationTests.java b/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/ChannelFactoryNettyTransportFragmentationTests.java index 589dd7f..323ad6f 100644 --- a/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/ChannelFactoryNettyTransportFragmentationTests.java +++ b/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/ChannelFactoryNettyTransportFragmentationTests.java @@ -71,12 +71,12 @@ void clientSucceedsWithEnabledFragmentationOnSufficientMtu( CloseableChannel server = RemotingServer.create(mockAcceptor()).fragment(100).bind(serverTransport).block(); - Mono rSocket = + Mono channel = ChannelConnector.create() .fragment(100) .connect(TcpClientTransport.create(server.address())) .doFinally(s -> server.dispose()); - StepVerifier.create(rSocket).expectNextCount(1).expectComplete().verify(Duration.ofSeconds(5)); + StepVerifier.create(channel).expectNextCount(1).expectComplete().verify(Duration.ofSeconds(5)); } @ParameterizedTest @@ -84,10 +84,10 @@ void clientSucceedsWithEnabledFragmentationOnSufficientMtu( void clientSucceedsWithDisabledFragmentation(ServerTransport serverTransport) { CloseableChannel server = RemotingServer.create(mockAcceptor()).bind(serverTransport).block(); - Mono rSocket = + Mono channel = ChannelConnector.connectWith(TcpClientTransport.create(server.address())) .doFinally(s -> server.dispose()); - StepVerifier.create(rSocket).expectNextCount(1).expectComplete().verify(Duration.ofSeconds(5)); + StepVerifier.create(channel).expectNextCount(1).expectComplete().verify(Duration.ofSeconds(5)); } private ChannelAcceptor mockAcceptor() { diff --git a/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/SetupRejectionTests.java b/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/SetupRejectionTests.java index 0ae2fb2..423dd94 100644 --- a/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/SetupRejectionTests.java +++ b/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/SetupRejectionTests.java @@ -48,7 +48,7 @@ public class SetupRejectionTests { /* TODO Fix this test @DisplayName( - "Rejecting setup by server causes requester RSocket disposal and RejectedSetupException") + "Rejecting setup by server causes requester Channel disposal and RejectedSetupException") @ParameterizedTest @MethodSource(value = "transports")*/ void rejectSetupTcp( @@ -57,7 +57,7 @@ void rejectSetupTcp( String errorMessage = "error"; RejectingAcceptor acceptor = new RejectingAcceptor(errorMessage); - Mono serverRequester = acceptor.requesterRSocket(); + Mono serverRequester = acceptor.requesterChannel(); CloseableChannel channel = RemotingServer.create(acceptor) @@ -129,7 +129,7 @@ public Mono accept(ConnectionSetupPayload setup, Channel sendingSocket) return Mono.error(new RuntimeException(msg)); } - public Mono requesterRSocket() { + public Mono requesterChannel() { return requesters.asFlux().next(); } } diff --git a/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/TcpPingTests.java b/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/TcpPingTests.java index acd0694..4c274e8 100644 --- a/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/TcpPingTests.java +++ b/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/TcpPingTests.java @@ -35,7 +35,7 @@ @PerfTest class TcpPingTests { private static final int INTERACTIONS_COUNT = 1_000_000_000; - private static final int port = Integer.valueOf(System.getProperty("RSOCKET_TEST_PORT", "7878")); + private static final int port = Integer.valueOf(System.getProperty("REMOTING_TEST_PORT", "7878")); @BeforeEach void setUp() { @@ -89,12 +89,12 @@ private static PingClient newPingClient(boolean isResumable) { if (isResumable) { connector.resume(new Resume()); } - Mono rSocket = + Mono channel = connector .payloadDecoder(PayloadDecoder.ZERO_COPY) .keepAlive(Duration.ofMinutes(1), Duration.ofMinutes(30)) .connect(TcpClientTransport.create(port)); - return new PingClient(rSocket); + return new PingClient(channel); } } diff --git a/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/TcpPongServer.java b/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/TcpPongServer.java index 844c2e3..97ab50d 100644 --- a/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/TcpPongServer.java +++ b/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/TcpPongServer.java @@ -25,8 +25,8 @@ public final class TcpPongServer { private static final boolean isResume = - Boolean.valueOf(System.getProperty("RSOCKET_TEST_RESUME", "false")); - private static final int port = Integer.valueOf(System.getProperty("RSOCKET_TEST_PORT", "7878")); + Boolean.valueOf(System.getProperty("REMOTING_TEST_RESUME", "false")); + private static final int port = Integer.valueOf(System.getProperty("REMOTING_TEST_PORT", "7878")); public static void main(String... args) { System.out.println("Starting TCP ping-pong server"); diff --git a/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/WebSocketTransportIntegrationTests.java b/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/WebSocketTransportIntegrationTests.java index e8086ff..5dcbfee 100644 --- a/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/WebSocketTransportIntegrationTests.java +++ b/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/WebSocketTransportIntegrationTests.java @@ -49,10 +49,10 @@ public void sendStreamOfDataWithExternalHttpServerTest() { .route(router -> router.ws("/test", WebsocketRouteTransport.newHandler(acceptor))) .bindNow(); - Channel rsocket = ChannelConnector.connectWith(WebsocketClientTransport.create(URI.create("ws://" + server.host() + ":" + server.port() + "/test"))) + Channel channel = ChannelConnector.connectWith(WebsocketClientTransport.create(URI.create("ws://" + server.host() + ":" + server.port() + "/test"))) .block(); - StepVerifier.create(rsocket.requestStream(EmptyPayload.INSTANCE)) + StepVerifier.create(channel.requestStream(EmptyPayload.INSTANCE)) .expectSubscription() .expectNextCount(10) .expectComplete() diff --git a/today-remoting-transport-tcp/src/test/resources/logback-test.xml b/today-remoting-transport-tcp/src/test/resources/logback-test.xml index 5e8b4cd..439393d 100644 --- a/today-remoting-transport-tcp/src/test/resources/logback-test.xml +++ b/today-remoting-transport-tcp/src/test/resources/logback-test.xml @@ -28,8 +28,8 @@ - - + + diff --git a/today-remoting/Protocol.md b/today-remoting/Protocol.md index fa2ffb1..d89ca90 100644 --- a/today-remoting/Protocol.md +++ b/today-remoting/Protocol.md @@ -2,7 +2,7 @@ This is an application protocol that provides [Reactive Streams](http://www.reactive-streams.org/) semantics across a network, asynchronous, binary boundary. -For more information, please see [rsocket.io](http://rsocket.io/). +原始协议参见:[rsocket.io](http://rsocket.io/). It assumes an operating paradigm. These assumptions are: - one-to-one communication @@ -95,7 +95,7 @@ Protocol as specified here has been designed for and tested with TCP, WebSocket, ### Framing Protocol Usage -Some supported transport protocols for RSocket may not support specific framing that preserves message boundaries. For these protocols, a framing protocol MUST be used with the RSocket frame that prepends the RSocket Frame Length. +Some supported transport protocols for this may not support specific framing that preserves message boundaries. For these protocols, a framing protocol MUST be used with the protocol frame that prepends the protocol Frame Length. The frame length field MUST be omitted if the transport protocol preserves message boundaries e.g. provides compatible framing. If, however, the transport protocol only provides a stream abstraction or can merge messages without preserving boundaries, or multiple transport protocols may be used, then the frame header MUST be used. @@ -108,7 +108,7 @@ The frame length field MUST be omitted if the transport protocol preserves messa ### Framing Format -When using a transport protocol providing framing, the RSocket frame is simply encapsulated into the transport protocol messages directly. +When using a transport protocol providing framing, the protocol frame is simply encapsulated into the transport protocol messages directly. ``` +-----------------------------------------------+ @@ -117,7 +117,7 @@ When using a transport protocol providing framing, the RSocket frame is simply e +-----------------------------------------------+ ``` -When using a transport protocol that does not provide compatible framing, the Frame Length MUST be prepended to the RSocket Frame. +When using a transport protocol that does not provide compatible framing, the Frame Length MUST be prepended to the protocol Frame. ``` 0 1 2 @@ -851,7 +851,7 @@ The requirements for the Resume Identification Token are implementation dependen * Tokens may be generated by the client. * Tokens may be generated outside the client and the server and managed externally to the protocol. -* Tokens should uniquely identify a connection on the server. The server should not assume a generation method of the token and should consider the token opaque. This allows a client to be compatible with any RSocket implementation that supports resuming operation and allows the client full control of Identification Token generation. +* Tokens should uniquely identify a connection on the server. The server should not assume a generation method of the token and should consider the token opaque. This allows a client to be compatible with any implementation that supports resuming operation and allows the client full control of Identification Token generation. * Tokens MUST be valid for the lifetime of an individual Protocol including possible resumption. * A server should not accept a SETUP with a Token that is currently already being used * Tokens should be resilient to replay attacks and thus should only be valid for the lifetime of an individual connection @@ -1196,7 +1196,7 @@ Credits are cumulative. Once credits are granted from Requester to Responder, th Please note that this explicitly does NOT follow rule number 17 in https://github.com/reactive-streams/reactive-streams-jvm/blob/v1.0.0/README.md#3-subscription-code -While Reactive Streams support a demand of up to 2^63-1, and treats 2^63-1 as a magic number signaling to not track demand, this is not the case for RSocket. RSocket prioritizes byte size and only uses 4 bytes instead of 8 so the magic number is unavailable. +While Reactive Streams support a demand of up to 2^63-1, and treats 2^63-1 as a magic number signaling to not track demand, this is not the case. prioritizes byte size and only uses 4 bytes instead of 8 so the magic number is unavailable. The Requester and the Responder MUST respect the Reactive Streams semantics. diff --git a/today-remoting/README.md b/today-remoting/README.md index bde6291..7fb3193 100644 --- a/today-remoting/README.md +++ b/today-remoting/README.md @@ -2,7 +2,7 @@ 使用 RSocket 协议 -原始代码来自 https://github.com/rsocket/rsocket-java.git cff5cdbb16da6393efc04d8f0b80793e54f79026 +原始代码来自 https://github.com/channel/rsocket-java.git cff5cdbb16da6393efc04d8f0b80793e54f79026 1.1.5 版本 It enables the following symmetric interaction models via async message passing over a single connection: diff --git a/today-remoting/src/main/java/infra/remoting/Channel.java b/today-remoting/src/main/java/infra/remoting/Channel.java index 15c2020..d1513e7 100644 --- a/today-remoting/src/main/java/infra/remoting/Channel.java +++ b/today-remoting/src/main/java/infra/remoting/Channel.java @@ -24,7 +24,7 @@ /** * A contract providing different interaction models for RSocket protocol. + * href="https://github.com/today-tech/today-cloud/blob/master/today-remoting/Protocol.md">protocol. * * @author 海子 Yang */ diff --git a/today-remoting/src/main/java/infra/remoting/ChannelAcceptor.java b/today-remoting/src/main/java/infra/remoting/ChannelAcceptor.java index 88c6acb..27b19b5 100644 --- a/today-remoting/src/main/java/infra/remoting/ChannelAcceptor.java +++ b/today-remoting/src/main/java/infra/remoting/ChannelAcceptor.java @@ -47,8 +47,8 @@ public interface ChannelAcceptor { /** * Create a {@code SocketAcceptor} that handles requests with the given {@code Channel}. */ - static ChannelAcceptor with(Channel rsocket) { - return (setup, sendingChannel) -> Mono.just(rsocket); + static ChannelAcceptor with(Channel channel) { + return (setup, sendingChannel) -> Mono.just(channel); } /** Create a {@code SocketAcceptor} for fire-and-forget interactions with the given handler. */ diff --git a/today-remoting/src/main/java/infra/remoting/Closeable.java b/today-remoting/src/main/java/infra/remoting/Closeable.java index fc14f2f..1ac0db3 100644 --- a/today-remoting/src/main/java/infra/remoting/Closeable.java +++ b/today-remoting/src/main/java/infra/remoting/Closeable.java @@ -22,7 +22,9 @@ import reactor.core.Disposable; import reactor.core.publisher.Mono; -/** An interface which allows listening to when a specific instance of this interface is closed */ +/** + * An interface which allows listening to when a specific instance of this interface is closed + */ public interface Closeable extends Disposable { /** @@ -32,7 +34,7 @@ public interface Closeable extends Disposable { * Subscriber#onComplete()} will be called. * * @return a {@link Mono} to track completion with success or error of the underlying resource. - * When the underlying resource is an `RSocket`, the {@code Mono} exposes stream 0 (i.e. + * When the underlying resource is an `Channel`, the {@code Mono} exposes stream 0 (i.e. * connection level) errors. */ Mono onClose(); diff --git a/today-remoting/src/main/java/infra/remoting/DuplexConnection.java b/today-remoting/src/main/java/infra/remoting/DuplexConnection.java index 7e7a830..5837dd0 100644 --- a/today-remoting/src/main/java/infra/remoting/DuplexConnection.java +++ b/today-remoting/src/main/java/infra/remoting/DuplexConnection.java @@ -65,7 +65,7 @@ public interface DuplexConnection extends Availability, Closeable { *

Multiple Subscriptions * *

Returned {@code Publisher} is not required to support multiple concurrent subscriptions. - * RSocket will never have multiple subscriptions to this source. Implementations MUST + * Channel will never have multiple subscriptions to this source. Implementations MUST * emit an {@link IllegalStateException} for subsequent concurrent subscriptions, if they do not * support multiple concurrent subscriptions. * diff --git a/today-remoting/src/main/java/infra/remoting/ProtocolErrorException.java b/today-remoting/src/main/java/infra/remoting/ProtocolErrorException.java index 949dad7..f5cb1ce 100644 --- a/today-remoting/src/main/java/infra/remoting/ProtocolErrorException.java +++ b/today-remoting/src/main/java/infra/remoting/ProtocolErrorException.java @@ -37,7 +37,7 @@ public class ProtocolErrorException extends RemotingException { /** * Constructor with a protocol error code and a message. * - * @param errorCode the RSocket protocol error code + * @param errorCode the protocol error code * @param message error explanation */ public ProtocolErrorException(int errorCode, String message) { @@ -47,7 +47,7 @@ public ProtocolErrorException(int errorCode, String message) { /** * Alternative to {@link #ProtocolErrorException(int, String)} with a root cause. * - * @param errorCode the RSocket protocol error code + * @param errorCode the protocol error code * @param message error explanation * @param cause a root cause for the error */ diff --git a/today-remoting/src/main/java/infra/remoting/core/ChannelConnector.java b/today-remoting/src/main/java/infra/remoting/core/ChannelConnector.java index d64a964..2d836f6 100644 --- a/today-remoting/src/main/java/infra/remoting/core/ChannelConnector.java +++ b/today-remoting/src/main/java/infra/remoting/core/ChannelConnector.java @@ -58,27 +58,25 @@ import static infra.remoting.core.ReassemblyUtils.assertInboundPayloadSize; /** - * The main class to use to establish a connection to an RSocket server. + * The main class to use to establish a connection to a server. * *

For using TCP using default settings: * *

{@code
- * import io.rsocket.transport.netty.client.TcpClientTransport;
+ * import infra.remoting.transport.netty.client.TcpClientTransport;
  *
- * Mono source =
+ * Mono source =
  *         ChannelConnector.connectWith(TcpClientTransport.create("localhost", 7000));
- * RSocketClient client = RSocketClient.from(source);
+ * RemotingClient client = RemotingClient.from(source);
  * }
* *

To customize connection settings before connecting: * *

{@code
- * Mono source =
- *         ChannelConnector.create()
- *                 .metadataMimeType("message/x.rsocket.composite-metadata.v0")
- *                 .dataMimeType("application/cbor")
+ * Mono source =
+ *        ChannelConnector.create()
  *                 .connect(TcpClientTransport.create("localhost", 7000));
- * RSocketClient client = RSocketClient.from(source);
+ * RemotingClient client = RemotingClient.from(source);
  * }
*/ public class ChannelConnector { @@ -90,8 +88,10 @@ public class ChannelConnector { private Mono setupPayloadMono = Mono.empty(); + @Deprecated private String metadataMimeType = "application/binary"; + @Deprecated private String dataMimeType = "application/binary"; private Duration keepAliveInterval = Duration.ofSeconds(20); @@ -135,7 +135,7 @@ public static ChannelConnector create() { * * * @param transport the transport of choice to connect with - * @return a {@code Mono} with the connected RSocket + * @return a {@code Mono} with the connected Channel */ public static Mono connectWith(ClientTransport transport) { return ChannelConnector.create().connect(() -> transport); @@ -199,14 +199,6 @@ public ChannelConnector dataMimeType(String dataMimeType) { * Set the MIME type to use for formatting payload metadata on the established connection. This is * set in the initial {@code SETUP} frame sent to the server. * - *

For metadata encoding, consider using one of the following encoders: - * - *

    - *
  • {@link io.rsocket.metadata.CompositeMetadataCodec Composite Metadata} - *
  • {@link io.rsocket.metadata.TaggingMetadataCodec Routing} - *
  • {@link io.rsocket.metadata.AuthMetadataCodec Authentication} - *
- * * @param metadataMimeType the MIME type to be used for payload metadata * @return the same instance for method chaining * @see SETUP @@ -275,35 +267,35 @@ public ChannelConnector interceptors(Consumer configurer) { /** * Configure a client-side {@link ChannelAcceptor} for responding to requests from the server. * - *

A full-form example with access to the {@code SETUP} frame and the "sending" RSocket (the + *

A full-form example with access to the {@code SETUP} frame and the "sending" Channel (the * same as the one returned from {@link #connect(ClientTransport)}): * *

{@code
-   * Mono rsocketMono =
+   * Mono channelMono =
    *     ChannelConnector.create()
-   *             .acceptor((setup, sendingRSocket) -> Mono.just(new RSocket() {...}))
+   *             .acceptor((setup, sending) -> Mono.just(new Channel() {...}))
    *             .connect(transport);
    * }
* - *

A shortcut example with just the handling RSocket: + *

A shortcut example with just the handling Channel: * *

{@code
-   * Mono rsocketMono =
+   * Mono channelMono =
    *     ChannelConnector.create()
-   *             .acceptor(SocketAcceptor.with(new RSocket() {...})))
+   *             .acceptor(ChannelAcceptor.with(new Channel() {...})))
    *             .connect(transport);
    * }
* *

A shortcut example handling only request-response: * *

{@code
-   * Mono rsocketMono =
+   * Mono channelMono =
    *     ChannelConnector.create()
-   *             .acceptor(SocketAcceptor.forRequestResponse(payload -> ...))
+   *             .acceptor(ChannelAcceptor.forRequestResponse(payload -> ...))
    *             .connect(transport);
    * }
* - *

By default, {@code new RSocket(){}} is used which rejects all requests from the server with + *

By default, {@code new Channel(){}} is used which rejects all requests from the server with * {@link UnsupportedOperationException}. * * @param acceptor the acceptor to use for responding to server requests @@ -315,37 +307,37 @@ public ChannelConnector acceptor(ChannelAcceptor acceptor) { } /** - * When this is enabled, the connect methods of this class return a special {@code Mono} - * that maintains a single, shared {@code RSocket} for all subscribers: + * When this is enabled, the connect methods of this class return a special {@code Mono} + * that maintains a single, shared {@code Channel} for all subscribers: * *

{@code
-   * Mono rsocketMono =
+   * Mono channelMono =
    *   ChannelConnector.create()
    *           .reconnect(Retry.fixedDelay(3, Duration.ofSeconds(1)))
    *           .connect(transport);
    *
-   *  RSocket r1 = rsocketMono.block();
-   *  RSocket r2 = rsocketMono.block();
+   *  Channel r1 = channelMono.block();
+   *  Channel r2 = channelMono.block();
    *
    *  assert r1 == r2;
    * }
* - *

The {@code RSocket} remains cached until the connection is lost and after that, new attempts - * to subscribe or re-subscribe trigger a reconnect and result in a new shared {@code RSocket}: + *

The {@code Channel} remains cached until the connection is lost and after that, new attempts + * to subscribe or re-subscribe trigger a reconnect and result in a new shared {@code Channel}: * *

{@code
-   * Mono rsocketMono =
+   * Mono channelMono =
    *   ChannelConnector.create()
    *           .reconnect(Retry.fixedDelay(3, Duration.ofSeconds(1)))
    *           .connect(transport);
    *
-   *  RSocket r1 = rsocketMono.block();
-   *  RSocket r2 = rsocketMono.block();
+   *  Channel r1 = channelMono.block();
+   *  Channel r2 = channelMono.block();
    *
    *  r1.dispose();
    *
-   *  RSocket r3 = rsocketMono.block();
-   *  RSocket r4 = rsocketMono.block();
+   *  Channel r3 = channelMono.block();
+   *  Channel r4 = channelMono.block();
    *
    *  assert r1 == r2;
    *  assert r3 == r4;
@@ -357,12 +349,12 @@ public ChannelConnector acceptor(ChannelAcceptor acceptor) {
    * if or when failed requests should be retried which in turn triggers the shared reconnect:
    *
    * 
{@code
-   * Mono rocketMono =
+   * Mono rocketMono =
    *   ChannelConnector.create()
    *           .reconnect(Retry.fixedDelay(3, Duration.ofSeconds(1)))
    *           .connect(transport);
    *
-   *  rsocketMono.flatMap(rsocket -> rsocket.requestResponse(...))
+   *  channelMono.flatMap(channel -> channel.requestResponse(...))
    *           .retryWhen(Retry.fixedDelay(1, Duration.ofSeconds(5)))
    *           .subscribe()
    * }
@@ -383,7 +375,7 @@ public ChannelConnector reconnect(Retry retry) { } /** - * Enables the Resume capability of the RSocket protocol where if the client gets disconnected, + * Enables the Resume capability of the protocol where if the client gets disconnected, * the connection is re-acquired and any interrupted streams are resumed automatically. For this * to work the server must also support and have the Resume capability enabled. * @@ -408,13 +400,13 @@ public ChannelConnector resume(Resume resume) { } /** - * Enables the Lease feature of the RSocket protocol where the number of requests that can be + * Enables the Lease feature of the protocol where the number of requests that can be * performed from either side are rationed via {@code LEASE} frames from the responder side. * *

Example usage: * *

{@code
-   * Mono rocketMono =
+   * Mono rocketMono =
    *         ChannelConnector.create()
    *                         .lease()
    *                         .connect(transport);
@@ -431,13 +423,13 @@ public ChannelConnector lease() {
   }
 
   /**
-   * Enables the Lease feature of the RSocket protocol where the number of requests that can be
+   * Enables the Lease feature of the protocol where the number of requests that can be
    * performed from either side are rationed via {@code LEASE} frames from the responder side.
    *
    * 

Example usage: * *

{@code
-   * Mono rocketMono =
+   * Mono rocketMono =
    *         ChannelConnector.create()
    *                         .lease(spec -> spec.maxPendingRequests(128))
    *                         .connect(transport);
@@ -523,7 +515,7 @@ public ChannelConnector payloadDecoder(PayloadDecoder decoder) {
    * #reconnect(Retry) reconnect} nor {@link #resume(Resume)} are enabled.
    *
    * @param transport the transport of choice to connect with
-   * @return a {@code Mono} with the connected RSocket
+   * @return a {@code Mono} with the connected Channel
    */
   public Mono connect(ClientTransport transport) {
     return connect(() -> transport);
@@ -536,7 +528,7 @@ public Mono connect(ClientTransport transport) {
    * 

* * @param transportSupplier supplier for the transport to connect with - * @return a {@code Mono} with the connected RSocket + * @return a {@code Mono} with the connected Channel */ public Mono connect(Supplier transportSupplier) { return Mono.fromSupplier(transportSupplier).flatMap(ct -> { @@ -633,8 +625,8 @@ public Mono connect(Supplier transportSupplier) { return interceptors.decorateAcceptor(acceptor) .accept(setup, wrappedChannelRequester) - .map(rSocketHandler -> { - Channel wrappedChannelHandler = interceptors.decorateResponder(rSocketHandler); + .map(channelHandler -> { + Channel wrappedChannelHandler = interceptors.decorateResponder(channelHandler); ResponderLeaseTracker responderLeaseTracker = leaseEnabled ? new ResponderLeaseTracker(CLIENT_TAG, wrappedConnection, leases.sender) @@ -643,7 +635,7 @@ public Mono connect(Supplier transportSupplier) { Channel channelResponder = new ChannelResponder(multiplexer.asServerConnection(), wrappedChannelHandler, payloadDecoder, responderLeaseTracker, mtu, maxFrameLength, maxInboundPayloadSize, leaseEnabled && leases.sender instanceof TrackingLeaseSender - ? rSocket -> interceptors.initResponderRequestInterceptor(rSocket, (TrackingLeaseSender) leases.sender) + ? channel -> interceptors.initResponderRequestInterceptor(channel, (TrackingLeaseSender) leases.sender) : interceptors::initResponderRequestInterceptor, responderOnAllClosedSink); return wrappedChannelRequester; diff --git a/today-remoting/src/main/java/infra/remoting/core/ChannelRequester.java b/today-remoting/src/main/java/infra/remoting/core/ChannelRequester.java index ed3cf5b..321180e 100644 --- a/today-remoting/src/main/java/infra/remoting/core/ChannelRequester.java +++ b/today-remoting/src/main/java/infra/remoting/core/ChannelRequester.java @@ -51,7 +51,7 @@ import static infra.remoting.keepalive.KeepAliveSupport.ClientKeepAliveSupport; /** - * Requester Side of a RSocket socket. Sends {@link ByteBuf}s to a {@link ChannelResponder} of peer + * Requester Side of a Channel socket. Sends {@link ByteBuf}s to a {@link ChannelResponder} of peer */ class ChannelRequester extends RequesterResponderSupport implements Channel { diff --git a/today-remoting/src/main/java/infra/remoting/core/ChannelResponder.java b/today-remoting/src/main/java/infra/remoting/core/ChannelResponder.java index 62da97c..1574ac7 100644 --- a/today-remoting/src/main/java/infra/remoting/core/ChannelResponder.java +++ b/today-remoting/src/main/java/infra/remoting/core/ChannelResponder.java @@ -50,7 +50,7 @@ import reactor.core.publisher.Sinks; /** - * Responder side of RSocket. Receives {@link ByteBuf}s from a peer's {@link ChannelRequester} + * Responder side of Channel. Receives {@link ByteBuf}s from a peer's {@link ChannelRequester} */ class ChannelResponder extends RequesterResponderSupport implements Channel { @@ -280,7 +280,7 @@ final void handleFrame(ByteBuf frame) { case LEASE: default: connection.sendFrame(streamId, ErrorFrameCodec.encode( - allocator, streamId, new IllegalStateException("ServerRSocket: Unexpected frame type: " + frameType))); + allocator, streamId, new IllegalStateException("ServerChannel: Unexpected frame type: " + frameType))); break; } } diff --git a/today-remoting/src/main/java/infra/remoting/core/DefaultConnectionSetupPayload.java b/today-remoting/src/main/java/infra/remoting/core/DefaultConnectionSetupPayload.java index a8618c3..76f4b34 100644 --- a/today-remoting/src/main/java/infra/remoting/core/DefaultConnectionSetupPayload.java +++ b/today-remoting/src/main/java/infra/remoting/core/DefaultConnectionSetupPayload.java @@ -25,7 +25,7 @@ /** * Default implementation of {@link ConnectionSetupPayload}. Primarily for internal use within - * RSocket Java but may be created in an application, e.g. for testing purposes. + * Java but may be created in an application, e.g. for testing purposes. */ public class DefaultConnectionSetupPayload extends ConnectionSetupPayload { diff --git a/today-remoting/src/main/java/infra/remoting/core/DefaultRemotingClient.java b/today-remoting/src/main/java/infra/remoting/core/DefaultRemotingClient.java index 98ce442..a3b9fbd 100644 --- a/today-remoting/src/main/java/infra/remoting/core/DefaultRemotingClient.java +++ b/today-remoting/src/main/java/infra/remoting/core/DefaultRemotingClient.java @@ -98,27 +98,27 @@ public Mono source() { @Override public Mono fireAndForget(Mono payloadMono) { - return new RSocketClientMonoOperator<>(this, FrameType.REQUEST_FNF, payloadMono); + return new ChannelClientMonoOperator<>(this, FrameType.REQUEST_FNF, payloadMono); } @Override public Mono requestResponse(Mono payloadMono) { - return new RSocketClientMonoOperator<>(this, FrameType.REQUEST_RESPONSE, payloadMono); + return new ChannelClientMonoOperator<>(this, FrameType.REQUEST_RESPONSE, payloadMono); } @Override public Flux requestStream(Mono payloadMono) { - return new RSocketClientFluxOperator<>(this, FrameType.REQUEST_STREAM, payloadMono); + return new ChannelClientFluxOperator<>(this, FrameType.REQUEST_STREAM, payloadMono); } @Override public Flux requestChannel(Publisher payloads) { - return new RSocketClientFluxOperator<>(this, FrameType.REQUEST_CHANNEL, payloads); + return new ChannelClientFluxOperator<>(this, FrameType.REQUEST_CHANNEL, payloads); } @Override public Mono metadataPush(Mono payloadMono) { - return new RSocketClientMonoOperator<>(this, FrameType.METADATA_PUSH, payloadMono); + return new ChannelClientMonoOperator<>(this, FrameType.METADATA_PUSH, payloadMono); } @Override @@ -528,12 +528,12 @@ public void accept(Channel channel, Throwable t) { } } - static class RSocketClientMonoOperator extends MonoOperator { + static class ChannelClientMonoOperator extends MonoOperator { final DefaultRemotingClient parent; final FrameType requestType; - public RSocketClientMonoOperator( + public ChannelClientMonoOperator( DefaultRemotingClient parent, FrameType requestType, Mono source) { super(source); this.parent = parent; @@ -546,13 +546,13 @@ public void subscribe(CoreSubscriber actual) { } } - static class RSocketClientFluxOperator> extends Flux { + static class ChannelClientFluxOperator> extends Flux { final DefaultRemotingClient parent; final FrameType requestType; final ST source; - public RSocketClientFluxOperator( + public ChannelClientFluxOperator( DefaultRemotingClient parent, FrameType requestType, ST source) { this.parent = parent; this.requestType = requestType; diff --git a/today-remoting/src/main/java/infra/remoting/core/RemotingClient.java b/today-remoting/src/main/java/infra/remoting/core/RemotingClient.java index 7aaec90..f43a2c7 100644 --- a/today-remoting/src/main/java/infra/remoting/core/RemotingClient.java +++ b/today-remoting/src/main/java/infra/remoting/core/RemotingClient.java @@ -26,52 +26,46 @@ import reactor.core.publisher.Mono; /** - * Contract for performing RSocket requests. + * Contract for performing protocol requests. * *

{@link RemotingClient} differs from {@link Channel} in a number of ways: * *

    - *
  • {@code RSocket} represents a "live" connection that is transient and needs to be obtained - * typically from a {@code Mono} source via {@code flatMap} or block. By contrast, - * {@code RSocketClient} is a higher level layer that contains such a {@link #source() source} + *
  • {@code Channel} represents a "live" connection that is transient and needs to be obtained + * typically from a {@code Mono} source via {@code flatMap} or block. By contrast, + * {@code RemotingClient} is a higher level layer that contains such a {@link #source() source} * of connections and transparently obtains and re-obtains a shared connection as needed when - * requests are made concurrently. That means an {@code RSocketClient} can simply be created + * requests are made concurrently. That means an {@code RemotingClient} can simply be created * once, even before a connection is established, and shared as a singleton across multiple * places as you would with any other client. - *
  • For request input {@code RSocket} accepts an instance of {@code Payload} and does not allow + *
  • For request input {@code Channel} accepts an instance of {@code Payload} and does not allow * more than one subscription per request because there is no way to safely re-use that input. - * By contrast {@code RSocketClient} accepts {@code Publisher} and allow + * By contrast {@code RemotingClient} accepts {@code Publisher} and allow * re-subscribing which repeats the request. - *
  • {@code RSocket} can be used for sending and it can also be implemented for receiving. By - * contrast {@code RSocketClient} is used only for sending, typically from the client side + *
  • {@code Channel} can be used for sending and it can also be implemented for receiving. By + * contrast {@code RemotingClient} is used only for sending, typically from the client side * which allows obtaining and re-obtaining connections from a source as needed. However it can * also be used from the server side by {@link #from(Channel) wrapping} the "live" {@code - * RSocket} for a given connection. + * Channel} for a given connection. *
* - *

The example below shows how to create an {@code RSocketClient}: + *

The example below shows how to create an {@code RemotingClient}: * - *

{@code
- * Mono source =
- *         RSocketConnector.create()
- *                 .metadataMimeType("message/x.rsocket.composite-metadata.v0")
- *                 .dataMimeType("application/cbor")
- *                 .connect(TcpClientTransport.create("localhost", 7000));
+ * 
{@code
+ * Mono source = ChannelConnector.create()
+ *      .connect(TcpClientTransport.create("localhost", 7000));
  *
- * RSocketClient client = RSocketClient.from(source);
+ * RemotingClient client = RemotingClient.from(source);
  * }
* - *

The below configures retry logic to use when a shared {@code RSocket} connection is obtained: + *

The below configures retry logic to use when a shared {@code Channel} connection is obtained: * - *

{@code
- * Mono source =
- *         RSocketConnector.create()
- *                 .metadataMimeType("message/x.rsocket.composite-metadata.v0")
- *                 .dataMimeType("application/cbor")
+ * 
{@code
+ * Mono source =
+ *         ChannelConnector.create()
  *                 .reconnect(Retry.fixedDelay(3, Duration.ofSeconds(1)))
  *                 .connect(TcpClientTransport.create("localhost", 7000));
- *
- * RSocketClient client = RSocketClient.from(source);
+ * RemotingClient client = RemotingClient.from(source);
  * }
* * @see LoadBalanceRemotingClient @@ -79,8 +73,8 @@ public interface RemotingClient extends Closeable { /** - * Connect to the remote rsocket endpoint, if not yet connected. This method is a shortcut for - * {@code RSocketClient#source().subscribe()}. + * Connect to the remote endpoint, if not yet connected. This method is a shortcut for + * {@code RemotingClient#source().subscribe()}. * * @return {@code true} if an attempt to connect was triggered or if already connected, or {@code * false} if the client is terminated. @@ -130,7 +124,7 @@ default Mono onClose() { /** * Create an {@link RemotingClient} that obtains shared connections as needed, when requests are - * made, from the given {@code Mono} source. + * made, from the given {@code Mono} source. * * @param source the source for connections, typically prepared via {@link ChannelConnector}. * @return the created client instance @@ -141,16 +135,16 @@ static RemotingClient from(Mono source) { /** * Adapt the given {@link Channel} to use as {@link RemotingClient}. This is useful to wrap the - * sending {@code RSocket} in a server. + * sending {@code Channel} in a server. * - *

Note: unlike an {@code RSocketClient} created via {@link + *

Note: unlike an {@code RemotingClient} created via {@link * RemotingClient#from(Mono)}, the instance returned from this factory method can only perform - * requests for as long as the given {@code RSocket} remains "live". + * requests for as long as the given {@code Channel} remains "live". * - * @param rsocket the {@code RSocket} to perform requests with + * @param channel the {@code Channel} to perform requests with * @return the created client instance */ - static RemotingClient from(Channel rsocket) { - return new RemotingClientAdapter(rsocket); + static RemotingClient from(Channel channel) { + return new RemotingClientAdapter(channel); } } diff --git a/today-remoting/src/main/java/infra/remoting/core/RemotingClientAdapter.java b/today-remoting/src/main/java/infra/remoting/core/RemotingClientAdapter.java index 6aec05e..540ac7b 100644 --- a/today-remoting/src/main/java/infra/remoting/core/RemotingClientAdapter.java +++ b/today-remoting/src/main/java/infra/remoting/core/RemotingClientAdapter.java @@ -31,58 +31,58 @@ */ class RemotingClientAdapter implements RemotingClient { - private final Channel rsocket; + private final Channel channel; - public RemotingClientAdapter(Channel rsocket) { - this.rsocket = rsocket; + public RemotingClientAdapter(Channel channel) { + this.channel = channel; } - public Channel rsocket() { - return rsocket; + public Channel channel() { + return channel; } @Override public boolean connect() { - throw new UnsupportedOperationException("Connect does not apply to a server side RSocket"); + throw new UnsupportedOperationException("Connect does not apply to a server side Channel"); } @Override public Mono source() { - return Mono.just(rsocket); + return Mono.just(channel); } @Override public Mono onClose() { - return rsocket.onClose(); + return channel.onClose(); } @Override public Mono fireAndForget(Mono payloadMono) { - return payloadMono.flatMap(rsocket::fireAndForget); + return payloadMono.flatMap(channel::fireAndForget); } @Override public Mono requestResponse(Mono payloadMono) { - return payloadMono.flatMap(rsocket::requestResponse); + return payloadMono.flatMap(channel::requestResponse); } @Override public Flux requestStream(Mono payloadMono) { - return payloadMono.flatMapMany(rsocket::requestStream); + return payloadMono.flatMapMany(channel::requestStream); } @Override public Flux requestChannel(Publisher payloads) { - return rsocket.requestChannel(payloads); + return channel.requestChannel(payloads); } @Override public Mono metadataPush(Mono payloadMono) { - return payloadMono.flatMap(rsocket::metadataPush); + return payloadMono.flatMap(channel::metadataPush); } @Override public void dispose() { - rsocket.dispose(); + channel.dispose(); } } diff --git a/today-remoting/src/main/java/infra/remoting/core/RemotingServer.java b/today-remoting/src/main/java/infra/remoting/core/RemotingServer.java index 7c3c881..307bcb2 100644 --- a/today-remoting/src/main/java/infra/remoting/core/RemotingServer.java +++ b/today-remoting/src/main/java/infra/remoting/core/RemotingServer.java @@ -53,13 +53,13 @@ import static infra.remoting.frame.FrameLengthCodec.FRAME_LENGTH_MASK; /** - * The main class for starting an RSocket server. + * The main class for starting a server. * *

For example: * *

{@code
  * CloseableChannel closeable =
- *         RemotingServer.create(SocketAcceptor.with(new RSocket() {...}))
+ *         RemotingServer.create(SocketAcceptor.with(new Channel() {...}))
  *                 .bind(TcpServerTransport.create("localhost", 7000))
  *                 .block();
  * }
@@ -111,19 +111,19 @@ public static RemotingServer create(ChannelAcceptor acceptor) { /** * Set the acceptor to handle incoming connections and handle requests. * - *

An example with access to the {@code SETUP} frame and sending RSocket for performing + *

An example with access to the {@code SETUP} frame and sending Channel for performing * requests back to the client if needed: * *

{@code
-   * RemotingServer.create((setup, sendingRSocket) -> Mono.just(new RSocket() {...}))
+   * RemotingServer.create((setup, sending) -> Mono.just(new Channel() {...}))
    *         .bind(TcpServerTransport.create("localhost", 7000))
    *         .subscribe();
    * }
* - *

A shortcut to provide the handling RSocket only: + *

A shortcut to provide the handling Channel only: * *

{@code
-   * RemotingServer.create(SocketAcceptor.with(new RSocket() {...}))
+   * RemotingServer.create(SocketAcceptor.with(new Channel() {...}))
    *         .bind(TcpServerTransport.create("localhost", 7000))
    *         .subscribe();
    * }
@@ -136,7 +136,7 @@ public static RemotingServer create(ChannelAcceptor acceptor) { * .subscribe(); * }
* - *

By default, {@code new RSocket(){}} is used for handling which rejects requests from the + *

By default, {@code new Channel(){}} is used for handling which rejects requests from the * client with {@link UnsupportedOperationException}. * * @param acceptor the acceptor to handle incoming connections and requests with @@ -168,7 +168,7 @@ public RemotingServer interceptors(Consumer configurer) { } /** - * Enables the Resume capability of the RSocket protocol where if the client gets disconnected, + * Enables the Resume capability of the protocol where if the client gets disconnected, * the connection is re-acquired and any interrupted streams are transparently resumed. For this * to work clients must also support and request to enable this when connecting. * @@ -189,14 +189,14 @@ public RemotingServer resume(Resume resume) { } /** - * Enables the Lease feature of the RSocket protocol where the number of requests that can be + * Enables the Lease feature of the protocol where the number of requests that can be * performed from either side are rationed via {@code LEASE} frames from the responder side. For * this to work clients must also support and request to enable this when connecting. * *

Example usage: * *

{@code
-   * RemotingServer.create(SocketAcceptor.with(new RSocket() {...}))
+   * RemotingServer.create(SocketAcceptor.with(new Channel() {...}))
    *         .lease(spec ->
    *            spec.sender(() -> Flux.interval(ofSeconds(1))
    *                                  .map(__ -> Lease.create(ofSeconds(1), 1)))
@@ -329,7 +329,7 @@ public  T bindNow(ServerTransport transport) {
   }
 
   /**
-   * An alternative to {@link #bind(ServerTransport)} that is useful for installing RSocket on a
+   * An alternative to {@link #bind(ServerTransport)} that is useful for installing Channel on a
    * server that is started independently.
    */
   public ConnectionAcceptor asConnectionAcceptor() {
@@ -337,7 +337,7 @@ public ConnectionAcceptor asConnectionAcceptor() {
   }
 
   /**
-   * An alternative to {@link #bind(ServerTransport)} that is useful for installing RSocket on a
+   * An alternative to {@link #bind(ServerTransport)} that is useful for installing Channel on a
    * server that is started independently.
    */
   public ConnectionAcceptor asConnectionAcceptor(int maxFrameLength) {
@@ -365,7 +365,7 @@ private Mono acceptor(ServerSetup serverSetup, DuplexConnection sourceConn
   }
 
   private Mono acceptResume(ServerSetup serverSetup, ByteBuf resumeFrame, DuplexConnection clientServerConnection) {
-    return serverSetup.acceptRSocketResume(resumeFrame, clientServerConnection);
+    return serverSetup.acceptChannelResume(resumeFrame, clientServerConnection);
   }
 
   private Mono accept(ServerSetup serverSetup, ByteBuf startFrame, DuplexConnection clientServerConnection, int maxFrameLength) {
@@ -392,7 +392,7 @@ private Mono acceptSetup(ServerSetup serverSetup, ByteBuf setupFrame, Dupl
       return clientServerConnection.onClose();
     }
 
-    return serverSetup.acceptRSocketSetup(setupFrame, clientServerConnection, (keepAliveHandler, wrappedDuplexConnection) -> {
+    return serverSetup.acceptChannelSetup(setupFrame, clientServerConnection, (keepAliveHandler, wrappedDuplexConnection) -> {
       final InitializingInterceptorRegistry interceptors = this.interceptors;
       final ConnectionSetupPayload setupPayload = new DefaultConnectionSetupPayload(setupFrame.retain());
       final ClientServerInputMultiplexer multiplexer = new ClientServerInputMultiplexer(wrappedDuplexConnection, interceptors, false);
@@ -425,8 +425,8 @@ private Mono acceptSetup(ServerSetup serverSetup, ByteBuf setupFrame, Dupl
                               wrappedDuplexConnection, rejectedSetupError(err)))
                       .then(wrappedDuplexConnection.onClose())
                       .then(Mono.error(err)))
-              .doOnNext(rSocketHandler -> {
-                Channel wrappedChannelHandler = interceptors.decorateResponder(rSocketHandler);
+              .doOnNext(channelHandler -> {
+                Channel wrappedChannelHandler = interceptors.decorateResponder(channelHandler);
                 DuplexConnection clientConnection = multiplexer.asClientConnection();
 
                 ResponderLeaseTracker responderLeaseTracker = leaseEnabled
@@ -436,7 +436,7 @@ wrappedDuplexConnection, rejectedSetupError(err)))
                 Channel channelResponder = new ChannelResponder(clientConnection, wrappedChannelHandler, payloadDecoder, responderLeaseTracker,
                         mtu, maxFrameLength, maxInboundPayloadSize,
                         leaseEnabled && leases.sender instanceof TrackingLeaseSender
-                                ? rSocket -> interceptors.initResponderRequestInterceptor(rSocket, (TrackingLeaseSender) leases.sender)
+                                ? channel -> interceptors.initResponderRequestInterceptor(channel, (TrackingLeaseSender) leases.sender)
                                 : interceptors::initResponderRequestInterceptor, responderOnAllClosedSink);
               })
               .doFinally(signalType -> setupPayload.release())
diff --git a/today-remoting/src/main/java/infra/remoting/core/ResolvingOperator.java b/today-remoting/src/main/java/infra/remoting/core/ResolvingOperator.java
index d106be6..837486c 100644
--- a/today-remoting/src/main/java/infra/remoting/core/ResolvingOperator.java
+++ b/today-remoting/src/main/java/infra/remoting/core/ResolvingOperator.java
@@ -33,8 +33,6 @@
 import reactor.core.publisher.Operators;
 import reactor.util.context.Context;
 
-// A copy of this class exists in io.rsocket.loadbalance
-
 class ResolvingOperator implements Disposable {
 
   static final CancellationException ON_DISPOSE = new CancellationException("Disposed");
diff --git a/today-remoting/src/main/java/infra/remoting/core/Resume.java b/today-remoting/src/main/java/infra/remoting/core/Resume.java
index 86a2818..ba89b94 100644
--- a/today-remoting/src/main/java/infra/remoting/core/Resume.java
+++ b/today-remoting/src/main/java/infra/remoting/core/Resume.java
@@ -30,7 +30,7 @@
 import reactor.util.retry.Retry;
 
 /**
- * Simple holder of configuration settings for the RSocket Resume capability. This can be used to
+ * Simple holder of configuration settings for the protocol Resume capability. This can be used to
  * configure an {@link ChannelConnector} or an {@link RemotingServer} except for {@link
  * #retry(Retry)} and {@link #token(Supplier)} which apply only to the client side.
  */
diff --git a/today-remoting/src/main/java/infra/remoting/core/ServerSetup.java b/today-remoting/src/main/java/infra/remoting/core/ServerSetup.java
index 00ff744..57b855c 100644
--- a/today-remoting/src/main/java/infra/remoting/core/ServerSetup.java
+++ b/today-remoting/src/main/java/infra/remoting/core/ServerSetup.java
@@ -54,11 +54,11 @@ Mono> init(DuplexConnection connection) {
             .or(connection.onClose().then(Mono.error(ClosedChannelException::new)));
   }
 
-  abstract Mono acceptRSocketSetup(ByteBuf frame,
+  abstract Mono acceptChannelSetup(ByteBuf frame,
           DuplexConnection clientServerConnection,
           BiFunction> then);
 
-  abstract Mono acceptRSocketResume(ByteBuf frame, DuplexConnection connection);
+  abstract Mono acceptChannelResume(ByteBuf frame, DuplexConnection connection);
 
   void dispose() { }
 
@@ -74,7 +74,7 @@ static class DefaultServerSetup extends ServerSetup {
     }
 
     @Override
-    public Mono acceptRSocketSetup(ByteBuf frame, DuplexConnection duplexConnection,
+    public Mono acceptChannelSetup(ByteBuf frame, DuplexConnection duplexConnection,
             BiFunction> then) {
 
       if (SetupFrameCodec.resumeEnabled(frame)) {
@@ -87,7 +87,7 @@ public Mono acceptRSocketSetup(ByteBuf frame, DuplexConnection duplexConne
     }
 
     @Override
-    public Mono acceptRSocketResume(ByteBuf frame, DuplexConnection duplexConnection) {
+    public Mono acceptChannelResume(ByteBuf frame, DuplexConnection duplexConnection) {
       sendError(duplexConnection, new RejectedResumeException("resume not supported"));
       return duplexConnection.onClose();
     }
@@ -112,7 +112,7 @@ static class ResumableServerSetup extends ServerSetup {
     }
 
     @Override
-    public Mono acceptRSocketSetup(ByteBuf frame, DuplexConnection duplexConnection,
+    public Mono acceptChannelSetup(ByteBuf frame, DuplexConnection duplexConnection,
             BiFunction> then) {
 
       if (SetupFrameCodec.resumeEnabled(frame)) {
@@ -122,7 +122,7 @@ public Mono acceptRSocketSetup(ByteBuf frame, DuplexConnection duplexConne
         final ResumableDuplexConnection resumableDuplexConnection =
                 new ResumableDuplexConnection(
                         "server", resumeToken, duplexConnection, resumableFramesStore);
-        final ServerChannelSession serverRSocketSession =
+        final ServerChannelSession serverChannelSession =
                 new ServerChannelSession(
                         resumeToken,
                         resumableDuplexConnection,
@@ -131,10 +131,10 @@ public Mono acceptRSocketSetup(ByteBuf frame, DuplexConnection duplexConne
                         resumeSessionDuration,
                         cleanupStoreOnKeepAlive);
 
-        sessionManager.save(serverRSocketSession, resumeToken);
+        sessionManager.save(serverChannelSession, resumeToken);
 
         return then.apply(new ResumableKeepAliveHandler(
-                        resumableDuplexConnection, serverRSocketSession, serverRSocketSession),
+                        resumableDuplexConnection, serverChannelSession, serverChannelSession),
                 resumableDuplexConnection);
       }
       else {
@@ -143,7 +143,7 @@ public Mono acceptRSocketSetup(ByteBuf frame, DuplexConnection duplexConne
     }
 
     @Override
-    public Mono acceptRSocketResume(ByteBuf frame, DuplexConnection duplexConnection) {
+    public Mono acceptChannelResume(ByteBuf frame, DuplexConnection duplexConnection) {
       ServerChannelSession session = sessionManager.get(ResumeFrameCodec.token(frame));
       if (session != null) {
         session.resumeWith(frame, duplexConnection);
diff --git a/today-remoting/src/main/java/infra/remoting/core/package-info.java b/today-remoting/src/main/java/infra/remoting/core/package-info.java
index 064f588..d4ed9b8 100644
--- a/today-remoting/src/main/java/infra/remoting/core/package-info.java
+++ b/today-remoting/src/main/java/infra/remoting/core/package-info.java
@@ -16,12 +16,12 @@
  */
 
 /**
- * Contains {@link infra.remoting.core.ChannelConnector RSocketConnector} and {@link
- * infra.remoting.core.RemotingServer RemotingServer}, the main classes for connecting to or starting an
- * RSocket server.
+ * Contains {@link infra.remoting.core.ChannelConnector ChannelConnector} and {@link
+ * infra.remoting.core.RemotingServer RemotingServer}, the main classes for connecting to or starting a
+ * protocol server.
  *
  * 

This package also contains a package private classes that implement support for the main - * RSocket interactions. + * interactions. */ @NonNullApi package infra.remoting.core; diff --git a/today-remoting/src/main/java/infra/remoting/exceptions/SetupException.java b/today-remoting/src/main/java/infra/remoting/exceptions/SetupException.java index 8904793..9d931ad 100644 --- a/today-remoting/src/main/java/infra/remoting/exceptions/SetupException.java +++ b/today-remoting/src/main/java/infra/remoting/exceptions/SetupException.java @@ -28,7 +28,7 @@ public abstract class SetupException extends ProtocolErrorException { /** * Constructs a new exception with the specified error code, message and cause. * - * @param errorCode the RSocket protocol code + * @param errorCode the protocol code * @param message the message * @param cause the cause of this exception */ diff --git a/today-remoting/src/main/java/infra/remoting/exceptions/package-info.java b/today-remoting/src/main/java/infra/remoting/exceptions/package-info.java index 09f733a..b0ab702 100644 --- a/today-remoting/src/main/java/infra/remoting/exceptions/package-info.java +++ b/today-remoting/src/main/java/infra/remoting/exceptions/package-info.java @@ -16,7 +16,7 @@ */ /** - * A hierarchy of exceptions that represent RSocket protocol error codes. + * A hierarchy of exceptions that represent protocol error codes. * * @see Error * Codes diff --git a/today-remoting/src/main/java/infra/remoting/frame/FrameHeaderCodec.java b/today-remoting/src/main/java/infra/remoting/frame/FrameHeaderCodec.java index 5c21f3b..e2750a7 100644 --- a/today-remoting/src/main/java/infra/remoting/frame/FrameHeaderCodec.java +++ b/today-remoting/src/main/java/infra/remoting/frame/FrameHeaderCodec.java @@ -45,7 +45,7 @@ public final class FrameHeaderCodec { /** (N)ext: bit to indicate payload or metadata present ({@link Subscriber#onNext(Object)}) */ public static final int FLAGS_N = 0b00_0010_0000; - public static final String DISABLE_FRAME_TYPE_CHECK = "io.rsocket.frames.disableFrameTypeCheck"; + public static final String DISABLE_FRAME_TYPE_CHECK = "infra.remoting.frames.disableFrameTypeCheck"; private static final int FRAME_FLAGS_MASK = 0b0000_0011_1111_1111; private static final int FRAME_TYPE_BITS = 6; private static final int FRAME_TYPE_SHIFT = 16 - FRAME_TYPE_BITS; diff --git a/today-remoting/src/main/java/infra/remoting/frame/decoder/package-info.java b/today-remoting/src/main/java/infra/remoting/frame/decoder/package-info.java index f85bbae..70760c9 100644 --- a/today-remoting/src/main/java/infra/remoting/frame/decoder/package-info.java +++ b/today-remoting/src/main/java/infra/remoting/frame/decoder/package-info.java @@ -16,7 +16,7 @@ */ /** - * Support for encoding and decoding of RSocket frames to and from {@link infra.remoting.Payload + * Support for encoding and decoding of protocol frames to and from {@link infra.remoting.Payload * Payload}. */ @NonNullApi diff --git a/today-remoting/src/main/java/infra/remoting/frame/package-info.java b/today-remoting/src/main/java/infra/remoting/frame/package-info.java index f411668..509d9a2 100644 --- a/today-remoting/src/main/java/infra/remoting/frame/package-info.java +++ b/today-remoting/src/main/java/infra/remoting/frame/package-info.java @@ -16,7 +16,7 @@ */ /** - * Support for encoding and decoding of RSocket frames to and from {@link infra.remoting.Payload + * Support for encoding and decoding of protocol frames to and from {@link infra.remoting.Payload * Payload}. */ @NonNullApi diff --git a/today-remoting/src/main/java/infra/remoting/lb/ChannelPool.java b/today-remoting/src/main/java/infra/remoting/lb/ChannelPool.java index 8dcb4f9..308ef90 100644 --- a/today-remoting/src/main/java/infra/remoting/lb/ChannelPool.java +++ b/today-remoting/src/main/java/infra/remoting/lb/ChannelPool.java @@ -53,7 +53,7 @@ class ChannelPool extends ResolvingOperator implements CoreSubscriber
  • S = AtomicReferenceFieldUpdater.newUpdater(ChannelPool.class, Subscription.class, "s"); - final DeferredResolutionChannel deferredResolutionRSocket = new DeferredResolutionChannel(this); + final DeferredResolutionChannel deferredResolutionChannel = new DeferredResolutionChannel(this); final ChannelConnector connector; @@ -115,38 +115,38 @@ public void onNext(List targets) { PooledChannel[] inactiveSockets; PooledChannel[] socketsToUse; for (; ; ) { - HashMap rSocketSuppliersCopy = new HashMap<>(targets.size()); + HashMap channelSuppliersCopy = new HashMap<>(targets.size()); int j = 0; for (LoadBalanceTarget target : targets) { - rSocketSuppliersCopy.put(target, j++); + channelSuppliersCopy.put(target, j++); } // Intersect current and new list of targets and find the ones to keep vs dispose previouslyActiveSockets = this.activeSockets; inactiveSockets = new PooledChannel[previouslyActiveSockets.length]; PooledChannel[] nextActiveSockets = - new PooledChannel[previouslyActiveSockets.length + rSocketSuppliersCopy.size()]; + new PooledChannel[previouslyActiveSockets.length + channelSuppliersCopy.size()]; int activeSocketsPosition = 0; int inactiveSocketsPosition = 0; - for (PooledChannel rSocket : previouslyActiveSockets) { - Integer index = rSocketSuppliersCopy.remove(rSocket.target()); + for (PooledChannel channel : previouslyActiveSockets) { + Integer index = channelSuppliersCopy.remove(channel.target()); if (index == null) { - // if one of the active rSockets is not included, we remove it and put in the + // if one of the active channels is not included, we remove it and put in the // pending removal - if (!rSocket.isDisposed()) { - inactiveSockets[inactiveSocketsPosition++] = rSocket; - // TODO: provide a meaningful algo for keeping removed rsocket in the list - // nextActiveSockets[position++] = rSocket; + if (!channel.isDisposed()) { + inactiveSockets[inactiveSocketsPosition++] = channel; + // TODO: provide a meaningful algo for keeping removed channel in the list + // nextActiveSockets[position++] = channel; } } else { - if (!rSocket.isDisposed()) { - // keep old RSocket instance - nextActiveSockets[activeSocketsPosition++] = rSocket; + if (!channel.isDisposed()) { + // keep old Channel instance + nextActiveSockets[activeSocketsPosition++] = channel; } else { - // put newly create RSocket instance + // put newly create Channel instance LoadBalanceTarget target = targets.get(index); nextActiveSockets[activeSocketsPosition++] = new PooledChannel(this, this.connector.connect(target.getTransport()), target); @@ -155,7 +155,7 @@ public void onNext(List targets) { } // The remainder are the brand new targets - for (LoadBalanceTarget target : rSocketSuppliersCopy.keySet()) { + for (LoadBalanceTarget target : channelSuppliersCopy.keySet()) { nextActiveSockets[activeSocketsPosition++] = new PooledChannel(this, this.connector.connect(target.getTransport()), target); } @@ -204,7 +204,7 @@ public void onComplete() { public Channel select() { if (isDisposed()) { - return this.deferredResolutionRSocket; + return this.deferredResolutionChannel; } Channel selected = doSelect(); @@ -223,7 +223,7 @@ public Channel select() { return selected; } } - return this.deferredResolutionRSocket; + return this.deferredResolutionChannel; } return selected; diff --git a/today-remoting/src/main/java/infra/remoting/lb/LoadBalanceRemotingClient.java b/today-remoting/src/main/java/infra/remoting/lb/LoadBalanceRemotingClient.java index e174cd9..2a5a5a5 100644 --- a/today-remoting/src/main/java/infra/remoting/lb/LoadBalanceRemotingClient.java +++ b/today-remoting/src/main/java/infra/remoting/lb/LoadBalanceRemotingClient.java @@ -31,8 +31,8 @@ import reactor.core.publisher.Mono; /** - * An implementation of {@link RemotingClient} backed by a pool of {@code RSocket} instances and - * using a {@link LoadBalanceStrategy} to select the {@code RSocket} to use for a given request. + * An implementation of {@link RemotingClient} backed by a pool of {@code Channel} instances and + * using a {@link LoadBalanceStrategy} to select the {@code Channel} to use for a given request. */ public class LoadBalanceRemotingClient implements RemotingClient { @@ -52,7 +52,9 @@ public boolean connect() { return channelPool.connect(); } - /** Return {@code Mono} that selects an RSocket from the underlying pool. */ + /** + * Return {@code Mono} that selects a Channel from the underlying pool. + */ @Override public Mono source() { return Mono.fromSupplier(channelPool::select); @@ -75,7 +77,7 @@ public Flux requestStream(Mono payloadMono) { @Override public Flux requestChannel(Publisher payloads) { - return source().flatMapMany(rSocket -> rSocket.requestChannel(payloads)); + return source().flatMapMany(channel -> channel.requestChannel(payloads)); } @Override @@ -94,7 +96,7 @@ public void dispose() { * *
        * LoadBalanceRemotingClient.builder(targetPublisher)
    -   *    .connector(RSocketConnector.create())
    +   *    .connector(ChannelConnector.create())
        *    .build();
        * 
    * diff --git a/today-remoting/src/main/java/infra/remoting/lb/PooledChannel.java b/today-remoting/src/main/java/infra/remoting/lb/PooledChannel.java index 9768d3a..fe79341 100644 --- a/today-remoting/src/main/java/infra/remoting/lb/PooledChannel.java +++ b/today-remoting/src/main/java/infra/remoting/lb/PooledChannel.java @@ -40,7 +40,7 @@ final class PooledChannel extends ResolvingOperator implements CoreSubs final ChannelPool parent; - final Mono rSocketSource; + final Mono channelSource; final LoadBalanceTarget loadbalanceTarget; @@ -51,9 +51,9 @@ final class PooledChannel extends ResolvingOperator implements CoreSubs static final AtomicReferenceFieldUpdater S = AtomicReferenceFieldUpdater.newUpdater(PooledChannel.class, Subscription.class, "s"); - PooledChannel(ChannelPool parent, Mono rSocketSource, LoadBalanceTarget loadbalanceTarget) { + PooledChannel(ChannelPool parent, Mono channelSource, LoadBalanceTarget loadbalanceTarget) { this.parent = parent; - this.rSocketSource = rSocketSource; + this.channelSource = channelSource; this.loadbalanceTarget = loadbalanceTarget; this.onCloseSink = Sinks.unsafe().empty(); } @@ -114,7 +114,7 @@ public void onNext(Channel value) { @Override protected void doSubscribe() { - this.rSocketSource.subscribe(this); + this.channelSource.subscribe(this); } @Override diff --git a/today-remoting/src/main/java/infra/remoting/lb/RoundRobinLoadBalanceStrategy.java b/today-remoting/src/main/java/infra/remoting/lb/RoundRobinLoadBalanceStrategy.java index ba39bce..3a24553 100644 --- a/today-remoting/src/main/java/infra/remoting/lb/RoundRobinLoadBalanceStrategy.java +++ b/today-remoting/src/main/java/infra/remoting/lb/RoundRobinLoadBalanceStrategy.java @@ -22,7 +22,7 @@ import infra.remoting.Channel; /** - * Simple {@link LoadBalanceStrategy} that selects the {@code RSocket} to use in round-robin order. + * Simple {@link LoadBalanceStrategy} that selects the {@code Channel} to use in round-robin order. */ public class RoundRobinLoadBalanceStrategy implements LoadBalanceStrategy { diff --git a/today-remoting/src/main/java/infra/remoting/lb/WeightedLoadBalanceStrategy.java b/today-remoting/src/main/java/infra/remoting/lb/WeightedLoadBalanceStrategy.java index c071b46..383bd21 100644 --- a/today-remoting/src/main/java/infra/remoting/lb/WeightedLoadBalanceStrategy.java +++ b/today-remoting/src/main/java/infra/remoting/lb/WeightedLoadBalanceStrategy.java @@ -27,9 +27,9 @@ import infra.remoting.core.ChannelConnector; /** - * {@link LoadBalanceStrategy} that assigns a weight to each {@code RSocket} based on {@link + * {@link LoadBalanceStrategy} that assigns a weight to each {@code Channel} based on {@link * Channel#availability() availability} and usage statistics. The weight is used to decide which - * {@code RSocket} to select. + * {@code Channel} to select. * *

    Use {@link #create()} or a {@link #builder() Builder} to create an instance. * @@ -184,7 +184,7 @@ private Builder() { } /** - * How many times to try to randomly select a pair of RSocket connections with non-zero + * How many times to try to randomly select a pair of Channel connections with non-zero * availability. This is applicable when there are more than two connections in the pool. If the * number of attempts is exceeded, the last selected pair is used. * @@ -199,7 +199,7 @@ public Builder maxPairSelectionAttempts(int numberOfAttempts) { /** * Configure how the created {@link WeightedLoadBalanceStrategy} should find the stats for a - * given RSocket. + * given Channel. * *

    By default this resolver is not set. * @@ -209,7 +209,7 @@ public Builder maxPairSelectionAttempts(int numberOfAttempts) { * ClientLoadBalanceStrategy} callback. If this strategy is used in any other context however, a * resolver here must be provided. * - * @param resolver to find the stats for an RSocket with + * @param resolver to find the stats for an Channel with */ public Builder weightedStatsResolver(Function resolver) { this.weightedStatsResolver = resolver; @@ -233,14 +233,14 @@ public WeightedStats apply(Channel channel) { } void init(ChannelConnector connector) { - connector.interceptors(registry -> registry.forRequestsInRequester(rSocket -> { + connector.interceptors(registry -> registry.forRequestsInRequester(channel -> { final WeightedStatsRequestInterceptor interceptor = new WeightedStatsRequestInterceptor() { @Override public void dispose() { - statsMap.remove(rSocket); + statsMap.remove(channel); } }; - statsMap.put(rSocket, interceptor); + statsMap.put(channel, interceptor); return interceptor; })); } diff --git a/today-remoting/src/main/java/infra/remoting/lease/Lease.java b/today-remoting/src/main/java/infra/remoting/lease/Lease.java index 761517e..cc7c687 100644 --- a/today-remoting/src/main/java/infra/remoting/lease/Lease.java +++ b/today-remoting/src/main/java/infra/remoting/lease/Lease.java @@ -23,7 +23,7 @@ import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; -/** A contract for RSocket lease, which is sent by a request acceptor and is time bound. */ +/** A contract for lease, which is sent by a request acceptor and is time bound. */ public final class Lease { public static Lease create( diff --git a/today-remoting/src/main/java/infra/remoting/lease/package-info.java b/today-remoting/src/main/java/infra/remoting/lease/package-info.java index 9d59091..ca80211 100644 --- a/today-remoting/src/main/java/infra/remoting/lease/package-info.java +++ b/today-remoting/src/main/java/infra/remoting/lease/package-info.java @@ -16,7 +16,7 @@ */ /** - * Contains support classes for the Lease feature of the RSocket protocol. + * Contains support classes for the Lease feature of the protocol. * * @see Resuming diff --git a/today-remoting/src/main/java/infra/remoting/plugins/ChannelAcceptorInterceptor.java b/today-remoting/src/main/java/infra/remoting/plugins/ChannelAcceptorInterceptor.java index 6a6ebd6..35b7dc5 100644 --- a/today-remoting/src/main/java/infra/remoting/plugins/ChannelAcceptorInterceptor.java +++ b/today-remoting/src/main/java/infra/remoting/plugins/ChannelAcceptorInterceptor.java @@ -24,7 +24,7 @@ * information and the ability to also decorate the sockets for requesting and responding. * *

    This could be used as an alternative to registering an individual "requester" {@code - * RSocketInterceptor} and "responder" {@code RSocketInterceptor}. + * ChannelInterceptor} and "responder" {@code ChannelInterceptor}. */ @FunctionalInterface public interface ChannelAcceptorInterceptor { diff --git a/today-remoting/src/main/java/infra/remoting/plugins/ConnectionInterceptor.java b/today-remoting/src/main/java/infra/remoting/plugins/ConnectionInterceptor.java index 439d4ac..38cf839 100644 --- a/today-remoting/src/main/java/infra/remoting/plugins/ConnectionInterceptor.java +++ b/today-remoting/src/main/java/infra/remoting/plugins/ConnectionInterceptor.java @@ -21,7 +21,7 @@ /** * Contract to decorate a {@link DuplexConnection} and intercept the sending and receiving of - * RSocket frames at the transport level. + * protocol frames at the transport level. */ @FunctionalInterface public interface ConnectionInterceptor { diff --git a/today-remoting/src/main/java/infra/remoting/plugins/InitializingInterceptorRegistry.java b/today-remoting/src/main/java/infra/remoting/plugins/InitializingInterceptorRegistry.java index a500d8d..46f03ef 100644 --- a/today-remoting/src/main/java/infra/remoting/plugins/InitializingInterceptorRegistry.java +++ b/today-remoting/src/main/java/infra/remoting/plugins/InitializingInterceptorRegistry.java @@ -54,18 +54,18 @@ public DuplexConnection initConnection(ConnectionInterceptor.Type type, DuplexCo return connection; } - public Channel decorateRequester(Channel rsocket) { + public Channel decorateRequester(Channel channel) { for (ChannelInterceptor interceptor : requesterChannelInterceptors) { - rsocket = interceptor.decorate(rsocket); + channel = interceptor.decorate(channel); } - return rsocket; + return channel; } - public Channel decorateResponder(Channel rsocket) { + public Channel decorateResponder(Channel channel) { for (ChannelInterceptor interceptor : responderChannelInterceptors) { - rsocket = interceptor.decorate(rsocket); + channel = interceptor.decorate(channel); } - return rsocket; + return channel; } public ChannelAcceptor decorateAcceptor(ChannelAcceptor acceptor) { diff --git a/today-remoting/src/main/java/infra/remoting/plugins/RateLimitInterceptor.java b/today-remoting/src/main/java/infra/remoting/plugins/RateLimitInterceptor.java index 23e38ea..58f7fc8 100644 --- a/today-remoting/src/main/java/infra/remoting/plugins/RateLimitInterceptor.java +++ b/today-remoting/src/main/java/infra/remoting/plugins/RateLimitInterceptor.java @@ -61,7 +61,7 @@ public Channel decorate(Channel socket) { } /** - * Create an interceptor for an {@code RSocket} that handles request-stream and/or request-channel + * Create an interceptor for an {@code Channel} that handles request-stream and/or request-channel * interactions. * * @param prefetchRate the prefetch rate to pass to {@link Flux#limitRate(int)} @@ -72,7 +72,7 @@ public static RateLimitInterceptor forResponder(int prefetchRate) { } /** - * Create an interceptor for an {@code RSocket} that handles request-stream and/or request-channel + * Create an interceptor for an {@code Channel} that handles request-stream and/or request-channel * interactions with more control over the overall prefetch rate and replenish threshold. * * @param highTide the high tide value to pass to {@link Flux#limitRate(int, int)} @@ -84,7 +84,7 @@ public static RateLimitInterceptor forResponder(int highTide, int lowTide) { } /** - * Create an interceptor for an {@code RSocket} that performs request-channel interactions. + * Create an interceptor for an {@code Channel} that performs request-channel interactions. * * @param prefetchRate the prefetch rate to pass to {@link Flux#limitRate(int)} * @return the created interceptor @@ -94,7 +94,7 @@ public static RateLimitInterceptor forRequester(int prefetchRate) { } /** - * Create an interceptor for an {@code RSocket} that performs request-channel interactions with + * Create an interceptor for an {@code Channel} that performs request-channel interactions with * more control over the overall prefetch rate and replenish threshold. * * @param highTide the high tide value to pass to {@link Flux#limitRate(int, int)} diff --git a/today-remoting/src/main/java/infra/remoting/plugins/RequestInterceptor.java b/today-remoting/src/main/java/infra/remoting/plugins/RequestInterceptor.java index fba579f..4154bd3 100644 --- a/today-remoting/src/main/java/infra/remoting/plugins/RequestInterceptor.java +++ b/today-remoting/src/main/java/infra/remoting/plugins/RequestInterceptor.java @@ -26,7 +26,7 @@ import reactor.util.context.Context; /** - * Class used to track the RSocket requests lifecycles. The main difference and advantage of this + * Class used to track the protocol requests lifecycles. The main difference and advantage of this * interceptor compares to {@link ChannelInterceptor} is that it allows intercepting the initial and * terminal phases on every individual request. * diff --git a/today-remoting/src/main/java/infra/remoting/plugins/package-info.java b/today-remoting/src/main/java/infra/remoting/plugins/package-info.java index 061ddb4..4709e52 100644 --- a/today-remoting/src/main/java/infra/remoting/plugins/package-info.java +++ b/today-remoting/src/main/java/infra/remoting/plugins/package-info.java @@ -15,7 +15,7 @@ * along with this program. If not, see [http://www.gnu.org/licenses/] */ -/** Contracts for interception of transports, connections, and requests in in RSocket Java. */ +/** Contracts for interception of transports, connections, and requests. */ @NonNullApi package infra.remoting.plugins; diff --git a/today-remoting/src/main/java/infra/remoting/resume/ResumableFramesStore.java b/today-remoting/src/main/java/infra/remoting/resume/ResumableFramesStore.java index 9bfa9a1..aebfa02 100644 --- a/today-remoting/src/main/java/infra/remoting/resume/ResumableFramesStore.java +++ b/today-remoting/src/main/java/infra/remoting/resume/ResumableFramesStore.java @@ -42,14 +42,14 @@ public interface ResumableFramesStore extends Closeable { */ Flux resumeStream(); - /** @return Local frame position as defined by RSocket protocol */ + /** @return Local frame position as defined by protocol */ long framePosition(); - /** @return Implied frame position as defined by RSocket protocol */ + /** @return Implied frame position as defined by protocol */ long frameImpliedPosition(); /** - * Received resumable frame as defined by RSocket protocol. Implementation must increment frame + * Received resumable frame as defined by protocol. Implementation must increment frame * implied position * * @return {@code true} if information about the frame has been stored diff --git a/today-remoting/src/main/java/infra/remoting/resume/package-info.java b/today-remoting/src/main/java/infra/remoting/resume/package-info.java index 31031ed..85b8e5b 100644 --- a/today-remoting/src/main/java/infra/remoting/resume/package-info.java +++ b/today-remoting/src/main/java/infra/remoting/resume/package-info.java @@ -16,7 +16,7 @@ */ /** - * Contains support classes for the RSocket resume capability. + * Contains support classes for the protocol resume capability. * * @see Resuming diff --git a/today-remoting/src/main/java/infra/remoting/transport/ClientTransport.java b/today-remoting/src/main/java/infra/remoting/transport/ClientTransport.java index 6e3dd7a..b792612 100644 --- a/today-remoting/src/main/java/infra/remoting/transport/ClientTransport.java +++ b/today-remoting/src/main/java/infra/remoting/transport/ClientTransport.java @@ -20,7 +20,7 @@ import infra.remoting.DuplexConnection; import reactor.core.publisher.Mono; -/** A client contract for writing transports of RSocket. */ +/** A client contract for writing transports of protocol. */ public interface ClientTransport extends Transport { /** diff --git a/today-remoting/src/main/java/infra/remoting/transport/ServerTransport.java b/today-remoting/src/main/java/infra/remoting/transport/ServerTransport.java index 0255fba..a3cef49 100644 --- a/today-remoting/src/main/java/infra/remoting/transport/ServerTransport.java +++ b/today-remoting/src/main/java/infra/remoting/transport/ServerTransport.java @@ -21,7 +21,7 @@ import reactor.core.publisher.Mono; /** - * A server contract for writing transports of RSocket. + * A server contract for writing transports of protocol. */ public interface ServerTransport extends Transport { diff --git a/today-remoting/src/main/java/infra/remoting/transport/Transport.java b/today-remoting/src/main/java/infra/remoting/transport/Transport.java index 6ed90e1..2dcc0b2 100644 --- a/today-remoting/src/main/java/infra/remoting/transport/Transport.java +++ b/today-remoting/src/main/java/infra/remoting/transport/Transport.java @@ -21,14 +21,12 @@ import static infra.remoting.frame.FrameLengthCodec.FRAME_LENGTH_MASK; -/** */ public interface Transport { /** - * Configurations that exposes the maximum frame size that a {@link DuplexConnection} can bring up - * to RSocket level. + * Configurations that exposes the maximum frame size that a {@link DuplexConnection} can bring up. * - *

    This number should not exist the 16,777,215 (maximum frame size specified by RSocket spec) + *

    This number should not exist the 16,777,215 (maximum frame size specified by protocol spec) * * @return return maximum configured frame size limit */ diff --git a/today-remoting/src/test/java/infra/remoting/FrameTest.java b/today-remoting/src/test/java/infra/remoting/FrameTest.java deleted file mode 100644 index 7448c44..0000000 --- a/today-remoting/src/test/java/infra/remoting/FrameTest.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2021 - 2024 the original author or authors. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] - */ - -package infra.remoting; - -public class FrameTest { - /*@Test - public void testFrameToString() { - final io.rsocket.Frame requestFrame = - io.rsocket.Frame.Request.from( - 1, FrameType.REQUEST_RESPONSE, DefaultPayload.create("streaming in -> 0"), 1); - assertEquals( - "Frame => Stream ID: 1 Type: REQUEST_RESPONSE Payload: data: \"streaming in -> 0\" ", - requestFrame.toString()); - } - - @Test - public void testFrameWithMetadataToString() { - final io.rsocket.Frame requestFrame = - io.rsocket.Frame.Request.from( - 1, - FrameType.REQUEST_RESPONSE, - DefaultPayload.create("streaming in -> 0", "metadata"), - 1); - assertEquals( - "Frame => Stream ID: 1 Type: REQUEST_RESPONSE Payload: metadata: \"metadata\" data: \"streaming in -> 0\" ", - requestFrame.toString()); - } - - @Test - public void testPayload() { - io.rsocket.Frame frame = - io.rsocket.Frame.PayloadFrame.from( - 1, - FrameType.NEXT_COMPLETE, - DefaultPayload.create("Hello"), - FrameHeaderFlyweight.FLAGS_C); - frame.toString(); - }*/ -} diff --git a/today-remoting/src/test/java/infra/remoting/RaceTestConstants.java b/today-remoting/src/test/java/infra/remoting/RaceTestConstants.java index 65f282d..e058926 100644 --- a/today-remoting/src/test/java/infra/remoting/RaceTestConstants.java +++ b/today-remoting/src/test/java/infra/remoting/RaceTestConstants.java @@ -19,5 +19,5 @@ public class RaceTestConstants { public static final int REPEATS = - Integer.parseInt(System.getProperty("rsocket.test.race.repeats", "1000")); + Integer.parseInt(System.getProperty("infra.remoting.test.race.repeats", "1000")); } diff --git a/today-remoting/src/test/java/infra/remoting/core/AbstractSocketRule.java b/today-remoting/src/test/java/infra/remoting/core/AbstractSocketRule.java index 0a1298e..fa88ba7 100644 --- a/today-remoting/src/test/java/infra/remoting/core/AbstractSocketRule.java +++ b/today-remoting/src/test/java/infra/remoting/core/AbstractSocketRule.java @@ -54,7 +54,7 @@ protected void doInit() { socket.dispose(); } connection = new TestDuplexConnection(allocator); - socket = newRSocket(); + socket = newChannel(); } public void setMaxInboundPayloadSize(int maxInboundPayloadSize) { @@ -67,7 +67,7 @@ public void setMaxFrameLength(int maxFrameLength) { doInit(); } - protected abstract T newRSocket(); + protected abstract T newChannel(); public LeaksTrackingByteBufAllocator alloc() { return allocator; diff --git a/today-remoting/src/test/java/infra/remoting/core/ChannelConnectorTests.java b/today-remoting/src/test/java/infra/remoting/core/ChannelConnectorTests.java index 33e3cb9..3005e34 100644 --- a/today-remoting/src/test/java/infra/remoting/core/ChannelConnectorTests.java +++ b/today-remoting/src/test/java/infra/remoting/core/ChannelConnectorTests.java @@ -148,7 +148,7 @@ public void ensuresThatSetupPayloadCanBeRetained() { } @Test - public void ensuresThatMonoFromRSocketConnectorCanBeUsedForMultipleSubscriptions() { + public void ensuresThatMonoFromChannelConnectorCanBeUsedForMultipleSubscriptions() { Payload setupPayload = ByteBufPayload.create("TestData", "TestMetadata"); assertThat(setupPayload.refCnt()).isOne(); diff --git a/today-remoting/src/test/java/infra/remoting/core/ChannelLeaseTests.java b/today-remoting/src/test/java/infra/remoting/core/ChannelLeaseTests.java index fc0d0cb..d170925 100644 --- a/today-remoting/src/test/java/infra/remoting/core/ChannelLeaseTests.java +++ b/today-remoting/src/test/java/infra/remoting/core/ChannelLeaseTests.java @@ -90,7 +90,7 @@ class ChannelLeaseTests { private ResponderLeaseTracker responderLeaseTracker; private LeaksTrackingByteBufAllocator byteBufAllocator; private TestDuplexConnection connection; - private ChannelResponder rSocketResponder; + private ChannelResponder channelResponder; private Channel mockChannelHandler; private Sinks.Many leaseSender = Sinks.many().multicast().onBackpressureBuffer(); @@ -183,7 +183,7 @@ protected void hookOnError(Throwable throwable) { })); }); - rSocketResponder = + channelResponder = new ChannelResponder( multiplexer.asServerConnection(), mockChannelHandler, @@ -202,7 +202,7 @@ void tearDownAndCheckForLeaks() { } @Test - public void serverRSocketFactoryRejectsUnsupportedLease() { + public void serverChannelFactoryRejectsUnsupportedLease() { Payload payload = DefaultPayload.create(DefaultPayload.EMPTY_BUFFER); ByteBuf setupFrame = SetupFrameCodec.encode( @@ -232,7 +232,7 @@ public void serverRSocketFactoryRejectsUnsupportedLease() { } @Test - public void clientRSocketFactorySetsLeaseFlag() { + public void clientChannelFactorySetsLeaseFlag() { TestClientTransport clientTransport = new TestClientTransport(); try { ChannelConnector.create().lease().connect(clientTransport).block(); @@ -426,25 +426,25 @@ void responderMissingLeaseRequestsAreRejected(FrameType frameType) { case REQUEST_FNF: final ByteBuf fnfFrame = RequestFireAndForgetFrameCodec.encodeReleasingPayload(byteBufAllocator, 1, payload1); - rSocketResponder.handleFrame(fnfFrame); + channelResponder.handleFrame(fnfFrame); fnfFrame.release(); break; case REQUEST_RESPONSE: final ByteBuf requestResponseFrame = RequestResponseFrameCodec.encodeReleasingPayload(byteBufAllocator, 1, payload1); - rSocketResponder.handleFrame(requestResponseFrame); + channelResponder.handleFrame(requestResponseFrame); requestResponseFrame.release(); break; case REQUEST_STREAM: final ByteBuf requestStreamFrame = RequestStreamFrameCodec.encodeReleasingPayload(byteBufAllocator, 1, 1, payload1); - rSocketResponder.handleFrame(requestStreamFrame); + channelResponder.handleFrame(requestStreamFrame); requestStreamFrame.release(); break; case REQUEST_CHANNEL: final ByteBuf requestChannelFrame = RequestChannelFrameCodec.encodeReleasingPayload(byteBufAllocator, 1, true, 1, payload1); - rSocketResponder.handleFrame(requestChannelFrame); + channelResponder.handleFrame(requestChannelFrame); requestChannelFrame.release(); break; } @@ -474,25 +474,25 @@ void responderPresentLeaseRequestsAreAccepted(FrameType frameType) { case REQUEST_FNF: final ByteBuf fnfFrame = RequestFireAndForgetFrameCodec.encodeReleasingPayload(byteBufAllocator, 1, payload1); - rSocketResponder.handleFireAndForget(1, fnfFrame); + channelResponder.handleFireAndForget(1, fnfFrame); fnfFrame.release(); break; case REQUEST_RESPONSE: final ByteBuf requestResponseFrame = RequestResponseFrameCodec.encodeReleasingPayload(byteBufAllocator, 1, payload1); - rSocketResponder.handleFrame(requestResponseFrame); + channelResponder.handleFrame(requestResponseFrame); requestResponseFrame.release(); break; case REQUEST_STREAM: final ByteBuf requestStreamFrame = RequestStreamFrameCodec.encodeReleasingPayload(byteBufAllocator, 1, 1, payload1); - rSocketResponder.handleFrame(requestStreamFrame); + channelResponder.handleFrame(requestStreamFrame); requestStreamFrame.release(); break; case REQUEST_CHANNEL: final ByteBuf requestChannelFrame = RequestChannelFrameCodec.encodeReleasingPayload(byteBufAllocator, 1, true, 1, payload1); - rSocketResponder.handleFrame(requestChannelFrame); + channelResponder.handleFrame(requestChannelFrame); requestChannelFrame.release(); break; } @@ -547,8 +547,8 @@ void responderDepletedAllowedLeaseRequestsAreRejected(FrameType frameType) { RequestFireAndForgetFrameCodec.encodeReleasingPayload(byteBufAllocator, 1, payload1); final ByteBuf fnfFrame2 = RequestFireAndForgetFrameCodec.encodeReleasingPayload(byteBufAllocator, 3, payload2); - rSocketResponder.handleFrame(fnfFrame); - rSocketResponder.handleFrame(fnfFrame2); + channelResponder.handleFrame(fnfFrame); + channelResponder.handleFrame(fnfFrame2); fnfFrame.release(); fnfFrame2.release(); break; @@ -557,8 +557,8 @@ void responderDepletedAllowedLeaseRequestsAreRejected(FrameType frameType) { RequestResponseFrameCodec.encodeReleasingPayload(byteBufAllocator, 1, payload1); final ByteBuf requestResponseFrame2 = RequestResponseFrameCodec.encodeReleasingPayload(byteBufAllocator, 3, payload2); - rSocketResponder.handleFrame(requestResponseFrame); - rSocketResponder.handleFrame(requestResponseFrame2); + channelResponder.handleFrame(requestResponseFrame); + channelResponder.handleFrame(requestResponseFrame2); requestResponseFrame.release(); requestResponseFrame2.release(); break; @@ -567,8 +567,8 @@ void responderDepletedAllowedLeaseRequestsAreRejected(FrameType frameType) { RequestStreamFrameCodec.encodeReleasingPayload(byteBufAllocator, 1, 1, payload1); final ByteBuf requestStreamFrame2 = RequestStreamFrameCodec.encodeReleasingPayload(byteBufAllocator, 3, 1, payload2); - rSocketResponder.handleFrame(requestStreamFrame); - rSocketResponder.handleFrame(requestStreamFrame2); + channelResponder.handleFrame(requestStreamFrame); + channelResponder.handleFrame(requestStreamFrame2); requestStreamFrame.release(); requestStreamFrame2.release(); break; @@ -577,8 +577,8 @@ void responderDepletedAllowedLeaseRequestsAreRejected(FrameType frameType) { RequestChannelFrameCodec.encodeReleasingPayload(byteBufAllocator, 1, true, 1, payload1); final ByteBuf requestChannelFrame2 = RequestChannelFrameCodec.encodeReleasingPayload(byteBufAllocator, 3, true, 1, payload2); - rSocketResponder.handleFrame(requestChannelFrame); - rSocketResponder.handleFrame(requestChannelFrame2); + channelResponder.handleFrame(requestChannelFrame); + channelResponder.handleFrame(requestChannelFrame2); requestChannelFrame.release(); requestChannelFrame2.release(); break; @@ -718,7 +718,7 @@ static Stream interactions() { FrameType.REQUEST_STREAM), Arguments.of( (BiFunction>) - (rSocket, payload) -> rSocket.requestChannel(Mono.just(payload)), + (channel, payload) -> channel.requestChannel(Mono.just(payload)), FrameType.REQUEST_CHANNEL)); } diff --git a/today-remoting/src/test/java/infra/remoting/core/ChannelReconnectTests.java b/today-remoting/src/test/java/infra/remoting/core/ChannelReconnectTests.java index b857b5e..4bfa859 100644 --- a/today-remoting/src/test/java/infra/remoting/core/ChannelReconnectTests.java +++ b/today-remoting/src/test/java/infra/remoting/core/ChannelReconnectTests.java @@ -44,16 +44,16 @@ public class ChannelReconnectTests { private Queue retries = new ConcurrentLinkedQueue<>(); @Test - public void shouldBeASharedReconnectableInstanceOfRSocketMono() throws InterruptedException { + public void shouldBeASharedReconnectableInstanceOfChannelMono() throws InterruptedException { TestClientTransport[] testClientTransport = new TestClientTransport[] { new TestClientTransport() }; - Mono rSocketMono = + Mono channelMono = ChannelConnector.create() .reconnect(Retry.indefinitely()) .connect(() -> testClientTransport[0]); - Channel channel1 = rSocketMono.block(); - Channel channel2 = rSocketMono.block(); + Channel channel1 = channelMono.block(); + Channel channel2 = channelMono.block(); FrameAssert.assertThat(testClientTransport[0].testConnection().awaitFrame()) .typeOf(FrameType.SETUP) @@ -67,8 +67,8 @@ public void shouldBeASharedReconnectableInstanceOfRSocketMono() throws Interrupt testClientTransport[0].alloc().assertHasNoLeaks(); testClientTransport[0] = new TestClientTransport(); - Channel channel3 = rSocketMono.block(); - Channel channel4 = rSocketMono.block(); + Channel channel3 = channelMono.block(); + Channel channel4 = channelMono.block(); FrameAssert.assertThat(testClientTransport[0].testConnection().awaitFrame()) .typeOf(FrameType.SETUP) @@ -84,7 +84,7 @@ public void shouldBeASharedReconnectableInstanceOfRSocketMono() throws Interrupt @Test @SuppressWarnings({ "rawtype" }) - public void shouldBeRetrieableConnectionSharedReconnectableInstanceOfRSocketMono() { + public void shouldBeRetrieableConnectionSharedReconnectableInstanceOfChannelMono() { ClientTransport transport = Mockito.mock(ClientTransport.class); TestClientTransport transport1 = new TestClientTransport(); Mockito.when(transport.connect()) @@ -93,7 +93,7 @@ public void shouldBeRetrieableConnectionSharedReconnectableInstanceOfRSocketMono .thenThrow(UncheckedIOException.class) .thenThrow(UncheckedIOException.class) .thenReturn(transport1.connect()); - Mono rSocketMono = + Mono channelMono = ChannelConnector.create() .reconnect( Retry.backoff(4, Duration.ofMillis(100)) @@ -101,8 +101,8 @@ public void shouldBeRetrieableConnectionSharedReconnectableInstanceOfRSocketMono .doAfterRetry(onRetry())) .connect(transport); - Channel channel1 = rSocketMono.block(); - Channel channel2 = rSocketMono.block(); + Channel channel1 = channelMono.block(); + Channel channel2 = channelMono.block(); assertThat(channel1).isEqualTo(channel2); assertRetries( @@ -123,7 +123,7 @@ public void shouldBeRetrieableConnectionSharedReconnectableInstanceOfRSocketMono @Test @SuppressWarnings({ "rawtype" }) - public void shouldBeExaustedRetrieableConnectionSharedReconnectableInstanceOfRSocketMono() { + public void shouldBeExaustedRetrieableConnectionSharedReconnectableInstanceOfChannelMono() { ClientTransport transport = Mockito.mock(ClientTransport.class); TestClientTransport transport1 = new TestClientTransport(); Mockito.when(transport.connect()) @@ -133,7 +133,7 @@ public void shouldBeExaustedRetrieableConnectionSharedReconnectableInstanceOfRSo .thenThrow(UncheckedIOException.class) .thenThrow(UncheckedIOException.class) .thenReturn(transport1.connect()); - Mono rSocketMono = + Mono channelMono = ChannelConnector.create() .reconnect( Retry.backoff(4, Duration.ofMillis(100)) @@ -141,11 +141,11 @@ public void shouldBeExaustedRetrieableConnectionSharedReconnectableInstanceOfRSo .doAfterRetry(onRetry())) .connect(transport); - Assertions.assertThatThrownBy(rSocketMono::block) + Assertions.assertThatThrownBy(channelMono::block) .matches(Exceptions::isRetryExhausted) .hasCauseInstanceOf(UncheckedIOException.class); - Assertions.assertThatThrownBy(rSocketMono::block) + Assertions.assertThatThrownBy(channelMono::block) .matches(Exceptions::isRetryExhausted) .hasCauseInstanceOf(UncheckedIOException.class); @@ -159,11 +159,11 @@ public void shouldBeExaustedRetrieableConnectionSharedReconnectableInstanceOfRSo } @Test - public void shouldBeNotBeASharedReconnectableInstanceOfRSocketMono() { + public void shouldBeNotBeASharedReconnectableInstanceOfChannelMono() { TestClientTransport transport = new TestClientTransport(); - Mono rSocketMono = ChannelConnector.connectWith(transport); + Mono channelMono = ChannelConnector.connectWith(transport); - Channel channel1 = rSocketMono.block(); + Channel channel1 = channelMono.block(); TestDuplexConnection connection1 = transport.testConnection(); FrameAssert.assertThat(connection1.awaitFrame()) @@ -171,7 +171,7 @@ public void shouldBeNotBeASharedReconnectableInstanceOfRSocketMono() { .hasStreamIdZero() .hasNoLeaks(); - Channel channel2 = rSocketMono.block(); + Channel channel2 = channelMono.block(); TestDuplexConnection connection2 = transport.testConnection(); assertThat(channel1).isNotEqualTo(channel2); diff --git a/today-remoting/src/test/java/infra/remoting/core/ChannelRequesterSubscribersTests.java b/today-remoting/src/test/java/infra/remoting/core/ChannelRequesterSubscribersTests.java index 6355208..2fa8d2e 100644 --- a/today-remoting/src/test/java/infra/remoting/core/ChannelRequesterSubscribersTests.java +++ b/today-remoting/src/test/java/infra/remoting/core/ChannelRequesterSubscribersTests.java @@ -186,24 +186,24 @@ static Stream allInteractions() { return Stream.of( Arguments.of( (Function>) - rSocket -> rSocket.fireAndForget(DefaultPayload.create("test")), + channel -> channel.fireAndForget(DefaultPayload.create("test")), FrameType.REQUEST_FNF), Arguments.of( (Function>) - rSocket -> rSocket.requestResponse(DefaultPayload.create("test")), + channel -> channel.requestResponse(DefaultPayload.create("test")), FrameType.REQUEST_RESPONSE), Arguments.of( (Function>) - rSocket -> rSocket.requestStream(DefaultPayload.create("test")), + channel -> channel.requestStream(DefaultPayload.create("test")), FrameType.REQUEST_STREAM), Arguments.of( (Function>) - rSocket -> rSocket.requestChannel(Mono.just(DefaultPayload.create("test"))), + channel -> channel.requestChannel(Mono.just(DefaultPayload.create("test"))), FrameType.REQUEST_CHANNEL), Arguments.of( (Function>) - rSocket -> - rSocket.metadataPush( + channel -> + channel.metadataPush( DefaultPayload.create(new byte[0], "test".getBytes(CharsetUtil.UTF_8))), FrameType.METADATA_PUSH)); } diff --git a/today-remoting/src/test/java/infra/remoting/core/ChannelRequesterTerminationTests.java b/today-remoting/src/test/java/infra/remoting/core/ChannelRequesterTerminationTests.java index 2ed4edc..4cfae09 100644 --- a/today-remoting/src/test/java/infra/remoting/core/ChannelRequesterTerminationTests.java +++ b/today-remoting/src/test/java/infra/remoting/core/ChannelRequesterTerminationTests.java @@ -54,12 +54,12 @@ public void tearDownAndCheckNoLeaks() { } @ParameterizedTest - @MethodSource("rsocketInteractions") + @MethodSource("interactions") public void testCurrentStreamIsTerminatedOnConnectionClose( FrameType requestType, Function> interaction) { - ChannelRequester rSocket = rule.socket; + ChannelRequester channel = rule.socket; - StepVerifier.create(interaction.apply(rSocket)) + StepVerifier.create(interaction.apply(channel)) .then( () -> { FrameAssert.assertThat(rule.connection.pollFrame()).typeOf(requestType).hasNoLeaks(); @@ -70,18 +70,18 @@ public void testCurrentStreamIsTerminatedOnConnectionClose( } @ParameterizedTest - @MethodSource("rsocketInteractions") + @MethodSource("interactions") public void testSubsequentStreamIsTerminatedAfterConnectionClose( FrameType requestType, Function> interaction) { - ChannelRequester rSocket = rule.socket; + ChannelRequester channel = rule.socket; rule.connection.dispose(); - StepVerifier.create(interaction.apply(rSocket)) + StepVerifier.create(interaction.apply(channel)) .expectError(ClosedChannelException.class) .verify(Duration.ofSeconds(5)); } - public static Iterable rsocketInteractions() { + public static Iterable interactions() { EmptyPayload payload = EmptyPayload.INSTANCE; Arguments resp = @@ -89,8 +89,8 @@ public static Iterable rsocketInteractions() { FrameType.REQUEST_RESPONSE, new Function>() { @Override - public Mono apply(Channel rSocket) { - return rSocket.requestResponse(payload); + public Mono apply(Channel channel) { + return channel.requestResponse(payload); } @Override @@ -103,8 +103,8 @@ public String toString() { FrameType.REQUEST_STREAM, new Function>() { @Override - public Flux apply(Channel rSocket) { - return rSocket.requestStream(payload); + public Flux apply(Channel channel) { + return channel.requestStream(payload); } @Override @@ -113,12 +113,11 @@ public String toString() { } }); Arguments channel = - Arguments.of( - FrameType.REQUEST_CHANNEL, + Arguments.of(FrameType.REQUEST_CHANNEL, new Function>() { @Override - public Flux apply(Channel rSocket) { - return rSocket.requestChannel(Flux.never().startWith(payload)); + public Flux apply(Channel channel) { + return channel.requestChannel(Flux.never().startWith(payload)); } @Override diff --git a/today-remoting/src/test/java/infra/remoting/core/ChannelRequesterTests.java b/today-remoting/src/test/java/infra/remoting/core/ChannelRequesterTests.java index dc61ab4..cb0ccf8 100644 --- a/today-remoting/src/test/java/infra/remoting/core/ChannelRequesterTests.java +++ b/today-remoting/src/test/java/infra/remoting/core/ChannelRequesterTests.java @@ -130,7 +130,7 @@ public void tearDown() { @Test @Timeout(2_000) - public void testInvalidFrameOnStream0ShouldNotTerminateRSocket() { + public void testInvalidFrameOnStream0ShouldNotTerminateChannel() { rule.connection.addToReceivedBuffer(RequestNFrameCodec.encode(rule.alloc(), 0, 10)); assertThat(rule.socket.isDisposed()).isFalse(); rule.assertHasNoLeaks(); @@ -443,7 +443,7 @@ static Stream>> prepareCalls() { Channel::fireAndForget, Channel::requestResponse, Channel::requestStream, - (rSocket, payload) -> rSocket.requestChannel(Flux.just(payload)), + (channel, payload) -> channel.requestChannel(Flux.just(payload)), Channel::metadataPush); } @@ -1485,7 +1485,7 @@ public static class ClientSocketRule extends AbstractSocketRule otherClosedSink; @Override - protected ChannelRequester newRSocket() { + protected ChannelRequester newChannel() { this.thisClosedSink = Sinks.empty(); this.otherClosedSink = Sinks.empty(); return new ChannelRequester( diff --git a/today-remoting/src/test/java/infra/remoting/core/ChannelResponderTests.java b/today-remoting/src/test/java/infra/remoting/core/ChannelResponderTests.java index 6cc540a..ca7c3e9 100644 --- a/today-remoting/src/test/java/infra/remoting/core/ChannelResponderTests.java +++ b/today-remoting/src/test/java/infra/remoting/core/ChannelResponderTests.java @@ -1223,7 +1223,7 @@ public void setAcceptingSocket(Channel acceptingSocket, int prefetch) { } @Override - protected ChannelResponder newRSocket() { + protected ChannelResponder newChannel() { onCloseSink = Sinks.empty(); return new ChannelResponder( connection, diff --git a/today-remoting/src/test/java/infra/remoting/core/ChannelTests.java b/today-remoting/src/test/java/infra/remoting/core/ChannelTests.java index cc5e604..64a2ef2 100644 --- a/today-remoting/src/test/java/infra/remoting/core/ChannelTests.java +++ b/today-remoting/src/test/java/infra/remoting/core/ChannelTests.java @@ -66,7 +66,7 @@ public void tearDownAndCheckOnLeaks() { } @Test - public void rsocketDisposalShouldEndupWithNoErrorsOnClose() { + public void channelDisposalShouldEndupWithNoErrorsOnClose() { Channel requestHandlingChannel = new Channel() { final Disposable disposable = Disposables.single(); diff --git a/today-remoting/src/test/java/infra/remoting/core/DefaultChannelClientTests.java b/today-remoting/src/test/java/infra/remoting/core/DefaultChannelClientTests.java index 39a680f..e684ac2 100644 --- a/today-remoting/src/test/java/infra/remoting/core/DefaultChannelClientTests.java +++ b/today-remoting/src/test/java/infra/remoting/core/DefaultChannelClientTests.java @@ -512,8 +512,8 @@ public void shouldReceiveOnCloseNotificationOnDisposeOriginalSource() { ClientSocketRule rule = new ClientSocketRule() { @Override - protected Channel newRSocket() { - return new ChannelDecorator(super.newRSocket()) { + protected Channel newChannel() { + return new ChannelDecorator(super.newChannel()) { @Override public Mono onClose() { return super.onClose().and(onCloseDelayer.asMono()); @@ -630,7 +630,7 @@ public void shouldBeRestartedIfSourceWasClosed() { Assertions.assertThat(rule.client.isDisposed()).isFalse(); rule.connection = new TestDuplexConnection(rule.allocator); - rule.socket = rule.newRSocket(); + rule.socket = rule.newChannel(); rule.producer = Sinks.one(); AssertSubscriber assertSubscriber2 = AssertSubscriber.create(); @@ -754,7 +754,7 @@ protected void doInit() { } @Override - protected Channel newRSocket() { + protected Channel newChannel() { this.thisClosedSink = Sinks.empty(); return new ChannelRequester( connection, diff --git a/today-remoting/src/test/java/infra/remoting/core/FireAndForgetRequesterMonoTest.java b/today-remoting/src/test/java/infra/remoting/core/FireAndForgetRequesterMonoTest.java index 833f553..72b9b32 100644 --- a/today-remoting/src/test/java/infra/remoting/core/FireAndForgetRequesterMonoTest.java +++ b/today-remoting/src/test/java/infra/remoting/core/FireAndForgetRequesterMonoTest.java @@ -320,9 +320,9 @@ public void shouldErrorIfFragmentExitsAllowanceIfFragmentationDisabled( } /** - * Ensures that frame will not be sent if we dont have availability for that. Options: 1. RSocket + * Ensures that frame will not be sent if we dont have availability for that. Options: 1. Channel * disposed / Connection Error, so all racing on existing interactions should be terminated as - * well 2. RSocket tries to use lease and end-ups with no available leases + * well 2. Channel tries to use lease and end-ups with no available leases */ @ParameterizedTest @MethodSource("shouldErrorIfNoAvailabilitySource") diff --git a/today-remoting/src/test/java/infra/remoting/core/KeepAliveTest.java b/today-remoting/src/test/java/infra/remoting/core/KeepAliveTest.java index 1b41f30..1d3623f 100644 --- a/today-remoting/src/test/java/infra/remoting/core/KeepAliveTest.java +++ b/today-remoting/src/test/java/infra/remoting/core/KeepAliveTest.java @@ -25,22 +25,22 @@ import java.time.Duration; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufAllocator; -import io.netty.buffer.Unpooled; -import infra.remoting.FrameAssert; import infra.remoting.Channel; +import infra.remoting.FrameAssert; import infra.remoting.buffer.LeaksTrackingByteBufAllocator; import infra.remoting.exceptions.ConnectionErrorException; import infra.remoting.frame.FrameHeaderCodec; import infra.remoting.frame.FrameType; import infra.remoting.frame.KeepAliveFrameCodec; import infra.remoting.frame.decoder.PayloadDecoder; -import infra.remoting.resume.InMemoryResumableFramesStore; import infra.remoting.resume.ChannelSession; +import infra.remoting.resume.InMemoryResumableFramesStore; import infra.remoting.resume.ResumableDuplexConnection; import infra.remoting.resume.ResumeStateHolder; import infra.remoting.test.util.TestDuplexConnection; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufAllocator; +import io.netty.buffer.Unpooled; import reactor.core.Disposable; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; @@ -69,12 +69,12 @@ public void tearDown() { VirtualTimeScheduler.reset(); } - static RSocketState requester(int tickPeriod, int timeout) { + static ChannelState requester(int tickPeriod, int timeout) { LeaksTrackingByteBufAllocator allocator = LeaksTrackingByteBufAllocator.instrument(ByteBufAllocator.DEFAULT); TestDuplexConnection connection = new TestDuplexConnection(allocator); Sinks.Empty empty = Sinks.empty(); - ChannelRequester rSocket = + ChannelRequester channel = new ChannelRequester( connection, PayloadDecoder.ZERO_COPY, @@ -89,10 +89,10 @@ static RSocketState requester(int tickPeriod, int timeout) { null, empty, empty.asMono()); - return new RSocketState(rSocket, allocator, connection, empty); + return new ChannelState(channel, allocator, connection, empty); } - static ResumableRSocketState resumableRequester(int tickPeriod, int timeout) { + static ResumableChannelState resumableRequester(int tickPeriod, int timeout) { LeaksTrackingByteBufAllocator allocator = LeaksTrackingByteBufAllocator.instrument(ByteBufAllocator.DEFAULT); TestDuplexConnection connection = new TestDuplexConnection(allocator); @@ -104,7 +104,7 @@ static ResumableRSocketState resumableRequester(int tickPeriod, int timeout) { new InMemoryResumableFramesStore("test", Unpooled.EMPTY_BUFFER, 10_000)); Sinks.Empty onClose = Sinks.empty(); - ChannelRequester rSocket = + ChannelRequester channel = new ChannelRequester( resumableConnection, PayloadDecoder.ZERO_COPY, @@ -122,12 +122,12 @@ static ResumableRSocketState resumableRequester(int tickPeriod, int timeout) { null, onClose, onClose.asMono()); - return new ResumableRSocketState(rSocket, connection, resumableConnection, onClose, allocator); + return new ResumableChannelState(channel, connection, resumableConnection, onClose, allocator); } @Test - void rSocketNotDisposedOnPresentKeepAlives() { - RSocketState requesterState = requester(KEEP_ALIVE_INTERVAL, KEEP_ALIVE_TIMEOUT); + void channelNotDisposedOnPresentKeepAlives() { + ChannelState requesterState = requester(KEEP_ALIVE_INTERVAL, KEEP_ALIVE_TIMEOUT); TestDuplexConnection connection = requesterState.connection(); @@ -141,7 +141,7 @@ void rSocketNotDisposedOnPresentKeepAlives() { virtualTimeScheduler.advanceTimeBy(Duration.ofMillis(KEEP_ALIVE_TIMEOUT * 2)); - Channel channel = requesterState.rSocket(); + Channel channel = requesterState.channel(); Assertions.assertThat(channel.isDisposed()).isFalse(); @@ -156,10 +156,10 @@ void rSocketNotDisposedOnPresentKeepAlives() { } @Test - void noKeepAlivesSentAfterRSocketDispose() { - RSocketState requesterState = requester(KEEP_ALIVE_INTERVAL, KEEP_ALIVE_TIMEOUT); + void noKeepAlivesSentAfterChannelDispose() { + ChannelState requesterState = requester(KEEP_ALIVE_INTERVAL, KEEP_ALIVE_TIMEOUT); - requesterState.rSocket().dispose(); + requesterState.channel().dispose(); Duration duration = Duration.ofMillis(500); @@ -174,10 +174,10 @@ void noKeepAlivesSentAfterRSocketDispose() { } @Test - void rSocketDisposedOnMissingKeepAlives() { - RSocketState requesterState = requester(KEEP_ALIVE_INTERVAL, KEEP_ALIVE_TIMEOUT); + void channelDisposedOnMissingKeepAlives() { + ChannelState requesterState = requester(KEEP_ALIVE_INTERVAL, KEEP_ALIVE_TIMEOUT); - Channel channel = requesterState.rSocket(); + Channel channel = requesterState.channel(); virtualTimeScheduler.advanceTimeBy(Duration.ofMillis(KEEP_ALIVE_TIMEOUT * 2)); @@ -195,8 +195,8 @@ void rSocketDisposedOnMissingKeepAlives() { @Test void clientRequesterSendsKeepAlives() { - RSocketState RSocketState = requester(KEEP_ALIVE_INTERVAL, KEEP_ALIVE_TIMEOUT); - TestDuplexConnection connection = RSocketState.connection(); + ChannelState channelState = requester(KEEP_ALIVE_INTERVAL, KEEP_ALIVE_TIMEOUT); + TestDuplexConnection connection = channelState.connection(); virtualTimeScheduler.advanceTimeBy(Duration.ofMillis(KEEP_ALIVE_INTERVAL)); this.keepAliveFrameWithRespondFlag(connection.pollFrame()); @@ -205,50 +205,50 @@ void clientRequesterSendsKeepAlives() { virtualTimeScheduler.advanceTimeBy(Duration.ofMillis(KEEP_ALIVE_INTERVAL)); this.keepAliveFrameWithRespondFlag(connection.pollFrame()); - RSocketState.channel.dispose(); + channelState.channel.dispose(); FrameAssert.assertThat(connection.pollFrame()) .typeOf(FrameType.ERROR) .hasData("Disposed") .hasNoLeaks(); - RSocketState.connection.dispose(); + channelState.connection.dispose(); - RSocketState.allocator.assertHasNoLeaks(); + channelState.allocator.assertHasNoLeaks(); } @Test void requesterRespondsToKeepAlives() { - RSocketState rSocketState = requester(100_000, 100_000); - TestDuplexConnection connection = rSocketState.connection(); + ChannelState channelState = requester(100_000, 100_000); + TestDuplexConnection connection = channelState.connection(); Duration duration = Duration.ofMillis(100); Mono.delay(duration) .subscribe( l -> connection.addToReceivedBuffer( KeepAliveFrameCodec.encode( - rSocketState.allocator, true, 0, Unpooled.EMPTY_BUFFER))); + channelState.allocator, true, 0, Unpooled.EMPTY_BUFFER))); virtualTimeScheduler.advanceTimeBy(duration); FrameAssert.assertThat(connection.awaitFrame()) .typeOf(FrameType.KEEPALIVE) .matches(this::keepAliveFrameWithoutRespondFlag); - rSocketState.channel.dispose(); - FrameAssert.assertThat(rSocketState.connection.pollFrame()) + channelState.channel.dispose(); + FrameAssert.assertThat(channelState.connection.pollFrame()) .typeOf(FrameType.ERROR) .hasStreamIdZero() .hasData("Disposed") .hasNoLeaks(); - rSocketState.connection.dispose(); + channelState.connection.dispose(); - rSocketState.allocator.assertHasNoLeaks(); + channelState.allocator.assertHasNoLeaks(); } @Test void resumableRequesterNoKeepAlivesAfterDisconnect() { - ResumableRSocketState rSocketState = + ResumableChannelState channelState = resumableRequester(KEEP_ALIVE_INTERVAL, KEEP_ALIVE_TIMEOUT); - TestDuplexConnection testConnection = rSocketState.connection(); - ResumableDuplexConnection resumableDuplexConnection = rSocketState.resumableDuplexConnection(); + TestDuplexConnection testConnection = channelState.connection(); + ResumableDuplexConnection resumableDuplexConnection = channelState.resumableDuplexConnection(); resumableDuplexConnection.disconnect(); @@ -256,19 +256,19 @@ void resumableRequesterNoKeepAlivesAfterDisconnect() { virtualTimeScheduler.advanceTimeBy(duration); Assertions.assertThat(testConnection.pollFrame()).isNull(); - rSocketState.channel.dispose(); - rSocketState.connection.dispose(); + channelState.channel.dispose(); + channelState.connection.dispose(); - rSocketState.allocator.assertHasNoLeaks(); + channelState.allocator.assertHasNoLeaks(); } @Test void resumableRequesterKeepAlivesAfterReconnect() { - ResumableRSocketState rSocketState = + ResumableChannelState channelState = resumableRequester(KEEP_ALIVE_INTERVAL, KEEP_ALIVE_TIMEOUT); - ResumableDuplexConnection resumableDuplexConnection = rSocketState.resumableDuplexConnection(); + ResumableDuplexConnection resumableDuplexConnection = channelState.resumableDuplexConnection(); resumableDuplexConnection.disconnect(); - TestDuplexConnection newTestConnection = new TestDuplexConnection(rSocketState.alloc()); + TestDuplexConnection newTestConnection = new TestDuplexConnection(channelState.alloc()); resumableDuplexConnection.connect(newTestConnection); // resumableDuplexConnection.(0, 0, ignored -> Mono.empty()); @@ -279,7 +279,7 @@ void resumableRequesterKeepAlivesAfterReconnect() { .hasStreamIdZero() .hasNoLeaks(); - rSocketState.channel.dispose(); + channelState.channel.dispose(); FrameAssert.assertThat(newTestConnection.pollFrame()) .typeOf(FrameType.ERROR) .hasStreamIdZero() @@ -292,41 +292,41 @@ void resumableRequesterKeepAlivesAfterReconnect() { .hasNoLeaks(); newTestConnection.dispose(); - rSocketState.allocator.assertHasNoLeaks(); + channelState.allocator.assertHasNoLeaks(); } @Test void resumableRequesterNoKeepAlivesAfterDispose() { - ResumableRSocketState rSocketState = + ResumableChannelState channelState = resumableRequester(KEEP_ALIVE_INTERVAL, KEEP_ALIVE_TIMEOUT); - rSocketState.rSocket().dispose(); + channelState.channel().dispose(); Duration duration = Duration.ofMillis(500); - StepVerifier.create(Flux.from(rSocketState.connection().getSentAsPublisher()).take(duration)) + StepVerifier.create(Flux.from(channelState.connection().getSentAsPublisher()).take(duration)) .then(() -> virtualTimeScheduler.advanceTimeBy(duration)) .expectComplete() .verify(Duration.ofSeconds(5)); - rSocketState.channel.dispose(); - FrameAssert.assertThat(rSocketState.connection.pollFrame()) + channelState.channel.dispose(); + FrameAssert.assertThat(channelState.connection.pollFrame()) .typeOf(FrameType.ERROR) .hasStreamIdZero() .hasData("Disposed") .hasNoLeaks(); - rSocketState.connection.dispose(); - FrameAssert.assertThat(rSocketState.connection.pollFrame()) + channelState.connection.dispose(); + FrameAssert.assertThat(channelState.connection.pollFrame()) .typeOf(FrameType.ERROR) .hasStreamIdZero() .hasData("Connection Closed Unexpectedly") .hasNoLeaks(); - rSocketState.allocator.assertHasNoLeaks(); + channelState.allocator.assertHasNoLeaks(); } @Test - void resumableRSocketsNotDisposedOnMissingKeepAlives() throws InterruptedException { - ResumableRSocketState resumableRequesterState = + void resumableChannelsNotDisposedOnMissingKeepAlives() throws InterruptedException { + ResumableChannelState resumableRequesterState = resumableRequester(KEEP_ALIVE_INTERVAL, RESUMABLE_KEEP_ALIVE_TIMEOUT); - Channel channel = resumableRequesterState.rSocket(); + Channel channel = resumableRequesterState.channel(); TestDuplexConnection connection = resumableRequesterState.connection(); virtualTimeScheduler.advanceTimeBy(Duration.ofMillis(500)); @@ -354,14 +354,13 @@ private boolean keepAliveFrameWithoutRespondFlag(ByteBuf frame) { return keepAliveFrame(frame) && !KeepAliveFrameCodec.respondFlag(frame) && frame.release(); } - static class RSocketState { + static class ChannelState { private final Channel channel; private final TestDuplexConnection connection; private final LeaksTrackingByteBufAllocator allocator; private final Sinks.Empty onClose; - public RSocketState( - Channel channel, + public ChannelState(Channel channel, LeaksTrackingByteBufAllocator allocator, TestDuplexConnection connection, Sinks.Empty onClose) { @@ -375,7 +374,7 @@ public TestDuplexConnection connection() { return connection; } - public Channel rSocket() { + public Channel channel() { return channel; } @@ -384,14 +383,14 @@ public LeaksTrackingByteBufAllocator alloc() { } } - static class ResumableRSocketState { + static class ResumableChannelState { private final Channel channel; private final TestDuplexConnection connection; private final ResumableDuplexConnection resumableDuplexConnection; private final LeaksTrackingByteBufAllocator allocator; private final Sinks.Empty onClose; - public ResumableRSocketState( + public ResumableChannelState( Channel channel, TestDuplexConnection connection, ResumableDuplexConnection resumableDuplexConnection, @@ -412,7 +411,7 @@ public ResumableDuplexConnection resumableDuplexConnection() { return resumableDuplexConnection; } - public Channel rSocket() { + public Channel channel() { return channel; } diff --git a/today-remoting/src/test/java/infra/remoting/core/RequestStreamRequesterFluxTest.java b/today-remoting/src/test/java/infra/remoting/core/RequestStreamRequesterFluxTest.java index 137e79a..194ecb7 100644 --- a/today-remoting/src/test/java/infra/remoting/core/RequestStreamRequesterFluxTest.java +++ b/today-remoting/src/test/java/infra/remoting/core/RequestStreamRequesterFluxTest.java @@ -1077,7 +1077,7 @@ public void shouldErrorIfFragmentExitsAllowanceIfFragmentationDisabled( } /** - * Ensures that the interactions check and respect rsocket availability (such as leasing) and + * Ensures that the interactions check and respect channel availability (such as leasing) and * propagate an error to the final subscriber. No frame should be sent. Check should happens * exactly on the first request. */ diff --git a/today-remoting/src/test/java/infra/remoting/core/SetupRejectionTest.java b/today-remoting/src/test/java/infra/remoting/core/SetupRejectionTest.java index 74c73db..f353c36 100644 --- a/today-remoting/src/test/java/infra/remoting/core/SetupRejectionTest.java +++ b/today-remoting/src/test/java/infra/remoting/core/SetupRejectionTest.java @@ -64,7 +64,7 @@ void responderRejectSetup() { sentFrame.release(); assertThat(errorMsg).isEqualTo(error.getMessage()); assertThat(error).isInstanceOf(RejectedSetupException.class); - Channel acceptorSender = acceptor.senderRSocket().block(); + Channel acceptorSender = acceptor.senderChannel().block(); assertThat(acceptorSender.isDisposed()).isTrue(); transport.allocator.assertHasNoLeaks(); } @@ -76,7 +76,7 @@ void requesterStreamsTerminatedOnZeroErrorFrame() { TestDuplexConnection conn = new TestDuplexConnection(allocator); Sinks.Empty onThisSideClosedSink = Sinks.empty(); - ChannelRequester rSocket = + ChannelRequester channel = new ChannelRequester( conn, DefaultPayload::create, @@ -95,7 +95,7 @@ void requesterStreamsTerminatedOnZeroErrorFrame() { String errorMsg = "error"; StepVerifier.create( - rSocket + channel .requestResponse(DefaultPayload.create("test")) .doOnRequest( ignored -> @@ -108,7 +108,7 @@ void requesterStreamsTerminatedOnZeroErrorFrame() { err -> err instanceof RejectedSetupException && errorMsg.equals(err.getMessage())) .verify(Duration.ofSeconds(5)); - assertThat(rSocket.isDisposed()).isTrue(); + assertThat(channel.isDisposed()).isTrue(); allocator.assertHasNoLeaks(); } @@ -118,7 +118,7 @@ void requesterNewStreamsTerminatedAfterZeroErrorFrame() { LeaksTrackingByteBufAllocator.instrument(ByteBufAllocator.DEFAULT); TestDuplexConnection conn = new TestDuplexConnection(allocator); Sinks.Empty onThisSideClosedSink = Sinks.empty(); - ChannelRequester rSocket = + ChannelRequester channel = new ChannelRequester( conn, DefaultPayload::create, @@ -138,7 +138,7 @@ void requesterNewStreamsTerminatedAfterZeroErrorFrame() { ErrorFrameCodec.encode(ByteBufAllocator.DEFAULT, 0, new RejectedSetupException("error"))); StepVerifier.create( - rSocket + channel .requestResponse(DefaultPayload.create("test")) .delaySubscription(Duration.ofMillis(100))) .expectErrorMatches( @@ -149,7 +149,7 @@ void requesterNewStreamsTerminatedAfterZeroErrorFrame() { private static class RejectingAcceptor implements ChannelAcceptor { private final String errorMessage; - private final Sinks.Many senderRSockets = + private final Sinks.Many senderChannels = Sinks.many().unicast().onBackpressureBuffer(); public RejectingAcceptor(String errorMessage) { @@ -158,12 +158,12 @@ public RejectingAcceptor(String errorMessage) { @Override public Mono accept(ConnectionSetupPayload setup, Channel sendingSocket) { - senderRSockets.tryEmitNext(sendingSocket); + senderChannels.tryEmitNext(sendingSocket); return Mono.error(new RuntimeException(errorMessage)); } - public Mono senderRSocket() { - return senderRSockets.asFlux().next(); + public Mono senderChannel() { + return senderChannels.asFlux().next(); } } diff --git a/today-remoting/src/test/java/infra/remoting/exceptions/ExceptionsTests.java b/today-remoting/src/test/java/infra/remoting/exceptions/ExceptionsTests.java index 1a62608..bafcc3f 100644 --- a/today-remoting/src/test/java/infra/remoting/exceptions/ExceptionsTests.java +++ b/today-remoting/src/test/java/infra/remoting/exceptions/ExceptionsTests.java @@ -22,10 +22,10 @@ import java.util.concurrent.ThreadLocalRandom; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.UnpooledByteBufAllocator; import infra.remoting.RaceTestConstants; import infra.remoting.frame.ErrorFrameCodec; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.UnpooledByteBufAllocator; import static infra.remoting.frame.ErrorFrameCodec.APPLICATION_ERROR; import static infra.remoting.frame.ErrorFrameCodec.CANCELED; @@ -256,9 +256,8 @@ void fromUnsupportedSetupException() { } } - @DisplayName("from returns CustomRSocketException") @Test - void fromCustomRSocketException() { + void fromCustomChannelException() { for (int i = 0; i < RaceTestConstants.REPEATS; i++) { int randomCode = ThreadLocalRandom.current().nextBoolean() diff --git a/today-remoting/src/test/java/infra/remoting/lb/LoadbalanceTests.java b/today-remoting/src/test/java/infra/remoting/lb/LoadbalanceTests.java index d59c0f6..16d87e7 100644 --- a/today-remoting/src/test/java/infra/remoting/lb/LoadbalanceTests.java +++ b/today-remoting/src/test/java/infra/remoting/lb/LoadbalanceTests.java @@ -130,14 +130,14 @@ public void shouldDeliverAllTheRequestsWithWeightedStrategy() throws Interrupted final LoadBalanceTarget target1 = LoadBalanceTarget.of("1", mockTransport1); final LoadBalanceTarget target2 = LoadBalanceTarget.of("2", mockTransport2); - final WeightedChannel weightedRSocket1 = new WeightedChannel(counter); - final WeightedChannel weightedRSocket2 = new WeightedChannel(counter); + final WeightedChannel weightedChannel1 = new WeightedChannel(counter); + final WeightedChannel weightedChannel2 = new WeightedChannel(counter); final ChannelConnector channelConnectorMock = Mockito.mock(ChannelConnector.class); Mockito.when(channelConnectorMock.connect(mockTransport1)) - .then(im -> Mono.just(new TestChannel(weightedRSocket1))); + .then(im -> Mono.just(new TestChannel(weightedChannel1))); Mockito.when(channelConnectorMock.connect(mockTransport2)) - .then(im -> Mono.just(new TestChannel(weightedRSocket2))); + .then(im -> Mono.just(new TestChannel(weightedChannel2))); final List collectionOfDestination1 = Collections.singletonList(target1); final List collectionOfDestination2 = Collections.singletonList(target2); final List collectionOfDestinations1And2 = Arrays.asList(target1, target2); @@ -151,13 +151,13 @@ public void shouldDeliverAllTheRequestsWithWeightedStrategy() throws Interrupted source.asFlux(), WeightedLoadBalanceStrategy.builder() .weightedStatsResolver( - rsocket -> { - if (rsocket instanceof TestChannel) { - return (WeightedChannel) ((TestChannel) rsocket).source(); + channel -> { + if (channel instanceof TestChannel) { + return (WeightedChannel) ((TestChannel) channel).source(); } - return ((PooledChannel) rsocket).target() == target1 - ? weightedRSocket1 - : weightedRSocket2; + return ((PooledChannel) channel).target() == target1 + ? weightedChannel1 + : weightedChannel2; }) .build()); final Mono fnfSource = @@ -188,12 +188,12 @@ public void shouldDeliverAllTheRequestsWithWeightedStrategy() throws Interrupted } @Test - public void ensureRSocketIsCleanedFromThePoolIfSourceRSocketIsDisposed() { + public void ensureChannelIsCleanedFromThePoolIfSourceChannelIsDisposed() { final AtomicInteger counter = new AtomicInteger(); final ClientTransport mockTransport = Mockito.mock(ClientTransport.class); final ChannelConnector channelConnectorMock = Mockito.mock(ChannelConnector.class); - final TestChannel testRSocket = + final TestChannel testChannel = new TestChannel( new Channel() { @Override @@ -204,7 +204,7 @@ public Mono fireAndForget(Payload payload) { }); Mockito.when(channelConnectorMock.connect(Mockito.any(ClientTransport.class))) - .then(im -> Mono.delay(Duration.ofMillis(200)).map(__ -> testRSocket)); + .then(im -> Mono.delay(Duration.ofMillis(200)).map(__ -> testChannel)); final TestPublisher> source = TestPublisher.create(); final ChannelPool channelPool = @@ -217,7 +217,7 @@ public Mono fireAndForget(Payload payload) { .expectComplete() .verify(Duration.ofSeconds(2)); - testRSocket.dispose(); + testChannel.dispose(); Assertions.assertThatThrownBy( () -> @@ -256,7 +256,7 @@ public Flux requestChannel(Publisher source) { final ChannelPool channelPool = new ChannelPool(channelConnectorMock, source, new RoundRobinLoadBalanceStrategy()); - // check that context is propagated when there is no rsocket + // check that context is propagated when there is no channel StepVerifier.create( channelPool .select() @@ -281,7 +281,7 @@ public Flux requestChannel(Publisher source) { .verify(Duration.ofSeconds(2)); source.next(Collections.singletonList(LoadBalanceTarget.of("2", mockTransport))); - // check that context is propagated when there is an RSocket but it is unresolved + // check that context is propagated when there is a Channel but it is unresolved StepVerifier.create( channelPool .select() @@ -302,7 +302,7 @@ public Flux requestChannel(Publisher source) { .expectComplete() .verify(Duration.ofSeconds(2)); - // check that context is propagated when there is an RSocket and it is resolved + // check that context is propagated when there is a Channel and it is resolved StepVerifier.create( channelPool .select() diff --git a/today-remoting/src/test/java/infra/remoting/lb/WeightedLoadBalanceStrategyTests.java b/today-remoting/src/test/java/infra/remoting/lb/WeightedLoadBalanceStrategyTests.java index 671d45b..fd3ce32 100644 --- a/today-remoting/src/test/java/infra/remoting/lb/WeightedLoadBalanceStrategyTests.java +++ b/today-remoting/src/test/java/infra/remoting/lb/WeightedLoadBalanceStrategyTests.java @@ -59,7 +59,7 @@ public void allRequestsShouldGoToTheSocketWithHigherWeight() { final AtomicInteger counter2 = new AtomicInteger(); final ClientTransport mockTransport = Mockito.mock(ClientTransport.class); final ChannelConnector channelConnectorMock = Mockito.mock(ChannelConnector.class); - final WeightedTestChannel rSocket1 = + final WeightedTestChannel channel = new WeightedTestChannel( new Channel() { @Override @@ -68,7 +68,7 @@ public Mono fireAndForget(Payload payload) { return Mono.empty(); } }); - final WeightedTestChannel rSocket2 = + final WeightedTestChannel channel1 = new WeightedTestChannel( new Channel() { @Override @@ -78,8 +78,8 @@ public Mono fireAndForget(Payload payload) { } }); Mockito.when(channelConnectorMock.connect(Mockito.any(ClientTransport.class))) - .then(im -> Mono.just(rSocket1)) - .then(im -> Mono.just(rSocket2)); + .then(im -> Mono.just(channel)) + .then(im -> Mono.just(channel1)); final TestPublisher> source = TestPublisher.create(); final ChannelPool channelPool = @@ -115,7 +115,7 @@ public void shouldDeliverValuesToTheSocketWithTheHighestCalculatedWeight() { final ClientTransport mockTransport1 = Mockito.mock(ClientTransport.class); final ClientTransport mockTransport2 = Mockito.mock(ClientTransport.class); final ChannelConnector channelConnectorMock = Mockito.mock(ChannelConnector.class); - final WeightedTestChannel rSocket1 = + final WeightedTestChannel channel1 = new WeightedTestChannel( new Channel() { @Override @@ -124,7 +124,7 @@ public Mono fireAndForget(Payload payload) { return Mono.empty(); } }); - final WeightedTestChannel rSocket2 = + final WeightedTestChannel channel2 = new WeightedTestChannel( new Channel() { @Override @@ -133,7 +133,7 @@ public Mono fireAndForget(Payload payload) { return Mono.empty(); } }); - final WeightedTestChannel rSocket3 = + final WeightedTestChannel channel3 = new WeightedTestChannel( new Channel() { @Override @@ -144,9 +144,9 @@ public Mono fireAndForget(Payload payload) { }); Mockito.when(channelConnectorMock.connect(Mockito.any(ClientTransport.class))) - .then(im -> Mono.just(rSocket1)) - .then(im -> Mono.just(rSocket2)) - .then(im -> Mono.just(rSocket3)); + .then(im -> Mono.just(channel1)) + .then(im -> Mono.just(channel2)) + .then(im -> Mono.just(channel3)); final TestPublisher> source = TestPublisher.create(); final ChannelPool channelPool = @@ -171,7 +171,7 @@ public Mono fireAndForget(Payload payload) { channelPool.select().fireAndForget(EmptyPayload.INSTANCE).subscribe(); } - rSocket1.updateAvailability(0.0); + channel1.updateAvailability(0.0); source.next(Collections.singletonList(LoadBalanceTarget.of("1", mockTransport1))); @@ -195,7 +195,7 @@ public Mono fireAndForget(Payload payload) { Assertions.assertThat(counter2.get()) .isCloseTo(0, Offset.offset(Math.round(RaceTestConstants.REPEATS * 3 * 0.1f))); - rSocket2.updateAvailability(0.0); + channel2.updateAvailability(0.0); source.next(Collections.singletonList(LoadBalanceTarget.of("2", mockTransport1))); diff --git a/today-remoting/src/test/java/infra/remoting/plugins/RequestInterceptorTests.java b/today-remoting/src/test/java/infra/remoting/plugins/RequestInterceptorTests.java index fe16336..614e3ed 100644 --- a/today-remoting/src/test/java/infra/remoting/plugins/RequestInterceptorTests.java +++ b/today-remoting/src/test/java/infra/remoting/plugins/RequestInterceptorTests.java @@ -172,28 +172,28 @@ void interceptorShouldBeInstalledProperlyOnTheClientResponderSide(boolean errorO CountDownLatch latch = new CountDownLatch(1); final Closeable closeable = RemotingServer.create( - (setup, rSocket) -> + (setup, channel) -> Mono.just(new Channel() { }) .doAfterTerminate( () -> { new Thread( () -> { - rSocket + channel .fireAndForget(DefaultPayload.create("test")) .onErrorResume(__ -> Mono.empty()) .block(); - rSocket + channel .requestResponse(DefaultPayload.create("test")) .onErrorResume(__ -> Mono.empty()) .block(); - rSocket + channel .requestStream(DefaultPayload.create("test")) .onErrorResume(__ -> Mono.empty()) .blockLast(); - rSocket + channel .requestChannel( Flux.just(DefaultPayload.create("test"))) .onErrorResume(__ -> Mono.empty()) @@ -412,25 +412,25 @@ void interceptorShouldBeInstalledProperlyOnTheServerResponderSide(boolean errorO CountDownLatch latch = new CountDownLatch(1); final TestRequestInterceptor testRequestInterceptor = new TestRequestInterceptor(); - final Closeable closeable = RemotingServer.create((setup, rSocket) -> Mono.just(new Channel() { }) + final Closeable closeable = RemotingServer.create((setup, channel) -> Mono.just(new Channel() { }) .doAfterTerminate(() -> { new Thread(() -> { - rSocket + channel .fireAndForget(DefaultPayload.create("test")) .onErrorResume(__ -> Mono.empty()) .block(); - rSocket + channel .requestResponse(DefaultPayload.create("test")) .onErrorResume(__ -> Mono.empty()) .block(); - rSocket + channel .requestStream(DefaultPayload.create("test")) .onErrorResume(__ -> Mono.empty()) .blockLast(); - rSocket + channel .requestChannel( Flux.just(DefaultPayload.create("test"))) .onErrorResume(__ -> Mono.empty()) diff --git a/today-remoting/src/test/java/infra/remoting/test/util/TestDuplexConnection.java b/today-remoting/src/test/java/infra/remoting/test/util/TestDuplexConnection.java index e02a98b..197ca4a 100644 --- a/today-remoting/src/test/java/infra/remoting/test/util/TestDuplexConnection.java +++ b/today-remoting/src/test/java/infra/remoting/test/util/TestDuplexConnection.java @@ -72,7 +72,7 @@ public TestDuplexConnection(LeaksTrackingByteBufAllocator allocator) { @Override public void sendFrame(int streamId, ByteBuf frame) { if (availability <= 0) { - throw new IllegalStateException("RSocket not available. Availability: " + availability); + throw new IllegalStateException("Channel not available. Availability: " + availability); } sendSink.next(frame); diff --git a/today-remoting/src/test/resources/logback-test.xml b/today-remoting/src/test/resources/logback-test.xml index 7d459cb..aa99ace 100644 --- a/today-remoting/src/test/resources/logback-test.xml +++ b/today-remoting/src/test/resources/logback-test.xml @@ -24,7 +24,7 @@ - + diff --git a/today-remoting/src/testFixtures/java/infra/remoting/test/BaseClientServerTest.java b/today-remoting/src/testFixtures/java/infra/remoting/test/BaseClientServerTest.java index 56d3b58..e0853e6 100644 --- a/today-remoting/src/testFixtures/java/infra/remoting/test/BaseClientServerTest.java +++ b/today-remoting/src/testFixtures/java/infra/remoting/test/BaseClientServerTest.java @@ -51,7 +51,7 @@ public void teardown() { public void testFireNForget10() { long outputCount = Flux.range(1, 10) - .flatMap(i -> setup.getRSocket().fireAndForget(testPayload(i))) + .flatMap(i -> setup.getChannel().fireAndForget(testPayload(i))) .doOnError(Throwable::printStackTrace) .count() .block(); @@ -64,7 +64,7 @@ public void testFireNForget10() { public void testPushMetadata10() { long outputCount = Flux.range(1, 10) - .flatMap(i -> setup.getRSocket().metadataPush(DefaultPayload.create("", "metadata"))) + .flatMap(i -> setup.getChannel().metadataPush(DefaultPayload.create("", "metadata"))) .doOnError(Throwable::printStackTrace) .count() .block(); @@ -77,7 +77,7 @@ public void testRequestResponse1() { long outputCount = Flux.range(1, 1) .flatMap( - i -> setup.getRSocket().requestResponse(testPayload(i)).map(Payload::getDataUtf8)) + i -> setup.getChannel().requestResponse(testPayload(i)).map(Payload::getDataUtf8)) .doOnError(Throwable::printStackTrace) .count() .block(); @@ -91,7 +91,7 @@ public void testRequestResponse10() { long outputCount = Flux.range(1, 10) .flatMap( - i -> setup.getRSocket().requestResponse(testPayload(i)).map(Payload::getDataUtf8)) + i -> setup.getChannel().requestResponse(testPayload(i)).map(Payload::getDataUtf8)) .doOnError(Throwable::printStackTrace) .count() .block(); @@ -121,7 +121,7 @@ public void testRequestResponse100() { long outputCount = Flux.range(1, 100) .flatMap( - i -> setup.getRSocket().requestResponse(testPayload(i)).map(Payload::getDataUtf8)) + i -> setup.getChannel().requestResponse(testPayload(i)).map(Payload::getDataUtf8)) .doOnError(Throwable::printStackTrace) .count() .block(); @@ -135,7 +135,7 @@ public void testRequestResponse10_000() { long outputCount = Flux.range(1, 10_000) .flatMap( - i -> setup.getRSocket().requestResponse(testPayload(i)).map(Payload::getDataUtf8)) + i -> setup.getChannel().requestResponse(testPayload(i)).map(Payload::getDataUtf8)) .doOnError(Throwable::printStackTrace) .count() .block(); @@ -146,7 +146,7 @@ public void testRequestResponse10_000() { @Test @Timeout(10000) public void testRequestStream() { - Flux publisher = setup.getRSocket().requestStream(testPayload(3)); + Flux publisher = setup.getChannel().requestStream(testPayload(3)); long count = publisher.take(5).count().block(); @@ -156,7 +156,7 @@ public void testRequestStream() { @Test @Timeout(10000) public void testRequestStreamAll() { - Flux publisher = setup.getRSocket().requestStream(testPayload(3)); + Flux publisher = setup.getChannel().requestStream(testPayload(3)); long count = publisher.count().block(); @@ -169,7 +169,7 @@ public void testRequestStreamWithRequestN() { CountdownBaseSubscriber ts = new CountdownBaseSubscriber(); ts.expect(5); - setup.getRSocket().requestStream(testPayload(3)).subscribe(ts); + setup.getChannel().requestStream(testPayload(3)).subscribe(ts); ts.await(); assertThat(ts.count()).isEqualTo(5); @@ -186,7 +186,7 @@ public void testRequestStreamWithRequestN() { public void testRequestStreamWithDelayedRequestN() { CountdownBaseSubscriber ts = new CountdownBaseSubscriber(); - setup.getRSocket().requestStream(testPayload(3)).subscribe(ts); + setup.getChannel().requestStream(testPayload(3)).subscribe(ts); ts.expect(5); @@ -203,7 +203,7 @@ public void testRequestStreamWithDelayedRequestN() { @Test @Timeout(10000) public void testChannel0() { - Flux publisher = setup.getRSocket().requestChannel(Flux.empty()); + Flux publisher = setup.getChannel().requestChannel(Flux.empty()); long count = publisher.count().block(); @@ -213,7 +213,7 @@ public void testChannel0() { @Test @Timeout(10000) public void testChannel1() { - Flux publisher = setup.getRSocket().requestChannel(Flux.just(testPayload(0))); + Flux publisher = setup.getChannel().requestChannel(Flux.just(testPayload(0))); long count = publisher.count().block(); @@ -225,7 +225,7 @@ public void testChannel1() { public void testChannel3() { Flux publisher = setup - .getRSocket() + .getChannel() .requestChannel(Flux.just(testPayload(0), testPayload(1), testPayload(2))); long count = publisher.count().block(); @@ -238,7 +238,7 @@ public void testChannel3() { public void testChannel512() { Flux payloads = Flux.range(1, 512).map(i -> DefaultPayload.create("hello " + i)); - long count = setup.getRSocket().requestChannel(payloads).count().block(); + long count = setup.getChannel().requestChannel(payloads).count().block(); assertThat(count).isEqualTo(512); } @@ -248,7 +248,7 @@ public void testChannel512() { public void testChannel20_000() { Flux payloads = Flux.range(1, 20_000).map(i -> DefaultPayload.create("hello " + i)); - long count = setup.getRSocket().requestChannel(payloads).count().block(); + long count = setup.getChannel().requestChannel(payloads).count().block(); assertThat(count).isEqualTo(20_000); } @@ -258,7 +258,7 @@ public void testChannel20_000() { public void testChannel200_000() { Flux payloads = Flux.range(1, 200_000).map(i -> DefaultPayload.create("hello " + i)); - long count = setup.getRSocket().requestChannel(payloads).count().block(); + long count = setup.getChannel().requestChannel(payloads).count().block(); assertThat(count).isEqualTo(200_000); } @@ -270,7 +270,7 @@ public void testChannel2_000_000() { AtomicInteger counter = new AtomicInteger(0); Flux payloads = Flux.range(1, 2_000_000).map(i -> DefaultPayload.create("hello " + i)); - long count = setup.getRSocket().requestChannel(payloads).count().block(); + long count = setup.getChannel().requestChannel(payloads).count().block(); assertThat(count).isEqualTo(2_000_000); } diff --git a/today-remoting/src/testFixtures/java/infra/remoting/test/ClientSetupRule.java b/today-remoting/src/testFixtures/java/infra/remoting/test/ClientSetupRule.java index e153296..68d0c3f 100644 --- a/today-remoting/src/testFixtures/java/infra/remoting/test/ClientSetupRule.java +++ b/today-remoting/src/testFixtures/java/infra/remoting/test/ClientSetupRule.java @@ -48,7 +48,7 @@ public ClientSetupRule( this.serverInit = address -> - RemotingServer.create((setup, rsocket) -> Mono.just(new TestChannel(data, metadata))) + RemotingServer.create((setup, channel) -> Mono.just(new TestChannel(data, metadata))) .bind(serverTransportSupplier.apply(address)) .block(); @@ -69,7 +69,7 @@ public void tearDown() { server.dispose(); } - public Channel getRSocket() { + public Channel getChannel() { return client; } diff --git a/today-remoting/src/testFixtures/java/infra/remoting/test/PingClient.java b/today-remoting/src/testFixtures/java/infra/remoting/test/PingClient.java index 7215bd4..b402930 100644 --- a/today-remoting/src/testFixtures/java/infra/remoting/test/PingClient.java +++ b/today-remoting/src/testFixtures/java/infra/remoting/test/PingClient.java @@ -68,12 +68,12 @@ Flux pingPong( final Recorder histogram) { return Flux.usingWhen( client, - rsocket -> + channel -> Flux.range(1, count) .flatMap( i -> { long start = System.nanoTime(); - return Flux.from(interaction.apply(rsocket, payload.retain())) + return Flux.from(interaction.apply(channel, payload.retain())) .doOnNext(Payload::release) .doFinally( signalType -> { @@ -82,9 +82,9 @@ Flux pingPong( }); }, 64), - rsocket -> { - rsocket.dispose(); - return rsocket.onClose(); + channel -> { + channel.dispose(); + return channel.onClose(); }) .doOnError(Throwable::printStackTrace); } diff --git a/today-remoting/src/testFixtures/java/infra/remoting/test/package-info.java b/today-remoting/src/testFixtures/java/infra/remoting/test/package-info.java index 15d905a..cb1596e 100644 --- a/today-remoting/src/testFixtures/java/infra/remoting/test/package-info.java +++ b/today-remoting/src/testFixtures/java/infra/remoting/test/package-info.java @@ -15,7 +15,7 @@ * along with this program. If not, see [http://www.gnu.org/licenses/] */ -/** Utilities for testing RSocket components. */ +/** Utilities for testing components. */ @NonNullApi package infra.remoting.test; diff --git a/today-remoting/src/testFixtures/resources/services/org.assertj.core.presentation.Representation b/today-remoting/src/testFixtures/resources/services/org.assertj.core.presentation.Representation index 4085e23..9c87471 100644 --- a/today-remoting/src/testFixtures/resources/services/org.assertj.core.presentation.Representation +++ b/today-remoting/src/testFixtures/resources/services/org.assertj.core.presentation.Representation @@ -1 +1 @@ -io.rsocket.test.ByteBufRepresentation \ No newline at end of file +infra.remoting.test.ByteBufRepresentation \ No newline at end of file From 3e24ad326c15095af7c63de5f5ea22155b5a7a79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Sun, 3 Aug 2025 17:12:27 +0800 Subject: [PATCH 002/104] :construction: --- .../actions/await-http-resource/action.yml | 20 ++++ .github/actions/building/action.yml | 101 ++++++++++++++++++ .github/actions/read-version/action.yml | 24 +++++ .github/workflows/ci.yaml | 48 +++++++++ build.gradle | 14 +++ .../remoting/frame/FragmentationCodec.java | 36 ------- 6 files changed, 207 insertions(+), 36 deletions(-) create mode 100644 .github/actions/await-http-resource/action.yml create mode 100644 .github/actions/building/action.yml create mode 100644 .github/actions/read-version/action.yml create mode 100644 .github/workflows/ci.yaml delete mode 100644 today-remoting/src/main/java/infra/remoting/frame/FragmentationCodec.java diff --git a/.github/actions/await-http-resource/action.yml b/.github/actions/await-http-resource/action.yml new file mode 100644 index 0000000..ba177fb --- /dev/null +++ b/.github/actions/await-http-resource/action.yml @@ -0,0 +1,20 @@ +name: Await HTTP Resource +description: 'Waits for an HTTP resource to be available (a HEAD request succeeds)' +inputs: + url: + description: 'URL of the resource to await' + required: true +runs: + using: composite + steps: + - name: Await HTTP resource + shell: bash + run: | + url=${{ inputs.url }} + echo "Waiting for $url" + until curl --fail --head --silent ${{ inputs.url }} > /dev/null + do + echo "." + sleep 60 + done + echo "$url is available" diff --git a/.github/actions/building/action.yml b/.github/actions/building/action.yml new file mode 100644 index 0000000..d9550c5 --- /dev/null +++ b/.github/actions/building/action.yml @@ -0,0 +1,101 @@ +name: 'Build' +description: 'Builds the project, optionally publishing it to a local deployment repository' +inputs: + java-distribution: + description: 'Java distribution to use' + required: false + default: 'liberica' + java-early-access: + description: 'Whether the Java version is in early access' + required: false + default: 'false' + java-toolchain: + description: 'Whether a Java toolchain should be used' + required: false + default: 'false' + java-version: + description: 'Java version to compile and test with' + required: false + default: '24' + publish: + description: 'Whether to publish artifacts ready for deployment to Artifactory' + required: false + default: 'false' + token-password: + description: 'Password for authentication with central.sonatype.com' + required: false + token-username: + description: 'Username for authentication with central.sonatype.com' + required: false + signing-keyId: + description: 'signing keyId' + required: false + signing-password: + description: 'signing password' + required: false + gpg-passphrase: + description: 'Environment variable name for the GPG private key passphrase. Default is $GPG_PASSPHRASE.' + required: false + gpg-private-key: + description: 'GPG private key to import. Default is empty string.' + required: false + server-id: + description: 'ID of the distributionManagement repository in the pom.xml file. Default is `github`' + required: false + default: 'github' + server-username: + description: 'Environment variable name for the username for authentication to the Apache Maven repository. Default is $GITHUB_ACTOR' + required: false + default: 'GITHUB_ACTOR' + server-password: + description: 'Environment variable name for password or token for authentication to the Apache Maven repository. Default is $GITHUB_TOKEN' + required: false + default: 'GITHUB_TOKEN' +outputs: + build-scan-url: + description: 'URL, if any, of the build scan produced by the build' + value: ${{ (inputs.publish == 'true' && steps.publish.outputs.build-scan-url) || steps.build.outputs.build-scan-url }} + version: + description: 'Version that was built' + value: ${{ steps.read-version.outputs.version }} +runs: + using: composite + steps: + - name: Set Up Java + uses: actions/setup-java@v4 + with: + distribution: ${{ inputs.java-early-access == 'true' && 'temurin' || (inputs.java-distribution || 'liberica') }} + java-version: | + ${{ inputs.java-early-access == 'true' && format('{0}-ea', inputs.java-version) || inputs.java-version }} + ${{ inputs.java-toolchain == 'true' && '17' || '' }} + gpg-passphrase: ${{ inputs.gpg-passphrase }} + gpg-private-key: ${{ inputs.gpg-private-key }} + server-id: ${{ inputs.server-id }} + server-username: ${{ inputs.server-username }} + server-password: ${{ inputs.server-password }} + + - name: Print JDK Version + shell: bash + run: java -version + + - name: Set Up Gradle + uses: gradle/actions/setup-gradle@v4 + + - name: Build + id: build + if: ${{ inputs.publish == 'false' }} + shell: bash + run: ./gradlew -DCI=true --no-daemon --no-parallel check --scan + + - name: Publish + id: publish + if: ${{ inputs.publish == 'true' }} + shell: bash + run: ./gradlew --no-daemon --no-parallel publishMavenPublicationToSonatypeRepository closeAndReleaseStagingRepositories + -PrepoUsername=${{ inputs.token-username }} -PrepoPassword=${{ inputs.token-password }} + -Psigning.keyId=${{ inputs.signing-password }} -Psigning.password=${{ inputs.signing-password }} + + - name: Read Version From gradle.properties + id: read-version + uses: ./.github/actions/read-version + diff --git a/.github/actions/read-version/action.yml b/.github/actions/read-version/action.yml new file mode 100644 index 0000000..b5ae248 --- /dev/null +++ b/.github/actions/read-version/action.yml @@ -0,0 +1,24 @@ +name: read-version +author: today +description: Read project version + +outputs: + version: + description: 'Version of this project' + value: ${{ steps.read-version.outputs.version }} + snapshot: + description: 'Version is snapshot' + value: ${{ steps.read-version.outputs.snapshot }} +runs: + using: composite + steps: + - name: Read Version From gradle.properties + id: read-version + shell: bash + run: | + version=$(sed -n 's/version=\(.*\)/\1/p' gradle.properties) + snapshot=$(echo $version | grep -q 'SNAPSHOT' && echo 'true' || echo 'false') + echo "Version is $version" + echo "snapshot = $snapshot" + echo "version=$version" >> $GITHUB_OUTPUT + echo "snapshot=$snapshot" >> $GITHUB_OUTPUT \ No newline at end of file diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml new file mode 100644 index 0000000..56c0b06 --- /dev/null +++ b/.github/workflows/ci.yaml @@ -0,0 +1,48 @@ +name: CI + +on: + push: + branches: + - master + + pull_request: + branches: + - master + - 'dev/**' + - 'fix/**' + - 'feat/**' + - 'feature/**' + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + check: + if: github.repository_owner == 'today-tech' + runs-on: ${{ matrix.os }} + timeout-minutes: 60 + strategy: + matrix: + os: [ ubuntu-latest, macOS-latest ] #, windows-latest + java: + - version: 21 + toolchain: true + - version: 24 + toolchain: true + fail-fast: false + max-parallel: 4 + name: JDK ${{ matrix.java.version }} on ${{ matrix.os }} + + steps: + - name: Checkout project sources + uses: actions/checkout@v4.1.2 + + - name: Build + id: build + uses: ./.github/actions/building + with: + java-early-access: ${{ matrix.java.early-access || 'false' }} + java-distribution: ${{ matrix.java.distribution }} + java-toolchain: ${{ matrix.java.toolchain }} + java-version: ${{ matrix.java.version }} diff --git a/build.gradle b/build.gradle index 208e741..02c6f03 100644 --- a/build.gradle +++ b/build.gradle @@ -17,6 +17,7 @@ plugins { id 'de.undercouch.download' version '5.4.0' + id "io.github.gradle-nexus.publish-plugin" version "2.0.0" } ext { @@ -82,3 +83,16 @@ configure(rootProject) { description = "TODAY Cloud" } +nexusPublishing { + String repoUsername = project.properties["repoUsername"] ?: System.getenv("SNAPSHOTS_USERNAME") + String repoPassword = project.properties["repoPassword"] ?: System.getenv("SNAPSHOTS_TOKEN") + + repositories { + sonatype { + username.set(repoUsername) + password.set(repoPassword) + nexusUrl.set(uri("https://ossrh-staging-api.central.sonatype.com/service/local/")) + snapshotRepositoryUrl.set(uri("https://central.sonatype.com/repository/maven-snapshots/")) + } + } +} diff --git a/today-remoting/src/main/java/infra/remoting/frame/FragmentationCodec.java b/today-remoting/src/main/java/infra/remoting/frame/FragmentationCodec.java deleted file mode 100644 index e74bef6..0000000 --- a/today-remoting/src/main/java/infra/remoting/frame/FragmentationCodec.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2021 - 2024 the original author or authors. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] - */ - -package infra.remoting.frame; - -import infra.lang.Nullable; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufAllocator; - -/** FragmentationFlyweight is used to re-assemble frames */ -public class FragmentationCodec { - public static ByteBuf encode(final ByteBufAllocator allocator, ByteBuf header, ByteBuf data) { - return encode(allocator, header, null, data); - } - - public static ByteBuf encode( - final ByteBufAllocator allocator, ByteBuf header, @Nullable ByteBuf metadata, ByteBuf data) { - - final boolean hasMetadata = metadata != null; - return FrameBodyCodec.encode(allocator, header, metadata, hasMetadata, data); - } -} From dade80183a0287a56fc82e3ee32fb86d2867e475 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Sun, 3 Aug 2025 17:13:44 +0800 Subject: [PATCH 003/104] :art: --- build.gradle | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/build.gradle b/build.gradle index 02c6f03..6e357c7 100644 --- a/build.gradle +++ b/build.gradle @@ -1,20 +1,3 @@ -/* - * Copyright 2021 - 2024 the original author or authors. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] - */ - plugins { id 'de.undercouch.download' version '5.4.0' id "io.github.gradle-nexus.publish-plugin" version "2.0.0" From c06f509abb19e463e5d946772f9fc2cfd0297754 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Sun, 3 Aug 2025 17:16:56 +0800 Subject: [PATCH 004/104] :art: --- .../java/infra/remoting/lb/ChannelPool.java | 16 +- .../java/infra/remoting/lb/PooledChannel.java | 4 +- ...cketRule.java => AbstractChannelRule.java} | 10 +- .../ChannelRequesterTerminationTests.java | 8 +- .../remoting/core/ChannelRequesterTests.java | 206 +++++++++--------- .../remoting/core/ChannelResponderTests.java | 8 +- .../infra/remoting/core/ChannelTests.java | 4 +- .../core/DefaultChannelClientTests.java | 40 ++-- 8 files changed, 148 insertions(+), 148 deletions(-) rename today-remoting/src/test/java/infra/remoting/core/{AbstractSocketRule.java => AbstractChannelRule.java} (92%) diff --git a/today-remoting/src/main/java/infra/remoting/lb/ChannelPool.java b/today-remoting/src/main/java/infra/remoting/lb/ChannelPool.java index 308ef90..ccff6e1 100644 --- a/today-remoting/src/main/java/infra/remoting/lb/ChannelPool.java +++ b/today-remoting/src/main/java/infra/remoting/lb/ChannelPool.java @@ -44,8 +44,8 @@ class ChannelPool extends ResolvingOperator implements CoreSubscriber>, Closeable { - static final AtomicReferenceFieldUpdater ACTIVE_SOCKETS = - AtomicReferenceFieldUpdater.newUpdater(ChannelPool.class, PooledChannel[].class, "activeSockets"); + static final AtomicReferenceFieldUpdater ACTIVE_CHANNELS = + AtomicReferenceFieldUpdater.newUpdater(ChannelPool.class, PooledChannel[].class, "activeChannels"); static final PooledChannel[] EMPTY = new PooledChannel[0]; static final PooledChannel[] TERMINATED = new PooledChannel[0]; @@ -61,14 +61,14 @@ class ChannelPool extends ResolvingOperator implements CoreSubscriber
  • onAllClosedSink = Sinks.unsafe().empty(); - volatile PooledChannel[] activeSockets; + volatile PooledChannel[] activeChannels; volatile Subscription s; public ChannelPool(ChannelConnector connector, Publisher> targetPublisher, LoadBalanceStrategy loadbalanceStrategy) { this.connector = connector; this.loadbalanceStrategy = loadbalanceStrategy; - ACTIVE_SOCKETS.lazySet(this, EMPTY); + ACTIVE_CHANNELS.lazySet(this, EMPTY); targetPublisher.subscribe(this); } @@ -81,7 +81,7 @@ public Mono onClose() { protected void doOnDispose() { Operators.terminate(S, this); - Channel[] activeSockets = ACTIVE_SOCKETS.getAndSet(this, TERMINATED); + Channel[] activeSockets = ACTIVE_CHANNELS.getAndSet(this, TERMINATED); for (Channel channel : activeSockets) { channel.dispose(); } @@ -123,7 +123,7 @@ public void onNext(List targets) { } // Intersect current and new list of targets and find the ones to keep vs dispose - previouslyActiveSockets = this.activeSockets; + previouslyActiveSockets = this.activeChannels; inactiveSockets = new PooledChannel[previouslyActiveSockets.length]; PooledChannel[] nextActiveSockets = new PooledChannel[previouslyActiveSockets.length + channelSuppliersCopy.size()]; @@ -166,7 +166,7 @@ public void onNext(List targets) { else { socketsToUse = Arrays.copyOf(nextActiveSockets, activeSocketsPosition); } - if (ACTIVE_SOCKETS.compareAndSet(this, previouslyActiveSockets, socketsToUse)) { + if (ACTIVE_CHANNELS.compareAndSet(this, previouslyActiveSockets, socketsToUse)) { break; } } @@ -231,7 +231,7 @@ public Channel select() { @Nullable public Channel doSelect() { - PooledChannel[] sockets = this.activeSockets; + PooledChannel[] sockets = this.activeChannels; if (sockets == EMPTY || sockets == TERMINATED) { return null; diff --git a/today-remoting/src/main/java/infra/remoting/lb/PooledChannel.java b/today-remoting/src/main/java/infra/remoting/lb/PooledChannel.java index fe79341..53cea0d 100644 --- a/today-remoting/src/main/java/infra/remoting/lb/PooledChannel.java +++ b/today-remoting/src/main/java/infra/remoting/lb/PooledChannel.java @@ -131,7 +131,7 @@ void doCleanup(Throwable t) { final ChannelPool parent = this.parent; for (; ; ) { - final PooledChannel[] sockets = parent.activeSockets; + final PooledChannel[] sockets = parent.activeChannels; final int activeSocketsCount = sockets.length; int index = -1; @@ -163,7 +163,7 @@ void doCleanup(Throwable t) { } } - if (ChannelPool.ACTIVE_SOCKETS.compareAndSet(parent, sockets, newSockets)) { + if (ChannelPool.ACTIVE_CHANNELS.compareAndSet(parent, sockets, newSockets)) { break; } } diff --git a/today-remoting/src/test/java/infra/remoting/core/AbstractSocketRule.java b/today-remoting/src/test/java/infra/remoting/core/AbstractChannelRule.java similarity index 92% rename from today-remoting/src/test/java/infra/remoting/core/AbstractSocketRule.java rename to today-remoting/src/test/java/infra/remoting/core/AbstractChannelRule.java index fa88ba7..5b9c3ca 100644 --- a/today-remoting/src/test/java/infra/remoting/core/AbstractSocketRule.java +++ b/today-remoting/src/test/java/infra/remoting/core/AbstractChannelRule.java @@ -29,11 +29,11 @@ import static infra.remoting.frame.FrameLengthCodec.FRAME_LENGTH_MASK; -public abstract class AbstractSocketRule { +public abstract class AbstractChannelRule { protected TestDuplexConnection connection; protected Subscriber connectSub; - protected T socket; + protected T channel; protected LeaksTrackingByteBufAllocator allocator; protected int maxFrameLength = FRAME_LENGTH_MASK; protected int maxInboundPayloadSize = Integer.MAX_VALUE; @@ -50,11 +50,11 @@ protected void doInit() { if (connection != null) { connection.dispose(); } - if (socket != null) { - socket.dispose(); + if (channel != null) { + channel.dispose(); } connection = new TestDuplexConnection(allocator); - socket = newChannel(); + channel = newChannel(); } public void setMaxInboundPayloadSize(int maxInboundPayloadSize) { diff --git a/today-remoting/src/test/java/infra/remoting/core/ChannelRequesterTerminationTests.java b/today-remoting/src/test/java/infra/remoting/core/ChannelRequesterTerminationTests.java index 4cfae09..3181f6d 100644 --- a/today-remoting/src/test/java/infra/remoting/core/ChannelRequesterTerminationTests.java +++ b/today-remoting/src/test/java/infra/remoting/core/ChannelRequesterTerminationTests.java @@ -32,7 +32,7 @@ import infra.remoting.FrameAssert; import infra.remoting.Payload; import infra.remoting.Channel; -import infra.remoting.core.ChannelRequesterTests.ClientSocketRule; +import infra.remoting.core.ChannelRequesterTests.ClientChannelRule; import infra.remoting.frame.FrameType; import infra.remoting.util.EmptyPayload; import reactor.core.publisher.Flux; @@ -41,7 +41,7 @@ public class ChannelRequesterTerminationTests { - public final ClientSocketRule rule = new ClientSocketRule(); + public final ClientChannelRule rule = new ClientChannelRule(); @BeforeEach public void setup() { @@ -57,7 +57,7 @@ public void tearDownAndCheckNoLeaks() { @MethodSource("interactions") public void testCurrentStreamIsTerminatedOnConnectionClose( FrameType requestType, Function> interaction) { - ChannelRequester channel = rule.socket; + ChannelRequester channel = rule.channel; StepVerifier.create(interaction.apply(channel)) .then( @@ -73,7 +73,7 @@ public void testCurrentStreamIsTerminatedOnConnectionClose( @MethodSource("interactions") public void testSubsequentStreamIsTerminatedAfterConnectionClose( FrameType requestType, Function> interaction) { - ChannelRequester channel = rule.socket; + ChannelRequester channel = rule.channel; rule.connection.dispose(); StepVerifier.create(interaction.apply(channel)) diff --git a/today-remoting/src/test/java/infra/remoting/core/ChannelRequesterTests.java b/today-remoting/src/test/java/infra/remoting/core/ChannelRequesterTests.java index cb0ccf8..9639b6c 100644 --- a/today-remoting/src/test/java/infra/remoting/core/ChannelRequesterTests.java +++ b/today-remoting/src/test/java/infra/remoting/core/ChannelRequesterTests.java @@ -111,13 +111,13 @@ public class ChannelRequesterTests { - ClientSocketRule rule; + ClientChannelRule rule; @BeforeEach public void setUp() throws Throwable { Hooks.onNextDropped(ReferenceCountUtil::safeRelease); Hooks.onErrorDropped((t) -> { }); - rule = new ClientSocketRule(); + rule = new ClientChannelRule(); rule.init(); } @@ -132,14 +132,14 @@ public void tearDown() { @Timeout(2_000) public void testInvalidFrameOnStream0ShouldNotTerminateChannel() { rule.connection.addToReceivedBuffer(RequestNFrameCodec.encode(rule.alloc(), 0, 10)); - assertThat(rule.socket.isDisposed()).isFalse(); + assertThat(rule.channel.isDisposed()).isFalse(); rule.assertHasNoLeaks(); } @Test @Timeout(2_000) public void testStreamInitialN() { - Flux stream = rule.socket.requestStream(EmptyPayload.INSTANCE); + Flux stream = rule.channel.requestStream(EmptyPayload.INSTANCE); BaseSubscriber subscriber = new BaseSubscriber() { @@ -173,7 +173,7 @@ protected void hookOnSubscribe(Subscription subscription) { public void testHandleSetupException() { rule.connection.addToReceivedBuffer( ErrorFrameCodec.encode(rule.alloc(), 0, new RejectedSetupException("boom"))); - assertThatThrownBy(() -> rule.socket.onClose().block()) + assertThatThrownBy(() -> rule.channel.onClose().block()) .isInstanceOf(RejectedSetupException.class); rule.assertHasNoLeaks(); } @@ -182,7 +182,7 @@ public void testHandleSetupException() { @Timeout(2_000) public void testHandleApplicationException() { rule.connection.clearSendReceiveBuffers(); - Publisher response = rule.socket.requestResponse(EmptyPayload.INSTANCE); + Publisher response = rule.channel.requestResponse(EmptyPayload.INSTANCE); Subscriber responseSub = TestSubscriber.create(); response.subscribe(responseSub); @@ -203,7 +203,7 @@ public void testHandleApplicationException() { @Test @Timeout(2_000) public void testHandleValidFrame() { - Publisher response = rule.socket.requestResponse(EmptyPayload.INSTANCE); + Publisher response = rule.channel.requestResponse(EmptyPayload.INSTANCE); Subscriber sub = TestSubscriber.create(); response.subscribe(sub); @@ -220,7 +220,7 @@ public void testHandleValidFrame() { @Test @Timeout(2_000) public void testRequestReplyWithCancel() { - Mono response = rule.socket.requestResponse(EmptyPayload.INSTANCE); + Mono response = rule.channel.requestResponse(EmptyPayload.INSTANCE); try { response.block(Duration.ofMillis(100)); @@ -245,12 +245,12 @@ public void testRequestReplyWithCancel() { @Timeout(2_000) public void testRequestReplyErrorOnSend() { rule.connection.setAvailability(0); // Fails send - Mono response = rule.socket.requestResponse(EmptyPayload.INSTANCE); + Mono response = rule.channel.requestResponse(EmptyPayload.INSTANCE); Subscriber responseSub = TestSubscriber.create(10); response.subscribe(responseSub); this.rule - .socket + .channel .onClose() .as(StepVerifier::create) .expectComplete() @@ -268,7 +268,7 @@ public void testRequestReplyErrorOnSend() { public void testChannelRequestCancellation() { Sinks.Empty cancelled = Sinks.empty(); Flux request = Flux.never().doOnCancel(cancelled::tryEmitEmpty); - rule.socket.requestChannel(request).subscribe().dispose(); + rule.channel.requestChannel(request).subscribe().dispose(); Flux.firstWithSignal( cancelled.asMono(), Flux.error(new IllegalStateException("Channel request not cancelled")) @@ -283,7 +283,7 @@ public void testChannelRequestCancellation2() { Sinks.Empty cancelled = Sinks.empty(); Flux request = Flux.just(EmptyPayload.INSTANCE).repeat(259).doOnCancel(cancelled::tryEmitEmpty); - rule.socket.requestChannel(request).subscribe().dispose(); + rule.channel.requestChannel(request).subscribe().dispose(); Flux.firstWithSignal( cancelled.asMono(), Flux.error(new IllegalStateException("Channel request not cancelled")) @@ -298,7 +298,7 @@ public void testChannelRequestServerSideCancellation() { Sinks.One cancelled = Sinks.one(); Sinks.Many request = Sinks.many().unicast().onBackpressureBuffer(); request.tryEmitNext(EmptyPayload.INSTANCE); - rule.socket + rule.channel .requestChannel(request.asFlux()) .subscribe(cancelled::tryEmitValue, cancelled::tryEmitError, cancelled::tryEmitEmpty); int streamId = rule.getStreamIdForRequestType(REQUEST_CHANNEL); @@ -328,7 +328,7 @@ public void testCorrectFrameOrder() { @Override protected void hookOnSubscribe(Subscription subscription) { } }; - rule.socket + rule.channel .requestChannel( Flux.concat(Flux.just(0).delayUntil(i -> delayer.asMono()), Flux.range(1, 999)) .map(i -> DefaultPayload.create(i + ""))) @@ -365,7 +365,7 @@ public void shouldThrownExceptionIfGivenPayloadIsExitsSizeAllowanceWithNoFragmen ThreadLocalRandom.current().nextBytes(metadata); ThreadLocalRandom.current().nextBytes(data); StepVerifier.create( - generator.apply(rule.socket, DefaultPayload.create(data, metadata))) + generator.apply(rule.channel, DefaultPayload.create(data, metadata))) .expectSubscription() .expectErrorSatisfies( t -> @@ -394,7 +394,7 @@ public void shouldThrownExceptionIfGivenPayloadIsExitsSizeAllowanceWithNoFragmen assertThatThrownBy( () -> { final Publisher source = - generator.apply(rule.socket, DefaultPayload.create(data, metadata)); + generator.apply(rule.channel, DefaultPayload.create(data, metadata)); if (source instanceof Mono) { ((Mono) source).block(); @@ -414,7 +414,7 @@ public void shouldThrownExceptionIfGivenPayloadIsExitsSizeAllowanceWithNoFragmen public void shouldRejectCallOfNoMetadataPayload() { final ByteBuf data = rule.allocator.buffer(10); final Payload payload = ByteBufPayload.create(data); - StepVerifier.create(rule.socket.metadataPush(payload)) + StepVerifier.create(rule.channel.metadataPush(payload)) .expectSubscription() .expectErrorSatisfies( t -> @@ -431,7 +431,7 @@ public void shouldRejectCallOfNoMetadataPayloadBlocking() { final ByteBuf data = rule.allocator.buffer(10); final Payload payload = ByteBufPayload.create(data); - assertThatThrownBy(() -> rule.socket.metadataPush(payload).block()) + assertThatThrownBy(() -> rule.channel.metadataPush(payload).block()) .isInstanceOf(IllegalArgumentException.class) .hasMessage("Metadata push should have metadata field present"); PayloadAssert.assertThat(payload).isReleased(); @@ -458,7 +458,7 @@ static Stream>> prepareCalls() { ThreadLocalRandom.current().nextBytes(metadata); ThreadLocalRandom.current().nextBytes(data); StepVerifier.create( - rule.socket.requestChannel( + rule.channel.requestChannel( Flux.just(EmptyPayload.INSTANCE, DefaultPayload.create(data, metadata))), 0) .expectSubscription() @@ -486,10 +486,10 @@ static Stream>> prepareCalls() { @ParameterizedTest @MethodSource("racingCases") public void checkNoLeaksOnRacing( - Function> initiator, - BiConsumer, ClientSocketRule> runner) { + Function> initiator, + BiConsumer, ClientChannelRule> runner) { for (int i = 0; i < RaceTestConstants.REPEATS; i++) { - ClientSocketRule clientSocketRule = new ClientSocketRule(); + ClientChannelRule clientSocketRule = new ClientChannelRule(); clientSocketRule.init(); @@ -514,9 +514,9 @@ public void checkNoLeaksOnRacing( private static Stream racingCases() { return Stream.of( Arguments.of( - (Function>) - (rule) -> rule.socket.requestStream(EmptyPayload.INSTANCE), - (BiConsumer, ClientSocketRule>) + (Function>) + (rule) -> rule.channel.requestStream(EmptyPayload.INSTANCE), + (BiConsumer, ClientChannelRule>) (as, rule) -> { ByteBufAllocator allocator = rule.alloc(); ByteBuf metadata = allocator.buffer(); @@ -532,9 +532,9 @@ private static Stream racingCases() { RaceTestUtils.race(as::cancel, () -> rule.connection.addToReceivedBuffer(frame)); }), Arguments.of( - (Function>) - (rule) -> rule.socket.requestChannel(Flux.just(EmptyPayload.INSTANCE)), - (BiConsumer, ClientSocketRule>) + (Function>) + (rule) -> rule.channel.requestChannel(Flux.just(EmptyPayload.INSTANCE)), + (BiConsumer, ClientChannelRule>) (as, rule) -> { ByteBufAllocator allocator = rule.alloc(); ByteBuf metadata = allocator.buffer(); @@ -550,7 +550,7 @@ private static Stream racingCases() { RaceTestUtils.race(as::cancel, () -> rule.connection.addToReceivedBuffer(frame)); }), Arguments.of( - (Function>) + (Function>) (rule) -> { ByteBufAllocator allocator = rule.alloc(); ByteBuf metadata = allocator.buffer(); @@ -559,9 +559,9 @@ private static Stream racingCases() { data.writeCharSequence("data", CharsetUtil.UTF_8); final Payload payload = ByteBufPayload.create(data, metadata); - return rule.socket.requestStream(payload); + return rule.channel.requestStream(payload); }, - (BiConsumer, ClientSocketRule>) + (BiConsumer, ClientChannelRule>) (as, rule) -> { RaceTestUtils.race(() -> as.request(1), as::cancel); // ensures proper frames order @@ -589,10 +589,10 @@ private static Stream racingCases() { } }), Arguments.of( - (Function>) + (Function>) (rule) -> { ByteBufAllocator allocator = rule.alloc(); - return rule.socket.requestChannel( + return rule.channel.requestChannel( Flux.generate( () -> 1L, (index, sink) -> { @@ -606,7 +606,7 @@ private static Stream racingCases() { return ++index; })); }, - (BiConsumer, ClientSocketRule>) + (BiConsumer, ClientChannelRule>) (as, rule) -> { RaceTestUtils.race(() -> as.request(1), as::cancel); // ensures proper frames order @@ -664,9 +664,9 @@ private static Stream racingCases() { } }), Arguments.of( - (Function>) + (Function>) (rule) -> - rule.socket.requestChannel( + rule.channel.requestChannel( Flux.generate( () -> 1L, (index, sink) -> { @@ -678,7 +678,7 @@ private static Stream racingCases() { sink.next(payload); return ++index; })), - (BiConsumer, ClientSocketRule>) + (BiConsumer, ClientChannelRule>) (as, rule) -> { ByteBufAllocator allocator = rule.alloc(); as.request(1); @@ -690,9 +690,9 @@ private static Stream racingCases() { () -> rule.connection.addToReceivedBuffer(frame)); }), Arguments.of( - (Function>) + (Function>) (rule) -> - rule.socket.requestChannel( + rule.channel.requestChannel( Flux.generate( () -> 1L, (index, sink) -> { @@ -704,7 +704,7 @@ private static Stream racingCases() { sink.next(payload); return ++index; })), - (BiConsumer, ClientSocketRule>) + (BiConsumer, ClientChannelRule>) (as, rule) -> { ByteBufAllocator allocator = rule.alloc(); as.request(1); @@ -717,7 +717,7 @@ private static Stream racingCases() { () -> rule.connection.addToReceivedBuffer(frame)); }), Arguments.of( - (Function>) + (Function>) (rule) -> { ByteBuf data = rule.allocator.buffer(); data.writeCharSequence("testData", CharsetUtil.UTF_8); @@ -725,9 +725,9 @@ private static Stream racingCases() { ByteBuf metadata = rule.allocator.buffer(); metadata.writeCharSequence("testMetadata", CharsetUtil.UTF_8); Payload requestPayload = ByteBufPayload.create(data, metadata); - return rule.socket.requestResponse(requestPayload); + return rule.channel.requestResponse(requestPayload); }, - (BiConsumer, ClientSocketRule>) + (BiConsumer, ClientChannelRule>) (as, rule) -> { ByteBufAllocator allocator = rule.alloc(); ByteBuf metadata = allocator.buffer(); @@ -743,7 +743,7 @@ private static Stream racingCases() { RaceTestUtils.race(as::cancel, () -> rule.connection.addToReceivedBuffer(frame)); }), Arguments.of( - (Function>) + (Function>) (rule) -> { ByteBuf data = rule.allocator.buffer(); data.writeCharSequence("testData", CharsetUtil.UTF_8); @@ -751,9 +751,9 @@ private static Stream racingCases() { ByteBuf metadata = rule.allocator.buffer(); metadata.writeCharSequence("testMetadata", CharsetUtil.UTF_8); Payload requestPayload = ByteBufPayload.create(data, metadata); - return rule.socket.requestStream(requestPayload); + return rule.channel.requestStream(requestPayload); }, - (BiConsumer, ClientSocketRule>) + (BiConsumer, ClientChannelRule>) (as, rule) -> { ByteBufAllocator allocator = rule.alloc(); ByteBuf metadata = allocator.buffer(); @@ -775,7 +775,7 @@ public void simpleOnDiscardRequestChannelTest() { AssertSubscriber assertSubscriber = AssertSubscriber.create(1); Sinks.Many testPublisher = Sinks.many().unicast().onBackpressureBuffer(); - Flux payloadFlux = rule.socket.requestChannel(testPublisher.asFlux()); + Flux payloadFlux = rule.channel.requestChannel(testPublisher.asFlux()); payloadFlux.subscribe(assertSubscriber); @@ -802,7 +802,7 @@ public void simpleOnDiscardRequestChannelTest2() { AssertSubscriber assertSubscriber = AssertSubscriber.create(1); Sinks.Many testPublisher = Sinks.many().unicast().onBackpressureBuffer(); - Flux payloadFlux = rule.socket.requestChannel(testPublisher.asFlux()); + Flux payloadFlux = rule.channel.requestChannel(testPublisher.asFlux()); payloadFlux.subscribe(assertSubscriber); @@ -840,16 +840,16 @@ public void verifiesThatFrameWithNoMetadataHasDecodedCorrectlyIntoPayload( switch (frameType) { case REQUEST_FNF: response = - testPublisher.mono().flatMap(p -> rule.socket.fireAndForget(p)).then(Mono.empty()); + testPublisher.mono().flatMap(p -> rule.channel.fireAndForget(p)).then(Mono.empty()); break; case REQUEST_RESPONSE: - response = testPublisher.mono().flatMap(p -> rule.socket.requestResponse(p)); + response = testPublisher.mono().flatMap(p -> rule.channel.requestResponse(p)); break; case REQUEST_STREAM: - response = testPublisher.mono().flatMapMany(p -> rule.socket.requestStream(p)); + response = testPublisher.mono().flatMapMany(p -> rule.channel.requestStream(p)); break; case REQUEST_CHANNEL: - response = rule.socket.requestChannel(testPublisher.flux()); + response = rule.channel.requestChannel(testPublisher.flux()); break; default: throw new UnsupportedOperationException("illegal case"); @@ -927,7 +927,7 @@ static Stream encodeDecodePayloadCases() { @ParameterizedTest @MethodSource("refCntCases") public void ensureSendsErrorOnIllegalRefCntPayload( - BiFunction> sourceProducer) { + BiFunction> sourceProducer) { Payload invalidPayload = ByteBufPayload.create( ByteBufUtil.writeUtf8(rule.alloc(), "test"), @@ -941,12 +941,12 @@ public void ensureSendsErrorOnIllegalRefCntPayload( .verify(Duration.ofMillis(1000)); } - private static Stream>> refCntCases() { + private static Stream>> refCntCases() { return Stream.of( - (p, clientSocketRule) -> clientSocketRule.socket.fireAndForget(p), - (p, clientSocketRule) -> clientSocketRule.socket.requestResponse(p), - (p, clientSocketRule) -> clientSocketRule.socket.requestStream(p), - (p, clientSocketRule) -> clientSocketRule.socket.requestChannel(Mono.just(p)), + (p, clientSocketRule) -> clientSocketRule.channel.fireAndForget(p), + (p, clientSocketRule) -> clientSocketRule.channel.requestResponse(p), + (p, clientSocketRule) -> clientSocketRule.channel.requestStream(p), + (p, clientSocketRule) -> clientSocketRule.channel.requestChannel(Mono.just(p)), (p, clientSocketRule) -> { Flux.from(clientSocketRule.connection.getSentAsPublisher()) .filter(bb -> frameType(bb) == REQUEST_CHANNEL) @@ -959,17 +959,17 @@ private static Stream>> refCn bb.release(); }); - return clientSocketRule.socket.requestChannel(Flux.just(EmptyPayload.INSTANCE, p)); + return clientSocketRule.channel.requestChannel(Flux.just(EmptyPayload.INSTANCE, p)); }); } @Test public void ensuresThatNoOpsMustHappenUntilSubscriptionInCaseOfFnfCall() { Payload payload1 = ByteBufPayload.create("abc1"); - Mono fnf1 = rule.socket.fireAndForget(payload1); + Mono fnf1 = rule.channel.fireAndForget(payload1); Payload payload2 = ByteBufPayload.create("abc2"); - Mono fnf2 = rule.socket.fireAndForget(payload2); + Mono fnf2 = rule.channel.fireAndForget(payload2); assertThat(rule.connection.getSent()).isEmpty(); @@ -1011,7 +1011,7 @@ public void ensuresThatNoOpsMustHappenUntilSubscriptionInCaseOfFnfCall() { @ParameterizedTest @MethodSource("requestNInteractions") public void ensuresThatNoOpsMustHappenUntilFirstRequestN( - FrameType frameType, BiFunction> interaction) { + FrameType frameType, BiFunction> interaction) { Payload payload1 = ByteBufPayload.create("abc1"); Publisher interaction1 = interaction.apply(rule, payload1); @@ -1120,24 +1120,24 @@ private static Stream requestNInteractions() { return Stream.of( Arguments.of( REQUEST_RESPONSE, - (BiFunction>) - (rule, payload) -> rule.socket.requestResponse(payload)), + (BiFunction>) + (rule, payload) -> rule.channel.requestResponse(payload)), Arguments.of( REQUEST_STREAM, - (BiFunction>) - (rule, payload) -> rule.socket.requestStream(payload)), + (BiFunction>) + (rule, payload) -> rule.channel.requestStream(payload)), Arguments.of( REQUEST_CHANNEL, - (BiFunction>) - (rule, payload) -> rule.socket.requestChannel(Flux.just(payload)))); + (BiFunction>) + (rule, payload) -> rule.channel.requestChannel(Flux.just(payload)))); } @ParameterizedTest @MethodSource("streamRacingCases") @Disabled("Connection should take care of ordering if such is necessary") public void ensuresCorrectOrderOfStreamIdIssuingInCaseOfRacing( - BiFunction> interaction1, - BiFunction> interaction2, + BiFunction> interaction1, + BiFunction> interaction2, FrameType interactionType1, FrameType interactionType2) { Assumptions.assumeThat(interactionType1).isNotEqualTo(METADATA_PUSH); @@ -1161,27 +1161,27 @@ public void ensuresCorrectOrderOfStreamIdIssuingInCaseOfRacing( public static Stream streamRacingCases() { return Stream.of( Arguments.of( - (BiFunction>) - (r, p) -> r.socket.fireAndForget(p), - (BiFunction>) - (r, p) -> r.socket.requestResponse(p), + (BiFunction>) + (r, p) -> r.channel.fireAndForget(p), + (BiFunction>) + (r, p) -> r.channel.requestResponse(p), REQUEST_FNF, REQUEST_RESPONSE), Arguments.of( - (BiFunction>) - (r, p) -> r.socket.requestResponse(p), - (BiFunction>) - (r, p) -> r.socket.requestStream(p), + (BiFunction>) + (r, p) -> r.channel.requestResponse(p), + (BiFunction>) + (r, p) -> r.channel.requestStream(p), REQUEST_RESPONSE, REQUEST_STREAM), Arguments.of( - (BiFunction>) - (r, p) -> r.socket.requestStream(p), - (BiFunction>) + (BiFunction>) + (r, p) -> r.channel.requestStream(p), + (BiFunction>) (r, p) -> { AtomicBoolean subscribed = new AtomicBoolean(); Flux just = Flux.just(p).doOnSubscribe((__) -> subscribed.set(true)); - return r.socket + return r.channel .requestChannel(just) .doFinally( __ -> { @@ -1193,11 +1193,11 @@ public static Stream streamRacingCases() { REQUEST_STREAM, REQUEST_CHANNEL), Arguments.of( - (BiFunction>) + (BiFunction>) (r, p) -> { AtomicBoolean subscribed = new AtomicBoolean(); Flux just = Flux.just(p).doOnSubscribe((__) -> subscribed.set(true)); - return r.socket + return r.channel .requestChannel(just) .doFinally( __ -> { @@ -1206,15 +1206,15 @@ public static Stream streamRacingCases() { } }); }, - (BiFunction>) - (r, p) -> r.socket.fireAndForget(p), + (BiFunction>) + (r, p) -> r.channel.fireAndForget(p), REQUEST_CHANNEL, REQUEST_FNF), Arguments.of( - (BiFunction>) - (r, p) -> r.socket.metadataPush(p), - (BiFunction>) - (r, p) -> r.socket.fireAndForget(p), + (BiFunction>) + (r, p) -> r.channel.metadataPush(p), + (BiFunction>) + (r, p) -> r.channel.fireAndForget(p), METADATA_PUSH, REQUEST_FNF)); } @@ -1223,8 +1223,8 @@ public static Stream streamRacingCases() { @MethodSource("streamRacingCases") @SuppressWarnings({ "rawtypes", "unchecked" }) public void shouldTerminateAllStreamsIfThereRacingBetweenDisposeAndRequests( - BiFunction> interaction1, - BiFunction> interaction2, + BiFunction> interaction1, + BiFunction> interaction2, FrameType interactionType1, FrameType interactionType2) { for (int i = 1; i < RaceTestConstants.REPEATS; i++) { @@ -1235,7 +1235,7 @@ public void shouldTerminateAllStreamsIfThereRacingBetweenDisposeAndRequests( Publisher publisher1 = interaction1.apply(rule, payload1); Publisher publisher2 = interaction2.apply(rule, payload2); RaceTestUtils.race( - () -> rule.socket.dispose(), + () -> rule.channel.dispose(), () -> publisher1.subscribe(assertSubscriber1), () -> publisher2.subscribe(assertSubscriber2)); @@ -1279,7 +1279,7 @@ public void testWorkaround858() { ByteBuf buffer = rule.alloc().buffer(); buffer.writeCharSequence("test", CharsetUtil.UTF_8); - rule.socket.requestResponse(ByteBufPayload.create(buffer)).subscribe(); + rule.channel.requestResponse(ByteBufPayload.create(buffer)).subscribe(); rule.connection.addToReceivedBuffer( ErrorFrameCodec.encode(rule.alloc(), 1, new RuntimeException("test"))); @@ -1290,7 +1290,7 @@ public void testWorkaround858() { .matches(bb -> FrameHeaderCodec.frameType(bb) == REQUEST_RESPONSE) .matches(ByteBuf::release); - assertThat(rule.socket.isDisposed()).isFalse(); + assertThat(rule.channel.isDisposed()).isFalse(); rule.assertHasNoLeaks(); } @@ -1300,7 +1300,7 @@ public void testWorkaround858() { @MethodSource("requestNInteractions") void reassembleData( FrameType frameType, - BiFunction> requestFunction) { + BiFunction> requestFunction) { final int mtu = ThreadLocalRandom.current().nextInt(64, 256); final LeaksTrackingByteBufAllocator leaksTrackingByteBufAllocator = LeaksTrackingByteBufAllocator.instrument(ByteBufAllocator.DEFAULT); @@ -1337,7 +1337,7 @@ void reassembleData( @MethodSource("requestNInteractions") void reassembleMetadata( FrameType frameType, - BiFunction> requestFunction) { + BiFunction> requestFunction) { final int mtu = ThreadLocalRandom.current().nextInt(64, 256); final LeaksTrackingByteBufAllocator leaksTrackingByteBufAllocator = LeaksTrackingByteBufAllocator.instrument(ByteBufAllocator.DEFAULT); @@ -1374,7 +1374,7 @@ void reassembleMetadata( @MethodSource("requestNInteractions") public void errorTooBigPayload( FrameType frameType, - BiFunction> requestFunction) { + BiFunction> requestFunction) { final int mtu = ThreadLocalRandom.current().nextInt(64, 256); final int maxInboundPayloadSize = ThreadLocalRandom.current().nextInt(mtu + 1, 4096); final LeaksTrackingByteBufAllocator leaksTrackingByteBufAllocator = @@ -1408,7 +1408,7 @@ public void errorTooBigPayload( @MethodSource("requestNInteractions") public void errorFragmentTooSmall( FrameType frameType, - BiFunction> requestFunction) { + BiFunction> requestFunction) { final int mtu = 32; final LeaksTrackingByteBufAllocator leaksTrackingByteBufAllocator = LeaksTrackingByteBufAllocator.instrument(ByteBufAllocator.DEFAULT); @@ -1443,10 +1443,10 @@ public void testWorkaround959(String type) { final AssertSubscriber assertSubscriber = new AssertSubscriber<>(3); if (type.equals("stream")) { - rule.socket.requestStream(ByteBufPayload.create(buffer)).subscribe(assertSubscriber); + rule.channel.requestStream(ByteBufPayload.create(buffer)).subscribe(assertSubscriber); } else if (type.equals("channel")) { - rule.socket + rule.channel .requestChannel(Flux.just(ByteBufPayload.create(buffer))) .subscribe(assertSubscriber); } @@ -1469,7 +1469,7 @@ else if (type.equals("channel")) { assertThat(rule.connection.getSent()).allMatch(ByteBuf::release); - assertThat(rule.socket.isDisposed()).isFalse(); + assertThat(rule.channel.isDisposed()).isFalse(); assertSubscriber.values().forEach(ReferenceCountUtil::safeRelease); assertSubscriber.assertNoError(); @@ -1479,7 +1479,7 @@ else if (type.equals("channel")) { } } - public static class ClientSocketRule extends AbstractSocketRule { + public static class ClientChannelRule extends AbstractChannelRule { protected Sinks.Empty thisClosedSink; protected Sinks.Empty otherClosedSink; diff --git a/today-remoting/src/test/java/infra/remoting/core/ChannelResponderTests.java b/today-remoting/src/test/java/infra/remoting/core/ChannelResponderTests.java index ca7c3e9..0cc9a37 100644 --- a/today-remoting/src/test/java/infra/remoting/core/ChannelResponderTests.java +++ b/today-remoting/src/test/java/infra/remoting/core/ChannelResponderTests.java @@ -102,13 +102,13 @@ public class ChannelResponderTests { - ServerSocketRule rule; + ServerChannelRule rule; @BeforeEach public void setUp() { Hooks.onNextDropped(ReferenceCountUtil::safeRelease); Hooks.onErrorDropped(t -> { }); - rule = new ServerSocketRule(); + rule = new ServerChannelRule(); rule.init(); } @@ -840,7 +840,7 @@ public Flux requestChannel(Publisher payloads) { .matches(bb -> FrameHeaderCodec.frameType(bb) == REQUEST_N) .matches(ReferenceCounted::release); - assertThat(rule.socket.isDisposed()).isFalse(); + assertThat(rule.channel.isDisposed()).isFalse(); testPublisher.assertWasCancelled(); rule.assertHasNoLeaks(); @@ -1182,7 +1182,7 @@ public Flux requestChannel(Publisher payloads) { rule.assertHasNoLeaks(); } - public static class ServerSocketRule extends AbstractSocketRule { + public static class ServerChannelRule extends AbstractChannelRule { private Channel acceptingSocket; private volatile int prefetch; diff --git a/today-remoting/src/test/java/infra/remoting/core/ChannelTests.java b/today-remoting/src/test/java/infra/remoting/core/ChannelTests.java index 64a2ef2..20730d7 100644 --- a/today-remoting/src/test/java/infra/remoting/core/ChannelTests.java +++ b/today-remoting/src/test/java/infra/remoting/core/ChannelTests.java @@ -53,7 +53,7 @@ public class ChannelTests { - public final SocketRule rule = new SocketRule(); + public final ChannelRule rule = new ChannelRule(); @BeforeEach public void setup() { @@ -506,7 +506,7 @@ void errorFromRequesterPublisher( responderPublisher.assertNoSubscribers(); } - public static class SocketRule { + public static class ChannelRule { Sinks.Many serverProcessor; Sinks.Many clientProcessor; diff --git a/today-remoting/src/test/java/infra/remoting/core/DefaultChannelClientTests.java b/today-remoting/src/test/java/infra/remoting/core/DefaultChannelClientTests.java index e684ac2..7eed620 100644 --- a/today-remoting/src/test/java/infra/remoting/core/DefaultChannelClientTests.java +++ b/today-remoting/src/test/java/infra/remoting/core/DefaultChannelClientTests.java @@ -71,13 +71,13 @@ public class DefaultChannelClientTests { - ClientSocketRule rule; + ClientChannelRule rule; @BeforeEach public void setUp() throws Throwable { Hooks.onNextDropped(ReferenceCountUtil::safeRelease); Hooks.onErrorDropped((t) -> { }); - rule = new ClientSocketRule(); + rule = new ClientChannelRule(); rule.init(); } @@ -201,7 +201,7 @@ public void shouldHaveNoLeaksOnPayloadInCaseOfRacingOfOnNextAndCancel( Assumptions.assumeThat(requestType).isNotEqualTo(FrameType.REQUEST_CHANNEL); for (int i = 0; i < RaceTestConstants.REPEATS; i++) { - ClientSocketRule rule = new ClientSocketRule(); + ClientChannelRule rule = new ClientChannelRule(); rule.init(); Payload payload = ByteBufPayload.create("test", "testMetadata"); TestPublisher testPublisher = @@ -258,7 +258,7 @@ public void shouldHaveNoLeaksOnPayloadInCaseOfRacingOfRequestAndCancel( Assumptions.assumeThat(requestType).isNotEqualTo(FrameType.REQUEST_CHANNEL); for (int i = 0; i < RaceTestConstants.REPEATS; i++) { - ClientSocketRule rule = new ClientSocketRule(); + ClientChannelRule rule = new ClientChannelRule(); rule.init(); ByteBuf dataBuffer = rule.allocator.buffer(); dataBuffer.writeCharSequence("test", CharsetUtil.UTF_8); @@ -496,7 +496,7 @@ public void shouldDisposeOriginalSource() { .assertError(CancellationException.class) .assertErrorMessage("Disposed"); - Assertions.assertThat(rule.socket.isDisposed()).isTrue(); + Assertions.assertThat(rule.channel.isDisposed()).isTrue(); FrameAssert.assertThat(rule.connection.awaitFrame()) .hasStreamIdZero() @@ -509,8 +509,8 @@ public void shouldDisposeOriginalSource() { @Test public void shouldReceiveOnCloseNotificationOnDisposeOriginalSource() { Sinks.Empty onCloseDelayer = Sinks.empty(); - ClientSocketRule rule = - new ClientSocketRule() { + ClientChannelRule rule = + new ClientChannelRule() { @Override protected Channel newChannel() { return new ChannelDecorator(super.newChannel()) { @@ -540,7 +540,7 @@ public Mono onClose() { onCloseSubscriber.assertTerminated().assertComplete(); - Assertions.assertThat(rule.socket.isDisposed()).isTrue(); + Assertions.assertThat(rule.channel.isDisposed()).isTrue(); FrameAssert.assertThat(rule.connection.awaitFrame()) .hasStreamIdZero() @@ -568,7 +568,7 @@ public void shouldResolveOnStartSource() { assertSubscriber1.assertTerminated().assertComplete(); - Assertions.assertThat(rule.socket.isDisposed()).isTrue(); + Assertions.assertThat(rule.channel.isDisposed()).isTrue(); FrameAssert.assertThat(rule.connection.awaitFrame()) .hasStreamIdZero() @@ -596,7 +596,7 @@ public void shouldNotStartIfAlreadyDisposed() { assertSubscriber1.assertTerminated().assertComplete(); - Assertions.assertThat(rule.socket.isDisposed()).isTrue(); + Assertions.assertThat(rule.channel.isDisposed()).isTrue(); FrameAssert.assertThat(rule.connection.awaitFrame()) .hasStreamIdZero() @@ -619,7 +619,7 @@ public void shouldBeRestartedIfSourceWasClosed() { assertSubscriber.assertTerminated().assertValueCount(1); - rule.socket.dispose(); + rule.channel.dispose(); FrameAssert.assertThat(rule.connection.awaitFrame()) .hasStreamIdZero() @@ -630,7 +630,7 @@ public void shouldBeRestartedIfSourceWasClosed() { Assertions.assertThat(rule.client.isDisposed()).isFalse(); rule.connection = new TestDuplexConnection(rule.allocator); - rule.socket = rule.newChannel(); + rule.channel = rule.newChannel(); rule.producer = Sinks.one(); AssertSubscriber assertSubscriber2 = AssertSubscriber.create(); @@ -648,7 +648,7 @@ public void shouldBeRestartedIfSourceWasClosed() { Assertions.assertThat(rule.client.connect()).isFalse(); - Assertions.assertThat(rule.socket.isDisposed()).isTrue(); + Assertions.assertThat(rule.channel.isDisposed()).isTrue(); FrameAssert.assertThat(rule.connection.awaitFrame()) .hasStreamIdZero() @@ -661,7 +661,7 @@ public void shouldBeRestartedIfSourceWasClosed() { @Test public void shouldDisposeOriginalSourceIfRacing() { for (int i = 0; i < RaceTestConstants.REPEATS; i++) { - ClientSocketRule rule = new ClientSocketRule(); + ClientChannelRule rule = new ClientChannelRule(); rule.init(); @@ -673,7 +673,7 @@ public void shouldDisposeOriginalSourceIfRacing() { assertSubscriber.assertTerminated(); Assertions.assertThat(rule.client.isDisposed()).isTrue(); - Assertions.assertThat(rule.socket.isDisposed()).isTrue(); + Assertions.assertThat(rule.channel.isDisposed()).isTrue(); AssertSubscriber assertSubscriber1 = AssertSubscriber.create(); @@ -696,7 +696,7 @@ public void shouldDisposeOriginalSourceIfRacing() { @Test public void shouldStartOriginalSourceOnceIfRacing() { for (int i = 0; i < RaceTestConstants.REPEATS; i++) { - ClientSocketRule rule = new ClientSocketRule(); + ClientChannelRule rule = new ClientChannelRule(); rule.init(); @@ -714,7 +714,7 @@ public void shouldStartOriginalSourceOnceIfRacing() { rule.client.dispose(); Assertions.assertThat(rule.client.isDisposed()).isTrue(); - Assertions.assertThat(rule.socket.isDisposed()).isTrue(); + Assertions.assertThat(rule.channel.isDisposed()).isTrue(); AssertSubscriber assertSubscriber1 = AssertSubscriber.create(); @@ -730,7 +730,7 @@ public void shouldStartOriginalSourceOnceIfRacing() { } } - public static class ClientSocketRule extends AbstractSocketRule { + public static class ClientChannelRule extends AbstractChannelRule { protected RemotingClient client; protected Runnable delayer; @@ -741,7 +741,7 @@ public static class ClientSocketRule extends AbstractSocketRule { @Override protected void doInit() { super.doInit(); - delayer = () -> producer.tryEmitValue(socket); + delayer = () -> producer.tryEmitValue(channel); producer = Sinks.one(); client = new DefaultRemotingClient( @@ -749,7 +749,7 @@ protected void doInit() { () -> producer .asMono() - .doOnCancel(() -> socket.dispose()) + .doOnCancel(() -> channel.dispose()) .doOnDiscard(Disposable.class, Disposable::dispose))); } From 0c2c4e13a06ba5c0494a73870cc9de0f1eb54b51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Sun, 3 Aug 2025 17:18:23 +0800 Subject: [PATCH 005/104] :art: --- settings.gradle | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/settings.gradle b/settings.gradle index f1bbd1c..d79dd93 100644 --- a/settings.gradle +++ b/settings.gradle @@ -6,6 +6,20 @@ pluginManagement { } } +plugins { + id("com.gradle.enterprise") version("3.14.1") +} + +gradleEnterprise { + if (System.getenv("CI") != null || Boolean.getBoolean("CI")) { + buildScan { + publishAlways() + termsOfServiceUrl = "https://gradle.com/terms-of-service" + termsOfServiceAgree = "yes" + } + } +} + // A Java library for studying to create a microservices framework like Spring Cloud. rootProject.name = 'today-cloud' From d153f5067f06e0dafc82ac54ef42ca55fe1814fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Sun, 3 Aug 2025 17:19:22 +0800 Subject: [PATCH 006/104] :construction: --- .github/workflows/ci.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 56c0b06..5b3a56e 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -26,6 +26,8 @@ jobs: matrix: os: [ ubuntu-latest, macOS-latest ] #, windows-latest java: + - version: 17 + - toolchain: false - version: 21 toolchain: true - version: 24 From c2a71f574c3fd6ec3140b0417a9c313872bd4ae2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Sun, 3 Aug 2025 17:23:05 +0800 Subject: [PATCH 007/104] :art: --- .../test/java/infra/config/etcd/EtcdPropertySourceTests.java | 2 ++ .../src/test/java/infra/config/etcd/EtcdTests.java | 2 ++ 2 files changed, 4 insertions(+) diff --git a/today-cloud-config-server-etcd/src/test/java/infra/config/etcd/EtcdPropertySourceTests.java b/today-cloud-config-server-etcd/src/test/java/infra/config/etcd/EtcdPropertySourceTests.java index 31237f1..31e7234 100644 --- a/today-cloud-config-server-etcd/src/test/java/infra/config/etcd/EtcdPropertySourceTests.java +++ b/today-cloud-config-server-etcd/src/test/java/infra/config/etcd/EtcdPropertySourceTests.java @@ -17,6 +17,7 @@ package infra.config.etcd; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import java.nio.charset.StandardCharsets; @@ -32,6 +33,7 @@ * @author Harry Yang * @since 1.0 2023/10/6 22:20 */ +@Disabled class EtcdPropertySourceTests { @Test diff --git a/today-cloud-config-server-etcd/src/test/java/infra/config/etcd/EtcdTests.java b/today-cloud-config-server-etcd/src/test/java/infra/config/etcd/EtcdTests.java index 0c3790d..70174e0 100644 --- a/today-cloud-config-server-etcd/src/test/java/infra/config/etcd/EtcdTests.java +++ b/today-cloud-config-server-etcd/src/test/java/infra/config/etcd/EtcdTests.java @@ -17,6 +17,7 @@ package infra.config.etcd; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import java.nio.charset.StandardCharsets; @@ -31,6 +32,7 @@ * @author Harry Yang * @since 1.0 2023/10/6 20:40 */ +@Disabled class EtcdTests { @Test From 95993df255cad25978a3fc558fc52d50b44aecff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Sun, 3 Aug 2025 17:27:05 +0800 Subject: [PATCH 008/104] :construction: --- .github/workflows/ci.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 5b3a56e..3e9adf4 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -27,7 +27,7 @@ jobs: os: [ ubuntu-latest, macOS-latest ] #, windows-latest java: - version: 17 - - toolchain: false + - toolchain: true - version: 21 toolchain: true - version: 24 From f7db32a97e20cf1d4b4498dfa8fdf533dac3589d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Sun, 3 Aug 2025 17:28:21 +0800 Subject: [PATCH 009/104] :construction: --- .github/workflows/ci.yaml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 3e9adf4..56c0b06 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -26,8 +26,6 @@ jobs: matrix: os: [ ubuntu-latest, macOS-latest ] #, windows-latest java: - - version: 17 - - toolchain: true - version: 21 toolchain: true - version: 24 From 6dbeb87a86be5214bf3b1ffacab740fee01139e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Sun, 3 Aug 2025 17:31:04 +0800 Subject: [PATCH 010/104] :art: --- build.gradle | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/build.gradle b/build.gradle index 6e357c7..51f4188 100644 --- a/build.gradle +++ b/build.gradle @@ -51,10 +51,15 @@ configure(javaProjects) { testImplementation 'org.projectlombok:lombok' testAnnotationProcessor("org.projectlombok:lombok") - // Pull in the latest JUnit 5 Launcher API to ensure proper support in IDEs. - testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine") - testRuntimeOnly("org.junit.platform:junit-platform-launcher") - testRuntimeOnly("org.junit.platform:junit-platform-suite-engine") + // 去除 测试警告 + testRuntimeOnly("com.google.code.findbugs:jsr305") + testRuntimeOnly("com.google.code.findbugs:findbugs") + testRuntimeOnly('org.jboss.logging:jboss-logging:3.5.3.Final') + + // JSR-305 only used for non-required meta-annotations + compileOnly("com.google.code.findbugs:jsr305") + compileOnly("com.google.code.findbugs:findbugs") + compileOnly('org.jboss.logging:jboss-logging:3.5.3.Final') } } From 418a52996074b245f44b27458898192b55d39d51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Sun, 3 Aug 2025 17:34:20 +0800 Subject: [PATCH 011/104] :art: --- buildSrc/src/main/java/infra/cloud/TestConventions.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/buildSrc/src/main/java/infra/cloud/TestConventions.java b/buildSrc/src/main/java/infra/cloud/TestConventions.java index 117b6e9..0f1e29a 100644 --- a/buildSrc/src/main/java/infra/cloud/TestConventions.java +++ b/buildSrc/src/main/java/infra/cloud/TestConventions.java @@ -57,10 +57,7 @@ private void configureTests(Project project, Test test) { test.include("**/*Tests.class", "**/*Test.class"); test.setSystemProperties(Map.of( "java.awt.headless", "true", - "io.netty.leakDetection.level", "paranoid", - "io.netty5.leakDetectionLevel", "paranoid", - "io.netty5.leakDetection.targetRecords", "32", - "io.netty5.buffer.lifecycleTracingEnabled", "true" + "io.netty.leakDetection.level", "paranoid" )); if (project.hasProperty("testGroups")) { test.systemProperty("testGroups", project.getProperties().get("testGroups")); From 7988b3a4a07945458471d851da1024b582f48974 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Sun, 3 Aug 2025 17:36:36 +0800 Subject: [PATCH 012/104] :art: --- build.gradle | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/build.gradle b/build.gradle index 51f4188..b7836e4 100644 --- a/build.gradle +++ b/build.gradle @@ -51,6 +51,11 @@ configure(javaProjects) { testImplementation 'org.projectlombok:lombok' testAnnotationProcessor("org.projectlombok:lombok") + // Pull in the latest JUnit 5 Launcher API to ensure proper support in IDEs. + testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine") + testRuntimeOnly("org.junit.platform:junit-platform-launcher") + testRuntimeOnly("org.junit.platform:junit-platform-suite-engine") + // 去除 测试警告 testRuntimeOnly("com.google.code.findbugs:jsr305") testRuntimeOnly("com.google.code.findbugs:findbugs") From 709ac131b28584fef2466261164103bb0d9e77ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Sun, 3 Aug 2025 17:37:43 +0800 Subject: [PATCH 013/104] :art: --- today-remoting-transport-local/build.gradle | 3 --- today-remoting-transport-tcp/build.gradle | 1 - 2 files changed, 4 deletions(-) diff --git a/today-remoting-transport-local/build.gradle b/today-remoting-transport-local/build.gradle index bc8b32d..9e11908 100644 --- a/today-remoting-transport-local/build.gradle +++ b/today-remoting-transport-local/build.gradle @@ -28,11 +28,8 @@ dependencies { api project(':today-remoting') testImplementation 'io.projectreactor:reactor-test' - testImplementation 'org.assertj:assertj-core' - testImplementation 'org.junit.jupiter:junit-jupiter-api' testRuntimeOnly 'ch.qos.logback:logback-classic' - testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine' testImplementation testFixtures(project(":today-remoting")) } diff --git a/today-remoting-transport-tcp/build.gradle b/today-remoting-transport-tcp/build.gradle index 9689833..195a1b3 100644 --- a/today-remoting-transport-tcp/build.gradle +++ b/today-remoting-transport-tcp/build.gradle @@ -28,7 +28,6 @@ dependencies { testRuntimeOnly 'org.bouncycastle:bcpkix-jdk15on:1.70' testRuntimeOnly 'ch.qos.logback:logback-classic' - testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine' testRuntimeOnly 'io.netty:netty-tcnative-boringssl-static' + os_suffix testImplementation testFixtures(project(":today-remoting")) From c6a0ce2ec52cf5b805c643a8e7eef7f8e0745a65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Sun, 3 Aug 2025 21:16:48 +0800 Subject: [PATCH 014/104] :art: --- .github/actions/building/action.yml | 2 +- buildSrc/build.gradle | 1 - settings.gradle | 26 +++++++++++++------------- 3 files changed, 14 insertions(+), 15 deletions(-) diff --git a/.github/actions/building/action.yml b/.github/actions/building/action.yml index d9550c5..b79723a 100644 --- a/.github/actions/building/action.yml +++ b/.github/actions/building/action.yml @@ -85,7 +85,7 @@ runs: id: build if: ${{ inputs.publish == 'false' }} shell: bash - run: ./gradlew -DCI=true --no-daemon --no-parallel check --scan + run: ./gradlew -DCI=true --no-daemon --no-parallel check #--scan - name: Publish id: publish diff --git a/buildSrc/build.gradle b/buildSrc/build.gradle index ddb17f0..e540677 100644 --- a/buildSrc/build.gradle +++ b/buildSrc/build.gradle @@ -32,7 +32,6 @@ dependencies { implementation "cn.taketoday:today-core" implementation "cn.taketoday:infra-gradle-plugin" implementation "org.gradle:test-retry-gradle-plugin:1.4.1" - implementation "org.apache.maven:maven-artifact:3.6.3" } gradlePlugin { diff --git a/settings.gradle b/settings.gradle index d79dd93..a35e74f 100644 --- a/settings.gradle +++ b/settings.gradle @@ -6,19 +6,19 @@ pluginManagement { } } -plugins { - id("com.gradle.enterprise") version("3.14.1") -} - -gradleEnterprise { - if (System.getenv("CI") != null || Boolean.getBoolean("CI")) { - buildScan { - publishAlways() - termsOfServiceUrl = "https://gradle.com/terms-of-service" - termsOfServiceAgree = "yes" - } - } -} +//plugins { +// id("com.gradle.enterprise") version("3.14.1") +//} +// +//gradleEnterprise { +// if (System.getenv("CI") != null || Boolean.getBoolean("CI")) { +// buildScan { +// publishAlways() +// termsOfServiceUrl = "https://gradle.com/terms-of-service" +// termsOfServiceAgree = "yes" +// } +// } +//} // A Java library for studying to create a microservices framework like Spring Cloud. From a90ef366a869831fd66964fecdaf2f88b49ddc38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Sun, 3 Aug 2025 21:28:01 +0800 Subject: [PATCH 015/104] :art: --- .../src/main/java/infra/remoting/core/ChannelConnector.java | 5 ++--- .../src/main/java/infra/remoting/core/ChannelResponder.java | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/today-remoting/src/main/java/infra/remoting/core/ChannelConnector.java b/today-remoting/src/main/java/infra/remoting/core/ChannelConnector.java index 2d836f6..1f970dd 100644 --- a/today-remoting/src/main/java/infra/remoting/core/ChannelConnector.java +++ b/today-remoting/src/main/java/infra/remoting/core/ChannelConnector.java @@ -73,9 +73,8 @@ *

    To customize connection settings before connecting: * *

    {@code
    - * Mono source =
    - *        ChannelConnector.create()
    - *                 .connect(TcpClientTransport.create("localhost", 7000));
    + * Mono source = ChannelConnector.create()
    + *      .connect(TcpClientTransport.create("localhost", 7000));
      * RemotingClient client = RemotingClient.from(source);
      * }
    */ diff --git a/today-remoting/src/main/java/infra/remoting/core/ChannelResponder.java b/today-remoting/src/main/java/infra/remoting/core/ChannelResponder.java index 1574ac7..071f0e9 100644 --- a/today-remoting/src/main/java/infra/remoting/core/ChannelResponder.java +++ b/today-remoting/src/main/java/infra/remoting/core/ChannelResponder.java @@ -429,7 +429,7 @@ final void handleChannel(int streamId, ByteBuf frame, long initialRequestN, bool } private void sendLeaseRejection(int streamId, Throwable leaseError) { - connection.sendFrame(streamId, ErrorFrameCodec.encode(getAllocator(), streamId, leaseError)); + connection.sendFrame(streamId, ErrorFrameCodec.encode(allocator, streamId, leaseError)); } private void handleMetadataPush(Mono result) { From e6efdc67d1d94c0691ca44e9d2258d47058bccb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Sun, 3 Aug 2025 22:35:28 +0800 Subject: [PATCH 016/104] :art: --- .../src/main/java/infra/remoting/Channel.java | 4 +- .../infra/remoting/core/ChannelRequester.java | 2 +- .../infra/remoting/core/ChannelResponder.java | 2 +- ...ponderSupport.java => ChannelSupport.java} | 22 +-- .../remoting/core/DefaultRemotingClient.java | 140 +++++++-------- .../core/FireAndForgetRequesterMono.java | 79 +++----- .../FireAndForgetResponderSubscriber.java | 44 +++-- .../core/MetadataPushRequesterMono.java | 31 ++-- .../core/RequestChannelRequesterFlux.java | 124 ++++++------- .../RequestChannelResponderSubscriber.java | 54 +++--- .../core/RequestResponseRequesterMono.java | 85 ++++----- .../RequestResponseResponderSubscriber.java | 48 ++--- .../core/RequestStreamRequesterFlux.java | 94 ++++------ .../RequestStreamResponderSubscriber.java | 54 +++--- .../java/infra/remoting/core/SendUtils.java | 168 +++++------------- .../core/SlowFireAndForgetRequesterMono.java | 44 ++--- .../remoting/core/ChannelRequesterTests.java | 10 +- .../remoting/core/ChannelResponderTests.java | 18 +- .../core/FireAndForgetRequesterMonoTest.java | 28 +-- .../core/RequestChannelRequesterFluxTest.java | 52 +++--- ...RequestChannelResponderSubscriberTest.java | 60 +++---- .../RequestResponseRequesterMonoTest.java | 44 ++--- .../core/RequestStreamRequesterFluxTest.java | 68 +++---- .../core/RequesterOperatorsRacingTest.java | 120 ++++++------- .../core/ResponderOperatorsCommonTest.java | 42 ++--- ...erSupport.java => TestChannelSupport.java} | 32 ++-- 26 files changed, 643 insertions(+), 826 deletions(-) rename today-remoting/src/main/java/infra/remoting/core/{RequesterResponderSupport.java => ChannelSupport.java} (89%) rename today-remoting/src/test/java/infra/remoting/core/{TestRequesterResponderSupport.java => TestChannelSupport.java} (88%) diff --git a/today-remoting/src/main/java/infra/remoting/Channel.java b/today-remoting/src/main/java/infra/remoting/Channel.java index d1513e7..464883d 100644 --- a/today-remoting/src/main/java/infra/remoting/Channel.java +++ b/today-remoting/src/main/java/infra/remoting/Channel.java @@ -89,7 +89,8 @@ default double availability() { } @Override - default void dispose() { } + default void dispose() { + } @Override default boolean isDisposed() { @@ -100,4 +101,5 @@ default boolean isDisposed() { default Mono onClose() { return Mono.never(); } + } diff --git a/today-remoting/src/main/java/infra/remoting/core/ChannelRequester.java b/today-remoting/src/main/java/infra/remoting/core/ChannelRequester.java index 321180e..37821c7 100644 --- a/today-remoting/src/main/java/infra/remoting/core/ChannelRequester.java +++ b/today-remoting/src/main/java/infra/remoting/core/ChannelRequester.java @@ -53,7 +53,7 @@ /** * Requester Side of a Channel socket. Sends {@link ByteBuf}s to a {@link ChannelResponder} of peer */ -class ChannelRequester extends RequesterResponderSupport implements Channel { +class ChannelRequester extends ChannelSupport implements Channel { private static final Logger LOGGER = LoggerFactory.getLogger(ChannelRequester.class); diff --git a/today-remoting/src/main/java/infra/remoting/core/ChannelResponder.java b/today-remoting/src/main/java/infra/remoting/core/ChannelResponder.java index 071f0e9..1e46c17 100644 --- a/today-remoting/src/main/java/infra/remoting/core/ChannelResponder.java +++ b/today-remoting/src/main/java/infra/remoting/core/ChannelResponder.java @@ -52,7 +52,7 @@ /** * Responder side of Channel. Receives {@link ByteBuf}s from a peer's {@link ChannelRequester} */ -class ChannelResponder extends RequesterResponderSupport implements Channel { +class ChannelResponder extends ChannelSupport implements Channel { private static final Logger LOGGER = LoggerFactory.getLogger(ChannelResponder.class); diff --git a/today-remoting/src/main/java/infra/remoting/core/RequesterResponderSupport.java b/today-remoting/src/main/java/infra/remoting/core/ChannelSupport.java similarity index 89% rename from today-remoting/src/main/java/infra/remoting/core/RequesterResponderSupport.java rename to today-remoting/src/main/java/infra/remoting/core/ChannelSupport.java index 10fc23c..79130fd 100644 --- a/today-remoting/src/main/java/infra/remoting/core/RequesterResponderSupport.java +++ b/today-remoting/src/main/java/infra/remoting/core/ChannelSupport.java @@ -29,29 +29,29 @@ import io.netty.util.collection.IntObjectHashMap; import io.netty.util.collection.IntObjectMap; -class RequesterResponderSupport { +class ChannelSupport { - protected final int mtu; + public final int mtu; - protected final int maxFrameLength; + public final int maxFrameLength; - protected final int maxInboundPayloadSize; + public final int maxInboundPayloadSize; - protected final PayloadDecoder payloadDecoder; + public final PayloadDecoder payloadDecoder; - protected final ByteBufAllocator allocator; + public final ByteBufAllocator allocator; - protected final DuplexConnection connection; + public final DuplexConnection connection; @Nullable - protected final RequestInterceptor requestInterceptor; + public final RequestInterceptor requestInterceptor; @Nullable protected final StreamIdProvider streamIdProvider; protected final IntObjectMap activeStreams; - public RequesterResponderSupport(int mtu, int maxFrameLength, int maxInboundPayloadSize, + public ChannelSupport(int mtu, int maxFrameLength, int maxInboundPayloadSize, PayloadDecoder payloadDecoder, DuplexConnection connection, @Nullable StreamIdProvider streamIdProvider, Function requestInterceptorFunction) { @@ -104,7 +104,7 @@ public RequestInterceptor getRequestInterceptor() { * Issues next {@code streamId} * * @return issued {@code streamId} - * @throws RuntimeException if the {@link RequesterResponderSupport} is terminated for any reason + * @throws RuntimeException if the {@link ChannelSupport} is terminated for any reason */ public int getNextStreamId() { final StreamIdProvider streamIdProvider = this.streamIdProvider; @@ -123,7 +123,7 @@ public int getNextStreamId() { * * @param frameHandler to store * @return issued {@code streamId} - * @throws RuntimeException if the {@link RequesterResponderSupport} is terminated for any reason + * @throws RuntimeException if the {@link ChannelSupport} is terminated for any reason */ public int addAndGetNextStreamId(FrameHandler frameHandler) { final StreamIdProvider streamIdProvider = this.streamIdProvider; diff --git a/today-remoting/src/main/java/infra/remoting/core/DefaultRemotingClient.java b/today-remoting/src/main/java/infra/remoting/core/DefaultRemotingClient.java index a3b9fbd..9e85a36 100644 --- a/today-remoting/src/main/java/infra/remoting/core/DefaultRemotingClient.java +++ b/today-remoting/src/main/java/infra/remoting/core/DefaultRemotingClient.java @@ -88,7 +88,7 @@ private Mono unwrapReconnectMono(Mono source) { @Override public Mono onClose() { - return this.onDisposeSink.asMono(); + return onDisposeSink.asMono(); } @Override @@ -128,7 +128,7 @@ public void subscribe(CoreSubscriber actual) { new ResolvingOperator.MonoDeferredResolutionOperator<>(this, actual); actual.onSubscribe(inner); - this.observe(inner); + observe(inner); } @Override @@ -149,15 +149,15 @@ public void onComplete() { final Channel value = this.value; if (s == Operators.cancelledSubscription() || !S.compareAndSet(this, s, null)) { - this.doFinally(); + doFinally(); return; } if (value == null) { - this.terminate(new IllegalStateException("Source completed empty")); + terminate(new IllegalStateException("Source completed empty")); } else { - this.complete(value); + complete(value); } } @@ -168,36 +168,36 @@ public void onError(Throwable t) { if (s == Operators.cancelledSubscription() || S.getAndSet(this, Operators.cancelledSubscription()) == Operators.cancelledSubscription()) { - this.doFinally(); + doFinally(); Operators.onErrorDropped(t, Context.empty()); return; } - this.doFinally(); + doFinally(); // terminate upstream which means retryBackoff has exhausted - this.terminate(t); + terminate(t); } @Override public void onNext(Channel value) { if (this.s == Operators.cancelledSubscription()) { - this.doOnValueExpired(value); + doOnValueExpired(value); return; } this.value = value; // volatile write and check on racing - this.doFinally(); + doFinally(); } @Override protected void doSubscribe() { - this.source.subscribe(this); + source.subscribe(this); } @Override protected void doOnValueResolved(Channel value) { - value.onClose().subscribe(null, t -> this.invalidate(), this::invalidate); + value.onClose().subscribe(null, t -> invalidate(), this::invalidate); } @Override @@ -219,17 +219,16 @@ protected void doOnDispose() { static final class FlatMapMain implements CoreSubscriber, Context, Scannable { - final DefaultRemotingClient parent; - final CoreSubscriber actual; + private final DefaultRemotingClient parent; + private final CoreSubscriber actual; - final FlattingInner second; + private final FlattingInner second; - Subscription s; + private Subscription s; - boolean done; + private boolean done; - FlatMapMain( - DefaultRemotingClient parent, CoreSubscriber actual, FrameType requestType) { + FlatMapMain(DefaultRemotingClient parent, CoreSubscriber actual, FrameType requestType) { this.parent = parent; this.actual = actual; this.second = new FlattingInner<>(parent, this, actual, requestType); @@ -242,18 +241,18 @@ public Context currentContext() { @Override public Stream inners() { - return Stream.of(this.second); + return Stream.of(second); } @Override @Nullable public Object scanUnsafe(Attr key) { if (key == Attr.PARENT) - return this.s; + return s; if (key == Attr.CANCELLED) - return this.second.isCancelled(); + return second.isCancelled(); if (key == Attr.TERMINATED) - return this.done; + return done; return null; } @@ -262,13 +261,13 @@ public Object scanUnsafe(Attr key) { public void onSubscribe(Subscription s) { if (Operators.validate(this.s, s)) { this.s = s; - this.actual.onSubscribe(this.second); + actual.onSubscribe(second); } } @Override public void onNext(Payload payload) { - if (this.done) { + if (done) { if (payload.refCnt() > 0) { try { payload.release(); @@ -311,18 +310,18 @@ public void onNext(Payload payload) { return; } - this.parent.observe(inner); + parent.observe(inner); } @Override public void onError(Throwable t) { - if (this.done) { - Operators.onErrorDropped(t, this.actual.currentContext()); + if (done) { + Operators.onErrorDropped(t, actual.currentContext()); return; } this.done = true; - this.actual.onError(t); + actual.onError(t); } @Override @@ -332,7 +331,7 @@ public void onComplete() { } this.done = true; - this.actual.onComplete(); + actual.onComplete(); } void request(long n) { @@ -349,7 +348,7 @@ public K get(Object key) { if (key == ON_DISCARD_KEY) { return (K) DISCARD_ELEMENTS_CONSUMER; } - return this.actual.currentContext().get(key); + return actual.currentContext().get(key); } @Override @@ -357,12 +356,12 @@ public boolean hasKey(Object key) { if (key == ON_DISCARD_KEY) { return true; } - return this.actual.currentContext().hasKey(key); + return actual.currentContext().hasKey(key); } @Override public Context put(Object key, Object value) { - return this.actual + return actual .currentContext() .put(ON_DISCARD_KEY, DISCARD_ELEMENTS_CONSUMER) .put(key, value); @@ -370,7 +369,7 @@ public Context put(Object key, Object value) { @Override public Context delete(Object key) { - return this.actual + return actual .currentContext() .put(ON_DISCARD_KEY, DISCARD_ELEMENTS_CONSUMER) .delete(key); @@ -378,34 +377,31 @@ public Context delete(Object key) { @Override public int size() { - return this.actual.currentContext().size() + 1; + return actual.currentContext().size() + 1; } @Override public Stream> stream() { return Stream.concat( - Stream.of( - new AbstractMap.SimpleImmutableEntry<>(ON_DISCARD_KEY, DISCARD_ELEMENTS_CONSUMER)), - this.actual.currentContext().stream()); + Stream.of(new AbstractMap.SimpleImmutableEntry<>(ON_DISCARD_KEY, DISCARD_ELEMENTS_CONSUMER)), + actual.currentContext().stream()); } } static final class FlattingInner extends DeferredResolution { - final FlatMapMain main; - final FrameType interactionType; + private final FlatMapMain main; + + private final FrameType interactionType; - volatile Payload payload; + private volatile Payload payload; @SuppressWarnings("rawtypes") static final AtomicReferenceFieldUpdater PAYLOAD = AtomicReferenceFieldUpdater.newUpdater(FlattingInner.class, Payload.class, "payload"); - FlattingInner( - DefaultRemotingClient parent, - FlatMapMain main, - CoreSubscriber actual, - FrameType interactionType) { + FlattingInner(DefaultRemotingClient parent, FlatMapMain main, + CoreSubscriber actual, FrameType interactionType) { super(parent, actual); this.main = main; @@ -415,7 +411,7 @@ static final class FlattingInner extends DeferredResolution { @Override @SuppressWarnings({ "unchecked", "rawtypes" }) public void accept(Channel channel, Throwable t) { - if (this.isCancelled()) { + if (isCancelled()) { return; } @@ -440,7 +436,7 @@ public void accept(Channel channel, Throwable t) { } CorePublisher source; - switch (this.interactionType) { + switch (interactionType) { case REQUEST_FNF: source = channel.fireAndForget(payload); break; @@ -454,7 +450,7 @@ public void accept(Channel channel, Throwable t) { source = channel.metadataPush(payload); break; default: - this.onError(new IllegalStateException("Should never happen")); + onError(new IllegalStateException("Should never happen")); return; } @@ -464,7 +460,7 @@ public void accept(Channel channel, Throwable t) { @Override public void request(long n) { super.request(n); - this.main.request(n); + main.request(n); } public void cancel() { @@ -473,13 +469,13 @@ public void cancel() { return; } - this.main.cancel(); + main.cancel(); if (state == STATE_SUBSCRIBED) { - this.s.cancel(); + s.cancel(); } else { - this.parent.remove(this); + parent.remove(this); Payload payload = PAYLOAD.getAndSet(this, null); if (payload != null) { payload.release(); @@ -490,14 +486,12 @@ public void cancel() { static final class RequestChannelInner extends DeferredResolution { - final FrameType interactionType; - final Publisher upstream; + private final FrameType interactionType; - RequestChannelInner( - DefaultRemotingClient parent, - Publisher upstream, - CoreSubscriber actual, - FrameType interactionType) { + private final Publisher upstream; + + RequestChannelInner(DefaultRemotingClient parent, Publisher upstream, + CoreSubscriber actual, FrameType interactionType) { super(parent, actual); this.upstream = upstream; @@ -506,7 +500,7 @@ static final class RequestChannelInner extends DeferredResolution source; - if (this.interactionType == FrameType.REQUEST_CHANNEL) { - source = channel.requestChannel(this.upstream); + if (interactionType == FrameType.REQUEST_CHANNEL) { + source = channel.requestChannel(upstream); } else { - this.onError(new IllegalStateException("Should never happen")); + onError(new IllegalStateException("Should never happen")); return; } @@ -531,10 +525,10 @@ public void accept(Channel channel, Throwable t) { static class ChannelClientMonoOperator extends MonoOperator { final DefaultRemotingClient parent; + final FrameType requestType; - public ChannelClientMonoOperator( - DefaultRemotingClient parent, FrameType requestType, Mono source) { + public ChannelClientMonoOperator(DefaultRemotingClient parent, FrameType requestType, Mono source) { super(source); this.parent = parent; this.requestType = requestType; @@ -542,18 +536,19 @@ public ChannelClientMonoOperator( @Override public void subscribe(CoreSubscriber actual) { - this.source.subscribe(new FlatMapMain(this.parent, actual, this.requestType)); + source.subscribe(new FlatMapMain(parent, actual, requestType)); } } static class ChannelClientFluxOperator> extends Flux { final DefaultRemotingClient parent; + final FrameType requestType; + final ST source; - public ChannelClientFluxOperator( - DefaultRemotingClient parent, FrameType requestType, ST source) { + public ChannelClientFluxOperator(DefaultRemotingClient parent, FrameType requestType, ST source) { this.parent = parent; this.requestType = requestType; this.source = source; @@ -562,13 +557,12 @@ public ChannelClientFluxOperator( @Override public void subscribe(CoreSubscriber actual) { if (requestType == FrameType.REQUEST_CHANNEL) { - RequestChannelInner inner = - new RequestChannelInner(this.parent, source, actual, requestType); + RequestChannelInner inner = new RequestChannelInner(parent, source, actual, requestType); actual.onSubscribe(inner); - this.parent.observe(inner); + parent.observe(inner); } else { - this.source.subscribe(new FlatMapMain<>(this.parent, actual, this.requestType)); + source.subscribe(new FlatMapMain<>(parent, actual, requestType)); } } } diff --git a/today-remoting/src/main/java/infra/remoting/core/FireAndForgetRequesterMono.java b/today-remoting/src/main/java/infra/remoting/core/FireAndForgetRequesterMono.java index 0f2268c..d58a0da 100644 --- a/today-remoting/src/main/java/infra/remoting/core/FireAndForgetRequesterMono.java +++ b/today-remoting/src/main/java/infra/remoting/core/FireAndForgetRequesterMono.java @@ -23,11 +23,9 @@ import infra.lang.NonNull; import infra.lang.Nullable; -import infra.remoting.DuplexConnection; import infra.remoting.Payload; import infra.remoting.frame.FrameType; import infra.remoting.plugins.RequestInterceptor; -import io.netty.buffer.ByteBufAllocator; import io.netty.util.IllegalReferenceCountException; import reactor.core.CoreSubscriber; import reactor.core.Exceptions; @@ -53,23 +51,11 @@ final class FireAndForgetRequesterMono extends Mono implements Subscriptio final Payload payload; - final ByteBufAllocator allocator; - final int mtu; - final int maxFrameLength; - final RequesterResponderSupport requesterResponderSupport; - final DuplexConnection connection; + final ChannelSupport channel; - @Nullable - final RequestInterceptor requestInterceptor; - - FireAndForgetRequesterMono(Payload payload, RequesterResponderSupport requesterResponderSupport) { - this.allocator = requesterResponderSupport.getAllocator(); + FireAndForgetRequesterMono(Payload payload, ChannelSupport channel) { this.payload = payload; - this.mtu = requesterResponderSupport.getMtu(); - this.maxFrameLength = requesterResponderSupport.getMaxFrameLength(); - this.requesterResponderSupport = requesterResponderSupport; - this.connection = requesterResponderSupport.getDuplexConnection(); - this.requestInterceptor = requesterResponderSupport.getRequestInterceptor(); + this.channel = channel; } @Override @@ -79,7 +65,7 @@ public void subscribe(CoreSubscriber actual) { final IllegalStateException e = new IllegalStateException("FireAndForgetMono allows only a single Subscriber"); - final RequestInterceptor requestInterceptor = this.requestInterceptor; + final RequestInterceptor requestInterceptor = channel.requestInterceptor; if (requestInterceptor != null) { requestInterceptor.onReject(e, FrameType.REQUEST_FNF, null); } @@ -91,15 +77,14 @@ public void subscribe(CoreSubscriber actual) { actual.onSubscribe(this); final Payload p = this.payload; - int mtu = this.mtu; + int mtu = channel.mtu; try { - if (!isValid(mtu, this.maxFrameLength, p, false)) { + if (!isValid(mtu, channel.maxFrameLength, p, false)) { lazyTerminate(STATE, this); - final IllegalArgumentException e = - new IllegalArgumentException( - String.format(INVALID_PAYLOAD_ERROR_MESSAGE, this.maxFrameLength)); - final RequestInterceptor requestInterceptor = this.requestInterceptor; + final IllegalArgumentException e = new IllegalArgumentException( + String.format(INVALID_PAYLOAD_ERROR_MESSAGE, channel.maxFrameLength)); + final RequestInterceptor requestInterceptor = channel.requestInterceptor; if (requestInterceptor != null) { requestInterceptor.onReject(e, FrameType.REQUEST_FNF, p.metadata()); } @@ -113,7 +98,7 @@ public void subscribe(CoreSubscriber actual) { catch (IllegalReferenceCountException e) { lazyTerminate(STATE, this); - final RequestInterceptor requestInterceptor = this.requestInterceptor; + final RequestInterceptor requestInterceptor = channel.requestInterceptor; if (requestInterceptor != null) { requestInterceptor.onReject(e, FrameType.REQUEST_FNF, null); } @@ -124,13 +109,13 @@ public void subscribe(CoreSubscriber actual) { final int streamId; try { - streamId = this.requesterResponderSupport.getNextStreamId(); + streamId = this.channel.getNextStreamId(); } catch (Throwable t) { lazyTerminate(STATE, this); final Throwable ut = Exceptions.unwrap(t); - final RequestInterceptor requestInterceptor = this.requestInterceptor; + final RequestInterceptor requestInterceptor = channel.requestInterceptor; if (requestInterceptor != null) { requestInterceptor.onReject(ut, FrameType.REQUEST_FNF, p.metadata()); } @@ -141,7 +126,7 @@ public void subscribe(CoreSubscriber actual) { return; } - final RequestInterceptor interceptor = this.requestInterceptor; + final RequestInterceptor interceptor = channel.requestInterceptor; if (interceptor != null) { interceptor.onStart(streamId, FrameType.REQUEST_FNF, p.metadata()); } @@ -157,8 +142,8 @@ public void subscribe(CoreSubscriber actual) { return; } - sendReleasingPayload( - streamId, FrameType.REQUEST_FNF, mtu, p, this.connection, this.allocator, true); + sendReleasingPayload(streamId, FrameType.REQUEST_FNF, mtu, p, + channel.connection, channel.allocator, true); } catch (Throwable e) { lazyTerminate(STATE, this); @@ -206,9 +191,8 @@ public Void block(Duration m) { public Void block() { long previousState = markSubscribed(STATE, this); if (isSubscribedOrTerminated(previousState)) { - final IllegalStateException e = - new IllegalStateException("FireAndForgetMono allows only a single Subscriber"); - final RequestInterceptor requestInterceptor = this.requestInterceptor; + final IllegalStateException e = new IllegalStateException("FireAndForgetMono allows only a single Subscriber"); + final RequestInterceptor requestInterceptor = channel.requestInterceptor; if (requestInterceptor != null) { requestInterceptor.onReject(e, FrameType.REQUEST_FNF, null); } @@ -217,14 +201,13 @@ public Void block() { final Payload p = this.payload; try { - if (!isValid(this.mtu, this.maxFrameLength, p, false)) { + if (!isValid(channel.mtu, channel.maxFrameLength, p, false)) { lazyTerminate(STATE, this); - final IllegalArgumentException e = - new IllegalArgumentException( - String.format(INVALID_PAYLOAD_ERROR_MESSAGE, this.maxFrameLength)); + final IllegalArgumentException e = new IllegalArgumentException( + String.format(INVALID_PAYLOAD_ERROR_MESSAGE, channel.maxFrameLength)); - final RequestInterceptor requestInterceptor = this.requestInterceptor; + final RequestInterceptor requestInterceptor = channel.requestInterceptor; if (requestInterceptor != null) { requestInterceptor.onReject(e, FrameType.REQUEST_FNF, p.metadata()); } @@ -237,7 +220,7 @@ public Void block() { catch (IllegalReferenceCountException e) { lazyTerminate(STATE, this); - final RequestInterceptor requestInterceptor = this.requestInterceptor; + final RequestInterceptor requestInterceptor = channel.requestInterceptor; if (requestInterceptor != null) { requestInterceptor.onReject(e, FrameType.REQUEST_FNF, null); } @@ -247,12 +230,12 @@ public Void block() { final int streamId; try { - streamId = this.requesterResponderSupport.getNextStreamId(); + streamId = this.channel.getNextStreamId(); } catch (Throwable t) { lazyTerminate(STATE, this); - final RequestInterceptor requestInterceptor = this.requestInterceptor; + final RequestInterceptor requestInterceptor = channel.requestInterceptor; if (requestInterceptor != null) { requestInterceptor.onReject(Exceptions.unwrap(t), FrameType.REQUEST_FNF, p.metadata()); } @@ -262,20 +245,14 @@ public Void block() { throw Exceptions.propagate(t); } - final RequestInterceptor interceptor = this.requestInterceptor; + final RequestInterceptor interceptor = channel.requestInterceptor; if (interceptor != null) { interceptor.onStart(streamId, FrameType.REQUEST_FNF, p.metadata()); } try { - sendReleasingPayload( - streamId, - FrameType.REQUEST_FNF, - this.mtu, - this.payload, - this.connection, - this.allocator, - true); + sendReleasingPayload(streamId, FrameType.REQUEST_FNF, channel.mtu, this.payload, + channel.connection, channel.allocator, true); } catch (Throwable e) { lazyTerminate(STATE, this); @@ -296,6 +273,7 @@ public Void block() { return null; } + @Nullable @Override public Object scanUnsafe(Scannable.Attr key) { return null; // no particular key to be represented, still useful in hooks @@ -306,4 +284,5 @@ public Object scanUnsafe(Scannable.Attr key) { public String stepName() { return "source(FireAndForgetMono)"; } + } diff --git a/today-remoting/src/main/java/infra/remoting/core/FireAndForgetResponderSubscriber.java b/today-remoting/src/main/java/infra/remoting/core/FireAndForgetResponderSubscriber.java index a1b903b..4e74534 100644 --- a/today-remoting/src/main/java/infra/remoting/core/FireAndForgetResponderSubscriber.java +++ b/today-remoting/src/main/java/infra/remoting/core/FireAndForgetResponderSubscriber.java @@ -14,6 +14,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see [http://www.gnu.org/licenses/] */ + package infra.remoting.core; import org.reactivestreams.Subscription; @@ -33,8 +34,7 @@ import reactor.core.CoreSubscriber; import reactor.core.publisher.Mono; -final class FireAndForgetResponderSubscriber - implements CoreSubscriber, ResponderFrameHandler { +final class FireAndForgetResponderSubscriber implements CoreSubscriber, ResponderFrameHandler { static final Logger logger = LoggerFactory.getLogger(FireAndForgetResponderSubscriber.class); @@ -43,7 +43,9 @@ final class FireAndForgetResponderSubscriber final int streamId; final ByteBufAllocator allocator; final PayloadDecoder payloadDecoder; - final RequesterResponderSupport requesterResponderSupport; + + final ChannelSupport channel; + final Channel handler; final int maxInboundPayloadSize; @@ -57,40 +59,34 @@ private FireAndForgetResponderSubscriber() { this.allocator = null; this.payloadDecoder = null; this.maxInboundPayloadSize = 0; - this.requesterResponderSupport = null; + this.channel = null; this.handler = null; this.requestInterceptor = null; this.frames = null; } - FireAndForgetResponderSubscriber( - int streamId, RequesterResponderSupport requesterResponderSupport) { + FireAndForgetResponderSubscriber(int streamId, ChannelSupport channel) { this.streamId = streamId; this.allocator = null; this.payloadDecoder = null; this.maxInboundPayloadSize = 0; - this.requesterResponderSupport = null; + this.channel = null; this.handler = null; - this.requestInterceptor = requesterResponderSupport.getRequestInterceptor(); + this.requestInterceptor = channel.getRequestInterceptor(); this.frames = null; } - FireAndForgetResponderSubscriber( - int streamId, - ByteBuf firstFrame, - RequesterResponderSupport requesterResponderSupport, - Channel handler) { + FireAndForgetResponderSubscriber(int streamId, ByteBuf firstFrame, ChannelSupport channel, Channel handler) { this.streamId = streamId; - this.allocator = requesterResponderSupport.getAllocator(); - this.payloadDecoder = requesterResponderSupport.getPayloadDecoder(); - this.maxInboundPayloadSize = requesterResponderSupport.getMaxInboundPayloadSize(); - this.requesterResponderSupport = requesterResponderSupport; + this.allocator = channel.getAllocator(); + this.payloadDecoder = channel.getPayloadDecoder(); + this.maxInboundPayloadSize = channel.getMaxInboundPayloadSize(); + this.channel = channel; this.handler = handler; - this.requestInterceptor = requesterResponderSupport.getRequestInterceptor(); + this.requestInterceptor = channel.getRequestInterceptor(); - this.frames = - ReassemblyUtils.addFollowingFrame( - allocator.compositeBuffer(), firstFrame, true, maxInboundPayloadSize); + this.frames = ReassemblyUtils.addFollowingFrame( + allocator.compositeBuffer(), firstFrame, true, maxInboundPayloadSize); } @Override @@ -129,7 +125,7 @@ public void handleNext(ByteBuf followingFrame, boolean hasFollows, boolean isLas } catch (IllegalStateException t) { final int streamId = this.streamId; - this.requesterResponderSupport.remove(streamId, this); + this.channel.remove(streamId, this); this.frames = null; frames.release(); @@ -144,7 +140,7 @@ public void handleNext(ByteBuf followingFrame, boolean hasFollows, boolean isLas } if (!hasFollows) { - this.requesterResponderSupport.remove(this.streamId, this); + this.channel.remove(this.streamId, this); this.frames = null; Payload payload; @@ -174,7 +170,7 @@ public final void handleCancel() { final CompositeByteBuf frames = this.frames; if (frames != null) { final int streamId = this.streamId; - this.requesterResponderSupport.remove(streamId, this); + this.channel.remove(streamId, this); this.frames = null; frames.release(); diff --git a/today-remoting/src/main/java/infra/remoting/core/MetadataPushRequesterMono.java b/today-remoting/src/main/java/infra/remoting/core/MetadataPushRequesterMono.java index 84a35b6..9ddb2eb 100644 --- a/today-remoting/src/main/java/infra/remoting/core/MetadataPushRequesterMono.java +++ b/today-remoting/src/main/java/infra/remoting/core/MetadataPushRequesterMono.java @@ -21,11 +21,9 @@ import infra.lang.NonNull; import infra.lang.Nullable; -import infra.remoting.DuplexConnection; import infra.remoting.Payload; import infra.remoting.frame.MetadataPushFrameCodec; import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufAllocator; import io.netty.util.IllegalReferenceCountException; import reactor.core.CoreSubscriber; import reactor.core.Scannable; @@ -44,16 +42,13 @@ final class MetadataPushRequesterMono extends Mono implements Scannable { static final AtomicLongFieldUpdater STATE = AtomicLongFieldUpdater.newUpdater(MetadataPushRequesterMono.class, "state"); - final ByteBufAllocator allocator; final Payload payload; - final int maxFrameLength; - final DuplexConnection connection; - MetadataPushRequesterMono(Payload payload, RequesterResponderSupport requesterResponderSupport) { - this.allocator = requesterResponderSupport.getAllocator(); + private final ChannelSupport channel; + + MetadataPushRequesterMono(Payload payload, ChannelSupport channel) { this.payload = payload; - this.maxFrameLength = requesterResponderSupport.getMaxFrameLength(); - this.connection = requesterResponderSupport.getDuplexConnection(); + this.channel = channel; } @Override @@ -78,13 +73,13 @@ public void subscribe(CoreSubscriber actual) { new IllegalArgumentException("Metadata push should have metadata field present")); return; } - if (!isValidMetadata(this.maxFrameLength, metadata)) { + if (!isValidMetadata(channel.maxFrameLength, metadata)) { lazyTerminate(STATE, this); p.release(); Operators.error( actual, new IllegalArgumentException( - String.format(INVALID_PAYLOAD_ERROR_MESSAGE, this.maxFrameLength))); + String.format(INVALID_PAYLOAD_ERROR_MESSAGE, channel.maxFrameLength))); return; } } @@ -115,8 +110,8 @@ public void subscribe(CoreSubscriber actual) { } final ByteBuf requestFrame = - MetadataPushFrameCodec.encode(this.allocator, metadataRetainedSlice); - this.connection.sendFrame(0, requestFrame); + MetadataPushFrameCodec.encode(channel.allocator, metadataRetainedSlice); + channel.connection.sendFrame(0, requestFrame); Operators.complete(actual); } @@ -150,11 +145,11 @@ public Void block() { p.release(); throw new IllegalArgumentException("Metadata push should have metadata field present"); } - if (!isValidMetadata(this.maxFrameLength, metadata)) { + if (!isValidMetadata(channel.maxFrameLength, metadata)) { lazyTerminate(STATE, this); p.release(); throw new IllegalArgumentException( - String.format(INVALID_PAYLOAD_ERROR_MESSAGE, this.maxFrameLength)); + String.format(INVALID_PAYLOAD_ERROR_MESSAGE, channel.maxFrameLength)); } } catch (IllegalReferenceCountException e) { @@ -180,13 +175,13 @@ public Void block() { throw e; } - final ByteBuf requestFrame = - MetadataPushFrameCodec.encode(this.allocator, metadataRetainedSlice); - this.connection.sendFrame(0, requestFrame); + final ByteBuf requestFrame = MetadataPushFrameCodec.encode(channel.allocator, metadataRetainedSlice); + channel.connection.sendFrame(0, requestFrame); return null; } + @Nullable @Override public Object scanUnsafe(Attr key) { return null; // no particular key to be represented, still useful in hooks diff --git a/today-remoting/src/main/java/infra/remoting/core/RequestChannelRequesterFlux.java b/today-remoting/src/main/java/infra/remoting/core/RequestChannelRequesterFlux.java index 0af1515..c2c53d4 100644 --- a/today-remoting/src/main/java/infra/remoting/core/RequestChannelRequesterFlux.java +++ b/today-remoting/src/main/java/infra/remoting/core/RequestChannelRequesterFlux.java @@ -32,7 +32,6 @@ import infra.remoting.frame.FrameType; import infra.remoting.frame.PayloadFrameCodec; import infra.remoting.frame.RequestNFrameCodec; -import infra.remoting.frame.decoder.PayloadDecoder; import infra.remoting.plugins.RequestInterceptor; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufAllocator; @@ -77,20 +76,12 @@ final class RequestChannelRequesterFlux extends Flux Subscription, Scannable { - final ByteBufAllocator allocator; - final int mtu; - final int maxFrameLength; - final int maxInboundPayloadSize; - final RequesterResponderSupport requesterResponderSupport; - final DuplexConnection connection; - final PayloadDecoder payloadDecoder; + final ChannelSupport channel; final Publisher payloadsPublisher; @Nullable final RequesterLeaseTracker requesterLeaseTracker; - @Nullable - final RequestInterceptor requestInterceptor; volatile long state; static final AtomicLongFieldUpdater STATE = @@ -113,18 +104,10 @@ final class RequestChannelRequesterFlux extends Flux CompositeByteBuf frames; - RequestChannelRequesterFlux( - Publisher payloadsPublisher, RequesterResponderSupport requesterResponderSupport) { - this.allocator = requesterResponderSupport.getAllocator(); + RequestChannelRequesterFlux(Publisher payloadsPublisher, ChannelSupport channel) { this.payloadsPublisher = payloadsPublisher; - this.mtu = requesterResponderSupport.getMtu(); - this.maxFrameLength = requesterResponderSupport.getMaxFrameLength(); - this.maxInboundPayloadSize = requesterResponderSupport.getMaxInboundPayloadSize(); - this.requesterResponderSupport = requesterResponderSupport; - this.connection = requesterResponderSupport.getDuplexConnection(); - this.payloadDecoder = requesterResponderSupport.getPayloadDecoder(); - this.requesterLeaseTracker = requesterResponderSupport.getRequesterLeaseTracker(); - this.requestInterceptor = requesterResponderSupport.getRequestInterceptor(); + this.channel = channel; + this.requesterLeaseTracker = channel.getRequesterLeaseTracker(); } @Override @@ -135,7 +118,7 @@ public void subscribe(CoreSubscriber actual) { if (isSubscribedOrTerminated(previousState)) { final IllegalStateException e = new IllegalStateException("RequestChannelFlux allows only a single Subscriber"); - final RequestInterceptor requestInterceptor = this.requestInterceptor; + final RequestInterceptor requestInterceptor = channel.requestInterceptor; if (requestInterceptor != null) { requestInterceptor.onReject(e, FrameType.REQUEST_CHANNEL, null); } @@ -173,8 +156,8 @@ public final void request(long n) { if (isFirstFrameSent(previousState) && !isMaxAllowedRequestN(extractRequestN(previousState))) { final int streamId = this.streamId; - final ByteBuf requestNFrame = RequestNFrameCodec.encode(this.allocator, streamId, n); - this.connection.sendFrame(streamId, requestNFrame); + final ByteBuf requestNFrame = RequestNFrameCodec.encode(channel.allocator, streamId, n); + channel.connection.sendFrame(streamId, requestNFrame); } return; } @@ -240,9 +223,9 @@ public boolean handlePermit() { } void sendFirstPayload(Payload firstPayload, long initialRequestN, boolean completed) { - int mtu = this.mtu; + int mtu = channel.mtu; try { - if (!isValid(mtu, this.maxFrameLength, firstPayload, true)) { + if (!isValid(mtu, channel.maxFrameLength, firstPayload, true)) { final long previousState = markTerminated(STATE, this); if (isTerminated(previousState)) { @@ -253,10 +236,8 @@ void sendFirstPayload(Payload firstPayload, long initialRequestN, boolean comple this.outboundSubscription.cancel(); } - final IllegalArgumentException e = - new IllegalArgumentException( - String.format(INVALID_PAYLOAD_ERROR_MESSAGE, this.maxFrameLength)); - final RequestInterceptor requestInterceptor = this.requestInterceptor; + final IllegalArgumentException e = new IllegalArgumentException(String.format(INVALID_PAYLOAD_ERROR_MESSAGE, channel.maxFrameLength)); + final RequestInterceptor requestInterceptor = channel.requestInterceptor; if (requestInterceptor != null) { requestInterceptor.onReject(e, FrameType.REQUEST_CHANNEL, firstPayload.metadata()); } @@ -280,7 +261,7 @@ void sendFirstPayload(Payload firstPayload, long initialRequestN, boolean comple this.outboundSubscription.cancel(); } - final RequestInterceptor requestInterceptor = this.requestInterceptor; + final RequestInterceptor requestInterceptor = channel.requestInterceptor; if (requestInterceptor != null) { requestInterceptor.onReject(e, FrameType.REQUEST_CHANNEL, null); } @@ -290,13 +271,13 @@ void sendFirstPayload(Payload firstPayload, long initialRequestN, boolean comple return; } - final RequesterResponderSupport sm = this.requesterResponderSupport; - final DuplexConnection connection = this.connection; - final ByteBufAllocator allocator = this.allocator; + final ChannelSupport channel = this.channel; + final DuplexConnection connection = channel.connection; + final ByteBufAllocator allocator = channel.allocator; final int streamId; try { - streamId = sm.addAndGetNextStreamId(this); + streamId = channel.addAndGetNextStreamId(this); this.streamId = streamId; } catch (Throwable t) { @@ -314,7 +295,7 @@ void sendFirstPayload(Payload firstPayload, long initialRequestN, boolean comple } final Throwable ut = Exceptions.unwrap(t); - final RequestInterceptor requestInterceptor = this.requestInterceptor; + final RequestInterceptor requestInterceptor = this.channel.requestInterceptor; if (requestInterceptor != null) { requestInterceptor.onReject(ut, FrameType.REQUEST_CHANNEL, firstPayload.metadata()); } @@ -325,7 +306,7 @@ void sendFirstPayload(Payload firstPayload, long initialRequestN, boolean comple return; } - final RequestInterceptor requestInterceptor = this.requestInterceptor; + final RequestInterceptor requestInterceptor = this.channel.requestInterceptor; if (requestInterceptor != null) { requestInterceptor.onStart(streamId, FrameType.REQUEST_CHANNEL, firstPayload.metadata()); } @@ -351,7 +332,7 @@ void sendFirstPayload(Payload firstPayload, long initialRequestN, boolean comple return; } - sm.remove(streamId, this); + channel.remove(streamId, this); if (!isOutboundTerminated(previousState)) { this.outboundSubscription.cancel(); @@ -377,7 +358,7 @@ void sendFirstPayload(Payload firstPayload, long initialRequestN, boolean comple return; } - sm.remove(streamId, this); + channel.remove(streamId, this); // 2) SendFirst is called asynchronously on the connection event-loop. Thus, we // need to check if outbound error is present. Note, we check outboundError since @@ -411,7 +392,7 @@ void sendFirstPayload(Payload firstPayload, long initialRequestN, boolean comple } if (!completed && isOutboundTerminated(previousState)) { - final ByteBuf completeFrame = PayloadFrameCodec.encodeComplete(this.allocator, streamId); + final ByteBuf completeFrame = PayloadFrameCodec.encodeComplete(this.channel.allocator, streamId); connection.sendFrame(streamId, completeFrame); } @@ -435,15 +416,13 @@ void sendFirstPayload(Payload firstPayload, long initialRequestN, boolean comple final void sendFollowingPayload(Payload followingPayload) { int streamId = this.streamId; - int mtu = this.mtu; + int mtu = channel.mtu; try { - if (!isValid(mtu, this.maxFrameLength, followingPayload, true)) { + if (!isValid(mtu, channel.maxFrameLength, followingPayload, true)) { followingPayload.release(); - final IllegalArgumentException e = - new IllegalArgumentException( - String.format(INVALID_PAYLOAD_ERROR_MESSAGE, this.maxFrameLength)); + final IllegalArgumentException e = new IllegalArgumentException(String.format(INVALID_PAYLOAD_ERROR_MESSAGE, channel.maxFrameLength)); if (!this.tryCancel()) { Operators.onErrorDropped(e, this.inboundSubscriber.currentContext()); return; @@ -473,8 +452,8 @@ final void sendFollowingPayload(Payload followingPayload) { FrameType.NEXT, mtu, followingPayload, - this.connection, - allocator, + channel.connection, + channel.allocator, true); } catch (Throwable e) { @@ -493,7 +472,7 @@ void propagateErrorSafely(Throwable t) { if (!this.inboundDone) { synchronized(this) { if (!this.inboundDone) { - final RequestInterceptor interceptor = requestInterceptor; + final RequestInterceptor interceptor = channel.requestInterceptor; if (interceptor != null) { interceptor.onTerminate(this.streamId, FrameType.REQUEST_CHANNEL, t); } @@ -517,7 +496,7 @@ public final void cancel() { return; } - final RequestInterceptor requestInterceptor = this.requestInterceptor; + final RequestInterceptor requestInterceptor = channel.requestInterceptor; if (requestInterceptor != null) { requestInterceptor.onCancel(this.streamId, FrameType.REQUEST_CHANNEL); } @@ -546,10 +525,11 @@ boolean tryCancel() { final boolean firstFrameSent = isFirstFrameSent(previousState); if (firstFrameSent) { final int streamId = this.streamId; - this.requesterResponderSupport.remove(streamId, this); + final ChannelSupport channel = this.channel; + channel.remove(streamId, this); - final ByteBuf cancelFrame = CancelFrameCodec.encode(this.allocator, streamId); - this.connection.sendFrame(streamId, cancelFrame); + final ByteBuf cancelFrame = CancelFrameCodec.encode(channel.allocator, streamId); + channel.connection.sendFrame(streamId, cancelFrame); } return firstFrameSent; @@ -595,16 +575,17 @@ else if (!isReadyToSendFirstFrame(previousState)) { if (isFirstFrameSent(previousState)) { final int streamId = this.streamId; - this.requesterResponderSupport.remove(streamId, this); + final ChannelSupport channel = this.channel; + channel.remove(streamId, this); // propagates error to remote responder - final ByteBuf errorFrame = ErrorFrameCodec.encode(this.allocator, streamId, t); - this.connection.sendFrame(streamId, errorFrame); + final ByteBuf errorFrame = ErrorFrameCodec.encode(channel.allocator, streamId, t); + channel.connection.sendFrame(streamId, errorFrame); if (!isInboundTerminated(previousState)) { // FIXME: must be scheduled on the connection event-loop to achieve serial // behaviour on the inbound subscriber synchronized(this) { - final RequestInterceptor interceptor = requestInterceptor; + final RequestInterceptor interceptor = channel.requestInterceptor; if (interceptor != null) { interceptor.onTerminate(streamId, FrameType.REQUEST_CHANNEL, t); } @@ -641,14 +622,15 @@ public void onComplete() { } final int streamId = this.streamId; - final ByteBuf completeFrame = PayloadFrameCodec.encodeComplete(this.allocator, streamId); + final ChannelSupport channel = this.channel; + final ByteBuf completeFrame = PayloadFrameCodec.encodeComplete(channel.allocator, streamId); - this.connection.sendFrame(streamId, completeFrame); + channel.connection.sendFrame(streamId, completeFrame); if (isInboundTerminated(previousState)) { - this.requesterResponderSupport.remove(streamId, this); + channel.remove(streamId, this); - final RequestInterceptor interceptor = requestInterceptor; + final RequestInterceptor interceptor = channel.requestInterceptor; if (interceptor != null) { interceptor.onTerminate(streamId, FrameType.REQUEST_CHANNEL, null); } @@ -669,9 +651,9 @@ public final void handleComplete() { } if (isOutboundTerminated(previousState)) { - this.requesterResponderSupport.remove(this.streamId, this); + this.channel.remove(this.streamId, this); - final RequestInterceptor interceptor = this.requestInterceptor; + final RequestInterceptor interceptor = channel.requestInterceptor; if (interceptor != null) { interceptor.onTerminate(this.streamId, FrameType.REQUEST_CHANNEL, null); } @@ -695,7 +677,7 @@ public final void handlePermitError(Throwable cause) { } final Payload p = this.firstPayload; - final RequestInterceptor interceptor = requestInterceptor; + final RequestInterceptor interceptor = channel.requestInterceptor; if (interceptor != null) { interceptor.onReject(cause, FrameType.REQUEST_CHANNEL, p.metadata()); } @@ -726,9 +708,9 @@ public final void handleError(Throwable cause) { ReassemblyUtils.release(this, previousState); final int streamId = this.streamId; - this.requesterResponderSupport.remove(streamId, this); + this.channel.remove(streamId, this); - final RequestInterceptor interceptor = requestInterceptor; + final RequestInterceptor interceptor = channel.requestInterceptor; if (interceptor != null) { interceptor.onTerminate(streamId, FrameType.REQUEST_CHANNEL, cause); } @@ -754,7 +736,7 @@ public final void handlePayload(Payload value) { final Throwable cause = Exceptions.failWithOverflow( "The number of messages received exceeds the number requested"); - final RequestInterceptor requestInterceptor = this.requestInterceptor; + final RequestInterceptor requestInterceptor = channel.requestInterceptor; if (requestInterceptor != null) { requestInterceptor.onTerminate(streamId, FrameType.REQUEST_CHANNEL, cause); } @@ -787,13 +769,13 @@ public void handleCancel() { final boolean inboundTerminated = isInboundTerminated(previousState); if (inboundTerminated) { - this.requesterResponderSupport.remove(this.streamId, this); + this.channel.remove(this.streamId, this); } this.outboundSubscription.cancel(); if (inboundTerminated) { - final RequestInterceptor interceptor = requestInterceptor; + final RequestInterceptor interceptor = channel.requestInterceptor; if (interceptor != null) { interceptor.onTerminate(this.streamId, FrameType.REQUEST_CHANNEL, null); } @@ -807,9 +789,9 @@ public void handleNext(ByteBuf frame, boolean hasFollows, boolean isLastPayload) this, this, this.inboundSubscriber, - this.payloadDecoder, - this.allocator, - this.maxInboundPayloadSize, + channel.payloadDecoder, + channel.allocator, + channel.maxInboundPayloadSize, frame, hasFollows, isLastPayload); diff --git a/today-remoting/src/main/java/infra/remoting/core/RequestChannelResponderSubscriber.java b/today-remoting/src/main/java/infra/remoting/core/RequestChannelResponderSubscriber.java index 62f516a..ca6dc26 100644 --- a/today-remoting/src/main/java/infra/remoting/core/RequestChannelResponderSubscriber.java +++ b/today-remoting/src/main/java/infra/remoting/core/RequestChannelResponderSubscriber.java @@ -80,7 +80,7 @@ final class RequestChannelResponderSubscriber extends Flux final int mtu; final int maxFrameLength; final int maxInboundPayloadSize; - final RequesterResponderSupport requesterResponderSupport; + final ChannelSupport channelSupport; final DuplexConnection connection; final long firstRequest; @@ -115,17 +115,17 @@ public RequestChannelResponderSubscriber( int streamId, long firstRequestN, ByteBuf firstFrame, - RequesterResponderSupport requesterResponderSupport, + ChannelSupport channelSupport, Channel handler) { this.streamId = streamId; - this.allocator = requesterResponderSupport.getAllocator(); - this.mtu = requesterResponderSupport.getMtu(); - this.maxFrameLength = requesterResponderSupport.getMaxFrameLength(); - this.maxInboundPayloadSize = requesterResponderSupport.getMaxInboundPayloadSize(); - this.requesterResponderSupport = requesterResponderSupport; - this.connection = requesterResponderSupport.getDuplexConnection(); - this.payloadDecoder = requesterResponderSupport.getPayloadDecoder(); - this.requestInterceptor = requesterResponderSupport.getRequestInterceptor(); + this.allocator = channelSupport.getAllocator(); + this.mtu = channelSupport.getMtu(); + this.maxFrameLength = channelSupport.getMaxFrameLength(); + this.maxInboundPayloadSize = channelSupport.getMaxInboundPayloadSize(); + this.channelSupport = channelSupport; + this.connection = channelSupport.getDuplexConnection(); + this.payloadDecoder = channelSupport.getPayloadDecoder(); + this.requestInterceptor = channelSupport.getRequestInterceptor(); this.handler = handler; this.firstRequest = firstRequestN; @@ -139,16 +139,16 @@ public RequestChannelResponderSubscriber( int streamId, long firstRequestN, Payload firstPayload, - RequesterResponderSupport requesterResponderSupport) { + ChannelSupport channelSupport) { this.streamId = streamId; - this.allocator = requesterResponderSupport.getAllocator(); - this.mtu = requesterResponderSupport.getMtu(); - this.maxFrameLength = requesterResponderSupport.getMaxFrameLength(); - this.maxInboundPayloadSize = requesterResponderSupport.getMaxInboundPayloadSize(); - this.requesterResponderSupport = requesterResponderSupport; - this.connection = requesterResponderSupport.getDuplexConnection(); - this.payloadDecoder = requesterResponderSupport.getPayloadDecoder(); - this.requestInterceptor = requesterResponderSupport.getRequestInterceptor(); + this.allocator = channelSupport.getAllocator(); + this.mtu = channelSupport.getMtu(); + this.maxFrameLength = channelSupport.getMaxFrameLength(); + this.maxInboundPayloadSize = channelSupport.getMaxInboundPayloadSize(); + this.channelSupport = channelSupport; + this.connection = channelSupport.getDuplexConnection(); + this.payloadDecoder = channelSupport.getPayloadDecoder(); + this.requestInterceptor = channelSupport.getRequestInterceptor(); this.firstRequest = firstRequestN; this.firstPayload = firstPayload; @@ -338,7 +338,7 @@ public void cancel() { final boolean isOutboundTerminated = isOutboundTerminated(previousState); if (isOutboundTerminated) { - this.requesterResponderSupport.remove(streamId, this); + this.channelSupport.remove(streamId, this); } final ByteBuf cancelFrame = CancelFrameCodec.encode(this.allocator, streamId); @@ -360,7 +360,7 @@ public final void handleCancel() { // and fragmentation of the first frame was cancelled before lazyTerminate(STATE, this); - this.requesterResponderSupport.remove(this.streamId, this); + this.channelSupport.remove(this.streamId, this); final CompositeByteBuf frames = this.frames; if (frames != null) { @@ -400,7 +400,7 @@ final long tryTerminate(boolean isFromInbound) { return previousState; } - this.requesterResponderSupport.remove(this.streamId, this); + this.channelSupport.remove(this.streamId, this); if (isReassembling(previousState)) { final CompositeByteBuf frames = this.frames; @@ -475,7 +475,7 @@ final void handlePayload(Payload p) { return; } - this.requesterResponderSupport.remove(this.streamId, this); + this.channelSupport.remove(this.streamId, this); this.connection.sendFrame( streamId, @@ -531,7 +531,7 @@ public final void handleError(Throwable t) { return; } - this.requesterResponderSupport.remove(this.streamId, this); + this.channelSupport.remove(this.streamId, this); if (isReassembling(previousState)) { final CompositeByteBuf frames = this.frames; @@ -575,7 +575,7 @@ public void handleComplete() { final boolean isOutboundTerminated = isOutboundTerminated(previousState); if (isOutboundTerminated) { - this.requesterResponderSupport.remove(this.streamId, this); + this.channelSupport.remove(this.streamId, this); } if (isFirstFrameSent(previousState)) { @@ -883,7 +883,7 @@ public void onError(Throwable t) { final int streamId = this.streamId; - this.requesterResponderSupport.remove(streamId, this); + this.channelSupport.remove(streamId, this); if (isReassembling(previousState)) { final CompositeByteBuf frames = this.frames; @@ -939,7 +939,7 @@ public void onComplete() { final boolean isInboundTerminated = isInboundTerminated(previousState); if (isInboundTerminated) { - this.requesterResponderSupport.remove(streamId, this); + this.channelSupport.remove(streamId, this); } final ByteBuf completeFrame = PayloadFrameCodec.encodeComplete(this.allocator, streamId); diff --git a/today-remoting/src/main/java/infra/remoting/core/RequestResponseRequesterMono.java b/today-remoting/src/main/java/infra/remoting/core/RequestResponseRequesterMono.java index a1219e3..9e8812a 100644 --- a/today-remoting/src/main/java/infra/remoting/core/RequestResponseRequesterMono.java +++ b/today-remoting/src/main/java/infra/remoting/core/RequestResponseRequesterMono.java @@ -26,7 +26,6 @@ import infra.remoting.Payload; import infra.remoting.frame.CancelFrameCodec; import infra.remoting.frame.FrameType; -import infra.remoting.frame.decoder.PayloadDecoder; import infra.remoting.plugins.RequestInterceptor; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufAllocator; @@ -57,19 +56,12 @@ final class RequestResponseRequesterMono extends Mono implements RequesterFrameHandler, LeasePermitHandler, Subscription, Scannable { - final ByteBufAllocator allocator; final Payload payload; - final int mtu; - final int maxFrameLength; - final int maxInboundPayloadSize; - final RequesterResponderSupport requesterResponderSupport; - final DuplexConnection connection; - final PayloadDecoder payloadDecoder; + + final ChannelSupport channel; @Nullable final RequesterLeaseTracker requesterLeaseTracker; - @Nullable - final RequestInterceptor requestInterceptor; volatile long state; static final AtomicLongFieldUpdater STATE = @@ -80,29 +72,20 @@ final class RequestResponseRequesterMono extends Mono CompositeByteBuf frames; boolean done; - RequestResponseRequesterMono( - Payload payload, RequesterResponderSupport requesterResponderSupport) { - - this.allocator = requesterResponderSupport.getAllocator(); + RequestResponseRequesterMono(Payload payload, ChannelSupport channel) { this.payload = payload; - this.mtu = requesterResponderSupport.getMtu(); - this.maxFrameLength = requesterResponderSupport.getMaxFrameLength(); - this.maxInboundPayloadSize = requesterResponderSupport.getMaxInboundPayloadSize(); - this.requesterResponderSupport = requesterResponderSupport; - this.connection = requesterResponderSupport.getDuplexConnection(); - this.payloadDecoder = requesterResponderSupport.getPayloadDecoder(); - this.requesterLeaseTracker = requesterResponderSupport.getRequesterLeaseTracker(); - this.requestInterceptor = requesterResponderSupport.getRequestInterceptor(); + this.channel = channel; + this.requesterLeaseTracker = channel.getRequesterLeaseTracker(); } @Override public void subscribe(CoreSubscriber actual) { - + ChannelSupport channel = this.channel; long previousState = markSubscribed(STATE, this); if (isSubscribedOrTerminated(previousState)) { final IllegalStateException e = new IllegalStateException("RequestResponseMono allows only a single " + "Subscriber"); - final RequestInterceptor requestInterceptor = this.requestInterceptor; + final RequestInterceptor requestInterceptor = channel.requestInterceptor; if (requestInterceptor != null) { requestInterceptor.onReject(e, FrameType.REQUEST_RESPONSE, null); } @@ -113,13 +96,11 @@ public void subscribe(CoreSubscriber actual) { final Payload p = this.payload; try { - if (!isValid(this.mtu, this.maxFrameLength, p, false)) { + if (!isValid(channel.mtu, channel.maxFrameLength, p, false)) { lazyTerminate(STATE, this); - final IllegalArgumentException e = - new IllegalArgumentException( - String.format(INVALID_PAYLOAD_ERROR_MESSAGE, this.maxFrameLength)); - final RequestInterceptor requestInterceptor = this.requestInterceptor; + final IllegalArgumentException e = new IllegalArgumentException(String.format(INVALID_PAYLOAD_ERROR_MESSAGE, channel.maxFrameLength)); + final RequestInterceptor requestInterceptor = channel.requestInterceptor; if (requestInterceptor != null) { requestInterceptor.onReject(e, FrameType.REQUEST_RESPONSE, p.metadata()); } @@ -133,7 +114,7 @@ public void subscribe(CoreSubscriber actual) { catch (IllegalReferenceCountException e) { lazyTerminate(STATE, this); - final RequestInterceptor requestInterceptor = this.requestInterceptor; + final RequestInterceptor requestInterceptor = channel.requestInterceptor; if (requestInterceptor != null) { requestInterceptor.onReject(e, FrameType.REQUEST_RESPONSE, null); } @@ -182,9 +163,9 @@ public boolean handlePermit() { void sendFirstPayload(Payload payload) { - final RequesterResponderSupport sm = this.requesterResponderSupport; - final DuplexConnection connection = this.connection; - final ByteBufAllocator allocator = this.allocator; + final ChannelSupport sm = this.channel; + final DuplexConnection connection = sm.connection; + final ByteBufAllocator allocator = sm.allocator; final int streamId; try { @@ -196,7 +177,7 @@ void sendFirstPayload(Payload payload) { final long previousState = markTerminated(STATE, this); final Throwable ut = Exceptions.unwrap(t); - final RequestInterceptor requestInterceptor = this.requestInterceptor; + final RequestInterceptor requestInterceptor = channel.requestInterceptor; if (requestInterceptor != null) { requestInterceptor.onReject(ut, FrameType.REQUEST_RESPONSE, payload.metadata()); } @@ -209,14 +190,14 @@ void sendFirstPayload(Payload payload) { return; } - final RequestInterceptor requestInterceptor = this.requestInterceptor; + final RequestInterceptor requestInterceptor = channel.requestInterceptor; if (requestInterceptor != null) { requestInterceptor.onStart(streamId, FrameType.REQUEST_RESPONSE, payload.metadata()); } try { sendReleasingPayload( - streamId, FrameType.REQUEST_RESPONSE, this.mtu, payload, connection, allocator, true); + streamId, FrameType.REQUEST_RESPONSE, sm.mtu, payload, connection, allocator, true); } catch (Throwable e) { this.done = true; @@ -258,13 +239,14 @@ public final void cancel() { if (isFirstFrameSent(previousState)) { final int streamId = this.streamId; - this.requesterResponderSupport.remove(streamId, this); + ChannelSupport channel = this.channel; + channel.remove(streamId, this); ReassemblyUtils.synchronizedRelease(this, previousState); - this.connection.sendFrame(streamId, CancelFrameCodec.encode(this.allocator, streamId)); + channel.connection.sendFrame(streamId, CancelFrameCodec.encode(channel.allocator, streamId)); - final RequestInterceptor requestInterceptor = this.requestInterceptor; + final RequestInterceptor requestInterceptor = channel.requestInterceptor; if (requestInterceptor != null) { requestInterceptor.onCancel(streamId, FrameType.REQUEST_RESPONSE); } @@ -290,9 +272,9 @@ public final void handlePayload(Payload value) { } final int streamId = this.streamId; - this.requesterResponderSupport.remove(streamId, this); + this.channel.remove(streamId, this); - final RequestInterceptor requestInterceptor = this.requestInterceptor; + final RequestInterceptor requestInterceptor = channel.requestInterceptor; if (requestInterceptor != null) { requestInterceptor.onTerminate(streamId, FrameType.REQUEST_RESPONSE, null); } @@ -316,9 +298,9 @@ public final void handleComplete() { } final int streamId = this.streamId; - this.requesterResponderSupport.remove(streamId, this); + this.channel.remove(streamId, this); - final RequestInterceptor requestInterceptor = this.requestInterceptor; + final RequestInterceptor requestInterceptor = channel.requestInterceptor; if (requestInterceptor != null) { requestInterceptor.onTerminate(streamId, FrameType.REQUEST_RESPONSE, null); } @@ -337,7 +319,7 @@ public final void handlePermitError(Throwable cause) { } final Payload p = this.payload; - final RequestInterceptor requestInterceptor = this.requestInterceptor; + final RequestInterceptor requestInterceptor = channel.requestInterceptor; if (requestInterceptor != null) { requestInterceptor.onReject(cause, FrameType.REQUEST_RESPONSE, p.metadata()); } @@ -364,9 +346,9 @@ public final void handleError(Throwable cause) { ReassemblyUtils.synchronizedRelease(this, previousState); final int streamId = this.streamId; - this.requesterResponderSupport.remove(streamId, this); + this.channel.remove(streamId, this); - final RequestInterceptor requestInterceptor = this.requestInterceptor; + final RequestInterceptor requestInterceptor = channel.requestInterceptor; if (requestInterceptor != null) { requestInterceptor.onTerminate(streamId, FrameType.REQUEST_RESPONSE, cause); } @@ -376,14 +358,13 @@ public final void handleError(Throwable cause) { @Override public void handleNext(ByteBuf frame, boolean hasFollows, boolean isLastPayload) { - handleNextSupport( - STATE, + handleNextSupport(STATE, this, this, this.actual, - this.payloadDecoder, - this.allocator, - this.maxInboundPayloadSize, + channel.payloadDecoder, + channel.allocator, + channel.maxInboundPayloadSize, frame, hasFollows, isLastPayload); @@ -395,7 +376,7 @@ public CompositeByteBuf getFrames() { } @Override - public void setFrames(CompositeByteBuf byteBuf) { + public void setFrames(@Nullable CompositeByteBuf byteBuf) { this.frames = byteBuf; } diff --git a/today-remoting/src/main/java/infra/remoting/core/RequestResponseResponderSubscriber.java b/today-remoting/src/main/java/infra/remoting/core/RequestResponseResponderSubscriber.java index e972f88..fb7d5ac 100644 --- a/today-remoting/src/main/java/infra/remoting/core/RequestResponseResponderSubscriber.java +++ b/today-remoting/src/main/java/infra/remoting/core/RequestResponseResponderSubscriber.java @@ -57,7 +57,7 @@ final class RequestResponseResponderSubscriber final int mtu; final int maxFrameLength; final int maxInboundPayloadSize; - final RequesterResponderSupport requesterResponderSupport; + final ChannelSupport channelSupport; final DuplexConnection connection; final Channel handler; @@ -75,17 +75,17 @@ final class RequestResponseResponderSubscriber public RequestResponseResponderSubscriber( int streamId, ByteBuf firstFrame, - RequesterResponderSupport requesterResponderSupport, + ChannelSupport channelSupport, Channel handler) { this.streamId = streamId; - this.allocator = requesterResponderSupport.getAllocator(); - this.mtu = requesterResponderSupport.getMtu(); - this.maxFrameLength = requesterResponderSupport.getMaxFrameLength(); - this.maxInboundPayloadSize = requesterResponderSupport.getMaxInboundPayloadSize(); - this.requesterResponderSupport = requesterResponderSupport; - this.connection = requesterResponderSupport.getDuplexConnection(); - this.payloadDecoder = requesterResponderSupport.getPayloadDecoder(); - this.requestInterceptor = requesterResponderSupport.getRequestInterceptor(); + this.allocator = channelSupport.getAllocator(); + this.mtu = channelSupport.getMtu(); + this.maxFrameLength = channelSupport.getMaxFrameLength(); + this.maxInboundPayloadSize = channelSupport.getMaxInboundPayloadSize(); + this.channelSupport = channelSupport; + this.connection = channelSupport.getDuplexConnection(); + this.payloadDecoder = channelSupport.getPayloadDecoder(); + this.requestInterceptor = channelSupport.getRequestInterceptor(); this.handler = handler; this.frames = @@ -94,15 +94,15 @@ public RequestResponseResponderSubscriber( } public RequestResponseResponderSubscriber( - int streamId, RequesterResponderSupport requesterResponderSupport) { + int streamId, ChannelSupport channelSupport) { this.streamId = streamId; - this.allocator = requesterResponderSupport.getAllocator(); - this.mtu = requesterResponderSupport.getMtu(); - this.maxFrameLength = requesterResponderSupport.getMaxFrameLength(); - this.maxInboundPayloadSize = requesterResponderSupport.getMaxInboundPayloadSize(); - this.requesterResponderSupport = requesterResponderSupport; - this.connection = requesterResponderSupport.getDuplexConnection(); - this.requestInterceptor = requesterResponderSupport.getRequestInterceptor(); + this.allocator = channelSupport.getAllocator(); + this.mtu = channelSupport.getMtu(); + this.maxFrameLength = channelSupport.getMaxFrameLength(); + this.maxInboundPayloadSize = channelSupport.getMaxInboundPayloadSize(); + this.channelSupport = channelSupport; + this.connection = channelSupport.getDuplexConnection(); + this.requestInterceptor = channelSupport.getRequestInterceptor(); this.payloadDecoder = null; this.handler = null; @@ -141,7 +141,7 @@ public void onNext(@Nullable Payload p) { final DuplexConnection connection = this.connection; final ByteBufAllocator allocator = this.allocator; - this.requesterResponderSupport.remove(streamId, this); + this.channelSupport.remove(streamId, this); if (p == null) { final ByteBuf completeFrame = PayloadFrameCodec.encodeComplete(allocator, streamId); @@ -227,7 +227,7 @@ public void onError(Throwable t) { final int streamId = this.streamId; - this.requesterResponderSupport.remove(streamId, this); + this.channelSupport.remove(streamId, this); final ByteBuf errorFrame = ErrorFrameCodec.encode(this.allocator, streamId, t); this.connection.sendFrame(streamId, errorFrame); @@ -256,7 +256,7 @@ public void handleCancel() { S.lazySet(this, Operators.cancelledSubscription()); final int streamId = this.streamId; - this.requesterResponderSupport.remove(streamId, this); + this.channelSupport.remove(streamId, this); final CompositeByteBuf frames = this.frames; if (frames != null) { @@ -276,7 +276,7 @@ public void handleCancel() { } final int streamId = this.streamId; - this.requesterResponderSupport.remove(streamId, this); + this.channelSupport.remove(streamId, this); currentSubscription.cancel(); @@ -299,7 +299,7 @@ public void handleNext(ByteBuf frame, boolean hasFollows, boolean isLastPayload) catch (IllegalStateException t) { S.lazySet(this, Operators.cancelledSubscription()); - this.requesterResponderSupport.remove(this.streamId, this); + this.channelSupport.remove(this.streamId, this); this.frames = null; frames.release(); @@ -333,7 +333,7 @@ public void handleNext(ByteBuf frame, boolean hasFollows, boolean isLastPayload) S.lazySet(this, Operators.cancelledSubscription()); final int streamId = this.streamId; - this.requesterResponderSupport.remove(streamId, this); + this.channelSupport.remove(streamId, this); ReferenceCountUtil.safeRelease(frames); diff --git a/today-remoting/src/main/java/infra/remoting/core/RequestStreamRequesterFlux.java b/today-remoting/src/main/java/infra/remoting/core/RequestStreamRequesterFlux.java index 81d6c14..958dd88 100644 --- a/today-remoting/src/main/java/infra/remoting/core/RequestStreamRequesterFlux.java +++ b/today-remoting/src/main/java/infra/remoting/core/RequestStreamRequesterFlux.java @@ -27,7 +27,6 @@ import infra.remoting.frame.CancelFrameCodec; import infra.remoting.frame.FrameType; import infra.remoting.frame.RequestNFrameCodec; -import infra.remoting.frame.decoder.PayloadDecoder; import infra.remoting.plugins.RequestInterceptor; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufAllocator; @@ -60,19 +59,12 @@ final class RequestStreamRequesterFlux extends Flux implements RequesterFrameHandler, LeasePermitHandler, Subscription, Scannable { - final ByteBufAllocator allocator; final Payload payload; - final int mtu; - final int maxFrameLength; - final int maxInboundPayloadSize; - final RequesterResponderSupport requesterResponderSupport; - final DuplexConnection connection; - final PayloadDecoder payloadDecoder; + + final ChannelSupport channel; @Nullable final RequesterLeaseTracker requesterLeaseTracker; - @Nullable - final RequestInterceptor requestInterceptor; volatile long state; static final AtomicLongFieldUpdater STATE = @@ -85,17 +77,10 @@ final class RequestStreamRequesterFlux extends Flux long requested; long produced; - RequestStreamRequesterFlux(Payload payload, RequesterResponderSupport requesterResponderSupport) { - this.allocator = requesterResponderSupport.getAllocator(); + RequestStreamRequesterFlux(Payload payload, ChannelSupport channel) { this.payload = payload; - this.mtu = requesterResponderSupport.getMtu(); - this.maxFrameLength = requesterResponderSupport.getMaxFrameLength(); - this.maxInboundPayloadSize = requesterResponderSupport.getMaxInboundPayloadSize(); - this.requesterResponderSupport = requesterResponderSupport; - this.connection = requesterResponderSupport.getDuplexConnection(); - this.payloadDecoder = requesterResponderSupport.getPayloadDecoder(); - this.requesterLeaseTracker = requesterResponderSupport.getRequesterLeaseTracker(); - this.requestInterceptor = requesterResponderSupport.getRequestInterceptor(); + this.channel = channel; + this.requesterLeaseTracker = channel.getRequesterLeaseTracker(); } @Override @@ -104,7 +89,7 @@ public void subscribe(CoreSubscriber actual) { if (isSubscribedOrTerminated(previousState)) { final IllegalStateException e = new IllegalStateException("RequestStreamFlux allows only a single Subscriber"); - final RequestInterceptor requestInterceptor = this.requestInterceptor; + final RequestInterceptor requestInterceptor = channel.requestInterceptor; if (requestInterceptor != null) { requestInterceptor.onReject(e, FrameType.REQUEST_STREAM, null); } @@ -115,13 +100,13 @@ public void subscribe(CoreSubscriber actual) { final Payload p = this.payload; try { - if (!isValid(this.mtu, this.maxFrameLength, p, false)) { + if (!isValid(channel.mtu, channel.maxFrameLength, p, false)) { lazyTerminate(STATE, this); final IllegalArgumentException e = new IllegalArgumentException( - String.format(INVALID_PAYLOAD_ERROR_MESSAGE, this.maxFrameLength)); - final RequestInterceptor requestInterceptor = this.requestInterceptor; + String.format(INVALID_PAYLOAD_ERROR_MESSAGE, channel.maxFrameLength)); + final RequestInterceptor requestInterceptor = channel.requestInterceptor; if (requestInterceptor != null) { requestInterceptor.onReject(e, FrameType.REQUEST_STREAM, p.metadata()); } @@ -135,7 +120,7 @@ public void subscribe(CoreSubscriber actual) { catch (IllegalReferenceCountException e) { lazyTerminate(STATE, this); - final RequestInterceptor requestInterceptor = this.requestInterceptor; + final RequestInterceptor requestInterceptor = channel.requestInterceptor; if (requestInterceptor != null) { requestInterceptor.onReject(e, FrameType.REQUEST_STREAM, null); } @@ -167,8 +152,8 @@ public final void request(long n) { if (isFirstFrameSent(previousState) && !isMaxAllowedRequestN(extractRequestN(previousState))) { final int streamId = this.streamId; - final ByteBuf requestNFrame = RequestNFrameCodec.encode(this.allocator, streamId, n); - this.connection.sendFrame(streamId, requestNFrame); + final ByteBuf requestNFrame = RequestNFrameCodec.encode(channel.allocator, streamId, n); + channel.connection.sendFrame(streamId, requestNFrame); } return; } @@ -194,14 +179,13 @@ public boolean handlePermit() { } void sendFirstPayload(Payload payload, long initialRequestN) { - - final RequesterResponderSupport sm = this.requesterResponderSupport; - final DuplexConnection connection = this.connection; - final ByteBufAllocator allocator = this.allocator; + final ChannelSupport channel = this.channel; + final DuplexConnection connection = channel.connection; + final ByteBufAllocator allocator = channel.allocator; final int streamId; try { - streamId = sm.addAndGetNextStreamId(this); + streamId = channel.addAndGetNextStreamId(this); this.streamId = streamId; } catch (Throwable t) { @@ -209,7 +193,7 @@ void sendFirstPayload(Payload payload, long initialRequestN) { final long previousState = markTerminated(STATE, this); final Throwable ut = Exceptions.unwrap(t); - final RequestInterceptor requestInterceptor = this.requestInterceptor; + final RequestInterceptor requestInterceptor = channel.requestInterceptor; if (requestInterceptor != null) { requestInterceptor.onReject(ut, FrameType.REQUEST_STREAM, payload.metadata()); } @@ -222,7 +206,7 @@ void sendFirstPayload(Payload payload, long initialRequestN) { return; } - final RequestInterceptor requestInterceptor = this.requestInterceptor; + final RequestInterceptor requestInterceptor = channel.requestInterceptor; if (requestInterceptor != null) { requestInterceptor.onStart(streamId, FrameType.REQUEST_STREAM, payload.metadata()); } @@ -232,7 +216,7 @@ void sendFirstPayload(Payload payload, long initialRequestN) { streamId, FrameType.REQUEST_STREAM, initialRequestN, - this.mtu, + channel.mtu, payload, connection, allocator, @@ -242,7 +226,7 @@ void sendFirstPayload(Payload payload, long initialRequestN) { this.done = true; lazyTerminate(STATE, this); - sm.remove(streamId, this); + channel.remove(streamId, this); if (requestInterceptor != null) { requestInterceptor.onTerminate(streamId, FrameType.REQUEST_STREAM, t); @@ -261,7 +245,7 @@ void sendFirstPayload(Payload payload, long initialRequestN) { final ByteBuf cancelFrame = CancelFrameCodec.encode(allocator, streamId); connection.sendFrame(streamId, cancelFrame); - sm.remove(streamId, this); + channel.remove(streamId, this); if (requestInterceptor != null) { requestInterceptor.onCancel(streamId, FrameType.REQUEST_STREAM); @@ -296,14 +280,14 @@ public final void cancel() { if (isFirstFrameSent(previousState)) { final int streamId = this.streamId; + final ChannelSupport channel = this.channel; ReassemblyUtils.synchronizedRelease(this, previousState); - this.connection.sendFrame(streamId, CancelFrameCodec.encode(this.allocator, streamId)); - - this.requesterResponderSupport.remove(streamId, this); + channel.connection.sendFrame(streamId, CancelFrameCodec.encode(channel.allocator, streamId)); + channel.remove(streamId, this); - final RequestInterceptor requestInterceptor = this.requestInterceptor; + final RequestInterceptor requestInterceptor = channel.requestInterceptor; if (requestInterceptor != null) { requestInterceptor.onCancel(streamId, FrameType.REQUEST_STREAM); } @@ -331,15 +315,15 @@ public final void handlePayload(Payload p) { } final int streamId = this.streamId; + final ChannelSupport channel = this.channel; - final IllegalStateException cause = - Exceptions.failWithOverflow( - "The number of messages received exceeds the number requested"); - this.connection.sendFrame(streamId, CancelFrameCodec.encode(this.allocator, streamId)); + final IllegalStateException cause = Exceptions.failWithOverflow( + "The number of messages received exceeds the number requested"); + channel.connection.sendFrame(streamId, CancelFrameCodec.encode(channel.allocator, streamId)); - this.requesterResponderSupport.remove(streamId, this); + channel.remove(streamId, this); - final RequestInterceptor requestInterceptor = this.requestInterceptor; + final RequestInterceptor requestInterceptor = channel.requestInterceptor; if (requestInterceptor != null) { requestInterceptor.onTerminate(streamId, FrameType.REQUEST_STREAM, cause); } @@ -367,9 +351,9 @@ public final void handleComplete() { } final int streamId = this.streamId; - this.requesterResponderSupport.remove(streamId, this); + channel.remove(streamId, this); - final RequestInterceptor requestInterceptor = this.requestInterceptor; + final RequestInterceptor requestInterceptor = channel.requestInterceptor; if (requestInterceptor != null) { requestInterceptor.onTerminate(streamId, FrameType.REQUEST_STREAM, null); } @@ -388,7 +372,7 @@ public final void handlePermitError(Throwable cause) { } final Payload p = this.payload; - final RequestInterceptor requestInterceptor = this.requestInterceptor; + final RequestInterceptor requestInterceptor = channel.requestInterceptor; if (requestInterceptor != null) { requestInterceptor.onReject(cause, FrameType.REQUEST_STREAM, p.metadata()); } @@ -413,11 +397,11 @@ public final void handleError(Throwable cause) { } final int streamId = this.streamId; - this.requesterResponderSupport.remove(streamId, this); + channel.remove(streamId, this); ReassemblyUtils.synchronizedRelease(this, previousState); - final RequestInterceptor requestInterceptor = this.requestInterceptor; + final RequestInterceptor requestInterceptor = channel.requestInterceptor; if (requestInterceptor != null) { requestInterceptor.onTerminate(streamId, FrameType.REQUEST_STREAM, cause); } @@ -432,9 +416,9 @@ public void handleNext(ByteBuf frame, boolean hasFollows, boolean isLastPayload) this, this, this.inboundSubscriber, - this.payloadDecoder, - this.allocator, - this.maxInboundPayloadSize, + channel.payloadDecoder, + channel.allocator, + channel.maxInboundPayloadSize, frame, hasFollows, isLastPayload); diff --git a/today-remoting/src/main/java/infra/remoting/core/RequestStreamResponderSubscriber.java b/today-remoting/src/main/java/infra/remoting/core/RequestStreamResponderSubscriber.java index f94cd33..c948d59 100644 --- a/today-remoting/src/main/java/infra/remoting/core/RequestStreamResponderSubscriber.java +++ b/today-remoting/src/main/java/infra/remoting/core/RequestStreamResponderSubscriber.java @@ -58,7 +58,7 @@ final class RequestStreamResponderSubscriber final int mtu; final int maxFrameLength; final int maxInboundPayloadSize; - final RequesterResponderSupport requesterResponderSupport; + final ChannelSupport channelSupport; final DuplexConnection connection; @Nullable @@ -78,18 +78,18 @@ public RequestStreamResponderSubscriber( int streamId, long firstRequest, ByteBuf firstFrame, - RequesterResponderSupport requesterResponderSupport, + ChannelSupport channelSupport, Channel handler) { this.streamId = streamId; this.firstRequest = firstRequest; - this.allocator = requesterResponderSupport.getAllocator(); - this.mtu = requesterResponderSupport.getMtu(); - this.maxFrameLength = requesterResponderSupport.getMaxFrameLength(); - this.maxInboundPayloadSize = requesterResponderSupport.getMaxInboundPayloadSize(); - this.requesterResponderSupport = requesterResponderSupport; - this.connection = requesterResponderSupport.getDuplexConnection(); - this.payloadDecoder = requesterResponderSupport.getPayloadDecoder(); - this.requestInterceptor = requesterResponderSupport.getRequestInterceptor(); + this.allocator = channelSupport.getAllocator(); + this.mtu = channelSupport.getMtu(); + this.maxFrameLength = channelSupport.getMaxFrameLength(); + this.maxInboundPayloadSize = channelSupport.getMaxInboundPayloadSize(); + this.channelSupport = channelSupport; + this.connection = channelSupport.getDuplexConnection(); + this.payloadDecoder = channelSupport.getPayloadDecoder(); + this.requestInterceptor = channelSupport.getRequestInterceptor(); this.handler = handler; this.frames = ReassemblyUtils.addFollowingFrame( @@ -97,16 +97,16 @@ public RequestStreamResponderSubscriber( } public RequestStreamResponderSubscriber( - int streamId, long firstRequest, RequesterResponderSupport requesterResponderSupport) { + int streamId, long firstRequest, ChannelSupport channelSupport) { this.streamId = streamId; this.firstRequest = firstRequest; - this.allocator = requesterResponderSupport.getAllocator(); - this.mtu = requesterResponderSupport.getMtu(); - this.maxFrameLength = requesterResponderSupport.getMaxFrameLength(); - this.maxInboundPayloadSize = requesterResponderSupport.getMaxInboundPayloadSize(); - this.requesterResponderSupport = requesterResponderSupport; - this.connection = requesterResponderSupport.getDuplexConnection(); - this.requestInterceptor = requesterResponderSupport.getRequestInterceptor(); + this.allocator = channelSupport.getAllocator(); + this.mtu = channelSupport.getMtu(); + this.maxFrameLength = channelSupport.getMaxFrameLength(); + this.maxInboundPayloadSize = channelSupport.getMaxInboundPayloadSize(); + this.channelSupport = channelSupport; + this.connection = channelSupport.getDuplexConnection(); + this.requestInterceptor = channelSupport.getRequestInterceptor(); this.payloadDecoder = null; this.handler = null; @@ -148,7 +148,7 @@ public void onNext(Payload p) { final ByteBuf errorFrame = ErrorFrameCodec.encode(allocator, streamId, e); sender.sendFrame(streamId, errorFrame); - this.requesterResponderSupport.remove(streamId, this); + this.channelSupport.remove(streamId, this); final RequestInterceptor requestInterceptor = this.requestInterceptor; if (requestInterceptor != null) { @@ -169,7 +169,7 @@ public void onNext(Payload p) { new CanceledException("Failed to validate payload. Cause" + e.getMessage())); sender.sendFrame(streamId, errorFrame); - this.requesterResponderSupport.remove(streamId, this); + this.channelSupport.remove(streamId, this); final RequestInterceptor requestInterceptor = this.requestInterceptor; if (requestInterceptor != null) { @@ -186,7 +186,7 @@ public void onNext(Payload p) { return; } - this.requesterResponderSupport.remove(streamId, this); + this.channelSupport.remove(streamId, this); final RequestInterceptor requestInterceptor = this.requestInterceptor; if (requestInterceptor != null) { @@ -236,7 +236,7 @@ public void onError(Throwable t) { final ByteBuf errorFrame = ErrorFrameCodec.encode(this.allocator, streamId, t); this.connection.sendFrame(streamId, errorFrame); - this.requesterResponderSupport.remove(streamId, this); + this.channelSupport.remove(streamId, this); final RequestInterceptor requestInterceptor = this.requestInterceptor; if (requestInterceptor != null) { @@ -261,7 +261,7 @@ public void onComplete() { final ByteBuf completeFrame = PayloadFrameCodec.encodeComplete(this.allocator, streamId); this.connection.sendFrame(streamId, completeFrame); - this.requesterResponderSupport.remove(streamId, this); + this.channelSupport.remove(streamId, this); final RequestInterceptor requestInterceptor = this.requestInterceptor; if (requestInterceptor != null) { @@ -287,7 +287,7 @@ public final void handleCancel() { S.lazySet(this, Operators.cancelledSubscription()); final int streamId = this.streamId; - this.requesterResponderSupport.remove(streamId, this); + this.channelSupport.remove(streamId, this); final CompositeByteBuf frames = this.frames; if (frames != null) { @@ -307,7 +307,7 @@ public final void handleCancel() { } final int streamId = this.streamId; - this.requesterResponderSupport.remove(streamId, this); + this.channelSupport.remove(streamId, this); currentSubscription.cancel(); @@ -346,7 +346,7 @@ public void handleNext(ByteBuf followingFrame, boolean hasFollows, boolean isLas new CanceledException("Failed to reassemble payload. Cause: " + e.getMessage())); this.connection.sendFrame(streamId, errorFrame); - this.requesterResponderSupport.remove(streamId, this); + this.channelSupport.remove(streamId, this); final RequestInterceptor requestInterceptor = this.requestInterceptor; if (requestInterceptor != null) { @@ -380,7 +380,7 @@ public void handleNext(ByteBuf followingFrame, boolean hasFollows, boolean isLas new CanceledException("Failed to reassemble payload. Cause: " + t.getMessage())); this.connection.sendFrame(streamId, errorFrame); - this.requesterResponderSupport.remove(streamId, this); + this.channelSupport.remove(streamId, this); final RequestInterceptor requestInterceptor = this.requestInterceptor; if (requestInterceptor != null) { diff --git a/today-remoting/src/main/java/infra/remoting/core/SendUtils.java b/today-remoting/src/main/java/infra/remoting/core/SendUtils.java index caaa657..b7b4491 100644 --- a/today-remoting/src/main/java/infra/remoting/core/SendUtils.java +++ b/today-remoting/src/main/java/infra/remoting/core/SendUtils.java @@ -40,29 +40,22 @@ import static infra.remoting.core.FragmentationUtils.isFragmentable; final class SendUtils { - private static final Consumer DROPPED_ELEMENTS_CONSUMER = - data -> { - if (data instanceof ReferenceCounted) { - try { - ReferenceCounted referenceCounted = (ReferenceCounted) data; - referenceCounted.release(); - } - catch (Throwable e) { - // ignored - } - } - }; + + private static final Consumer DROPPED_ELEMENTS_CONSUMER = data -> { + if (data instanceof ReferenceCounted rc) { + try { + rc.release(); + } + catch (Throwable e) { + // ignored + } + } + }; static final Context DISCARD_CONTEXT = Operators.enableOnDiscard(null, DROPPED_ELEMENTS_CONSUMER); - static void sendReleasingPayload( - int streamId, - FrameType frameType, - int mtu, - Payload payload, - DuplexConnection connection, - ByteBufAllocator allocator, - boolean requester) { + static void sendReleasingPayload(int streamId, FrameType frameType, int mtu, Payload payload, + DuplexConnection connection, ByteBufAllocator allocator, boolean requester) { final boolean hasMetadata = payload.hasMetadata(); final ByteBuf metadata = hasMetadata ? payload.metadata() : null; @@ -83,9 +76,8 @@ static void sendReleasingPayload( final ByteBuf first; try { - first = - FragmentationUtils.encodeFirstFragment( - allocator, mtu, frameType, streamId, hasMetadata, slicedMetadata, slicedData); + first = FragmentationUtils.encodeFirstFragment( + allocator, mtu, frameType, streamId, hasMetadata, slicedMetadata, slicedData); } catch (IllegalReferenceCountException e) { sendTerminalFrame(streamId, frameType, connection, allocator, requester, false, e); @@ -98,9 +90,8 @@ static void sendReleasingPayload( while (slicedData.isReadable() || slicedMetadata.isReadable()) { final ByteBuf following; try { - following = - FragmentationUtils.encodeFollowsFragment( - allocator, mtu, streamId, complete, slicedMetadata, slicedData); + following = FragmentationUtils.encodeFollowsFragment( + allocator, mtu, streamId, complete, slicedMetadata, slicedData); } catch (IllegalReferenceCountException e) { sendTerminalFrame(streamId, frameType, connection, allocator, requester, true, e); @@ -144,48 +135,20 @@ static void sendReleasingPayload( throw e; } - final ByteBuf requestFrame; - switch (frameType) { - case REQUEST_FNF: - requestFrame = - RequestFireAndForgetFrameCodec.encode( - allocator, streamId, false, metadataRetainedSlice, dataRetainedSlice); - break; - case REQUEST_RESPONSE: - requestFrame = - RequestResponseFrameCodec.encode( - allocator, streamId, false, metadataRetainedSlice, dataRetainedSlice); - break; - case PAYLOAD: - case NEXT: - case NEXT_COMPLETE: - requestFrame = - PayloadFrameCodec.encode( - allocator, - streamId, - false, - frameType == FrameType.NEXT_COMPLETE, - frameType != FrameType.PAYLOAD, - metadataRetainedSlice, - dataRetainedSlice); - break; - default: - throw new IllegalArgumentException("Unsupported frame type " + frameType); - } + final ByteBuf requestFrame = switch (frameType) { + case REQUEST_FNF -> RequestFireAndForgetFrameCodec.encode(allocator, streamId, false, metadataRetainedSlice, dataRetainedSlice); + case REQUEST_RESPONSE -> RequestResponseFrameCodec.encode(allocator, streamId, false, metadataRetainedSlice, dataRetainedSlice); + case PAYLOAD, NEXT, NEXT_COMPLETE -> PayloadFrameCodec.encode(allocator, streamId, false, + frameType == FrameType.NEXT_COMPLETE, frameType != FrameType.PAYLOAD, metadataRetainedSlice, dataRetainedSlice); + default -> throw new IllegalArgumentException("Unsupported frame type " + frameType); + }; connection.sendFrame(streamId, requestFrame); } } - static void sendReleasingPayload( - int streamId, - FrameType frameType, - long initialRequestN, - int mtu, - Payload payload, - DuplexConnection connection, - ByteBufAllocator allocator, - boolean complete) { + static void sendReleasingPayload(int streamId, FrameType frameType, long initialRequestN, int mtu, + Payload payload, DuplexConnection connection, ByteBufAllocator allocator, boolean complete) { final boolean hasMetadata = payload.hasMetadata(); final ByteBuf metadata = hasMetadata ? payload.metadata() : null; @@ -206,16 +169,8 @@ static void sendReleasingPayload( final ByteBuf first; try { - first = - FragmentationUtils.encodeFirstFragment( - allocator, - mtu, - initialRequestN, - frameType, - streamId, - hasMetadata, - slicedMetadata, - slicedData); + first = FragmentationUtils.encodeFirstFragment(allocator, mtu, initialRequestN, + frameType, streamId, hasMetadata, slicedMetadata, slicedData); } catch (IllegalReferenceCountException e) { sendTerminalFrame(streamId, frameType, connection, allocator, true, false, e); @@ -227,9 +182,8 @@ static void sendReleasingPayload( while (slicedData.isReadable() || slicedMetadata.isReadable()) { final ByteBuf following; try { - following = - FragmentationUtils.encodeFollowsFragment( - allocator, mtu, streamId, complete, slicedMetadata, slicedData); + following = FragmentationUtils.encodeFollowsFragment( + allocator, mtu, streamId, complete, slicedMetadata, slicedData); } catch (IllegalReferenceCountException e) { sendTerminalFrame(streamId, frameType, connection, allocator, true, true, e); @@ -273,45 +227,20 @@ static void sendReleasingPayload( throw e; } - final ByteBuf requestFrame; - switch (frameType) { - case REQUEST_STREAM: - requestFrame = - RequestStreamFrameCodec.encode( - allocator, - streamId, - false, - initialRequestN, - metadataRetainedSlice, - dataRetainedSlice); - break; - case REQUEST_CHANNEL: - requestFrame = - RequestChannelFrameCodec.encode( - allocator, - streamId, - false, - complete, - initialRequestN, - metadataRetainedSlice, - dataRetainedSlice); - break; - default: - throw new IllegalArgumentException("Unsupported frame type " + frameType); - } + final ByteBuf requestFrame = switch (frameType) { + case REQUEST_STREAM -> RequestStreamFrameCodec.encode(allocator, streamId, false, initialRequestN, + metadataRetainedSlice, dataRetainedSlice); + case REQUEST_CHANNEL -> RequestChannelFrameCodec.encode(allocator, streamId, false, complete, + initialRequestN, metadataRetainedSlice, dataRetainedSlice); + default -> throw new IllegalArgumentException("Unsupported frame type " + frameType); + }; connection.sendFrame(streamId, requestFrame); } } - static void sendTerminalFrame( - int streamId, - FrameType frameType, - DuplexConnection connection, - ByteBufAllocator allocator, - boolean requester, - boolean onFollowingFrame, - Throwable t) { + static void sendTerminalFrame(int streamId, FrameType frameType, DuplexConnection connection, + ByteBufAllocator allocator, boolean requester, boolean onFollowingFrame, Throwable t) { if (onFollowingFrame) { if (requester) { @@ -319,15 +248,8 @@ static void sendTerminalFrame( connection.sendFrame(streamId, cancelFrame); } else { - final ByteBuf errorFrame = - ErrorFrameCodec.encode( - allocator, - streamId, - new CanceledException( - "Failed to encode fragmented " - + frameType - + " frame. Cause: " - + t.getMessage())); + final ByteBuf errorFrame = ErrorFrameCodec.encode(allocator, streamId, + new CanceledException("Failed to encode fragmented %s frame. Cause: %s".formatted(frameType, t.getMessage()))); connection.sendFrame(streamId, errorFrame); } } @@ -341,12 +263,8 @@ static void sendTerminalFrame( connection.sendFrame(streamId, cancelFrame); } else { - final ByteBuf errorFrame = - ErrorFrameCodec.encode( - allocator, - streamId, - new CanceledException( - "Failed to encode " + frameType + " frame. Cause: " + t.getMessage())); + final ByteBuf errorFrame = ErrorFrameCodec.encode(allocator, streamId, new CanceledException( + "Failed to encode %s frame. Cause: %s".formatted(frameType, t.getMessage()))); connection.sendFrame(streamId, errorFrame); } } diff --git a/today-remoting/src/main/java/infra/remoting/core/SlowFireAndForgetRequesterMono.java b/today-remoting/src/main/java/infra/remoting/core/SlowFireAndForgetRequesterMono.java index accdfd6..015a4dc 100644 --- a/today-remoting/src/main/java/infra/remoting/core/SlowFireAndForgetRequesterMono.java +++ b/today-remoting/src/main/java/infra/remoting/core/SlowFireAndForgetRequesterMono.java @@ -22,11 +22,9 @@ import infra.lang.NonNull; import infra.lang.Nullable; -import infra.remoting.DuplexConnection; import infra.remoting.Payload; import infra.remoting.frame.FrameType; import infra.remoting.plugins.RequestInterceptor; -import io.netty.buffer.ByteBufAllocator; import io.netty.util.IllegalReferenceCountException; import reactor.core.CoreSubscriber; import reactor.core.Exceptions; @@ -55,29 +53,17 @@ final class SlowFireAndForgetRequesterMono extends Mono final Payload payload; - final ByteBufAllocator allocator; - final int mtu; - final int maxFrameLength; - final RequesterResponderSupport requesterResponderSupport; - final DuplexConnection connection; + final ChannelSupport channel; @Nullable final RequesterLeaseTracker requesterLeaseTracker; - @Nullable - final RequestInterceptor requestInterceptor; CoreSubscriber actual; - SlowFireAndForgetRequesterMono( - Payload payload, RequesterResponderSupport requesterResponderSupport) { - this.allocator = requesterResponderSupport.getAllocator(); + SlowFireAndForgetRequesterMono(Payload payload, ChannelSupport channel) { this.payload = payload; - this.mtu = requesterResponderSupport.getMtu(); - this.maxFrameLength = requesterResponderSupport.getMaxFrameLength(); - this.requesterResponderSupport = requesterResponderSupport; - this.connection = requesterResponderSupport.getDuplexConnection(); - this.requestInterceptor = requesterResponderSupport.getRequestInterceptor(); - this.requesterLeaseTracker = requesterResponderSupport.getRequesterLeaseTracker(); + this.channel = channel; + this.requesterLeaseTracker = channel.getRequesterLeaseTracker(); } @Override @@ -89,7 +75,7 @@ public void subscribe(CoreSubscriber actual) { final IllegalStateException e = new IllegalStateException("FireAndForgetMono allows only a single Subscriber"); - final RequestInterceptor requestInterceptor = this.requestInterceptor; + final RequestInterceptor requestInterceptor = channel.requestInterceptor; if (requestInterceptor != null) { requestInterceptor.onReject(e, FrameType.REQUEST_FNF, null); } @@ -99,15 +85,14 @@ public void subscribe(CoreSubscriber actual) { } final Payload p = this.payload; - int mtu = this.mtu; try { - if (!isValid(mtu, this.maxFrameLength, p, false)) { + if (!isValid(channel.mtu, channel.maxFrameLength, p, false)) { lazyTerminate(STATE, this); final IllegalArgumentException e = new IllegalArgumentException( - String.format(INVALID_PAYLOAD_ERROR_MESSAGE, this.maxFrameLength)); - final RequestInterceptor requestInterceptor = this.requestInterceptor; + String.format(INVALID_PAYLOAD_ERROR_MESSAGE, channel.maxFrameLength)); + final RequestInterceptor requestInterceptor = channel.requestInterceptor; if (requestInterceptor != null) { requestInterceptor.onReject(e, FrameType.REQUEST_FNF, p.metadata()); } @@ -121,7 +106,7 @@ public void subscribe(CoreSubscriber actual) { catch (IllegalReferenceCountException e) { lazyTerminate(STATE, this); - final RequestInterceptor requestInterceptor = this.requestInterceptor; + final RequestInterceptor requestInterceptor = channel.requestInterceptor; if (requestInterceptor != null) { requestInterceptor.onReject(e, FrameType.REQUEST_FNF, null); } @@ -157,13 +142,13 @@ void sendFirstFrame(Payload p) { final CoreSubscriber actual = this.actual; final int streamId; try { - streamId = this.requesterResponderSupport.getNextStreamId(); + streamId = this.channel.getNextStreamId(); } catch (Throwable t) { lazyTerminate(STATE, this); final Throwable ut = Exceptions.unwrap(t); - final RequestInterceptor requestInterceptor = this.requestInterceptor; + final RequestInterceptor requestInterceptor = channel.requestInterceptor; if (requestInterceptor != null) { requestInterceptor.onReject(ut, FrameType.REQUEST_FNF, p.metadata()); } @@ -174,7 +159,7 @@ void sendFirstFrame(Payload p) { return; } - final RequestInterceptor interceptor = this.requestInterceptor; + final RequestInterceptor interceptor = channel.requestInterceptor; if (interceptor != null) { interceptor.onStart(streamId, FrameType.REQUEST_FNF, p.metadata()); } @@ -191,7 +176,7 @@ void sendFirstFrame(Payload p) { } sendReleasingPayload( - streamId, FrameType.REQUEST_FNF, mtu, p, this.connection, this.allocator, true); + streamId, FrameType.REQUEST_FNF, channel.mtu, p, channel.connection, channel.allocator, true); } catch (Throwable e) { lazyTerminate(STATE, this); @@ -240,7 +225,7 @@ public final void handlePermitError(Throwable cause) { } final Payload p = this.payload; - final RequestInterceptor requestInterceptor = this.requestInterceptor; + final RequestInterceptor requestInterceptor = channel.requestInterceptor; if (requestInterceptor != null) { requestInterceptor.onReject(cause, FrameType.REQUEST_RESPONSE, p.metadata()); } @@ -250,6 +235,7 @@ public final void handlePermitError(Throwable cause) { this.actual.onError(cause); } + @Nullable @Override public Object scanUnsafe(Attr key) { return null; // no particular key to be represented, still useful in hooks diff --git a/today-remoting/src/test/java/infra/remoting/core/ChannelRequesterTests.java b/today-remoting/src/test/java/infra/remoting/core/ChannelRequesterTests.java index 9639b6c..8b6c239 100644 --- a/today-remoting/src/test/java/infra/remoting/core/ChannelRequesterTests.java +++ b/today-remoting/src/test/java/infra/remoting/core/ChannelRequesterTests.java @@ -90,11 +90,11 @@ import static infra.remoting.core.PayloadValidationUtils.INVALID_PAYLOAD_ERROR_MESSAGE; import static infra.remoting.core.ReassemblyUtils.ILLEGAL_REASSEMBLED_PAYLOAD_SIZE; -import static infra.remoting.core.TestRequesterResponderSupport.fixedSizePayload; -import static infra.remoting.core.TestRequesterResponderSupport.genericPayload; -import static infra.remoting.core.TestRequesterResponderSupport.prepareFragments; -import static infra.remoting.core.TestRequesterResponderSupport.randomMetadataOnlyPayload; -import static infra.remoting.core.TestRequesterResponderSupport.randomPayload; +import static infra.remoting.core.TestChannelSupport.fixedSizePayload; +import static infra.remoting.core.TestChannelSupport.genericPayload; +import static infra.remoting.core.TestChannelSupport.prepareFragments; +import static infra.remoting.core.TestChannelSupport.randomMetadataOnlyPayload; +import static infra.remoting.core.TestChannelSupport.randomPayload; import static infra.remoting.frame.FrameHeaderCodec.frameType; import static infra.remoting.frame.FrameLengthCodec.FRAME_LENGTH_MASK; import static infra.remoting.frame.FrameType.CANCEL; diff --git a/today-remoting/src/test/java/infra/remoting/core/ChannelResponderTests.java b/today-remoting/src/test/java/infra/remoting/core/ChannelResponderTests.java index 0cc9a37..0ff21fd 100644 --- a/today-remoting/src/test/java/infra/remoting/core/ChannelResponderTests.java +++ b/today-remoting/src/test/java/infra/remoting/core/ChannelResponderTests.java @@ -82,11 +82,11 @@ import static infra.remoting.core.PayloadValidationUtils.INVALID_PAYLOAD_ERROR_MESSAGE; import static infra.remoting.core.ReassemblyUtils.ILLEGAL_REASSEMBLED_PAYLOAD_SIZE; -import static infra.remoting.core.TestRequesterResponderSupport.fixedSizePayload; -import static infra.remoting.core.TestRequesterResponderSupport.genericPayload; -import static infra.remoting.core.TestRequesterResponderSupport.prepareFragments; -import static infra.remoting.core.TestRequesterResponderSupport.randomMetadataOnlyPayload; -import static infra.remoting.core.TestRequesterResponderSupport.randomPayload; +import static infra.remoting.core.TestChannelSupport.fixedSizePayload; +import static infra.remoting.core.TestChannelSupport.genericPayload; +import static infra.remoting.core.TestChannelSupport.prepareFragments; +import static infra.remoting.core.TestChannelSupport.randomMetadataOnlyPayload; +import static infra.remoting.core.TestChannelSupport.randomPayload; import static infra.remoting.frame.FrameHeaderCodec.frameType; import static infra.remoting.frame.FrameLengthCodec.FRAME_LENGTH_MASK; import static infra.remoting.frame.FrameType.COMPLETE; @@ -894,8 +894,8 @@ public Flux requestChannel(Publisher payloads) { if (frameType != REQUEST_FNF) { FrameAssert.assertThat(rule.connection.getSent().poll()) .typeOf(frameType == REQUEST_RESPONSE ? NEXT_COMPLETE : NEXT) - .hasData(TestRequesterResponderSupport.DATA_CONTENT) - .hasMetadata(TestRequesterResponderSupport.METADATA_CONTENT) + .hasData(TestChannelSupport.DATA_CONTENT) + .hasMetadata(TestChannelSupport.METADATA_CONTENT) .hasNoLeaks(); if (frameType != REQUEST_RESPONSE) { FrameAssert.assertThat(rule.connection.getSent().poll()).typeOf(COMPLETE).hasNoLeaks(); @@ -952,8 +952,8 @@ public Flux requestChannel(Publisher payloads) { if (frameType != REQUEST_FNF) { FrameAssert.assertThat(rule.connection.getSent().poll()) .typeOf(frameType == REQUEST_RESPONSE ? NEXT_COMPLETE : NEXT) - .hasData(TestRequesterResponderSupport.DATA_CONTENT) - .hasMetadata(TestRequesterResponderSupport.METADATA_CONTENT) + .hasData(TestChannelSupport.DATA_CONTENT) + .hasMetadata(TestChannelSupport.METADATA_CONTENT) .hasNoLeaks(); if (frameType != REQUEST_RESPONSE) { FrameAssert.assertThat(rule.connection.getSent().poll()).typeOf(COMPLETE).hasNoLeaks(); diff --git a/today-remoting/src/test/java/infra/remoting/core/FireAndForgetRequesterMonoTest.java b/today-remoting/src/test/java/infra/remoting/core/FireAndForgetRequesterMonoTest.java index 72b9b32..5170b25 100644 --- a/today-remoting/src/test/java/infra/remoting/core/FireAndForgetRequesterMonoTest.java +++ b/today-remoting/src/test/java/infra/remoting/core/FireAndForgetRequesterMonoTest.java @@ -49,7 +49,7 @@ import static infra.remoting.core.FragmentationUtils.FRAME_OFFSET; import static infra.remoting.core.FragmentationUtils.FRAME_OFFSET_WITH_METADATA; import static infra.remoting.core.PayloadValidationUtils.INVALID_PAYLOAD_ERROR_MESSAGE; -import static infra.remoting.core.TestRequesterResponderSupport.genericPayload; +import static infra.remoting.core.TestChannelSupport.genericPayload; import static infra.remoting.frame.FrameLengthCodec.FRAME_LENGTH_MASK; public class FireAndForgetRequesterMonoTest { @@ -67,8 +67,8 @@ public static void setUp() { @MethodSource("frameSent") public void frameShouldBeSentOnSubscription(Consumer monoConsumer) { final TestRequestInterceptor testRequestInterceptor = new TestRequestInterceptor(); - final TestRequesterResponderSupport activeStreams = - TestRequesterResponderSupport.client(testRequestInterceptor); + final TestChannelSupport activeStreams = + TestChannelSupport.client(testRequestInterceptor); final Payload payload = genericPayload(activeStreams.getAllocator()); final FireAndForgetRequesterMono fireAndForgetRequesterMono = new FireAndForgetRequesterMono(payload, activeStreams); @@ -116,7 +116,7 @@ public void frameShouldBeSentOnSubscription(Consumer public void frameFragmentsShouldBeSentOnSubscription( Consumer monoConsumer) { final int mtu = 64; - final TestRequesterResponderSupport streamManager = TestRequesterResponderSupport.client(mtu); + final TestChannelSupport streamManager = TestChannelSupport.client(mtu); final LeaksTrackingByteBufAllocator allocator = streamManager.getAllocator(); final TestDuplexConnection sender = streamManager.getDuplexConnection(); @@ -215,8 +215,8 @@ static Stream> frameSent() { public void shouldErrorOnIncorrectRefCntInGivenPayload( Consumer monoConsumer) { final TestRequestInterceptor testRequestInterceptor = new TestRequestInterceptor(); - final TestRequesterResponderSupport streamManager = - TestRequesterResponderSupport.client(testRequestInterceptor); + final TestChannelSupport streamManager = + TestChannelSupport.client(testRequestInterceptor); final LeaksTrackingByteBufAllocator allocator = streamManager.getAllocator(); final TestDuplexConnection sender = streamManager.getDuplexConnection(); final Payload payload = ByteBufPayload.create(""); @@ -264,8 +264,8 @@ public void shouldErrorOnIncorrectRefCntInGivenPayload( public void shouldErrorIfFragmentExitsAllowanceIfFragmentationDisabled( Consumer monoConsumer) { final TestRequestInterceptor testRequestInterceptor = new TestRequestInterceptor(); - final TestRequesterResponderSupport streamManager = - TestRequesterResponderSupport.client(testRequestInterceptor); + final TestChannelSupport streamManager = + TestChannelSupport.client(testRequestInterceptor); final LeaksTrackingByteBufAllocator allocator = streamManager.getAllocator(); final TestDuplexConnection sender = streamManager.getDuplexConnection(); @@ -329,8 +329,8 @@ public void shouldErrorIfFragmentExitsAllowanceIfFragmentationDisabled( public void shouldErrorIfNoAvailability(Consumer monoConsumer) { final TestRequestInterceptor testRequestInterceptor = new TestRequestInterceptor(); final RuntimeException exception = new RuntimeException("test"); - final TestRequesterResponderSupport streamManager = - TestRequesterResponderSupport.client(exception, testRequestInterceptor); + final TestChannelSupport streamManager = + TestChannelSupport.client(exception, testRequestInterceptor); final LeaksTrackingByteBufAllocator allocator = streamManager.getAllocator(); final TestDuplexConnection sender = streamManager.getDuplexConnection(); final Payload payload = genericPayload(allocator); @@ -375,8 +375,8 @@ static Stream> shouldErrorIfNoAvailabilityS @Test public void shouldSubscribeExactlyOnce1() { final TestRequestInterceptor testRequestInterceptor = new TestRequestInterceptor(); - final TestRequesterResponderSupport streamManager = - TestRequesterResponderSupport.client(testRequestInterceptor); + final TestChannelSupport streamManager = + TestChannelSupport.client(testRequestInterceptor); final LeaksTrackingByteBufAllocator allocator = streamManager.getAllocator(); final TestDuplexConnection sender = streamManager.getDuplexConnection(); @@ -452,8 +452,8 @@ public void shouldSubscribeExactlyOnce1() { @Test public void checkName() { - final TestRequesterResponderSupport testRequesterResponderSupport = - TestRequesterResponderSupport.client(); + final TestChannelSupport testRequesterResponderSupport = + TestChannelSupport.client(); final LeaksTrackingByteBufAllocator allocator = testRequesterResponderSupport.getAllocator(); final Payload payload = ByteBufPayload.create("testData", "testMetadata"); diff --git a/today-remoting/src/test/java/infra/remoting/core/RequestChannelRequesterFluxTest.java b/today-remoting/src/test/java/infra/remoting/core/RequestChannelRequesterFluxTest.java index dc214ad..913e701 100644 --- a/today-remoting/src/test/java/infra/remoting/core/RequestChannelRequesterFluxTest.java +++ b/today-remoting/src/test/java/infra/remoting/core/RequestChannelRequesterFluxTest.java @@ -70,10 +70,10 @@ public static void setUp() { @ParameterizedTest @ValueSource(strings = { "inbound", "outbound" }) public void requestNFrameShouldBeSentOnSubscriptionAndThenSeparately(String completionCase) { - final TestRequesterResponderSupport activeStreams = TestRequesterResponderSupport.client(); + final TestChannelSupport activeStreams = TestChannelSupport.client(); final LeaksTrackingByteBufAllocator allocator = activeStreams.getAllocator(); final TestDuplexConnection sender = activeStreams.getDuplexConnection(); - final Payload payload = TestRequesterResponderSupport.genericPayload(allocator); + final Payload payload = TestChannelSupport.genericPayload(allocator); final TestPublisher publisher = TestPublisher.create(); final RequestChannelRequesterFlux requestChannelRequesterFlux = @@ -163,13 +163,13 @@ public void requestNFrameShouldBeSentOnSubscriptionAndThenSeparately(String comp // state machine check stateAssert.hasSubscribedFlag().hasRequestN(Integer.MAX_VALUE).hasFirstFrameSentFlag(); - Payload nextPayload = TestRequesterResponderSupport.genericPayload(allocator); + Payload nextPayload = TestChannelSupport.genericPayload(allocator); requestChannelRequesterFlux.handlePayload(nextPayload); int mtu = ThreadLocalRandom.current().nextInt(64, 256); - Payload randomPayload = TestRequesterResponderSupport.randomPayload(allocator); + Payload randomPayload = TestChannelSupport.randomPayload(allocator); ArrayList fragments = - TestRequesterResponderSupport.prepareFragments(allocator, mtu, randomPayload); + TestChannelSupport.prepareFragments(allocator, mtu, randomPayload); ByteBuf firstFragment = fragments.remove(0); requestChannelRequesterFlux.handleNext(firstFragment, true, false); @@ -252,7 +252,7 @@ else if (completionCase.equals("outbound")) { @ParameterizedTest @ValueSource(booleans = { true, false }) public void streamShouldErrorWithoutInitializingRemoteStreamIfSourceIsEmpty(boolean doRequest) { - final TestRequesterResponderSupport activeStreams = TestRequesterResponderSupport.client(); + final TestChannelSupport activeStreams = TestChannelSupport.client(); final LeaksTrackingByteBufAllocator allocator = activeStreams.getAllocator(); final TestDuplexConnection sender = activeStreams.getDuplexConnection(); final TestPublisher publisher = TestPublisher.create(); @@ -297,7 +297,7 @@ public void streamShouldErrorWithoutInitializingRemoteStreamIfSourceIsEmpty(bool @ValueSource(booleans = { true, false }) public void streamShouldPropagateErrorWithoutInitializingRemoteStreamIfTheFirstSignalIsError( boolean doRequest) { - final TestRequesterResponderSupport activeStreams = TestRequesterResponderSupport.client(); + final TestChannelSupport activeStreams = TestChannelSupport.client(); final LeaksTrackingByteBufAllocator allocator = activeStreams.getAllocator(); final TestDuplexConnection sender = activeStreams.getDuplexConnection(); final TestPublisher publisher = TestPublisher.create(); @@ -341,7 +341,7 @@ public void streamShouldPropagateErrorWithoutInitializingRemoteStreamIfTheFirstS @ParameterizedTest @ValueSource(strings = { "inbound", "outbound" }) public void streamShouldBeInHalfClosedStateOnTheInboundCancellation(String terminationMode) { - final TestRequesterResponderSupport activeStreams = TestRequesterResponderSupport.client(); + final TestChannelSupport activeStreams = TestChannelSupport.client(); final LeaksTrackingByteBufAllocator allocator = activeStreams.getAllocator(); final TestDuplexConnection sender = activeStreams.getDuplexConnection(); final TestPublisher publisher = TestPublisher.create(); @@ -367,9 +367,9 @@ public void streamShouldBeInHalfClosedStateOnTheInboundCancellation(String termi stateAssert.hasSubscribedFlag().hasRequestN(Integer.MAX_VALUE).hasNoFirstFrameSentFlag(); activeStreams.assertNoActiveStreams(); - Payload payload1 = TestRequesterResponderSupport.randomPayload(allocator); - Payload payload2 = TestRequesterResponderSupport.randomPayload(allocator); - Payload payload3 = TestRequesterResponderSupport.randomPayload(allocator); + Payload payload1 = TestChannelSupport.randomPayload(allocator); + Payload payload2 = TestChannelSupport.randomPayload(allocator); + Payload payload3 = TestChannelSupport.randomPayload(allocator); publisher.next(payload1.retain()); @@ -440,7 +440,7 @@ else if (terminationMode.equals("inbound")) { @ParameterizedTest @ValueSource(strings = { "inbound", "outbound" }) public void errorShouldTerminateExecution(String terminationMode) { - final TestRequesterResponderSupport activeStreams = TestRequesterResponderSupport.client(); + final TestChannelSupport activeStreams = TestChannelSupport.client(); final LeaksTrackingByteBufAllocator allocator = activeStreams.getAllocator(); final TestDuplexConnection sender = activeStreams.getDuplexConnection(); final TestPublisher publisher = TestPublisher.create(); @@ -466,9 +466,9 @@ public void errorShouldTerminateExecution(String terminationMode) { stateAssert.hasSubscribedFlag().hasRequestN(Integer.MAX_VALUE).hasNoFirstFrameSentFlag(); activeStreams.assertNoActiveStreams(); - Payload payload1 = TestRequesterResponderSupport.randomPayload(allocator); - Payload payload2 = TestRequesterResponderSupport.randomPayload(allocator); - Payload payload3 = TestRequesterResponderSupport.randomPayload(allocator); + Payload payload1 = TestChannelSupport.randomPayload(allocator); + Payload payload2 = TestChannelSupport.randomPayload(allocator); + Payload payload3 = TestChannelSupport.randomPayload(allocator); publisher.next(payload1.retain()); @@ -523,7 +523,7 @@ else if (terminationMode.equals("inbound")) { @Test public void failOnOverflow() { - final TestRequesterResponderSupport activeStreams = TestRequesterResponderSupport.client(); + final TestChannelSupport activeStreams = TestChannelSupport.client(); final LeaksTrackingByteBufAllocator allocator = activeStreams.getAllocator(); final TestDuplexConnection sender = activeStreams.getDuplexConnection(); final TestPublisher publisher = TestPublisher.create(); @@ -549,7 +549,7 @@ public void failOnOverflow() { stateAssert.hasSubscribedFlag().hasRequestN(1).hasNoFirstFrameSentFlag(); activeStreams.assertNoActiveStreams(); - Payload payload1 = TestRequesterResponderSupport.randomPayload(allocator); + Payload payload1 = TestChannelSupport.randomPayload(allocator); publisher.next(payload1.retain()); @@ -565,10 +565,10 @@ public void failOnOverflow() { publisher.assertMaxRequested(1); - Payload nextPayload = TestRequesterResponderSupport.genericPayload(allocator); + Payload nextPayload = TestChannelSupport.genericPayload(allocator); requestChannelRequesterFlux.handlePayload(nextPayload); - Payload unrequestedPayload = TestRequesterResponderSupport.genericPayload(allocator); + Payload unrequestedPayload = TestChannelSupport.genericPayload(allocator); requestChannelRequesterFlux.handlePayload(unrequestedPayload); final ByteBuf cancelFrame = sender.awaitFrame(); @@ -626,7 +626,7 @@ public void shouldHaveEventsDeliveredSeriallyWhenOutboundErrorRacingWithInboundS Hooks.onErrorDropped(droppedErrors::add); try { for (int i = 0; i < RaceTestConstants.REPEATS; i++) { - final TestRequesterResponderSupport activeStreams = TestRequesterResponderSupport.client(); + final TestChannelSupport activeStreams = TestChannelSupport.client(); final LeaksTrackingByteBufAllocator allocator = activeStreams.getAllocator(); final TestDuplexConnection sender = activeStreams.getDuplexConnection(); final TestPublisher publisher = @@ -651,7 +651,7 @@ public void shouldHaveEventsDeliveredSeriallyWhenOutboundErrorRacingWithInboundS stateAssert.hasSubscribedFlag().hasRequestN(Integer.MAX_VALUE).hasNoFirstFrameSentFlag(); activeStreams.assertNoActiveStreams(); - Payload requestPayload = TestRequesterResponderSupport.randomPayload(allocator); + Payload requestPayload = TestChannelSupport.randomPayload(allocator); publisher.next(requestPayload); stateAssert.hasSubscribedFlag().hasRequestN(Integer.MAX_VALUE).hasFirstFrameSentFlag(); @@ -663,9 +663,9 @@ public void shouldHaveEventsDeliveredSeriallyWhenOutboundErrorRacingWithInboundS requestChannelRequesterFlux.handleRequestN(Long.MAX_VALUE); - Payload responsePayload1 = TestRequesterResponderSupport.randomPayload(allocator); - Payload responsePayload2 = TestRequesterResponderSupport.randomPayload(allocator); - Payload responsePayload3 = TestRequesterResponderSupport.randomPayload(allocator); + Payload responsePayload1 = TestChannelSupport.randomPayload(allocator); + Payload responsePayload2 = TestChannelSupport.randomPayload(allocator); + Payload responsePayload3 = TestChannelSupport.randomPayload(allocator); Payload releasedPayload = ByteBufPayload.create(Unpooled.EMPTY_BUFFER); releasedPayload.release(); @@ -798,7 +798,7 @@ else if (inboundTerminationMode.equals("complete")) { public void shouldRemoveItselfFromActiveStreamsWhenInboundAndOutboundAreTerminated( String outboundTerminationMode) { for (int i = 0; i < RaceTestConstants.REPEATS; i++) { - final TestRequesterResponderSupport activeStreams = TestRequesterResponderSupport.client(); + final TestChannelSupport activeStreams = TestChannelSupport.client(); final LeaksTrackingByteBufAllocator allocator = activeStreams.getAllocator(); final TestDuplexConnection sender = activeStreams.getDuplexConnection(); final TestPublisher publisher = @@ -823,7 +823,7 @@ public void shouldRemoveItselfFromActiveStreamsWhenInboundAndOutboundAreTerminat stateAssert.hasSubscribedFlag().hasRequestN(Integer.MAX_VALUE).hasNoFirstFrameSentFlag(); activeStreams.assertNoActiveStreams(); - Payload requestPayload = TestRequesterResponderSupport.randomPayload(allocator); + Payload requestPayload = TestChannelSupport.randomPayload(allocator); publisher.next(requestPayload); stateAssert.hasSubscribedFlag().hasRequestN(Integer.MAX_VALUE).hasFirstFrameSentFlag(); diff --git a/today-remoting/src/test/java/infra/remoting/core/RequestChannelResponderSubscriberTest.java b/today-remoting/src/test/java/infra/remoting/core/RequestChannelResponderSubscriberTest.java index c168981..38bd73c 100644 --- a/today-remoting/src/test/java/infra/remoting/core/RequestChannelResponderSubscriberTest.java +++ b/today-remoting/src/test/java/infra/remoting/core/RequestChannelResponderSubscriberTest.java @@ -79,10 +79,10 @@ public static void setUp() { @ParameterizedTest @ValueSource(strings = { "inbound", "outbound", "inboundCancel" }) public void requestNFrameShouldBeSentOnSubscriptionAndThenSeparately(String completionCase) { - final TestRequesterResponderSupport activeStreams = TestRequesterResponderSupport.client(); + final TestChannelSupport activeStreams = TestChannelSupport.client(); final LeaksTrackingByteBufAllocator allocator = activeStreams.getAllocator(); final TestDuplexConnection sender = activeStreams.getDuplexConnection(); - final Payload firstPayload = TestRequesterResponderSupport.genericPayload(allocator); + final Payload firstPayload = TestChannelSupport.genericPayload(allocator); final TestPublisher publisher = TestPublisher.create(); final RequestChannelResponderSubscriber requestChannelResponderSubscriber = @@ -126,7 +126,7 @@ public void requestNFrameShouldBeSentOnSubscriptionAndThenSeparately(String comp .hasRequestN(1) .hasNoLeaks(); - publisher.next(TestRequesterResponderSupport.genericPayload(allocator)); + publisher.next(TestChannelSupport.genericPayload(allocator)); final ByteBuf frame = sender.awaitFrame(); FrameAssert.assertThat(frame) @@ -157,13 +157,13 @@ public void requestNFrameShouldBeSentOnSubscriptionAndThenSeparately(String comp // state machine check stateAssert.hasSubscribedFlag().hasRequestN(Integer.MAX_VALUE).hasFirstFrameSentFlag(); - Payload nextPayload = TestRequesterResponderSupport.genericPayload(allocator); + Payload nextPayload = TestChannelSupport.genericPayload(allocator); requestChannelResponderSubscriber.handlePayload(nextPayload); int mtu = ThreadLocalRandom.current().nextInt(64, 256); - Payload randomPayload = TestRequesterResponderSupport.randomPayload(allocator); + Payload randomPayload = TestChannelSupport.randomPayload(allocator); ArrayList fragments = - TestRequesterResponderSupport.prepareFragments(allocator, mtu, randomPayload); + TestChannelSupport.prepareFragments(allocator, mtu, randomPayload); ByteBuf firstFragment = fragments.remove(0); requestChannelResponderSubscriber.handleNext(firstFragment, true, false); @@ -274,10 +274,10 @@ else if (completionCase.equals("outbound")) { @Test public void failOnOverflow() { - final TestRequesterResponderSupport activeStreams = TestRequesterResponderSupport.client(); + final TestChannelSupport activeStreams = TestChannelSupport.client(); final LeaksTrackingByteBufAllocator allocator = activeStreams.getAllocator(); final TestDuplexConnection sender = activeStreams.getDuplexConnection(); - final Payload firstPayload = TestRequesterResponderSupport.genericPayload(allocator); + final Payload firstPayload = TestChannelSupport.genericPayload(allocator); final TestPublisher publisher = TestPublisher.create(); final RequestChannelResponderSubscriber requestChannelResponderSubscriber = @@ -321,10 +321,10 @@ public void failOnOverflow() { .hasRequestN(1) .hasNoLeaks(); - Payload nextPayload = TestRequesterResponderSupport.genericPayload(allocator); + Payload nextPayload = TestChannelSupport.genericPayload(allocator); requestChannelResponderSubscriber.handlePayload(nextPayload); - Payload unrequestedPayload = TestRequesterResponderSupport.genericPayload(allocator); + Payload unrequestedPayload = TestChannelSupport.genericPayload(allocator); requestChannelResponderSubscriber.handlePayload(unrequestedPayload); final ByteBuf cancelErrorFrame = sender.awaitFrame(); @@ -354,10 +354,10 @@ public void failOnOverflow() { @Test public void failOnOverflowBeforeFirstPayloadIsSent() { - final TestRequesterResponderSupport activeStreams = TestRequesterResponderSupport.client(); + final TestChannelSupport activeStreams = TestChannelSupport.client(); final LeaksTrackingByteBufAllocator allocator = activeStreams.getAllocator(); final TestDuplexConnection sender = activeStreams.getDuplexConnection(); - final Payload firstPayload = TestRequesterResponderSupport.genericPayload(allocator); + final Payload firstPayload = TestChannelSupport.genericPayload(allocator); final TestPublisher publisher = TestPublisher.create(); final RequestChannelResponderSubscriber requestChannelResponderSubscriber = @@ -382,7 +382,7 @@ public void failOnOverflowBeforeFirstPayloadIsSent() { // state machine check stateAssert.hasSubscribedFlagOnly().hasRequestN(0); - Payload unrequestedPayload = TestRequesterResponderSupport.genericPayload(allocator); + Payload unrequestedPayload = TestChannelSupport.genericPayload(allocator); requestChannelResponderSubscriber.handlePayload(unrequestedPayload); final ByteBuf cancelErrorFrame = sender.awaitFrame(); @@ -418,11 +418,11 @@ public void failOnOverflowBeforeFirstPayloadIsSent() { @Test public void streamShouldWorkCorrectlyWhenRacingHandleCompleteWithSubscription() { for (int i = 0; i < RaceTestConstants.REPEATS; i++) { - final TestRequesterResponderSupport activeStreams = TestRequesterResponderSupport.client(); + final TestChannelSupport activeStreams = TestChannelSupport.client(); final LeaksTrackingByteBufAllocator allocator = activeStreams.getAllocator(); final TestDuplexConnection sender = activeStreams.getDuplexConnection(); ; - final Payload firstPayload = TestRequesterResponderSupport.randomPayload(allocator); + final Payload firstPayload = TestChannelSupport.randomPayload(allocator); final TestPublisher publisher = TestPublisher.create(); final RequestChannelResponderSubscriber requestChannelResponderSubscriber = @@ -479,9 +479,9 @@ public void streamShouldWorkCorrectlyWhenRacingHandleErrorWithSubscription() { ApplicationErrorException applicationErrorException = new ApplicationErrorException("test"); for (int i = 0; i < RaceTestConstants.REPEATS; i++) { - final TestRequesterResponderSupport activeStreams = TestRequesterResponderSupport.client(); + final TestChannelSupport activeStreams = TestChannelSupport.client(); final LeaksTrackingByteBufAllocator allocator = activeStreams.getAllocator(); - final Payload firstPayload = TestRequesterResponderSupport.randomPayload(allocator); + final Payload firstPayload = TestChannelSupport.randomPayload(allocator); final TestPublisher publisher = TestPublisher.create(); final RequestChannelResponderSubscriber requestChannelResponderSubscriber = @@ -525,9 +525,9 @@ public void streamShouldWorkCorrectlyWhenRacingOutboundErrorWithSubscription() { RuntimeException exception = new RuntimeException("test"); for (int i = 0; i < RaceTestConstants.REPEATS; i++) { - final TestRequesterResponderSupport activeStreams = TestRequesterResponderSupport.client(); + final TestChannelSupport activeStreams = TestChannelSupport.client(); final LeaksTrackingByteBufAllocator allocator = activeStreams.getAllocator(); - final Payload firstPayload = TestRequesterResponderSupport.randomPayload(allocator); + final Payload firstPayload = TestChannelSupport.randomPayload(allocator); final TestPublisher publisher = TestPublisher.create(); final RequestChannelResponderSubscriber requestChannelResponderSubscriber = @@ -573,9 +573,9 @@ public void streamShouldWorkCorrectlyWhenRacingOutboundErrorWithSubscription() { @Test public void streamShouldWorkCorrectlyWhenRacingHandleCancelWithSubscription() { for (int i = 0; i < RaceTestConstants.REPEATS; i++) { - final TestRequesterResponderSupport activeStreams = TestRequesterResponderSupport.client(); + final TestChannelSupport activeStreams = TestChannelSupport.client(); final LeaksTrackingByteBufAllocator allocator = activeStreams.getAllocator(); - final Payload firstPayload = TestRequesterResponderSupport.randomPayload(allocator); + final Payload firstPayload = TestChannelSupport.randomPayload(allocator); final TestPublisher publisher = TestPublisher.create(); final RequestChannelResponderSubscriber requestChannelResponderSubscriber = @@ -641,13 +641,13 @@ public void shouldHaveEventsDeliveredSeriallyWhenOutboundErrorRacingWithInboundS Hooks.onErrorDropped(droppedErrors::add); try { for (int i = 0; i < RaceTestConstants.REPEATS; i++) { - final TestRequesterResponderSupport activeStreams = TestRequesterResponderSupport.client(); + final TestChannelSupport activeStreams = TestChannelSupport.client(); final LeaksTrackingByteBufAllocator allocator = activeStreams.getAllocator(); final TestDuplexConnection sender = activeStreams.getDuplexConnection(); final TestPublisher publisher = TestPublisher.createNoncompliant(DEFER_CANCELLATION, CLEANUP_ON_TERMINATE); - Payload requestPayload = TestRequesterResponderSupport.randomPayload(allocator); + Payload requestPayload = TestChannelSupport.randomPayload(allocator); final RequestChannelResponderSubscriber requestChannelResponderSubscriber = new RequestChannelResponderSubscriber(1, 1, requestPayload, activeStreams); @@ -668,9 +668,9 @@ public void shouldHaveEventsDeliveredSeriallyWhenOutboundErrorRacingWithInboundS requestChannelResponderSubscriber.handleRequestN(Long.MAX_VALUE); - Payload responsePayload1 = TestRequesterResponderSupport.randomPayload(allocator); - Payload responsePayload2 = TestRequesterResponderSupport.randomPayload(allocator); - Payload responsePayload3 = TestRequesterResponderSupport.randomPayload(allocator); + Payload responsePayload1 = TestChannelSupport.randomPayload(allocator); + Payload responsePayload2 = TestChannelSupport.randomPayload(allocator); + Payload responsePayload3 = TestChannelSupport.randomPayload(allocator); Payload releasedPayload = ByteBufPayload.create(Unpooled.EMPTY_BUFFER); releasedPayload.release(); @@ -817,7 +817,7 @@ public void shouldHaveNoLeaksOnReassemblyAndCancelRacing(String terminationMode) DefaultPayload.create(new byte[FRAME_LENGTH_MASK], new byte[FRAME_LENGTH_MASK]); for (int i = 0; i < RaceTestConstants.REPEATS; i++) { - final TestRequesterResponderSupport activeStreams = TestRequesterResponderSupport.client(); + final TestChannelSupport activeStreams = TestChannelSupport.client(); final LeaksTrackingByteBufAllocator allocator = activeStreams.getAllocator(); final TestDuplexConnection sender = activeStreams.getDuplexConnection(); ; @@ -825,7 +825,7 @@ public void shouldHaveNoLeaksOnReassemblyAndCancelRacing(String terminationMode) TestPublisher.createNoncompliant(DEFER_CANCELLATION, CLEANUP_ON_TERMINATE); final AssertSubscriber assertSubscriber = new AssertSubscriber<>(2); - Payload firstPayload = TestRequesterResponderSupport.genericPayload(allocator); + Payload firstPayload = TestChannelSupport.genericPayload(allocator); final RequestChannelResponderSubscriber requestOperator = new RequestChannelResponderSubscriber(1, Long.MAX_VALUE, firstPayload, activeStreams); @@ -833,9 +833,9 @@ public void shouldHaveNoLeaksOnReassemblyAndCancelRacing(String terminationMode) requestOperator.subscribe(assertSubscriber); int mtu = ThreadLocalRandom.current().nextInt(64, 256); - Payload responsePayload = TestRequesterResponderSupport.randomPayload(allocator); + Payload responsePayload = TestChannelSupport.randomPayload(allocator); ArrayList fragments = - TestRequesterResponderSupport.prepareFragments(allocator, mtu, responsePayload); + TestChannelSupport.prepareFragments(allocator, mtu, responsePayload); Payload releasedPayload1 = ByteBufPayload.create(new byte[0]); Payload releasedPayload2 = ByteBufPayload.create(new byte[0]); diff --git a/today-remoting/src/test/java/infra/remoting/core/RequestResponseRequesterMonoTest.java b/today-remoting/src/test/java/infra/remoting/core/RequestResponseRequesterMonoTest.java index 3d3aa0b..4d9fe22 100644 --- a/today-remoting/src/test/java/infra/remoting/core/RequestResponseRequesterMonoTest.java +++ b/today-remoting/src/test/java/infra/remoting/core/RequestResponseRequesterMonoTest.java @@ -29,10 +29,6 @@ import java.util.function.Consumer; import java.util.stream.Stream; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; -import io.netty.util.CharsetUtil; -import io.netty.util.IllegalReferenceCountException; import infra.remoting.FrameAssert; import infra.remoting.Payload; import infra.remoting.PayloadAssert; @@ -42,13 +38,17 @@ import infra.remoting.test.util.TestDuplexConnection; import infra.remoting.util.ByteBufPayload; import infra.remoting.util.EmptyPayload; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.util.CharsetUtil; +import io.netty.util.IllegalReferenceCountException; import reactor.core.Scannable; import reactor.test.StepVerifier; import static infra.remoting.core.FragmentationUtils.FRAME_OFFSET; import static infra.remoting.core.FragmentationUtils.FRAME_OFFSET_WITH_METADATA; import static infra.remoting.core.PayloadValidationUtils.INVALID_PAYLOAD_ERROR_MESSAGE; -import static infra.remoting.core.TestRequesterResponderSupport.genericPayload; +import static infra.remoting.core.TestChannelSupport.genericPayload; import static infra.remoting.frame.FrameLengthCodec.FRAME_LENGTH_MASK; public class RequestResponseRequesterMonoTest { @@ -76,7 +76,7 @@ public static void setUp() { public void frameShouldBeSentOnSubscription( BiFunction, StepVerifier> transformer) { - final TestRequesterResponderSupport activeStreams = TestRequesterResponderSupport.client(); + final TestChannelSupport activeStreams = TestChannelSupport.client(); final LeaksTrackingByteBufAllocator allocator = activeStreams.getAllocator(); final TestDuplexConnection sender = activeStreams.getDuplexConnection(); final Payload payload = genericPayload(allocator); @@ -169,7 +169,7 @@ public void frameShouldBeSentOnSubscription( () -> { final ByteBuf followingFrame = FragmentationUtils.encodeFirstFragment( - rrm.allocator, + rrm.channel.allocator, 64, FrameType.REQUEST_RESPONSE, 1, @@ -190,7 +190,7 @@ public void frameShouldBeSentOnSubscription( () -> { final ByteBuf followingFrame = FragmentationUtils.encodeFollowsFragment( - rrm.allocator, 64, 1, false, payload.metadata(), payload.data()); + rrm.channel.allocator, 64, 1, false, payload.metadata(), payload.data()); rrm.handleNext(followingFrame, true, false); followingFrame.release(); }) @@ -205,7 +205,7 @@ public void frameShouldBeSentOnSubscription( () -> { final ByteBuf followingFrame = FragmentationUtils.encodeFollowsFragment( - rrm.allocator, 64, 1, false, payload.metadata(), payload.data()); + rrm.channel.allocator, 64, 1, false, payload.metadata(), payload.data()); rrm.handleNext(followingFrame, true, false); followingFrame.release(); }) @@ -220,7 +220,7 @@ public void frameShouldBeSentOnSubscription( () -> { final ByteBuf followingFrame = FragmentationUtils.encodeFollowsFragment( - rrm.allocator, 64, 1, false, payload.metadata(), payload.data()); + rrm.channel.allocator, 64, 1, false, payload.metadata(), payload.data()); rrm.handleNext(followingFrame, false, false); followingFrame.release(); }) @@ -247,7 +247,7 @@ public void frameShouldBeSentOnSubscription( ByteBuf[] fragments = new ByteBuf[] { FragmentationUtils.encodeFirstFragment( - rrm.allocator, + rrm.channel.allocator, 64, FrameType.REQUEST_RESPONSE, 1, @@ -255,9 +255,9 @@ public void frameShouldBeSentOnSubscription( payload.metadata(), payload.data()), FragmentationUtils.encodeFollowsFragment( - rrm.allocator, 64, 1, false, payload.metadata(), payload.data()), + rrm.channel.allocator, 64, 1, false, payload.metadata(), payload.data()), FragmentationUtils.encodeFollowsFragment( - rrm.allocator, 64, 1, false, payload.metadata(), payload.data()) + rrm.channel.allocator, 64, 1, false, payload.metadata(), payload.data()) }; final StepVerifier stepVerifier = @@ -321,7 +321,7 @@ public void frameFragmentsShouldBeSentOnSubscription( BiFunction, StepVerifier> transformer) { final int mtu = 64; - final TestRequesterResponderSupport activeStreams = TestRequesterResponderSupport.client(mtu); + final TestChannelSupport activeStreams = TestChannelSupport.client(mtu); final LeaksTrackingByteBufAllocator allocator = activeStreams.getAllocator(); final TestDuplexConnection sender = activeStreams.getDuplexConnection(); @@ -431,7 +431,7 @@ public void frameFragmentsShouldBeSentOnSubscription( */ @Test public void shouldBeNoOpsOnCancel() { - final TestRequesterResponderSupport activeStreams = TestRequesterResponderSupport.client(); + final TestChannelSupport activeStreams = TestChannelSupport.client(); final LeaksTrackingByteBufAllocator allocator = activeStreams.getAllocator(); final TestDuplexConnection sender = activeStreams.getDuplexConnection(); final Payload payload = ByteBufPayload.create("testData", "testMetadata"); @@ -467,7 +467,7 @@ public void shouldBeNoOpsOnCancel() { @MethodSource("shouldErrorOnIncorrectRefCntInGivenPayloadSource") public void shouldErrorOnIncorrectRefCntInGivenPayload( Consumer monoConsumer) { - final TestRequesterResponderSupport activeStreams = TestRequesterResponderSupport.client(); + final TestChannelSupport activeStreams = TestChannelSupport.client(); final LeaksTrackingByteBufAllocator allocator = activeStreams.getAllocator(); final TestDuplexConnection sender = activeStreams.getDuplexConnection(); ; @@ -511,7 +511,7 @@ public void shouldErrorOnIncorrectRefCntInGivenPayload( */ @Test public void shouldErrorOnIncorrectRefCntInGivenPayloadLatePhase() { - final TestRequesterResponderSupport activeStreams = TestRequesterResponderSupport.client(); + final TestChannelSupport activeStreams = TestChannelSupport.client(); final LeaksTrackingByteBufAllocator allocator = activeStreams.getAllocator(); final TestDuplexConnection sender = activeStreams.getDuplexConnection(); ; @@ -546,7 +546,7 @@ public void shouldErrorOnIncorrectRefCntInGivenPayloadLatePhase() { @Test public void shouldErrorOnIncorrectRefCntInGivenPayloadLatePhaseWithFragmentation() { final int mtu = 64; - final TestRequesterResponderSupport activeStreams = TestRequesterResponderSupport.client(mtu); + final TestChannelSupport activeStreams = TestChannelSupport.client(mtu); final LeaksTrackingByteBufAllocator allocator = activeStreams.getAllocator(); final TestDuplexConnection sender = activeStreams.getDuplexConnection(); ; @@ -586,7 +586,7 @@ public void shouldErrorOnIncorrectRefCntInGivenPayloadLatePhaseWithFragmentation @MethodSource("shouldErrorIfFragmentExitsAllowanceIfFragmentationDisabledSource") public void shouldErrorIfFragmentExitsAllowanceIfFragmentationDisabled( Consumer monoConsumer) { - final TestRequesterResponderSupport activeStreams = TestRequesterResponderSupport.client(); + final TestChannelSupport activeStreams = TestChannelSupport.client(); final LeaksTrackingByteBufAllocator allocator = activeStreams.getAllocator(); final TestDuplexConnection sender = activeStreams.getDuplexConnection(); ; @@ -643,8 +643,8 @@ public void shouldErrorIfFragmentExitsAllowanceIfFragmentationDisabled( @ParameterizedTest @MethodSource("shouldErrorIfNoAvailabilitySource") public void shouldErrorIfNoAvailability(Consumer monoConsumer) { - final TestRequesterResponderSupport activeStreams = - TestRequesterResponderSupport.client(new RuntimeException("test")); + final TestChannelSupport activeStreams = + TestChannelSupport.client(new RuntimeException("test")); final LeaksTrackingByteBufAllocator allocator = activeStreams.getAllocator(); final Payload payload = genericPayload(allocator); @@ -686,7 +686,7 @@ static Stream> shouldErrorIfNoAvailabilit @Test public void checkName() { - final TestRequesterResponderSupport activeStreams = TestRequesterResponderSupport.client(); + final TestChannelSupport activeStreams = TestChannelSupport.client(); final LeaksTrackingByteBufAllocator allocator = activeStreams.getAllocator(); final Payload payload = genericPayload(allocator); diff --git a/today-remoting/src/test/java/infra/remoting/core/RequestStreamRequesterFluxTest.java b/today-remoting/src/test/java/infra/remoting/core/RequestStreamRequesterFluxTest.java index 194ecb7..03bd6fb 100644 --- a/today-remoting/src/test/java/infra/remoting/core/RequestStreamRequesterFluxTest.java +++ b/today-remoting/src/test/java/infra/remoting/core/RequestStreamRequesterFluxTest.java @@ -30,10 +30,6 @@ import java.util.function.Consumer; import java.util.stream.Stream; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; -import io.netty.util.CharsetUtil; -import io.netty.util.IllegalReferenceCountException; import infra.remoting.FrameAssert; import infra.remoting.Payload; import infra.remoting.PayloadAssert; @@ -44,6 +40,10 @@ import infra.remoting.test.util.TestDuplexConnection; import infra.remoting.util.ByteBufPayload; import infra.remoting.util.EmptyPayload; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.util.CharsetUtil; +import io.netty.util.IllegalReferenceCountException; import reactor.core.Scannable; import reactor.test.StepVerifier; @@ -81,10 +81,10 @@ public static void setUp() { */ @Test public void requestNFrameShouldBeSentOnSubscriptionAndThenSeparately() { - final TestRequesterResponderSupport activeStreams = TestRequesterResponderSupport.client(); + final TestChannelSupport activeStreams = TestChannelSupport.client(); final LeaksTrackingByteBufAllocator allocator = activeStreams.getAllocator(); final TestDuplexConnection sender = activeStreams.getDuplexConnection(); - final Payload payload = TestRequesterResponderSupport.genericPayload(allocator); + final Payload payload = TestChannelSupport.genericPayload(allocator); final RequestStreamRequesterFlux requestStreamRequesterFlux = new RequestStreamRequesterFlux(payload, activeStreams); @@ -166,9 +166,9 @@ public void requestNFrameShouldBeSentOnSubscriptionAndThenSeparately() { stateAssert.hasSubscribedFlag().hasRequestN(Integer.MAX_VALUE).hasFirstFrameSentFlag(); int mtu = ThreadLocalRandom.current().nextInt(64, 256); - Payload randomPayload = TestRequesterResponderSupport.randomPayload(allocator); + Payload randomPayload = TestChannelSupport.randomPayload(allocator); ArrayList fragments = - TestRequesterResponderSupport.prepareFragments(allocator, mtu, randomPayload); + TestChannelSupport.prepareFragments(allocator, mtu, randomPayload); ByteBuf firstFragment = fragments.remove(0); requestStreamRequesterFlux.handleNext(firstFragment, true, false); firstFragment.release(); @@ -195,7 +195,7 @@ public void requestNFrameShouldBeSentOnSubscriptionAndThenSeparately() { .hasFirstFrameSentFlag() .hasNoReassemblingFlag(); - Payload finalRandomPayload = TestRequesterResponderSupport.randomPayload(allocator); + Payload finalRandomPayload = TestChannelSupport.randomPayload(allocator); requestStreamRequesterFlux.handlePayload(finalRandomPayload); requestStreamRequesterFlux.handleComplete(); @@ -228,10 +228,10 @@ public void requestNFrameShouldBeSentOnSubscriptionAndThenSeparately() { */ @Test public void requestNFrameShouldBeSentExactlyOnceIfItIsMaxAllowed() { - final TestRequesterResponderSupport activeStreams = TestRequesterResponderSupport.client(); + final TestChannelSupport activeStreams = TestChannelSupport.client(); final LeaksTrackingByteBufAllocator allocator = activeStreams.getAllocator(); final TestDuplexConnection sender = activeStreams.getDuplexConnection(); - final Payload payload = TestRequesterResponderSupport.genericPayload(allocator); + final Payload payload = TestChannelSupport.genericPayload(allocator); final RequestStreamRequesterFlux requestStreamRequesterFlux = new RequestStreamRequesterFlux(payload, activeStreams); @@ -333,10 +333,10 @@ public void requestNFrameShouldBeSentExactlyOnceIfItIsMaxAllowed() { public void frameShouldBeSentOnFirstRequest( BiFunction, StepVerifier> transformer) { - final TestRequesterResponderSupport activeStreams = TestRequesterResponderSupport.client(); + final TestChannelSupport activeStreams = TestChannelSupport.client(); final LeaksTrackingByteBufAllocator allocator = activeStreams.getAllocator(); final TestDuplexConnection sender = activeStreams.getDuplexConnection(); - final Payload payload = TestRequesterResponderSupport.genericPayload(allocator); + final Payload payload = TestChannelSupport.genericPayload(allocator); final RequestStreamRequesterFlux requestStreamRequesterFlux = new RequestStreamRequesterFlux(payload, activeStreams); @@ -504,7 +504,7 @@ public void frameShouldBeSentOnFirstRequest( () -> { final ByteBuf followingFrame = FragmentationUtils.encodeFirstFragment( - rsf.allocator, + rsf.channel.allocator, 64, FrameType.NEXT, 1, @@ -526,7 +526,7 @@ public void frameShouldBeSentOnFirstRequest( () -> { final ByteBuf followingFrame = FragmentationUtils.encodeFollowsFragment( - rsf.allocator, 64, 1, false, payload.metadata(), payload.data()); + rsf.channel.allocator, 64, 1, false, payload.metadata(), payload.data()); rsf.handleNext(followingFrame, true, false); followingFrame.release(); }) @@ -542,7 +542,7 @@ public void frameShouldBeSentOnFirstRequest( () -> { final ByteBuf followingFrame = FragmentationUtils.encodeFollowsFragment( - rsf.allocator, 64, 1, false, payload.metadata(), payload.data()); + rsf.channel.allocator, 64, 1, false, payload.metadata(), payload.data()); rsf.handleNext(followingFrame, true, false); followingFrame.release(); }) @@ -567,7 +567,7 @@ public void frameShouldBeSentOnFirstRequest( () -> { final ByteBuf followingFrame = FragmentationUtils.encodeFollowsFragment( - rsf.allocator, 64, 1, false, payload.metadata(), payload.data()); + rsf.channel.allocator, 64, 1, false, payload.metadata(), payload.data()); rsf.handleNext(followingFrame, false, false); followingFrame.release(); }) @@ -632,7 +632,7 @@ public void frameShouldBeSentOnFirstRequest( ByteBuf[] fragments = new ByteBuf[] { FragmentationUtils.encodeFirstFragment( - rsf.allocator, + rsf.channel.allocator, 64, FrameType.NEXT, 1, @@ -640,9 +640,9 @@ public void frameShouldBeSentOnFirstRequest( payload.metadata(), payload.data()), FragmentationUtils.encodeFollowsFragment( - rsf.allocator, 64, 1, false, payload.metadata(), payload.data()), + rsf.channel.allocator, 64, 1, false, payload.metadata(), payload.data()), FragmentationUtils.encodeFollowsFragment( - rsf.allocator, 64, 1, false, payload.metadata(), payload.data()) + rsf.channel.allocator, 64, 1, false, payload.metadata(), payload.data()) }; final StepVerifier stepVerifier = @@ -765,7 +765,7 @@ public void frameFragmentsShouldBeSentOnFirstRequest( BiFunction, StepVerifier> transformer) { final int mtu = 64; - final TestRequesterResponderSupport activeStreams = TestRequesterResponderSupport.client(mtu); + final TestChannelSupport activeStreams = TestChannelSupport.client(mtu); final LeaksTrackingByteBufAllocator allocator = activeStreams.getAllocator(); final TestDuplexConnection sender = activeStreams.getDuplexConnection(); @@ -883,7 +883,7 @@ public void frameFragmentsShouldBeSentOnFirstRequest( @MethodSource("shouldErrorOnIncorrectRefCntInGivenPayloadSource") public void shouldErrorOnIncorrectRefCntInGivenPayload( Consumer monoConsumer) { - final TestRequesterResponderSupport activeStreams = TestRequesterResponderSupport.client(); + final TestChannelSupport activeStreams = TestChannelSupport.client(); final LeaksTrackingByteBufAllocator allocator = activeStreams.getAllocator(); final TestDuplexConnection sender = activeStreams.getDuplexConnection(); final Payload payload = ByteBufPayload.create(""); @@ -926,7 +926,7 @@ public void shouldErrorOnIncorrectRefCntInGivenPayload( */ @Test public void shouldErrorOnIncorrectRefCntInGivenPayloadLatePhase() { - final TestRequesterResponderSupport activeStreams = TestRequesterResponderSupport.client(); + final TestChannelSupport activeStreams = TestChannelSupport.client(); final LeaksTrackingByteBufAllocator allocator = activeStreams.getAllocator(); final TestDuplexConnection sender = activeStreams.getDuplexConnection(); @@ -971,7 +971,7 @@ public void shouldErrorOnIncorrectRefCntInGivenPayloadLatePhase() { @Test public void shouldErrorOnIncorrectRefCntInGivenPayloadLatePhaseWithFragmentation() { final int mtu = 64; - final TestRequesterResponderSupport activeStreams = TestRequesterResponderSupport.client(mtu); + final TestChannelSupport activeStreams = TestChannelSupport.client(mtu); final LeaksTrackingByteBufAllocator allocator = activeStreams.getAllocator(); final TestDuplexConnection sender = activeStreams.getDuplexConnection(); @@ -1021,7 +1021,7 @@ public void shouldErrorOnIncorrectRefCntInGivenPayloadLatePhaseWithFragmentation @MethodSource("shouldErrorIfFragmentExitsAllowanceIfFragmentationDisabledSource") public void shouldErrorIfFragmentExitsAllowanceIfFragmentationDisabled( Consumer monoConsumer) { - final TestRequesterResponderSupport activeStreams = TestRequesterResponderSupport.client(); + final TestChannelSupport activeStreams = TestChannelSupport.client(); final LeaksTrackingByteBufAllocator allocator = activeStreams.getAllocator(); final TestDuplexConnection sender = activeStreams.getDuplexConnection(); @@ -1084,10 +1084,10 @@ public void shouldErrorIfFragmentExitsAllowanceIfFragmentationDisabled( @ParameterizedTest @MethodSource("shouldErrorIfNoAvailabilitySource") public void shouldErrorIfNoAvailability(Consumer monoConsumer) { - final TestRequesterResponderSupport activeStreams = - TestRequesterResponderSupport.client(new RuntimeException("test")); + final TestChannelSupport activeStreams = + TestChannelSupport.client(new RuntimeException("test")); final LeaksTrackingByteBufAllocator allocator = activeStreams.getAllocator(); - final Payload payload = TestRequesterResponderSupport.genericPayload(allocator); + final Payload payload = TestChannelSupport.genericPayload(allocator); final RequestStreamRequesterFlux requestStreamRequesterFlux = new RequestStreamRequesterFlux(payload, activeStreams); @@ -1134,10 +1134,10 @@ static Stream> shouldErrorIfNoAvailabilityS @Test public void failOnOverflow() { - final TestRequesterResponderSupport activeStreams = TestRequesterResponderSupport.client(); + final TestChannelSupport activeStreams = TestChannelSupport.client(); final LeaksTrackingByteBufAllocator allocator = activeStreams.getAllocator(); final TestDuplexConnection sender = activeStreams.getDuplexConnection(); - final Payload payload = TestRequesterResponderSupport.genericPayload(allocator); + final Payload payload = TestChannelSupport.genericPayload(allocator); final RequestStreamRequesterFlux requestStreamRequesterFlux = new RequestStreamRequesterFlux(payload, activeStreams); @@ -1181,10 +1181,10 @@ public void failOnOverflow() { Assertions.assertThat(sender.isEmpty()).isTrue(); - Payload requestedPayload = TestRequesterResponderSupport.randomPayload(allocator); + Payload requestedPayload = TestChannelSupport.randomPayload(allocator); requestStreamRequesterFlux.handlePayload(requestedPayload); - Payload unrequestedPayload = TestRequesterResponderSupport.randomPayload(allocator); + Payload unrequestedPayload = TestChannelSupport.randomPayload(allocator); requestStreamRequesterFlux.handlePayload(unrequestedPayload); final ByteBuf cancelFrame = sender.awaitFrame(); @@ -1215,9 +1215,9 @@ public void failOnOverflow() { @Test public void checkName() { - final TestRequesterResponderSupport activeStreams = TestRequesterResponderSupport.client(); + final TestChannelSupport activeStreams = TestChannelSupport.client(); final LeaksTrackingByteBufAllocator allocator = activeStreams.getAllocator(); - final Payload payload = TestRequesterResponderSupport.genericPayload(allocator); + final Payload payload = TestChannelSupport.genericPayload(allocator); final RequestStreamRequesterFlux requestStreamRequesterFlux = new RequestStreamRequesterFlux(payload, activeStreams); diff --git a/today-remoting/src/test/java/infra/remoting/core/RequesterOperatorsRacingTest.java b/today-remoting/src/test/java/infra/remoting/core/RequesterOperatorsRacingTest.java index 1ec5b7d..e1a6dce 100644 --- a/today-remoting/src/test/java/infra/remoting/core/RequesterOperatorsRacingTest.java +++ b/today-remoting/src/test/java/infra/remoting/core/RequesterOperatorsRacingTest.java @@ -61,7 +61,7 @@ interface Scenario { FrameType requestType(); Publisher requestOperator( - Supplier payloadsSupplier, RequesterResponderSupport requesterResponderSupport); + Supplier payloadsSupplier, ChannelSupport channelSupport); } static Stream scenarios() { @@ -75,8 +75,8 @@ public FrameType requestType() { @Override public Publisher requestOperator( Supplier payloadsSupplier, - RequesterResponderSupport requesterResponderSupport) { - return new MetadataPushRequesterMono(payloadsSupplier.get(), requesterResponderSupport); + ChannelSupport channelSupport) { + return new MetadataPushRequesterMono(payloadsSupplier.get(), channelSupport); } @Override @@ -93,9 +93,9 @@ public FrameType requestType() { @Override public Publisher requestOperator( Supplier payloadsSupplier, - RequesterResponderSupport requesterResponderSupport) { + ChannelSupport channelSupport) { return new FireAndForgetRequesterMono( - payloadsSupplier.get(), requesterResponderSupport); + payloadsSupplier.get(), channelSupport); } @Override @@ -112,9 +112,9 @@ public FrameType requestType() { @Override public Publisher requestOperator( Supplier payloadsSupplier, - RequesterResponderSupport requesterResponderSupport) { + ChannelSupport channelSupport) { return new RequestResponseRequesterMono( - payloadsSupplier.get(), requesterResponderSupport); + payloadsSupplier.get(), channelSupport); } @Override @@ -131,9 +131,9 @@ public FrameType requestType() { @Override public Publisher requestOperator( Supplier payloadsSupplier, - RequesterResponderSupport requesterResponderSupport) { + ChannelSupport channelSupport) { return new RequestStreamRequesterFlux( - payloadsSupplier.get(), requesterResponderSupport); + payloadsSupplier.get(), channelSupport); } @Override @@ -150,9 +150,9 @@ public FrameType requestType() { @Override public Publisher requestOperator( Supplier payloadsSupplier, - RequesterResponderSupport requesterResponderSupport) { + ChannelSupport channelSupport) { return new RequestChannelRequesterFlux( - Flux.generate(s -> s.next(payloadsSupplier.get())), requesterResponderSupport); + Flux.generate(s -> s.next(payloadsSupplier.get())), channelSupport); } @Override @@ -174,11 +174,11 @@ public String toString() { public void shouldSubscribeExactlyOnce(Scenario scenario) { for (int i = 0; i < RaceTestConstants.REPEATS; i++) { final TestRequestInterceptor testRequestInterceptor = new TestRequestInterceptor(); - final TestRequesterResponderSupport requesterResponderSupport = - TestRequesterResponderSupport.client(testRequestInterceptor); + final TestChannelSupport requesterResponderSupport = + TestChannelSupport.client(testRequestInterceptor); final Supplier payloadSupplier = () -> - TestRequesterResponderSupport.genericPayload( + TestChannelSupport.genericPayload( requesterResponderSupport.getAllocator()); final Publisher requestOperator = @@ -197,24 +197,24 @@ public void shouldSubscribeExactlyOnce(Scenario scenario) { frameAssert .hasStreamIdZero() .hasPayloadSize( - TestRequesterResponderSupport.METADATA_CONTENT.getBytes( + TestChannelSupport.METADATA_CONTENT.getBytes( CharsetUtil.UTF_8) .length) - .hasMetadata(TestRequesterResponderSupport.METADATA_CONTENT); + .hasMetadata(TestChannelSupport.METADATA_CONTENT); } else { frameAssert .hasClientSideStreamId() .hasStreamId(1) .hasPayloadSize( - TestRequesterResponderSupport.METADATA_CONTENT.getBytes( + TestChannelSupport.METADATA_CONTENT.getBytes( CharsetUtil.UTF_8) .length - + TestRequesterResponderSupport.DATA_CONTENT.getBytes( + + TestChannelSupport.DATA_CONTENT.getBytes( CharsetUtil.UTF_8) .length) - .hasMetadata(TestRequesterResponderSupport.METADATA_CONTENT) - .hasData(TestRequesterResponderSupport.DATA_CONTENT); + .hasMetadata(TestChannelSupport.METADATA_CONTENT) + .hasData(TestChannelSupport.DATA_CONTENT); } frameAssert.hasNoLeaks(); @@ -284,10 +284,10 @@ public void shouldSentRequestFrameOnceInCaseOfRequestRacing(Scenario scenario) { for (int i = 0; i < RaceTestConstants.REPEATS; i++) { final TestRequestInterceptor testRequestInterceptor = new TestRequestInterceptor(); - final TestRequesterResponderSupport activeStreams = - TestRequesterResponderSupport.client(testRequestInterceptor); + final TestChannelSupport activeStreams = + TestChannelSupport.client(testRequestInterceptor); final Supplier payloadSupplier = - () -> TestRequesterResponderSupport.genericPayload(activeStreams.getAllocator()); + () -> TestChannelSupport.genericPayload(activeStreams.getAllocator()); final Publisher requestOperator = (Publisher) scenario.requestOperator(payloadSupplier, activeStreams); @@ -318,11 +318,11 @@ public void shouldSentRequestFrameOnceInCaseOfRequestRacing(Scenario scenario) { FrameAssert.assertThat(sentFrame) .isNotNull() .hasPayloadSize( - TestRequesterResponderSupport.DATA_CONTENT.getBytes(CharsetUtil.UTF_8).length - + TestRequesterResponderSupport.METADATA_CONTENT.getBytes(CharsetUtil.UTF_8) + TestChannelSupport.DATA_CONTENT.getBytes(CharsetUtil.UTF_8).length + + TestChannelSupport.METADATA_CONTENT.getBytes(CharsetUtil.UTF_8) .length) - .hasMetadata(TestRequesterResponderSupport.METADATA_CONTENT) - .hasData(TestRequesterResponderSupport.DATA_CONTENT) + .hasMetadata(TestChannelSupport.METADATA_CONTENT) + .hasData(TestChannelSupport.DATA_CONTENT) .hasNoFragmentsFollow() .typeOf(scenario.requestType()) .hasClientSideStreamId() @@ -372,10 +372,10 @@ public void shouldHaveNoLeaksOnReassemblyAndCancelRacing(Scenario scenario) { for (int i = 0; i < RaceTestConstants.REPEATS; i++) { final TestRequestInterceptor testRequestInterceptor = new TestRequestInterceptor(); - final TestRequesterResponderSupport activeStreams = - TestRequesterResponderSupport.client(testRequestInterceptor); + final TestChannelSupport activeStreams = + TestChannelSupport.client(testRequestInterceptor); final Supplier payloadSupplier = - () -> TestRequesterResponderSupport.genericPayload(activeStreams.getAllocator()); + () -> TestChannelSupport.genericPayload(activeStreams.getAllocator()); final Publisher requestOperator = (Publisher) scenario.requestOperator(payloadSupplier, activeStreams); @@ -388,11 +388,11 @@ public void shouldHaveNoLeaksOnReassemblyAndCancelRacing(Scenario scenario) { FrameAssert.assertThat(sentFrame) .isNotNull() .hasPayloadSize( - TestRequesterResponderSupport.DATA_CONTENT.getBytes(CharsetUtil.UTF_8).length - + TestRequesterResponderSupport.METADATA_CONTENT.getBytes(CharsetUtil.UTF_8) + TestChannelSupport.DATA_CONTENT.getBytes(CharsetUtil.UTF_8).length + + TestChannelSupport.METADATA_CONTENT.getBytes(CharsetUtil.UTF_8) .length) - .hasMetadata(TestRequesterResponderSupport.METADATA_CONTENT) - .hasData(TestRequesterResponderSupport.DATA_CONTENT) + .hasMetadata(TestChannelSupport.METADATA_CONTENT) + .hasData(TestChannelSupport.DATA_CONTENT) .hasNoFragmentsFollow() .typeOf(scenario.requestType()) .hasClientSideStreamId() @@ -401,9 +401,9 @@ public void shouldHaveNoLeaksOnReassemblyAndCancelRacing(Scenario scenario) { int mtu = ThreadLocalRandom.current().nextInt(64, 256); Payload responsePayload = - TestRequesterResponderSupport.randomPayload(activeStreams.getAllocator()); + TestChannelSupport.randomPayload(activeStreams.getAllocator()); ArrayList fragments = - TestRequesterResponderSupport.prepareFragments( + TestChannelSupport.prepareFragments( activeStreams.getAllocator(), mtu, responsePayload); RaceTestUtils.race( assertSubscriber::cancel, @@ -481,10 +481,10 @@ public void shouldHaveNoLeaksOnNextAndCancelRacing(Scenario scenario) { for (int i = 0; i < RaceTestConstants.REPEATS; i++) { final TestRequestInterceptor testRequestInterceptor = new TestRequestInterceptor(); - final TestRequesterResponderSupport activeStreams = - TestRequesterResponderSupport.client(testRequestInterceptor); + final TestChannelSupport activeStreams = + TestChannelSupport.client(testRequestInterceptor); final Supplier payloadSupplier = - () -> TestRequesterResponderSupport.genericPayload(activeStreams.getAllocator()); + () -> TestChannelSupport.genericPayload(activeStreams.getAllocator()); final Publisher requestOperator = scenario.requestOperator(payloadSupplier, activeStreams); @@ -496,11 +496,11 @@ public void shouldHaveNoLeaksOnNextAndCancelRacing(Scenario scenario) { FrameAssert.assertThat(sentFrame) .isNotNull() .hasPayloadSize( - TestRequesterResponderSupport.DATA_CONTENT.getBytes(CharsetUtil.UTF_8).length - + TestRequesterResponderSupport.METADATA_CONTENT.getBytes(CharsetUtil.UTF_8) + TestChannelSupport.DATA_CONTENT.getBytes(CharsetUtil.UTF_8).length + + TestChannelSupport.METADATA_CONTENT.getBytes(CharsetUtil.UTF_8) .length) - .hasMetadata(TestRequesterResponderSupport.METADATA_CONTENT) - .hasData(TestRequesterResponderSupport.DATA_CONTENT) + .hasMetadata(TestChannelSupport.METADATA_CONTENT) + .hasData(TestChannelSupport.DATA_CONTENT) .hasNoFragmentsFollow() .typeOf(scenario.requestType()) .hasClientSideStreamId() @@ -560,10 +560,10 @@ public void shouldHaveNoUnexpectedErrorDuringOnErrorAndCancelRacing(Scenario sce for (boolean withReassembly : withReassemblyOptions) { for (int i = 0; i < RaceTestConstants.REPEATS; i++) { final TestRequestInterceptor testRequestInterceptor = new TestRequestInterceptor(); - final TestRequesterResponderSupport activeStreams = - TestRequesterResponderSupport.client(testRequestInterceptor); + final TestChannelSupport activeStreams = + TestChannelSupport.client(testRequestInterceptor); final Supplier payloadSupplier = - () -> TestRequesterResponderSupport.genericPayload(activeStreams.getAllocator()); + () -> TestChannelSupport.genericPayload(activeStreams.getAllocator()); final Publisher requestOperator = scenario.requestOperator(payloadSupplier, activeStreams); @@ -594,11 +594,11 @@ else if (requestOperator instanceof RequestStreamRequesterFlux) { FrameAssert.assertThat(sentFrame) .isNotNull() .hasPayloadSize( - TestRequesterResponderSupport.DATA_CONTENT.getBytes(CharsetUtil.UTF_8).length - + TestRequesterResponderSupport.METADATA_CONTENT.getBytes(CharsetUtil.UTF_8) + TestChannelSupport.DATA_CONTENT.getBytes(CharsetUtil.UTF_8).length + + TestChannelSupport.METADATA_CONTENT.getBytes(CharsetUtil.UTF_8) .length) - .hasMetadata(TestRequesterResponderSupport.METADATA_CONTENT) - .hasData(TestRequesterResponderSupport.DATA_CONTENT) + .hasMetadata(TestChannelSupport.METADATA_CONTENT) + .hasData(TestChannelSupport.DATA_CONTENT) .hasNoFragmentsFollow() .typeOf(scenario.requestType()) .hasClientSideStreamId() @@ -682,10 +682,10 @@ public void shouldBeConsistentInCaseOfRacingOfCancellationAndRequest(Scenario sc .isIn(REQUEST_RESPONSE, REQUEST_STREAM, REQUEST_CHANNEL); for (int i = 0; i < RaceTestConstants.REPEATS; i++) { final TestRequestInterceptor testRequestInterceptor = new TestRequestInterceptor(); - final TestRequesterResponderSupport activeStreams = - TestRequesterResponderSupport.client(testRequestInterceptor); + final TestChannelSupport activeStreams = + TestChannelSupport.client(testRequestInterceptor); final Supplier payloadSupplier = - () -> TestRequesterResponderSupport.genericPayload(activeStreams.getAllocator()); + () -> TestChannelSupport.genericPayload(activeStreams.getAllocator()); final Publisher requestOperator = scenario.requestOperator(payloadSupplier, activeStreams); @@ -702,8 +702,8 @@ public void shouldBeConsistentInCaseOfRacingOfCancellationAndRequest(Scenario sc FrameAssert.assertThat(sentFrame) .isNotNull() .typeOf(scenario.requestType()) - .hasMetadata(TestRequesterResponderSupport.METADATA_CONTENT) - .hasData(TestRequesterResponderSupport.DATA_CONTENT) + .hasMetadata(TestChannelSupport.METADATA_CONTENT) + .hasData(TestChannelSupport.DATA_CONTENT) .hasNoFragmentsFollow() .hasClientSideStreamId() .hasStreamId(1) @@ -741,10 +741,10 @@ public void shouldSentCancelFrameExactlyOnce(Scenario scenario) { .isIn(REQUEST_RESPONSE, REQUEST_STREAM, REQUEST_CHANNEL); for (int i = 0; i < RaceTestConstants.REPEATS; i++) { final TestRequestInterceptor testRequestInterceptor = new TestRequestInterceptor(); - final TestRequesterResponderSupport activeStreams = - TestRequesterResponderSupport.client(testRequestInterceptor); + final TestChannelSupport activeStreams = + TestChannelSupport.client(testRequestInterceptor); final Supplier payloadSupplier = - () -> TestRequesterResponderSupport.genericPayload(activeStreams.getAllocator()); + () -> TestChannelSupport.genericPayload(activeStreams.getAllocator()); final Publisher requesterOperator = scenario.requestOperator(payloadSupplier, activeStreams); @@ -763,8 +763,8 @@ public void shouldSentCancelFrameExactlyOnce(Scenario scenario) { .hasNoFragmentsFollow() .typeOf(scenario.requestType()) .hasClientSideStreamId() - .hasMetadata(TestRequesterResponderSupport.METADATA_CONTENT) - .hasData(TestRequesterResponderSupport.DATA_CONTENT) + .hasMetadata(TestChannelSupport.METADATA_CONTENT) + .hasData(TestChannelSupport.DATA_CONTENT) .hasStreamId(1) .hasNoLeaks(); diff --git a/today-remoting/src/test/java/infra/remoting/core/ResponderOperatorsCommonTest.java b/today-remoting/src/test/java/infra/remoting/core/ResponderOperatorsCommonTest.java index 900f180..1bf1c72 100755 --- a/today-remoting/src/test/java/infra/remoting/core/ResponderOperatorsCommonTest.java +++ b/today-remoting/src/test/java/infra/remoting/core/ResponderOperatorsCommonTest.java @@ -58,13 +58,13 @@ interface Scenario { ResponderFrameHandler responseOperator( long initialRequestN, Payload firstPayload, - TestRequesterResponderSupport streamManager, + TestChannelSupport streamManager, Channel handler); ResponderFrameHandler responseOperator( long initialRequestN, ByteBuf firstFragment, - TestRequesterResponderSupport streamManager, + TestChannelSupport streamManager, Channel handler); } @@ -85,7 +85,7 @@ public int maxElements() { public ResponderFrameHandler responseOperator( long initialRequestN, ByteBuf firstFragment, - TestRequesterResponderSupport streamManager, + TestChannelSupport streamManager, Channel handler) { int streamId = streamManager.getNextStreamId(); RequestResponseResponderSubscriber subscriber = @@ -105,7 +105,7 @@ public ResponderFrameHandler responseOperator( public ResponderFrameHandler responseOperator( long initialRequestN, Payload firstPayload, - TestRequesterResponderSupport streamManager, + TestChannelSupport streamManager, Channel handler) { int streamId = streamManager.getNextStreamId(); RequestResponseResponderSubscriber subscriber = @@ -140,7 +140,7 @@ public int maxElements() { public ResponderFrameHandler responseOperator( long initialRequestN, ByteBuf firstFragment, - TestRequesterResponderSupport streamManager, + TestChannelSupport streamManager, Channel handler) { int streamId = streamManager.getNextStreamId(); RequestStreamResponderSubscriber subscriber = @@ -160,7 +160,7 @@ public ResponderFrameHandler responseOperator( public ResponderFrameHandler responseOperator( long initialRequestN, Payload firstPayload, - TestRequesterResponderSupport streamManager, + TestChannelSupport streamManager, Channel handler) { int streamId = streamManager.getNextStreamId(); RequestStreamResponderSubscriber subscriber = @@ -195,7 +195,7 @@ public int maxElements() { public ResponderFrameHandler responseOperator( long initialRequestN, ByteBuf firstFragment, - TestRequesterResponderSupport streamManager, + TestChannelSupport streamManager, Channel handler) { int streamId = streamManager.getNextStreamId(); RequestChannelResponderSubscriber subscriber = @@ -215,7 +215,7 @@ public ResponderFrameHandler responseOperator( public ResponderFrameHandler responseOperator( long initialRequestN, Payload firstPayload, - TestRequesterResponderSupport streamManager, + TestChannelSupport streamManager, Channel handler) { int streamId = streamManager.getNextStreamId(); RequestChannelResponderSubscriber responderSubscriber = @@ -285,8 +285,8 @@ void shouldHandleRequest(Scenario scenario) { Assumptions.assumeThat(scenario.requestType()).isNotIn(REQUEST_FNF, METADATA_PUSH); TestRequestInterceptor testRequestInterceptor = new TestRequestInterceptor(); - TestRequesterResponderSupport testRequesterResponderSupport = - TestRequesterResponderSupport.client(testRequestInterceptor); + TestChannelSupport testRequesterResponderSupport = + TestChannelSupport.client(testRequestInterceptor); final LeaksTrackingByteBufAllocator allocator = testRequesterResponderSupport.getAllocator(); final TestDuplexConnection sender = testRequesterResponderSupport.getDuplexConnection(); TestPublisher testPublisher = TestPublisher.create(); @@ -295,11 +295,11 @@ void shouldHandleRequest(Scenario scenario) { ResponderFrameHandler responderFrameHandler = scenario.responseOperator( Long.MAX_VALUE, - TestRequesterResponderSupport.genericPayload(allocator), + TestChannelSupport.genericPayload(allocator), testRequesterResponderSupport, testHandler); - Payload randomPayload = TestRequesterResponderSupport.randomPayload(allocator); + Payload randomPayload = TestChannelSupport.randomPayload(allocator); testPublisher.assertWasSubscribed(); testPublisher.next(randomPayload.retain()); testPublisher.complete(); @@ -353,17 +353,17 @@ void shouldHandleFragmentedRequest(Scenario scenario) { Assumptions.assumeThat(scenario.requestType()).isNotIn(REQUEST_FNF, METADATA_PUSH); TestRequestInterceptor testRequestInterceptor = new TestRequestInterceptor(); - TestRequesterResponderSupport testRequesterResponderSupport = - TestRequesterResponderSupport.client(testRequestInterceptor); + TestChannelSupport testRequesterResponderSupport = + TestChannelSupport.client(testRequestInterceptor); final LeaksTrackingByteBufAllocator allocator = testRequesterResponderSupport.getAllocator(); final TestDuplexConnection sender = testRequesterResponderSupport.getDuplexConnection(); TestPublisher testPublisher = TestPublisher.create(); TestHandler testHandler = new TestHandler(testPublisher, new AssertSubscriber<>(0)); int mtu = ThreadLocalRandom.current().nextInt(64, 256); - Payload firstPayload = TestRequesterResponderSupport.randomPayload(allocator); + Payload firstPayload = TestChannelSupport.randomPayload(allocator); ArrayList fragments = - TestRequesterResponderSupport.prepareFragments(allocator, mtu, firstPayload); + TestChannelSupport.prepareFragments(allocator, mtu, firstPayload); ByteBuf firstFragment = fragments.remove(0); ResponderFrameHandler responderFrameHandler = @@ -381,7 +381,7 @@ void shouldHandleFragmentedRequest(Scenario scenario) { fragment.release(); } - Payload randomPayload = TestRequesterResponderSupport.randomPayload(allocator); + Payload randomPayload = TestChannelSupport.randomPayload(allocator); testPublisher.assertWasSubscribed(); testPublisher.next(randomPayload.retain()); testPublisher.complete(); @@ -435,16 +435,16 @@ void shouldHandleInterruptedFragmentation(Scenario scenario) { Assumptions.assumeThat(scenario.requestType()).isNotIn(REQUEST_FNF, METADATA_PUSH); final TestRequestInterceptor testRequestInterceptor = new TestRequestInterceptor(); - TestRequesterResponderSupport testRequesterResponderSupport = - TestRequesterResponderSupport.client(testRequestInterceptor); + TestChannelSupport testRequesterResponderSupport = + TestChannelSupport.client(testRequestInterceptor); final LeaksTrackingByteBufAllocator allocator = testRequesterResponderSupport.getAllocator(); TestPublisher testPublisher = TestPublisher.create(); TestHandler testHandler = new TestHandler(testPublisher, new AssertSubscriber<>(0)); int mtu = ThreadLocalRandom.current().nextInt(64, 256); - Payload firstPayload = TestRequesterResponderSupport.randomPayload(allocator); + Payload firstPayload = TestChannelSupport.randomPayload(allocator); ArrayList fragments = - TestRequesterResponderSupport.prepareFragments(allocator, mtu, firstPayload); + TestChannelSupport.prepareFragments(allocator, mtu, firstPayload); firstPayload.release(); ByteBuf firstFragment = fragments.remove(0); diff --git a/today-remoting/src/test/java/infra/remoting/core/TestRequesterResponderSupport.java b/today-remoting/src/test/java/infra/remoting/core/TestChannelSupport.java similarity index 88% rename from today-remoting/src/test/java/infra/remoting/core/TestRequesterResponderSupport.java rename to today-remoting/src/test/java/infra/remoting/core/TestChannelSupport.java index 76d83ea..5501e49 100644 --- a/today-remoting/src/test/java/infra/remoting/core/TestRequesterResponderSupport.java +++ b/today-remoting/src/test/java/infra/remoting/core/TestChannelSupport.java @@ -39,14 +39,14 @@ import static infra.remoting.frame.FrameLengthCodec.FRAME_LENGTH_MASK; -final class TestRequesterResponderSupport extends RequesterResponderSupport implements Channel { +final class TestChannelSupport extends ChannelSupport implements Channel { static final String DATA_CONTENT = "testData"; static final String METADATA_CONTENT = "testMetadata"; final Throwable error; - TestRequesterResponderSupport(@Nullable Throwable error, StreamIdProvider streamIdProvider, DuplexConnection connection, + TestChannelSupport(@Nullable Throwable error, StreamIdProvider streamIdProvider, DuplexConnection connection, int mtu, int maxFrameLength, int maxInboundPayloadSize, @Nullable RequestInterceptor requestInterceptor) { super(mtu, maxFrameLength, maxInboundPayloadSize, PayloadDecoder.ZERO_COPY, connection, streamIdProvider, (__) -> requestInterceptor); this.error = error; @@ -166,7 +166,7 @@ public synchronized int addAndGetNextStreamId(FrameHandler frameHandler) { return nextStreamId; } - public static TestRequesterResponderSupport client( + public static TestChannelSupport client( @Nullable Throwable e, @Nullable RequestInterceptor requestInterceptor) { return client( new TestDuplexConnection( @@ -178,11 +178,11 @@ public static TestRequesterResponderSupport client( e); } - public static TestRequesterResponderSupport client(@Nullable Throwable e) { + public static TestChannelSupport client(@Nullable Throwable e) { return client(0, FRAME_LENGTH_MASK, Integer.MAX_VALUE, e); } - public static TestRequesterResponderSupport client( + public static TestChannelSupport client( int mtu, int maxFrameLength, int maxInboundPayloadSize, @Nullable Throwable e) { return client( new TestDuplexConnection( @@ -194,7 +194,7 @@ public static TestRequesterResponderSupport client( e); } - public static TestRequesterResponderSupport client( + public static TestChannelSupport client( TestDuplexConnection duplexConnection, int mtu, int maxFrameLength, @@ -202,7 +202,7 @@ public static TestRequesterResponderSupport client( return client(duplexConnection, mtu, maxFrameLength, maxInboundPayloadSize, null); } - public static TestRequesterResponderSupport client( + public static TestChannelSupport client( TestDuplexConnection duplexConnection, int mtu, int maxFrameLength, @@ -212,14 +212,14 @@ public static TestRequesterResponderSupport client( duplexConnection, mtu, maxFrameLength, maxInboundPayloadSize, requestInterceptor, null); } - public static TestRequesterResponderSupport client( + public static TestChannelSupport client( TestDuplexConnection duplexConnection, int mtu, int maxFrameLength, int maxInboundPayloadSize, @Nullable RequestInterceptor requestInterceptor, @Nullable Throwable e) { - return new TestRequesterResponderSupport( + return new TestChannelSupport( e, StreamIdProvider.forClient(), duplexConnection, @@ -229,24 +229,24 @@ public static TestRequesterResponderSupport client( requestInterceptor); } - public static TestRequesterResponderSupport client( + public static TestChannelSupport client( int mtu, int maxFrameLength, int maxInboundPayloadSize) { return client(mtu, maxFrameLength, maxInboundPayloadSize, null); } - public static TestRequesterResponderSupport client(int mtu, int maxFrameLength) { + public static TestChannelSupport client(int mtu, int maxFrameLength) { return client(mtu, maxFrameLength, Integer.MAX_VALUE); } - public static TestRequesterResponderSupport client(int mtu) { + public static TestChannelSupport client(int mtu) { return client(mtu, FRAME_LENGTH_MASK); } - public static TestRequesterResponderSupport client() { + public static TestChannelSupport client() { return client(0); } - public static TestRequesterResponderSupport client(RequestInterceptor requestInterceptor) { + public static TestChannelSupport client(RequestInterceptor requestInterceptor) { return client( new TestDuplexConnection( LeaksTrackingByteBufAllocator.instrument(ByteBufAllocator.DEFAULT)), @@ -256,12 +256,12 @@ public static TestRequesterResponderSupport client(RequestInterceptor requestInt requestInterceptor); } - public TestRequesterResponderSupport assertNoActiveStreams() { + public TestChannelSupport assertNoActiveStreams() { Assertions.assertThat(activeStreams).isEmpty(); return this; } - public TestRequesterResponderSupport assertHasStream(int i, FrameHandler stream) { + public TestChannelSupport assertHasStream(int i, FrameHandler stream) { Assertions.assertThat(activeStreams).containsEntry(i, stream); return this; } From 5640d5dabac1e70a1f78aa1a7093d33471c88bbb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Sun, 3 Aug 2025 22:38:16 +0800 Subject: [PATCH 017/104] :art: --- .../src/test/resources/logback-test.xml | 4 +- .../src/test/resources/logback-test.xml | 4 +- .../infra/remoting/core/ChannelConnector.java | 4 +- .../infra/remoting/core/RemotingServer.java | 6 +-- ...elRequester.java => RequesterChannel.java} | 12 +++--- ...elResponder.java => ResponderChannel.java} | 12 +++--- .../remoting/core/ChannelLeaseTests.java | 40 +++++++++---------- .../infra/remoting/core/ChannelTests.java | 8 ++-- .../core/DefaultChannelClientTests.java | 2 +- .../infra/remoting/core/KeepAliveTest.java | 8 ++-- ...a => RequestRequesterChannelFluxTest.java} | 2 +- ...equestResponderChannelSubscriberTest.java} | 2 +- ... => RequesterChannelSubscribersTests.java} | 4 +- ... => RequesterChannelTerminationTests.java} | 8 ++-- ...rTests.java => RequesterChannelTests.java} | 8 ++-- ...rTests.java => ResponderChannelTests.java} | 8 ++-- .../remoting/core/SetupRejectionTest.java | 8 ++-- 17 files changed, 70 insertions(+), 70 deletions(-) rename today-remoting/src/main/java/infra/remoting/core/{ChannelRequester.java => RequesterChannel.java} (96%) rename today-remoting/src/main/java/infra/remoting/core/{ChannelResponder.java => ResponderChannel.java} (97%) rename today-remoting/src/test/java/infra/remoting/core/{RequestChannelRequesterFluxTest.java => RequestRequesterChannelFluxTest.java} (99%) rename today-remoting/src/test/java/infra/remoting/core/{RequestChannelResponderSubscriberTest.java => RequestResponderChannelSubscriberTest.java} (99%) rename today-remoting/src/test/java/infra/remoting/core/{ChannelRequesterSubscribersTests.java => RequesterChannelSubscribersTests.java} (99%) rename today-remoting/src/test/java/infra/remoting/core/{ChannelRequesterTerminationTests.java => RequesterChannelTerminationTests.java} (95%) rename today-remoting/src/test/java/infra/remoting/core/{ChannelRequesterTests.java => RequesterChannelTests.java} (99%) rename today-remoting/src/test/java/infra/remoting/core/{ChannelResponderTests.java => ResponderChannelTests.java} (99%) diff --git a/today-remoting-transport-local/src/test/resources/logback-test.xml b/today-remoting-transport-local/src/test/resources/logback-test.xml index 24b1089..2ecf24f 100644 --- a/today-remoting-transport-local/src/test/resources/logback-test.xml +++ b/today-remoting-transport-local/src/test/resources/logback-test.xml @@ -34,8 +34,8 @@ - - + + diff --git a/today-remoting-transport-tcp/src/test/resources/logback-test.xml b/today-remoting-transport-tcp/src/test/resources/logback-test.xml index 439393d..2b44f51 100644 --- a/today-remoting-transport-tcp/src/test/resources/logback-test.xml +++ b/today-remoting-transport-tcp/src/test/resources/logback-test.xml @@ -28,8 +28,8 @@ - - + + diff --git a/today-remoting/src/main/java/infra/remoting/core/ChannelConnector.java b/today-remoting/src/main/java/infra/remoting/core/ChannelConnector.java index 1f970dd..53dc575 100644 --- a/today-remoting/src/main/java/infra/remoting/core/ChannelConnector.java +++ b/today-remoting/src/main/java/infra/remoting/core/ChannelConnector.java @@ -611,7 +611,7 @@ public Mono connect(Supplier transportSupplier) { final Sinks.Empty requesterOnAllClosedSink = Sinks.unsafe().empty(); final Sinks.Empty responderOnAllClosedSink = Sinks.unsafe().empty(); - Channel channelRequester = new ChannelRequester(multiplexer.asClientConnection(), payloadDecoder, + Channel channelRequester = new RequesterChannel(multiplexer.asClientConnection(), payloadDecoder, StreamIdProvider.forClient(), mtu, maxFrameLength, maxInboundPayloadSize, (int) keepAliveInterval.toMillis(), (int) keepAliveMaxLifeTime.toMillis(), keepAliveHandler, interceptors::initRequesterRequestInterceptor, requesterLeaseTracker, requesterOnAllClosedSink, @@ -631,7 +631,7 @@ public Mono connect(Supplier transportSupplier) { ? new ResponderLeaseTracker(CLIENT_TAG, wrappedConnection, leases.sender) : null; - Channel channelResponder = new ChannelResponder(multiplexer.asServerConnection(), wrappedChannelHandler, + Channel responderChannel = new ResponderChannel(multiplexer.asServerConnection(), wrappedChannelHandler, payloadDecoder, responderLeaseTracker, mtu, maxFrameLength, maxInboundPayloadSize, leaseEnabled && leases.sender instanceof TrackingLeaseSender ? channel -> interceptors.initResponderRequestInterceptor(channel, (TrackingLeaseSender) leases.sender) diff --git a/today-remoting/src/main/java/infra/remoting/core/RemotingServer.java b/today-remoting/src/main/java/infra/remoting/core/RemotingServer.java index 307bcb2..982f4dd 100644 --- a/today-remoting/src/main/java/infra/remoting/core/RemotingServer.java +++ b/today-remoting/src/main/java/infra/remoting/core/RemotingServer.java @@ -411,12 +411,12 @@ private Mono acceptSetup(ServerSetup serverSetup, ByteBuf setupFrame, Dupl final Sinks.Empty requesterOnAllClosedSink = Sinks.unsafe().empty(); final Sinks.Empty responderOnAllClosedSink = Sinks.unsafe().empty(); - Channel channelRequester = new ChannelRequester(multiplexer.asServerConnection(), payloadDecoder, StreamIdProvider.forServer(), + Channel requesterChannel = new RequesterChannel(multiplexer.asServerConnection(), payloadDecoder, StreamIdProvider.forServer(), mtu, maxFrameLength, maxInboundPayloadSize, setupPayload.keepAliveInterval(), setupPayload.keepAliveMaxLifetime(), keepAliveHandler, interceptors::initRequesterRequestInterceptor, requesterLeaseTracker, requesterOnAllClosedSink, Mono.whenDelayError(responderOnAllClosedSink.asMono(), requesterOnAllClosedSink.asMono())); - Channel wrappedChannelRequester = interceptors.decorateRequester(channelRequester); + Channel wrappedChannelRequester = interceptors.decorateRequester(requesterChannel); return interceptors .decorateAcceptor(acceptor) @@ -433,7 +433,7 @@ wrappedDuplexConnection, rejectedSetupError(err))) ? new ResponderLeaseTracker(SERVER_TAG, clientConnection, leases.sender) : null; - Channel channelResponder = new ChannelResponder(clientConnection, wrappedChannelHandler, payloadDecoder, responderLeaseTracker, + Channel channelResponder = new ResponderChannel(clientConnection, wrappedChannelHandler, payloadDecoder, responderLeaseTracker, mtu, maxFrameLength, maxInboundPayloadSize, leaseEnabled && leases.sender instanceof TrackingLeaseSender ? channel -> interceptors.initResponderRequestInterceptor(channel, (TrackingLeaseSender) leases.sender) diff --git a/today-remoting/src/main/java/infra/remoting/core/ChannelRequester.java b/today-remoting/src/main/java/infra/remoting/core/RequesterChannel.java similarity index 96% rename from today-remoting/src/main/java/infra/remoting/core/ChannelRequester.java rename to today-remoting/src/main/java/infra/remoting/core/RequesterChannel.java index 37821c7..50b1539 100644 --- a/today-remoting/src/main/java/infra/remoting/core/ChannelRequester.java +++ b/today-remoting/src/main/java/infra/remoting/core/RequesterChannel.java @@ -51,11 +51,11 @@ import static infra.remoting.keepalive.KeepAliveSupport.ClientKeepAliveSupport; /** - * Requester Side of a Channel socket. Sends {@link ByteBuf}s to a {@link ChannelResponder} of peer + * Requester Side of a Channel socket. Sends {@link ByteBuf}s to a {@link ResponderChannel} of peer */ -class ChannelRequester extends ChannelSupport implements Channel { +class RequesterChannel extends ChannelSupport implements Channel { - private static final Logger LOGGER = LoggerFactory.getLogger(ChannelRequester.class); + private static final Logger LOGGER = LoggerFactory.getLogger(RequesterChannel.class); private static final Exception CLOSED_CHANNEL_EXCEPTION = new ClosedChannelException(); @@ -64,8 +64,8 @@ class ChannelRequester extends ChannelSupport implements Channel { } private volatile Throwable terminationError; - private static final AtomicReferenceFieldUpdater TERMINATION_ERROR = - AtomicReferenceFieldUpdater.newUpdater(ChannelRequester.class, Throwable.class, "terminationError"); + private static final AtomicReferenceFieldUpdater TERMINATION_ERROR = + AtomicReferenceFieldUpdater.newUpdater(RequesterChannel.class, Throwable.class, "terminationError"); @Nullable private final RequesterLeaseTracker requesterLeaseTracker; @@ -76,7 +76,7 @@ class ChannelRequester extends ChannelSupport implements Channel { private final Mono onAllClosed; - ChannelRequester(DuplexConnection connection, PayloadDecoder payloadDecoder, StreamIdProvider streamIdProvider, + RequesterChannel(DuplexConnection connection, PayloadDecoder payloadDecoder, StreamIdProvider streamIdProvider, int mtu, int maxFrameLength, int maxInboundPayloadSize, int keepAliveTickPeriod, int keepAliveAckTimeout, @Nullable KeepAliveHandler keepAliveHandler, Function requestInterceptorFunction, @Nullable RequesterLeaseTracker requesterLeaseTracker, Sinks.Empty onThisSideClosedSink, Mono onAllClosed) { diff --git a/today-remoting/src/main/java/infra/remoting/core/ChannelResponder.java b/today-remoting/src/main/java/infra/remoting/core/ResponderChannel.java similarity index 97% rename from today-remoting/src/main/java/infra/remoting/core/ChannelResponder.java rename to today-remoting/src/main/java/infra/remoting/core/ResponderChannel.java index 1e46c17..a8a7848 100644 --- a/today-remoting/src/main/java/infra/remoting/core/ChannelResponder.java +++ b/today-remoting/src/main/java/infra/remoting/core/ResponderChannel.java @@ -50,11 +50,11 @@ import reactor.core.publisher.Sinks; /** - * Responder side of Channel. Receives {@link ByteBuf}s from a peer's {@link ChannelRequester} + * Responder side of Channel. Receives {@link ByteBuf}s from a peer's {@link RequesterChannel} */ -class ChannelResponder extends ChannelSupport implements Channel { +class ResponderChannel extends ChannelSupport implements Channel { - private static final Logger LOGGER = LoggerFactory.getLogger(ChannelResponder.class); + private static final Logger LOGGER = LoggerFactory.getLogger(ResponderChannel.class); private static final Exception CLOSED_CHANNEL_EXCEPTION = new ClosedChannelException(); @@ -66,11 +66,11 @@ class ChannelResponder extends ChannelSupport implements Channel { private final ResponderLeaseTracker leaseHandler; private volatile Throwable terminationError; - private static final AtomicReferenceFieldUpdater TERMINATION_ERROR = + private static final AtomicReferenceFieldUpdater TERMINATION_ERROR = AtomicReferenceFieldUpdater.newUpdater( - ChannelResponder.class, Throwable.class, "terminationError"); + ResponderChannel.class, Throwable.class, "terminationError"); - ChannelResponder(DuplexConnection connection, Channel requestHandler, PayloadDecoder payloadDecoder, @Nullable ResponderLeaseTracker leaseHandler, + ResponderChannel(DuplexConnection connection, Channel requestHandler, PayloadDecoder payloadDecoder, @Nullable ResponderLeaseTracker leaseHandler, int mtu, int maxFrameLength, int maxInboundPayloadSize, Function requestInterceptorFunction, Sinks.Empty onThisSideClosedSink) { super(mtu, maxFrameLength, maxInboundPayloadSize, payloadDecoder, connection, null, requestInterceptorFunction); diff --git a/today-remoting/src/test/java/infra/remoting/core/ChannelLeaseTests.java b/today-remoting/src/test/java/infra/remoting/core/ChannelLeaseTests.java index d170925..6dc0d58 100644 --- a/today-remoting/src/test/java/infra/remoting/core/ChannelLeaseTests.java +++ b/today-remoting/src/test/java/infra/remoting/core/ChannelLeaseTests.java @@ -90,7 +90,7 @@ class ChannelLeaseTests { private ResponderLeaseTracker responderLeaseTracker; private LeaksTrackingByteBufAllocator byteBufAllocator; private TestDuplexConnection connection; - private ChannelResponder channelResponder; + private ResponderChannel responderChannel; private Channel mockChannelHandler; private Sinks.Many leaseSender = Sinks.many().multicast().onBackpressureBuffer(); @@ -112,7 +112,7 @@ void setUp() { ClientServerInputMultiplexer multiplexer = new ClientServerInputMultiplexer(connection, new InitializingInterceptorRegistry(), true); channelRequester = - new ChannelRequester( + new RequesterChannel( multiplexer.asClientConnection(), payloadDecoder, StreamIdProvider.forClient(), @@ -183,8 +183,8 @@ protected void hookOnError(Throwable throwable) { })); }); - channelResponder = - new ChannelResponder( + responderChannel = + new ResponderChannel( multiplexer.asServerConnection(), mockChannelHandler, payloadDecoder, @@ -426,25 +426,25 @@ void responderMissingLeaseRequestsAreRejected(FrameType frameType) { case REQUEST_FNF: final ByteBuf fnfFrame = RequestFireAndForgetFrameCodec.encodeReleasingPayload(byteBufAllocator, 1, payload1); - channelResponder.handleFrame(fnfFrame); + responderChannel.handleFrame(fnfFrame); fnfFrame.release(); break; case REQUEST_RESPONSE: final ByteBuf requestResponseFrame = RequestResponseFrameCodec.encodeReleasingPayload(byteBufAllocator, 1, payload1); - channelResponder.handleFrame(requestResponseFrame); + responderChannel.handleFrame(requestResponseFrame); requestResponseFrame.release(); break; case REQUEST_STREAM: final ByteBuf requestStreamFrame = RequestStreamFrameCodec.encodeReleasingPayload(byteBufAllocator, 1, 1, payload1); - channelResponder.handleFrame(requestStreamFrame); + responderChannel.handleFrame(requestStreamFrame); requestStreamFrame.release(); break; case REQUEST_CHANNEL: final ByteBuf requestChannelFrame = RequestChannelFrameCodec.encodeReleasingPayload(byteBufAllocator, 1, true, 1, payload1); - channelResponder.handleFrame(requestChannelFrame); + responderChannel.handleFrame(requestChannelFrame); requestChannelFrame.release(); break; } @@ -474,25 +474,25 @@ void responderPresentLeaseRequestsAreAccepted(FrameType frameType) { case REQUEST_FNF: final ByteBuf fnfFrame = RequestFireAndForgetFrameCodec.encodeReleasingPayload(byteBufAllocator, 1, payload1); - channelResponder.handleFireAndForget(1, fnfFrame); + responderChannel.handleFireAndForget(1, fnfFrame); fnfFrame.release(); break; case REQUEST_RESPONSE: final ByteBuf requestResponseFrame = RequestResponseFrameCodec.encodeReleasingPayload(byteBufAllocator, 1, payload1); - channelResponder.handleFrame(requestResponseFrame); + responderChannel.handleFrame(requestResponseFrame); requestResponseFrame.release(); break; case REQUEST_STREAM: final ByteBuf requestStreamFrame = RequestStreamFrameCodec.encodeReleasingPayload(byteBufAllocator, 1, 1, payload1); - channelResponder.handleFrame(requestStreamFrame); + responderChannel.handleFrame(requestStreamFrame); requestStreamFrame.release(); break; case REQUEST_CHANNEL: final ByteBuf requestChannelFrame = RequestChannelFrameCodec.encodeReleasingPayload(byteBufAllocator, 1, true, 1, payload1); - channelResponder.handleFrame(requestChannelFrame); + responderChannel.handleFrame(requestChannelFrame); requestChannelFrame.release(); break; } @@ -547,8 +547,8 @@ void responderDepletedAllowedLeaseRequestsAreRejected(FrameType frameType) { RequestFireAndForgetFrameCodec.encodeReleasingPayload(byteBufAllocator, 1, payload1); final ByteBuf fnfFrame2 = RequestFireAndForgetFrameCodec.encodeReleasingPayload(byteBufAllocator, 3, payload2); - channelResponder.handleFrame(fnfFrame); - channelResponder.handleFrame(fnfFrame2); + responderChannel.handleFrame(fnfFrame); + responderChannel.handleFrame(fnfFrame2); fnfFrame.release(); fnfFrame2.release(); break; @@ -557,8 +557,8 @@ void responderDepletedAllowedLeaseRequestsAreRejected(FrameType frameType) { RequestResponseFrameCodec.encodeReleasingPayload(byteBufAllocator, 1, payload1); final ByteBuf requestResponseFrame2 = RequestResponseFrameCodec.encodeReleasingPayload(byteBufAllocator, 3, payload2); - channelResponder.handleFrame(requestResponseFrame); - channelResponder.handleFrame(requestResponseFrame2); + responderChannel.handleFrame(requestResponseFrame); + responderChannel.handleFrame(requestResponseFrame2); requestResponseFrame.release(); requestResponseFrame2.release(); break; @@ -567,8 +567,8 @@ void responderDepletedAllowedLeaseRequestsAreRejected(FrameType frameType) { RequestStreamFrameCodec.encodeReleasingPayload(byteBufAllocator, 1, 1, payload1); final ByteBuf requestStreamFrame2 = RequestStreamFrameCodec.encodeReleasingPayload(byteBufAllocator, 3, 1, payload2); - channelResponder.handleFrame(requestStreamFrame); - channelResponder.handleFrame(requestStreamFrame2); + responderChannel.handleFrame(requestStreamFrame); + responderChannel.handleFrame(requestStreamFrame2); requestStreamFrame.release(); requestStreamFrame2.release(); break; @@ -577,8 +577,8 @@ void responderDepletedAllowedLeaseRequestsAreRejected(FrameType frameType) { RequestChannelFrameCodec.encodeReleasingPayload(byteBufAllocator, 1, true, 1, payload1); final ByteBuf requestChannelFrame2 = RequestChannelFrameCodec.encodeReleasingPayload(byteBufAllocator, 3, true, 1, payload2); - channelResponder.handleFrame(requestChannelFrame); - channelResponder.handleFrame(requestChannelFrame2); + responderChannel.handleFrame(requestChannelFrame); + responderChannel.handleFrame(requestChannelFrame2); requestChannelFrame.release(); requestChannelFrame2.release(); break; diff --git a/today-remoting/src/test/java/infra/remoting/core/ChannelTests.java b/today-remoting/src/test/java/infra/remoting/core/ChannelTests.java index 20730d7..18c8439 100644 --- a/today-remoting/src/test/java/infra/remoting/core/ChannelTests.java +++ b/today-remoting/src/test/java/infra/remoting/core/ChannelTests.java @@ -510,10 +510,10 @@ public static class ChannelRule { Sinks.Many serverProcessor; Sinks.Many clientProcessor; - private ChannelRequester crs; + private RequesterChannel crs; @SuppressWarnings("unused") - private ChannelResponder srs; + private ResponderChannel srs; private Channel requestAcceptor; @@ -572,7 +572,7 @@ public Flux requestChannel(Publisher payloads) { }; srs = - new ChannelResponder( + new ResponderChannel( serverConnection, requestAcceptor, PayloadDecoder.DEFAULT, @@ -584,7 +584,7 @@ public Flux requestChannel(Publisher payloads) { otherClosedSink); crs = - new ChannelRequester( + new RequesterChannel( clientConnection, PayloadDecoder.DEFAULT, StreamIdProvider.forClient(), diff --git a/today-remoting/src/test/java/infra/remoting/core/DefaultChannelClientTests.java b/today-remoting/src/test/java/infra/remoting/core/DefaultChannelClientTests.java index 7eed620..114c6e1 100644 --- a/today-remoting/src/test/java/infra/remoting/core/DefaultChannelClientTests.java +++ b/today-remoting/src/test/java/infra/remoting/core/DefaultChannelClientTests.java @@ -756,7 +756,7 @@ protected void doInit() { @Override protected Channel newChannel() { this.thisClosedSink = Sinks.empty(); - return new ChannelRequester( + return new RequesterChannel( connection, PayloadDecoder.ZERO_COPY, StreamIdProvider.forClient(), diff --git a/today-remoting/src/test/java/infra/remoting/core/KeepAliveTest.java b/today-remoting/src/test/java/infra/remoting/core/KeepAliveTest.java index 1d3623f..9d0a927 100644 --- a/today-remoting/src/test/java/infra/remoting/core/KeepAliveTest.java +++ b/today-remoting/src/test/java/infra/remoting/core/KeepAliveTest.java @@ -74,8 +74,8 @@ static ChannelState requester(int tickPeriod, int timeout) { LeaksTrackingByteBufAllocator.instrument(ByteBufAllocator.DEFAULT); TestDuplexConnection connection = new TestDuplexConnection(allocator); Sinks.Empty empty = Sinks.empty(); - ChannelRequester channel = - new ChannelRequester( + RequesterChannel channel = + new RequesterChannel( connection, PayloadDecoder.ZERO_COPY, StreamIdProvider.forClient(), @@ -104,8 +104,8 @@ static ResumableChannelState resumableRequester(int tickPeriod, int timeout) { new InMemoryResumableFramesStore("test", Unpooled.EMPTY_BUFFER, 10_000)); Sinks.Empty onClose = Sinks.empty(); - ChannelRequester channel = - new ChannelRequester( + RequesterChannel channel = + new RequesterChannel( resumableConnection, PayloadDecoder.ZERO_COPY, StreamIdProvider.forClient(), diff --git a/today-remoting/src/test/java/infra/remoting/core/RequestChannelRequesterFluxTest.java b/today-remoting/src/test/java/infra/remoting/core/RequestRequesterChannelFluxTest.java similarity index 99% rename from today-remoting/src/test/java/infra/remoting/core/RequestChannelRequesterFluxTest.java rename to today-remoting/src/test/java/infra/remoting/core/RequestRequesterChannelFluxTest.java index 913e701..a4c7aef 100644 --- a/today-remoting/src/test/java/infra/remoting/core/RequestChannelRequesterFluxTest.java +++ b/today-remoting/src/test/java/infra/remoting/core/RequestRequesterChannelFluxTest.java @@ -55,7 +55,7 @@ import static infra.remoting.frame.FrameLengthCodec.FRAME_LENGTH_MASK; import static infra.remoting.frame.FrameType.CANCEL; -public class RequestChannelRequesterFluxTest { +public class RequestRequesterChannelFluxTest { @BeforeAll public static void setUp() { diff --git a/today-remoting/src/test/java/infra/remoting/core/RequestChannelResponderSubscriberTest.java b/today-remoting/src/test/java/infra/remoting/core/RequestResponderChannelSubscriberTest.java similarity index 99% rename from today-remoting/src/test/java/infra/remoting/core/RequestChannelResponderSubscriberTest.java rename to today-remoting/src/test/java/infra/remoting/core/RequestResponderChannelSubscriberTest.java index 38bd73c..8e4304d 100644 --- a/today-remoting/src/test/java/infra/remoting/core/RequestChannelResponderSubscriberTest.java +++ b/today-remoting/src/test/java/infra/remoting/core/RequestResponderChannelSubscriberTest.java @@ -64,7 +64,7 @@ import static reactor.test.publisher.TestPublisher.Violation.CLEANUP_ON_TERMINATE; import static reactor.test.publisher.TestPublisher.Violation.DEFER_CANCELLATION; -public class RequestChannelResponderSubscriberTest { +public class RequestResponderChannelSubscriberTest { @BeforeAll public static void setUp() { diff --git a/today-remoting/src/test/java/infra/remoting/core/ChannelRequesterSubscribersTests.java b/today-remoting/src/test/java/infra/remoting/core/RequesterChannelSubscribersTests.java similarity index 99% rename from today-remoting/src/test/java/infra/remoting/core/ChannelRequesterSubscribersTests.java rename to today-remoting/src/test/java/infra/remoting/core/RequesterChannelSubscribersTests.java index 2fa8d2e..0607794 100644 --- a/today-remoting/src/test/java/infra/remoting/core/ChannelRequesterSubscribersTests.java +++ b/today-remoting/src/test/java/infra/remoting/core/RequesterChannelSubscribersTests.java @@ -52,7 +52,7 @@ import static infra.remoting.frame.FrameLengthCodec.FRAME_LENGTH_MASK; -class ChannelRequesterSubscribersTests { +class RequesterChannelSubscribersTests { private static final Set REQUEST_TYPES = new HashSet<>( @@ -81,7 +81,7 @@ void setUp() { this.thisClosedSink = Sinks.empty(); this.otherClosedSink = Sinks.empty(); channelRequester = - new ChannelRequester( + new RequesterChannel( connection, PayloadDecoder.DEFAULT, StreamIdProvider.forClient(), diff --git a/today-remoting/src/test/java/infra/remoting/core/ChannelRequesterTerminationTests.java b/today-remoting/src/test/java/infra/remoting/core/RequesterChannelTerminationTests.java similarity index 95% rename from today-remoting/src/test/java/infra/remoting/core/ChannelRequesterTerminationTests.java rename to today-remoting/src/test/java/infra/remoting/core/RequesterChannelTerminationTests.java index 3181f6d..8ef305d 100644 --- a/today-remoting/src/test/java/infra/remoting/core/ChannelRequesterTerminationTests.java +++ b/today-remoting/src/test/java/infra/remoting/core/RequesterChannelTerminationTests.java @@ -32,14 +32,14 @@ import infra.remoting.FrameAssert; import infra.remoting.Payload; import infra.remoting.Channel; -import infra.remoting.core.ChannelRequesterTests.ClientChannelRule; +import infra.remoting.core.RequesterChannelTests.ClientChannelRule; import infra.remoting.frame.FrameType; import infra.remoting.util.EmptyPayload; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import reactor.test.StepVerifier; -public class ChannelRequesterTerminationTests { +public class RequesterChannelTerminationTests { public final ClientChannelRule rule = new ClientChannelRule(); @@ -57,7 +57,7 @@ public void tearDownAndCheckNoLeaks() { @MethodSource("interactions") public void testCurrentStreamIsTerminatedOnConnectionClose( FrameType requestType, Function> interaction) { - ChannelRequester channel = rule.channel; + RequesterChannel channel = rule.channel; StepVerifier.create(interaction.apply(channel)) .then( @@ -73,7 +73,7 @@ public void testCurrentStreamIsTerminatedOnConnectionClose( @MethodSource("interactions") public void testSubsequentStreamIsTerminatedAfterConnectionClose( FrameType requestType, Function> interaction) { - ChannelRequester channel = rule.channel; + RequesterChannel channel = rule.channel; rule.connection.dispose(); StepVerifier.create(interaction.apply(channel)) diff --git a/today-remoting/src/test/java/infra/remoting/core/ChannelRequesterTests.java b/today-remoting/src/test/java/infra/remoting/core/RequesterChannelTests.java similarity index 99% rename from today-remoting/src/test/java/infra/remoting/core/ChannelRequesterTests.java rename to today-remoting/src/test/java/infra/remoting/core/RequesterChannelTests.java index 8b6c239..2673c9e 100644 --- a/today-remoting/src/test/java/infra/remoting/core/ChannelRequesterTests.java +++ b/today-remoting/src/test/java/infra/remoting/core/RequesterChannelTests.java @@ -109,7 +109,7 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.verify; -public class ChannelRequesterTests { +public class RequesterChannelTests { ClientChannelRule rule; @@ -1479,16 +1479,16 @@ else if (type.equals("channel")) { } } - public static class ClientChannelRule extends AbstractChannelRule { + public static class ClientChannelRule extends AbstractChannelRule { protected Sinks.Empty thisClosedSink; protected Sinks.Empty otherClosedSink; @Override - protected ChannelRequester newChannel() { + protected RequesterChannel newChannel() { this.thisClosedSink = Sinks.empty(); this.otherClosedSink = Sinks.empty(); - return new ChannelRequester( + return new RequesterChannel( connection, PayloadDecoder.ZERO_COPY, StreamIdProvider.forClient(), diff --git a/today-remoting/src/test/java/infra/remoting/core/ChannelResponderTests.java b/today-remoting/src/test/java/infra/remoting/core/ResponderChannelTests.java similarity index 99% rename from today-remoting/src/test/java/infra/remoting/core/ChannelResponderTests.java rename to today-remoting/src/test/java/infra/remoting/core/ResponderChannelTests.java index 0ff21fd..6194ae9 100644 --- a/today-remoting/src/test/java/infra/remoting/core/ChannelResponderTests.java +++ b/today-remoting/src/test/java/infra/remoting/core/ResponderChannelTests.java @@ -100,7 +100,7 @@ import static infra.remoting.frame.FrameType.REQUEST_STREAM; import static org.assertj.core.api.Assertions.assertThat; -public class ChannelResponderTests { +public class ResponderChannelTests { ServerChannelRule rule; @@ -1182,7 +1182,7 @@ public Flux requestChannel(Publisher payloads) { rule.assertHasNoLeaks(); } - public static class ServerChannelRule extends AbstractChannelRule { + public static class ServerChannelRule extends AbstractChannelRule { private Channel acceptingSocket; private volatile int prefetch; @@ -1223,9 +1223,9 @@ public void setAcceptingSocket(Channel acceptingSocket, int prefetch) { } @Override - protected ChannelResponder newChannel() { + protected ResponderChannel newChannel() { onCloseSink = Sinks.empty(); - return new ChannelResponder( + return new ResponderChannel( connection, acceptingSocket, PayloadDecoder.ZERO_COPY, diff --git a/today-remoting/src/test/java/infra/remoting/core/SetupRejectionTest.java b/today-remoting/src/test/java/infra/remoting/core/SetupRejectionTest.java index f353c36..8de0ab4 100644 --- a/today-remoting/src/test/java/infra/remoting/core/SetupRejectionTest.java +++ b/today-remoting/src/test/java/infra/remoting/core/SetupRejectionTest.java @@ -76,8 +76,8 @@ void requesterStreamsTerminatedOnZeroErrorFrame() { TestDuplexConnection conn = new TestDuplexConnection(allocator); Sinks.Empty onThisSideClosedSink = Sinks.empty(); - ChannelRequester channel = - new ChannelRequester( + RequesterChannel channel = + new RequesterChannel( conn, DefaultPayload::create, StreamIdProvider.forClient(), @@ -118,8 +118,8 @@ void requesterNewStreamsTerminatedAfterZeroErrorFrame() { LeaksTrackingByteBufAllocator.instrument(ByteBufAllocator.DEFAULT); TestDuplexConnection conn = new TestDuplexConnection(allocator); Sinks.Empty onThisSideClosedSink = Sinks.empty(); - ChannelRequester channel = - new ChannelRequester( + RequesterChannel channel = + new RequesterChannel( conn, DefaultPayload::create, StreamIdProvider.forClient(), From c6a4632a00fd2eb11be2cc094f676f0d0996ad8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Mon, 4 Aug 2025 21:28:41 +0800 Subject: [PATCH 018/104] :sparkles: today-remoting-micrometer --- settings.gradle | 1 + today-cloud-dependencies/build.gradle | 2 + today-remoting-micrometer/build.gradle | 31 ++ .../micrometer/MicrometerChannel.java | 207 +++++++++++++ .../MicrometerChannelDecorator.java | 62 ++++ .../MicrometerDuplexConnection.java | 286 ++++++++++++++++++ .../MicrometerDuplexConnectionDecorator.java | 66 ++++ .../observation/ChannelContext.java | 77 +++++ ...ChannelRequesterObservationConvention.java | 36 +++ ...nelRequesterTracingObservationHandler.java | 94 ++++++ ...ChannelResponderObservationConvention.java | 36 +++ ...nelResponderTracingObservationHandler.java | 93 ++++++ .../DefaultChannelObservationConvention.java | 51 ++++ ...ChannelRequesterObservationConvention.java | 59 ++++ ...ChannelResponderObservationConvention.java | 60 ++++ .../ObservationRequesterChannel.java | 185 +++++++++++ .../ObservationResponderChannel.java | 156 ++++++++++ .../micrometer/observation/PayloadUtils.java | 54 ++++ .../RemotingObservationDocumentation.java | 229 ++++++++++++++ .../remoting/micrometer/package-info.java | 28 ++ .../MicrometerChannelDecoratorTests.java | 59 ++++ .../micrometer/MicrometerChannelTests.java | 148 +++++++++ ...rometerDuplexConnectionDecoratorTests.java | 70 +++++ .../MicrometerDuplexConnectionTests.java | 228 ++++++++++++++ .../integration/IntegrationTests.java | 196 ++++++++++++ .../integration/InteractionsLoadTests.java | 110 +++++++ .../integration/StreamingTests.java | 123 ++++++++ .../integration/TcpIntegrationTests.java | 197 ++++++++++++ .../observation/ByteBufGetter.java | 38 +++ .../observation/ByteBufSetter.java | 35 +++ .../ObservationIntegrationTests.java | 233 ++++++++++++++ .../src/test/resources/logback-test.xml | 33 ++ .../remoting/integration/FragmentTests.java | 4 +- .../transport/netty/SetupRejectionTests.java | 4 +- today-remoting/build.gradle | 3 + .../java/infra/remoting/ChannelAcceptor.java | 14 +- .../infra/remoting/core/ChannelConnector.java | 55 ++-- .../core/ClientServerInputMultiplexer.java | 2 +- .../FireAndForgetResponderSubscriber.java | 2 +- .../remoting/core/FragmentationUtils.java | 108 +++---- .../infra/remoting/core/ReassemblyUtils.java | 4 +- .../infra/remoting/core/RemotingServer.java | 18 +- .../core/RequestChannelRequesterFlux.java | 7 +- .../RequestChannelResponderSubscriber.java | 202 +++++-------- .../RequestResponseResponderSubscriber.java | 173 +++++------ .../RequestStreamResponderSubscriber.java | 184 +++++------ .../infra/remoting/core/ResponderChannel.java | 12 +- .../frame/decoder/DefaultPayloadDecoder.java | 6 +- .../frame/decoder/PayloadDecoder.java | 9 +- .../frame/decoder/ZeroCopyPayloadDecoder.java | 47 ++- .../remoting/lb/WeightedStatsChannel.java | 6 +- ...Interceptor.java => ChannelDecorator.java} | 6 +- ...erceptor.java => ConnectionDecorator.java} | 4 +- .../InitializingInterceptorRegistry.java | 10 +- .../remoting/plugins/InterceptorRegistry.java | 48 +-- ...terceptor.java => RateLimitDecorator.java} | 22 +- .../remoting/plugins/RequestInterceptor.java | 2 +- ...nnelDecorator.java => ChannelWrapper.java} | 5 +- .../core/DefaultChannelClientTests.java | 4 +- .../remoting/core/SetupRejectionTest.java | 4 +- .../tcp/channel/ChannelEchoClient.java | 63 ++++ .../examples/tcp/client/ClientExample.java | 70 +++++ ...ingWithServerSideNotificationsExample.java | 239 +++++++++++++++ .../lease/advanced/common/LeaseManager.java | 164 ++++++++++ .../common/LimitBasedLeaseSender.java | 75 +++++ .../common/LimitBasedStatsCollector.java | 92 ++++++ .../tcp/lease/advanced/controller/Task.java | 45 +++ .../controller/TasksHandlingChannel.java | 62 ++++ .../invertmulticlient/RequestingServer.java | 80 +++++ .../invertmulticlient/RespondingClient.java | 87 ++++++ .../multiclient/RequestingClient.java | 59 ++++ .../multiclient/RespondingServer.java | 84 +++++ .../tcp/lease/simple/LeaseExample.java | 161 ++++++++++ .../RoundRobinLoadbalancerExample.java | 113 +++++++ .../plugins/LimitRateInterceptorExample.java | 102 +++++++ .../tcp/requestresponse/HelloWorldClient.java | 70 +++++ .../remoting/examples/tcp/resume/Files.java | 166 ++++++++++ .../tcp/resume/ResumeFileTransfer.java | 116 +++++++ .../remoting/examples/tcp/resume/readme.md | 29 ++ .../tcp/stream/ClientStreamingToServer.java | 65 ++++ .../tcp/stream/ServerStreamingToClient.java | 59 ++++ .../ws/WebSocketAggregationSample.java | 77 +++++ .../examples/ws/WebSocketHeadersSample.java | 98 ++++++ .../infra/remoting/lb/LoadbalanceTests.java | 4 +- .../resume/DisconnectableClientTransport.java | 78 +++++ .../resume/ResumeIntegrationTests.java | 227 ++++++++++++++ .../src/test/resources/logback-test.xml | 3 + today-remoting/src/test/resources/lorem.txt | 32 ++ .../java/infra/remoting/test/PingHandler.java | 2 +- .../infra/remoting/test/TransportPair.java | 8 +- 90 files changed, 6210 insertions(+), 568 deletions(-) create mode 100644 today-remoting-micrometer/build.gradle create mode 100644 today-remoting-micrometer/src/main/java/infra/remoting/micrometer/MicrometerChannel.java create mode 100644 today-remoting-micrometer/src/main/java/infra/remoting/micrometer/MicrometerChannelDecorator.java create mode 100644 today-remoting-micrometer/src/main/java/infra/remoting/micrometer/MicrometerDuplexConnection.java create mode 100644 today-remoting-micrometer/src/main/java/infra/remoting/micrometer/MicrometerDuplexConnectionDecorator.java create mode 100644 today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/ChannelContext.java create mode 100644 today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/ChannelRequesterObservationConvention.java create mode 100644 today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/ChannelRequesterTracingObservationHandler.java create mode 100644 today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/ChannelResponderObservationConvention.java create mode 100644 today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/ChannelResponderTracingObservationHandler.java create mode 100644 today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/DefaultChannelObservationConvention.java create mode 100644 today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/DefaultChannelRequesterObservationConvention.java create mode 100644 today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/DefaultChannelResponderObservationConvention.java create mode 100644 today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/ObservationRequesterChannel.java create mode 100644 today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/ObservationResponderChannel.java create mode 100644 today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/PayloadUtils.java create mode 100644 today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/RemotingObservationDocumentation.java create mode 100644 today-remoting-micrometer/src/main/java/infra/remoting/micrometer/package-info.java create mode 100644 today-remoting-micrometer/src/test/java/infra/remoting/micrometer/MicrometerChannelDecoratorTests.java create mode 100644 today-remoting-micrometer/src/test/java/infra/remoting/micrometer/MicrometerChannelTests.java create mode 100644 today-remoting-micrometer/src/test/java/infra/remoting/micrometer/MicrometerDuplexConnectionDecoratorTests.java create mode 100644 today-remoting-micrometer/src/test/java/infra/remoting/micrometer/MicrometerDuplexConnectionTests.java create mode 100644 today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/IntegrationTests.java create mode 100644 today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/InteractionsLoadTests.java create mode 100644 today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/StreamingTests.java create mode 100644 today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/TcpIntegrationTests.java create mode 100644 today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/observation/ByteBufGetter.java create mode 100644 today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/observation/ByteBufSetter.java create mode 100644 today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/observation/ObservationIntegrationTests.java create mode 100644 today-remoting-micrometer/src/test/resources/logback-test.xml rename today-remoting/src/main/java/infra/remoting/plugins/{ChannelInterceptor.java => ChannelDecorator.java} (80%) rename today-remoting/src/main/java/infra/remoting/plugins/{ConnectionInterceptor.java => ConnectionDecorator.java} (89%) rename today-remoting/src/main/java/infra/remoting/plugins/{RateLimitInterceptor.java => RateLimitDecorator.java} (85%) rename today-remoting/src/main/java/infra/remoting/util/{ChannelDecorator.java => ChannelWrapper.java} (95%) create mode 100644 today-remoting/src/test/java/infra/remoting/examples/tcp/channel/ChannelEchoClient.java create mode 100644 today-remoting/src/test/java/infra/remoting/examples/tcp/client/ClientExample.java create mode 100644 today-remoting/src/test/java/infra/remoting/examples/tcp/fnf/TaskProcessingWithServerSideNotificationsExample.java create mode 100644 today-remoting/src/test/java/infra/remoting/examples/tcp/lease/advanced/common/LeaseManager.java create mode 100644 today-remoting/src/test/java/infra/remoting/examples/tcp/lease/advanced/common/LimitBasedLeaseSender.java create mode 100644 today-remoting/src/test/java/infra/remoting/examples/tcp/lease/advanced/common/LimitBasedStatsCollector.java create mode 100644 today-remoting/src/test/java/infra/remoting/examples/tcp/lease/advanced/controller/Task.java create mode 100644 today-remoting/src/test/java/infra/remoting/examples/tcp/lease/advanced/controller/TasksHandlingChannel.java create mode 100644 today-remoting/src/test/java/infra/remoting/examples/tcp/lease/advanced/invertmulticlient/RequestingServer.java create mode 100644 today-remoting/src/test/java/infra/remoting/examples/tcp/lease/advanced/invertmulticlient/RespondingClient.java create mode 100644 today-remoting/src/test/java/infra/remoting/examples/tcp/lease/advanced/multiclient/RequestingClient.java create mode 100644 today-remoting/src/test/java/infra/remoting/examples/tcp/lease/advanced/multiclient/RespondingServer.java create mode 100644 today-remoting/src/test/java/infra/remoting/examples/tcp/lease/simple/LeaseExample.java create mode 100644 today-remoting/src/test/java/infra/remoting/examples/tcp/loadbalancer/RoundRobinLoadbalancerExample.java create mode 100644 today-remoting/src/test/java/infra/remoting/examples/tcp/plugins/LimitRateInterceptorExample.java create mode 100644 today-remoting/src/test/java/infra/remoting/examples/tcp/requestresponse/HelloWorldClient.java create mode 100644 today-remoting/src/test/java/infra/remoting/examples/tcp/resume/Files.java create mode 100644 today-remoting/src/test/java/infra/remoting/examples/tcp/resume/ResumeFileTransfer.java create mode 100644 today-remoting/src/test/java/infra/remoting/examples/tcp/resume/readme.md create mode 100644 today-remoting/src/test/java/infra/remoting/examples/tcp/stream/ClientStreamingToServer.java create mode 100644 today-remoting/src/test/java/infra/remoting/examples/tcp/stream/ServerStreamingToClient.java create mode 100644 today-remoting/src/test/java/infra/remoting/examples/ws/WebSocketAggregationSample.java create mode 100644 today-remoting/src/test/java/infra/remoting/examples/ws/WebSocketHeadersSample.java create mode 100644 today-remoting/src/test/java/infra/remoting/resume/DisconnectableClientTransport.java create mode 100644 today-remoting/src/test/java/infra/remoting/resume/ResumeIntegrationTests.java create mode 100644 today-remoting/src/test/resources/lorem.txt diff --git a/settings.gradle b/settings.gradle index a35e74f..50fcc8b 100644 --- a/settings.gradle +++ b/settings.gradle @@ -37,6 +37,7 @@ include 'today-service-provider' include 'today-service-registry' include 'today-remoting' +include 'today-remoting-micrometer' include 'today-remoting-transport-tcp' include 'today-remoting-transport-local' diff --git a/today-cloud-dependencies/build.gradle b/today-cloud-dependencies/build.gradle index 5b07dca..a39045d 100644 --- a/today-cloud-dependencies/build.gradle +++ b/today-cloud-dependencies/build.gradle @@ -10,6 +10,8 @@ javaPlatform { dependencies { api(platform(project(":today-cloud-bom"))) + api platform('io.micrometer:micrometer-tracing-bom:1.5.2') + constraints { } diff --git a/today-remoting-micrometer/build.gradle b/today-remoting-micrometer/build.gradle new file mode 100644 index 0000000..58b716e --- /dev/null +++ b/today-remoting-micrometer/build.gradle @@ -0,0 +1,31 @@ +plugins { + id 'java-library' + id 'maven-publish' + id 'signing' +} + +description = 'Transparent Metrics exposure to Micrometer' + +dependencies { + api project(':today-remoting') + api 'io.micrometer:micrometer-observation' + api 'io.micrometer:micrometer-core' + api 'io.micrometer:micrometer-tracing' + + testImplementation testFixtures(project(':today-remoting')) + testImplementation project(':today-remoting-transport-tcp') + testImplementation project(':today-remoting-transport-local') + testImplementation 'org.awaitility:awaitility' + testImplementation 'io.projectreactor:reactor-test' + testImplementation "io.micrometer:micrometer-test" + testImplementation "io.micrometer:micrometer-tracing-integration-test" + + testRuntimeOnly 'ch.qos.logback:logback-classic' +} + +jar { + manifest { + attributes("Automatic-Module-Name": "infra.remoting.micrometer") + } +} + diff --git a/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/MicrometerChannel.java b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/MicrometerChannel.java new file mode 100644 index 0000000..fbf58a1 --- /dev/null +++ b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/MicrometerChannel.java @@ -0,0 +1,207 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.remoting.micrometer; + +import org.reactivestreams.Publisher; + +import java.util.Objects; +import java.util.function.BiConsumer; +import java.util.function.Consumer; + +import infra.remoting.Channel; +import infra.remoting.Payload; +import io.micrometer.core.instrument.Counter; +import io.micrometer.core.instrument.Meter; +import io.micrometer.core.instrument.MeterRegistry; +import io.micrometer.core.instrument.Tag; +import io.micrometer.core.instrument.Tags; +import io.micrometer.core.instrument.Timer; +import io.micrometer.core.instrument.Timer.Sample; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; +import reactor.core.publisher.SignalType; + +import static reactor.core.publisher.SignalType.CANCEL; +import static reactor.core.publisher.SignalType.ON_COMPLETE; +import static reactor.core.publisher.SignalType.ON_ERROR; + +/** + * An implementation of {@link Channel} that intercepts interactions and gathers Micrometer metrics + * about them. + * + *

    The metrics are called {@code infra.remoting.[ metadata.push | request.channel | request.fnf | + * request.response | request.stream ]} and is tagged with {@code signal.type} ({@link SignalType}) + * and any additional configured tags. + * + * @see Micrometer + */ +final class MicrometerChannel implements Channel { + + private final Channel delegate; + + private final InteractionCounters metadataPush; + + private final InteractionCounters requestChannel; + + private final InteractionCounters requestFireAndForget; + + private final InteractionTimers requestResponse; + + private final InteractionCounters requestStream; + + /** + * Creates a new {@link Channel}. + * + * @param delegate the {@link Channel} to delegate to + * @param meterRegistry the {@link MeterRegistry} to use + * @param tags additional tags to attach to {@link Meter}s + * @throws NullPointerException if {@code delegate} or {@code meterRegistry} is {@code null} + */ + MicrometerChannel(Channel delegate, MeterRegistry meterRegistry, Tag... tags) { + this.delegate = Objects.requireNonNull(delegate, "delegate is required"); + Objects.requireNonNull(meterRegistry, "meterRegistry is required"); + + this.metadataPush = new InteractionCounters(meterRegistry, "metadata.push", tags); + this.requestChannel = new InteractionCounters(meterRegistry, "request.channel", tags); + this.requestFireAndForget = new InteractionCounters(meterRegistry, "request.fnf", tags); + this.requestResponse = new InteractionTimers(meterRegistry, "request.response", tags); + this.requestStream = new InteractionCounters(meterRegistry, "request.stream", tags); + } + + @Override + public void dispose() { + delegate.dispose(); + } + + @Override + public Mono fireAndForget(Payload payload) { + return delegate.fireAndForget(payload).doFinally(requestFireAndForget); + } + + @Override + public Mono metadataPush(Payload payload) { + return delegate.metadataPush(payload).doFinally(metadataPush); + } + + @Override + public Mono onClose() { + return delegate.onClose(); + } + + @Override + public Flux requestChannel(Publisher payloads) { + return delegate.requestChannel(payloads).doFinally(requestChannel); + } + + @Override + public Mono requestResponse(Payload payload) { + return Mono.defer(() -> { + Sample sample = requestResponse.start(); + return delegate + .requestResponse(payload) + .doFinally(signalType -> requestResponse.accept(sample, signalType)); + }); + } + + @Override + public Flux requestStream(Payload payload) { + return delegate.requestStream(payload).doFinally(requestStream); + } + + private static final class InteractionCounters implements Consumer { + + private final Counter cancel; + + private final Counter onComplete; + + private final Counter onError; + + private InteractionCounters(MeterRegistry meterRegistry, String interactionModel, Tag... tags) { + this.cancel = counter(meterRegistry, interactionModel, CANCEL, tags); + this.onComplete = counter(meterRegistry, interactionModel, ON_COMPLETE, tags); + this.onError = counter(meterRegistry, interactionModel, ON_ERROR, tags); + } + + @Override + public void accept(SignalType signalType) { + switch (signalType) { + case CANCEL: + cancel.increment(); + break; + case ON_COMPLETE: + onComplete.increment(); + break; + case ON_ERROR: + onError.increment(); + break; + } + } + + private static Counter counter( + MeterRegistry meterRegistry, String interactionModel, SignalType signalType, Tag... tags) { + + return meterRegistry.counter( + "infra.remoting." + interactionModel, Tags.of(tags).and("signal.type", signalType.name())); + } + } + + private static final class InteractionTimers implements BiConsumer { + + private final Timer cancel; + + private final MeterRegistry meterRegistry; + + private final Timer onComplete; + + private final Timer onError; + + private InteractionTimers(MeterRegistry meterRegistry, String interactionModel, Tag... tags) { + this.meterRegistry = meterRegistry; + + this.cancel = timer(meterRegistry, interactionModel, CANCEL, tags); + this.onComplete = timer(meterRegistry, interactionModel, ON_COMPLETE, tags); + this.onError = timer(meterRegistry, interactionModel, ON_ERROR, tags); + } + + @Override + public void accept(Sample sample, SignalType signalType) { + switch (signalType) { + case CANCEL: + sample.stop(cancel); + break; + case ON_COMPLETE: + sample.stop(onComplete); + break; + case ON_ERROR: + sample.stop(onError); + break; + } + } + + Sample start() { + return Timer.start(meterRegistry); + } + + private static Timer timer(MeterRegistry meterRegistry, + String interactionModel, SignalType signalType, Tag... tags) { + + return meterRegistry.timer( + "infra.remoting." + interactionModel, Tags.of(tags).and("signal.type", signalType.name())); + } + } +} diff --git a/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/MicrometerChannelDecorator.java b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/MicrometerChannelDecorator.java new file mode 100644 index 0000000..0c69c34 --- /dev/null +++ b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/MicrometerChannelDecorator.java @@ -0,0 +1,62 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.remoting.micrometer; + +import java.util.Objects; + +import infra.remoting.Channel; +import infra.remoting.plugins.ChannelDecorator; +import io.micrometer.core.instrument.Meter; +import io.micrometer.core.instrument.MeterRegistry; +import io.micrometer.core.instrument.Tag; +import reactor.core.publisher.SignalType; + +/** + * An implementation of {@link ChannelDecorator} that intercepts interactions and gathers + * Micrometer metrics about them. + * + *

    The metrics are called {@code infra.remoting.[ metadata.push | request.channel | request.fnf | + * request.response | request.stream ]} and is tagged with {@code signal.type} ({@link SignalType}) + * and any additional configured tags. + * + * @see Micrometer + */ +public final class MicrometerChannelDecorator implements ChannelDecorator { + + private final MeterRegistry meterRegistry; + + private final Tag[] tags; + + /** + * Creates a new {@link ChannelDecorator}. + * + * @param meterRegistry the {@link MeterRegistry} to use to create {@link Meter}s. + * @param tags the additional tags to attach to each {@link Meter} + * @throws NullPointerException if {@code meterRegistry} is {@code null} + */ + public MicrometerChannelDecorator(MeterRegistry meterRegistry, Tag... tags) { + this.meterRegistry = Objects.requireNonNull(meterRegistry, "meterRegistry is required"); + this.tags = tags; + } + + @Override + public Channel decorate(Channel delegate) { + Objects.requireNonNull(delegate, "delegate is required"); + return new MicrometerChannel(delegate, meterRegistry, tags); + } +} diff --git a/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/MicrometerDuplexConnection.java b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/MicrometerDuplexConnection.java new file mode 100644 index 0000000..f9a5846 --- /dev/null +++ b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/MicrometerDuplexConnection.java @@ -0,0 +1,286 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.remoting.micrometer; + +import java.net.SocketAddress; +import java.util.Objects; +import java.util.function.Consumer; + +import infra.logging.Logger; +import infra.logging.LoggerFactory; +import infra.remoting.DuplexConnection; +import infra.remoting.ProtocolErrorException; +import infra.remoting.frame.FrameHeaderCodec; +import infra.remoting.frame.FrameType; +import infra.remoting.plugins.ConnectionDecorator.Type; +import io.micrometer.core.instrument.Counter; +import io.micrometer.core.instrument.Meter; +import io.micrometer.core.instrument.MeterRegistry; +import io.micrometer.core.instrument.Tag; +import io.micrometer.core.instrument.Tags; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufAllocator; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +import static infra.remoting.frame.FrameType.CANCEL; +import static infra.remoting.frame.FrameType.COMPLETE; +import static infra.remoting.frame.FrameType.ERROR; +import static infra.remoting.frame.FrameType.EXT; +import static infra.remoting.frame.FrameType.KEEPALIVE; +import static infra.remoting.frame.FrameType.LEASE; +import static infra.remoting.frame.FrameType.METADATA_PUSH; +import static infra.remoting.frame.FrameType.NEXT; +import static infra.remoting.frame.FrameType.NEXT_COMPLETE; +import static infra.remoting.frame.FrameType.PAYLOAD; +import static infra.remoting.frame.FrameType.REQUEST_CHANNEL; +import static infra.remoting.frame.FrameType.REQUEST_FNF; +import static infra.remoting.frame.FrameType.REQUEST_N; +import static infra.remoting.frame.FrameType.REQUEST_RESPONSE; +import static infra.remoting.frame.FrameType.REQUEST_STREAM; +import static infra.remoting.frame.FrameType.RESUME; +import static infra.remoting.frame.FrameType.RESUME_OK; +import static infra.remoting.frame.FrameType.SETUP; + +/** + * An implementation of {@link DuplexConnection} that intercepts frames and gathers Micrometer + * metrics about them. + * + *

    The metric is called {@code infra.remoting.frame} and is tagged with {@code connection.type} ({@link + * Type}), {@code frame.type} ({@link FrameType}), and any additional configured tags. {@code + * infra.remoting.duplex.connection.close} and {@code infra.remoting.duplex.connection.dispose} metrics, tagged + * with {@code connection.type} ({@link Type}) and any additional configured tags are also + * collected. + * + * @see Micrometer + */ +final class MicrometerDuplexConnection implements DuplexConnection { + + private final Counter close; + + private final DuplexConnection delegate; + + private final Counter dispose; + + private final FrameCounters frameCounters; + + /** + * Creates a new {@link DuplexConnection}. + * + * @param connectionType the type of connection being monitored + * @param delegate the {@link DuplexConnection} to delegate to + * @param meterRegistry the {@link MeterRegistry} to use + * @param tags additional tags to attach to {@link Meter}s + * @throws NullPointerException if {@code connectionType}, {@code delegate}, or {@code + * meterRegistry} is {@code null} + */ + MicrometerDuplexConnection(Type connectionType, DuplexConnection delegate, MeterRegistry meterRegistry, Tag... tags) { + Objects.requireNonNull(connectionType, "connectionType is required"); + this.delegate = Objects.requireNonNull(delegate, "delegate is required"); + Objects.requireNonNull(meterRegistry, "meterRegistry is required"); + + this.close = meterRegistry.counter("infra.remoting.duplex.connection.close", + Tags.of(tags).and("connection.type", connectionType.name())); + + this.dispose = meterRegistry.counter("infra.remoting.duplex.connection.dispose", + Tags.of(tags).and("connection.type", connectionType.name())); + + this.frameCounters = new FrameCounters(connectionType, meterRegistry, tags); + } + + @Override + public ByteBufAllocator alloc() { + return delegate.alloc(); + } + + @Override + public SocketAddress remoteAddress() { + return delegate.remoteAddress(); + } + + @Override + public void dispose() { + delegate.dispose(); + dispose.increment(); + } + + @Override + public Mono onClose() { + return delegate.onClose().doAfterTerminate(close::increment); + } + + @Override + public Flux receive() { + return delegate.receive().doOnNext(frameCounters); + } + + @Override + public void sendFrame(int streamId, ByteBuf frame) { + frameCounters.accept(frame); + delegate.sendFrame(streamId, frame); + } + + @Override + public void sendErrorAndClose(ProtocolErrorException e) { + delegate.sendErrorAndClose(e); + } + + private static final class FrameCounters implements Consumer { + + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + private final Counter cancel; + + private final Counter complete; + + private final Counter error; + + private final Counter extension; + + private final Counter keepalive; + + private final Counter lease; + + private final Counter metadataPush; + + private final Counter next; + + private final Counter nextComplete; + + private final Counter payload; + + private final Counter requestChannel; + + private final Counter requestFireAndForget; + + private final Counter requestN; + + private final Counter requestResponse; + + private final Counter requestStream; + + private final Counter resume; + + private final Counter resumeOk; + + private final Counter setup; + + private final Counter unknown; + + private FrameCounters(Type connectionType, MeterRegistry meterRegistry, Tag... tags) { + this.cancel = counter(connectionType, meterRegistry, CANCEL, tags); + this.complete = counter(connectionType, meterRegistry, COMPLETE, tags); + this.error = counter(connectionType, meterRegistry, ERROR, tags); + this.extension = counter(connectionType, meterRegistry, EXT, tags); + this.keepalive = counter(connectionType, meterRegistry, KEEPALIVE, tags); + this.lease = counter(connectionType, meterRegistry, LEASE, tags); + this.metadataPush = counter(connectionType, meterRegistry, METADATA_PUSH, tags); + this.next = counter(connectionType, meterRegistry, NEXT, tags); + this.nextComplete = counter(connectionType, meterRegistry, NEXT_COMPLETE, tags); + this.payload = counter(connectionType, meterRegistry, PAYLOAD, tags); + this.requestChannel = counter(connectionType, meterRegistry, REQUEST_CHANNEL, tags); + this.requestFireAndForget = counter(connectionType, meterRegistry, REQUEST_FNF, tags); + this.requestN = counter(connectionType, meterRegistry, REQUEST_N, tags); + this.requestResponse = counter(connectionType, meterRegistry, REQUEST_RESPONSE, tags); + this.requestStream = counter(connectionType, meterRegistry, REQUEST_STREAM, tags); + this.resume = counter(connectionType, meterRegistry, RESUME, tags); + this.resumeOk = counter(connectionType, meterRegistry, RESUME_OK, tags); + this.setup = counter(connectionType, meterRegistry, SETUP, tags); + this.unknown = counter(connectionType, meterRegistry, "UNKNOWN", tags); + } + + private static Counter counter( + Type connectionType, MeterRegistry meterRegistry, FrameType frameType, Tag... tags) { + + return counter(connectionType, meterRegistry, frameType.name(), tags); + } + + private static Counter counter( + Type connectionType, MeterRegistry meterRegistry, String frameType, Tag... tags) { + + return meterRegistry.counter( + "infra.remoting.frame", + Tags.of(tags).and("connection.type", connectionType.name()).and("frame.type", frameType)); + } + + @Override + public void accept(ByteBuf frame) { + FrameType frameType = FrameHeaderCodec.frameType(frame); + + switch (frameType) { + case SETUP: + this.setup.increment(); + break; + case LEASE: + this.lease.increment(); + break; + case KEEPALIVE: + this.keepalive.increment(); + break; + case REQUEST_RESPONSE: + this.requestResponse.increment(); + break; + case REQUEST_FNF: + this.requestFireAndForget.increment(); + break; + case REQUEST_STREAM: + this.requestStream.increment(); + break; + case REQUEST_CHANNEL: + this.requestChannel.increment(); + break; + case REQUEST_N: + this.requestN.increment(); + break; + case CANCEL: + this.cancel.increment(); + break; + case PAYLOAD: + this.payload.increment(); + break; + case ERROR: + this.error.increment(); + break; + case METADATA_PUSH: + this.metadataPush.increment(); + break; + case RESUME: + this.resume.increment(); + break; + case RESUME_OK: + this.resumeOk.increment(); + break; + case NEXT: + this.next.increment(); + break; + case COMPLETE: + this.complete.increment(); + break; + case NEXT_COMPLETE: + this.nextComplete.increment(); + break; + case EXT: + this.extension.increment(); + break; + default: + this.logger.debug("Skipping count of unknown frame type: {}", frameType); + this.unknown.increment(); + } + } + } +} diff --git a/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/MicrometerDuplexConnectionDecorator.java b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/MicrometerDuplexConnectionDecorator.java new file mode 100644 index 0000000..c2c2231 --- /dev/null +++ b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/MicrometerDuplexConnectionDecorator.java @@ -0,0 +1,66 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.remoting.micrometer; + +import java.util.Objects; + +import infra.remoting.DuplexConnection; +import infra.remoting.frame.FrameType; +import infra.remoting.plugins.ConnectionDecorator; +import io.micrometer.core.instrument.Meter; +import io.micrometer.core.instrument.MeterRegistry; +import io.micrometer.core.instrument.Tag; + +/** + * An implementation of {@link ConnectionDecorator} that intercepts frames and gathers + * Micrometer metrics about them. + * + *

    The metric is called {@code infra.remoting.frame} and is tagged with {@code connection.type} ({@link + * Type}), {@code frame.type} ({@link FrameType}), and any additional configured tags. {@code + * infra.remoting.duplex.connection.close} and {@code infra.remoting.duplex.connection.dispose} metrics, tagged + * with {@code connection.type} ({@link Type}) and any additional configured tags are also + * collected. + * + * @see Micrometer + */ +public final class MicrometerDuplexConnectionDecorator implements ConnectionDecorator { + + private final MeterRegistry meterRegistry; + + private final Tag[] tags; + + /** + * Creates a new {@link ConnectionDecorator}. + * + * @param meterRegistry the {@link MeterRegistry} to use to create {@link Meter}s. + * @param tags the additional tags to attach to each {@link Meter} + * @throws NullPointerException if {@code meterRegistry} is {@code null} + */ + public MicrometerDuplexConnectionDecorator(MeterRegistry meterRegistry, Tag... tags) { + this.meterRegistry = Objects.requireNonNull(meterRegistry, "meterRegistry is required"); + this.tags = tags; + } + + @Override + public DuplexConnection decorate(Type connectionType, DuplexConnection delegate) { + Objects.requireNonNull(delegate, "delegate is required"); + Objects.requireNonNull(connectionType, "connectionType is required"); + + return new MicrometerDuplexConnection(connectionType, delegate, meterRegistry, tags); + } +} diff --git a/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/ChannelContext.java b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/ChannelContext.java new file mode 100644 index 0000000..0f1832c --- /dev/null +++ b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/ChannelContext.java @@ -0,0 +1,77 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.remoting.micrometer.observation; + +import infra.lang.Nullable; +import infra.remoting.Payload; +import infra.remoting.frame.FrameType; +import io.micrometer.observation.Observation; +import io.netty.buffer.ByteBuf; + +public class ChannelContext extends Observation.Context { + + final Payload payload; + + final ByteBuf metadata; + + final FrameType frameType; + + final String route; + + final Side side; + + Payload modifiedPayload; + + ChannelContext(Payload payload, ByteBuf metadata, + FrameType frameType, @Nullable String route, Side side) { + this.payload = payload; + this.metadata = metadata; + this.frameType = frameType; + this.route = route; + this.side = side; + } + + public enum Side { + REQUESTER, + RESPONDER + } + + public Payload getPayload() { + return payload; + } + + public ByteBuf getMetadata() { + return metadata; + } + + public FrameType getFrameType() { + return frameType; + } + + public String getRoute() { + return route; + } + + public Side getSide() { + return side; + } + + public Payload getModifiedPayload() { + return modifiedPayload; + } +} diff --git a/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/ChannelRequesterObservationConvention.java b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/ChannelRequesterObservationConvention.java new file mode 100644 index 0000000..9f47ef5 --- /dev/null +++ b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/ChannelRequesterObservationConvention.java @@ -0,0 +1,36 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.remoting.micrometer.observation; + +import io.micrometer.observation.Observation; +import io.micrometer.observation.ObservationConvention; + +/** + * {@link ObservationConvention} for requester {@link ChannelContext}. + * + * @author Marcin Grzejszczak + * @author 海子 Yang + */ +public interface ChannelRequesterObservationConvention extends ObservationConvention { + + @Override + default boolean supportsContext(Observation.Context context) { + return context instanceof ChannelContext + && ((ChannelContext) context).side == ChannelContext.Side.REQUESTER; + } +} diff --git a/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/ChannelRequesterTracingObservationHandler.java b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/ChannelRequesterTracingObservationHandler.java new file mode 100644 index 0000000..1d8d5ba --- /dev/null +++ b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/ChannelRequesterTracingObservationHandler.java @@ -0,0 +1,94 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.remoting.micrometer.observation; + +import java.util.HashSet; + +import infra.logging.Logger; +import infra.logging.LoggerFactory; +import infra.remoting.Payload; +import io.micrometer.observation.Observation; +import io.micrometer.tracing.Span; +import io.micrometer.tracing.TraceContext; +import io.micrometer.tracing.Tracer; +import io.micrometer.tracing.handler.TracingObservationHandler; +import io.micrometer.tracing.propagation.Propagator; +import io.netty.buffer.ByteBuf; + +public class ChannelRequesterTracingObservationHandler implements TracingObservationHandler { + + private static final Logger log = LoggerFactory.getLogger(ChannelRequesterTracingObservationHandler.class); + + private final Propagator propagator; + + private final Propagator.Setter setter; + + private final Tracer tracer; + + public ChannelRequesterTracingObservationHandler(Tracer tracer, + Propagator propagator, Propagator.Setter setter) { + this.tracer = tracer; + this.propagator = propagator; + this.setter = setter; + } + + @Override + public boolean supportsContext(Observation.Context context) { + return context instanceof ChannelContext + && ((ChannelContext) context).side == ChannelContext.Side.REQUESTER; + } + + @Override + public Tracer getTracer() { + return this.tracer; + } + + @Override + public void onStart(ChannelContext context) { + Payload payload = context.payload; + Span.Builder spanBuilder = this.tracer.spanBuilder(); + Span parentSpan = getParentSpan(context); + if (parentSpan != null) { + spanBuilder.setParent(parentSpan.context()); + } + Span span = spanBuilder.kind(Span.Kind.PRODUCER).start(); + log.debug("Extracted result from context or thread local {}", span); + + final ByteBuf newMetadata = PayloadUtils.cleanTracingMetadata(payload, new HashSet<>(propagator.fields())); + TraceContext traceContext = span.context(); + this.propagator.inject(traceContext, newMetadata, this.setter); + context.modifiedPayload = PayloadUtils.payload(payload, newMetadata); + getTracingContext(context).setSpan(span); + } + + @Override + public void onError(ChannelContext context) { + Throwable error = context.getError(); + if (error != null) { + getRequiredSpan(context).error(error); + } + } + + @Override + public void onStop(ChannelContext context) { + Span span = getRequiredSpan(context); + tagSpan(context, span); + span.name(context.getContextualName()).end(); + } + +} diff --git a/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/ChannelResponderObservationConvention.java b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/ChannelResponderObservationConvention.java new file mode 100644 index 0000000..fc1d41f --- /dev/null +++ b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/ChannelResponderObservationConvention.java @@ -0,0 +1,36 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.remoting.micrometer.observation; + +import io.micrometer.observation.Observation; +import io.micrometer.observation.ObservationConvention; + +/** + * {@link ObservationConvention} for responder {@link ChannelContext}. + * + * @author Marcin Grzejszczak + * @author 海子 Yang + */ +public interface ChannelResponderObservationConvention extends ObservationConvention { + + @Override + default boolean supportsContext(Observation.Context context) { + return context instanceof ChannelContext + && ((ChannelContext) context).side == ChannelContext.Side.RESPONDER; + } +} diff --git a/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/ChannelResponderTracingObservationHandler.java b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/ChannelResponderTracingObservationHandler.java new file mode 100644 index 0000000..1e0c745 --- /dev/null +++ b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/ChannelResponderTracingObservationHandler.java @@ -0,0 +1,93 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.remoting.micrometer.observation; + +import java.util.HashSet; + +import infra.logging.Logger; +import infra.logging.LoggerFactory; +import infra.remoting.Payload; +import infra.remoting.frame.FrameType; +import io.micrometer.observation.Observation; +import io.micrometer.tracing.Span; +import io.micrometer.tracing.Tracer; +import io.micrometer.tracing.handler.TracingObservationHandler; +import io.micrometer.tracing.propagation.Propagator; +import io.netty.buffer.ByteBuf; + +public class ChannelResponderTracingObservationHandler implements TracingObservationHandler { + + private static final Logger log = LoggerFactory.getLogger(ChannelResponderTracingObservationHandler.class); + + private final Propagator propagator; + + private final Propagator.Getter getter; + + private final Tracer tracer; + + public ChannelResponderTracingObservationHandler(Tracer tracer, Propagator propagator, Propagator.Getter getter) { + this.tracer = tracer; + this.propagator = propagator; + this.getter = getter; + } + + @Override + public void onStart(ChannelContext context) { + Span handle = consumerSpanBuilder(context.payload, context.metadata, context.frameType); + ByteBuf bufs = PayloadUtils.cleanTracingMetadata(context.payload, new HashSet<>(propagator.fields())); + context.modifiedPayload = PayloadUtils.payload(context.payload, bufs); + getTracingContext(context).setSpan(handle); + } + + @Override + public void onError(ChannelContext context) { + Throwable error = context.getError(); + if (error != null) { + getRequiredSpan(context).error(error); + } + } + + @Override + public void onStop(ChannelContext context) { + Span span = getRequiredSpan(context); + tagSpan(context, span); + span.end(); + } + + @Override + public boolean supportsContext(Observation.Context context) { + return context instanceof ChannelContext + && ((ChannelContext) context).side == ChannelContext.Side.RESPONDER; + } + + @Override + public Tracer getTracer() { + return this.tracer; + } + + private Span consumerSpanBuilder(Payload payload, ByteBuf headers, FrameType requestType) { + Span.Builder consumerSpanBuilder = consumerSpanBuilder(payload, headers); + log.debug("Extracted result from headers {}", consumerSpanBuilder); + String name = "handle"; + return consumerSpanBuilder.kind(Span.Kind.CONSUMER).name(name).start(); + } + + private Span.Builder consumerSpanBuilder(Payload payload, ByteBuf headers) { + return this.propagator.extract(headers, this.getter); + } +} diff --git a/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/DefaultChannelObservationConvention.java b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/DefaultChannelObservationConvention.java new file mode 100644 index 0000000..a6eebe6 --- /dev/null +++ b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/DefaultChannelObservationConvention.java @@ -0,0 +1,51 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.remoting.micrometer.observation; + +import infra.remoting.frame.FrameType; + +/** + * Default {@link ChannelRequesterObservationConvention} implementation. + * + * @author Marcin Grzejszczak + */ +class DefaultChannelObservationConvention { + + private final ChannelContext channelContext; + + public DefaultChannelObservationConvention(ChannelContext channelContext) { + this.channelContext = channelContext; + } + + String getName() { + if (this.channelContext.frameType == FrameType.REQUEST_FNF) { + return "infra.remoting.fnf"; + } + else if (this.channelContext.frameType == FrameType.REQUEST_STREAM) { + return "infra.remoting.stream"; + } + else if (this.channelContext.frameType == FrameType.REQUEST_CHANNEL) { + return "infra.remoting.channel"; + } + return "%s"; + } + + protected ChannelContext getChannelContext() { + return this.channelContext; + } +} diff --git a/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/DefaultChannelRequesterObservationConvention.java b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/DefaultChannelRequesterObservationConvention.java new file mode 100644 index 0000000..2b874cb --- /dev/null +++ b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/DefaultChannelRequesterObservationConvention.java @@ -0,0 +1,59 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.remoting.micrometer.observation; + +import infra.remoting.frame.FrameType; +import io.micrometer.common.KeyValues; +import io.micrometer.common.util.StringUtils; +import io.micrometer.observation.Observation; + +/** + * Default {@link ChannelRequesterObservationConvention} implementation. + * + * @author Marcin Grzejszczak + * @author 海子 Yang + */ +public class DefaultChannelRequesterObservationConvention extends DefaultChannelObservationConvention implements ChannelRequesterObservationConvention { + + public DefaultChannelRequesterObservationConvention(ChannelContext channelContext) { + super(channelContext); + } + + @Override + public KeyValues getLowCardinalityKeyValues(ChannelContext context) { + KeyValues values = KeyValues.of( + RemotingObservationDocumentation.ResponderTags.REQUEST_TYPE.withValue(context.frameType.name())); + if (StringUtils.isNotBlank(context.route)) { + values = values.and(RemotingObservationDocumentation.ResponderTags.ROUTE.withValue(context.route)); + } + return values; + } + + @Override + public boolean supportsContext(Observation.Context context) { + return context instanceof ChannelContext; + } + + @Override + public String getName() { + if (getChannelContext().frameType == FrameType.REQUEST_RESPONSE) { + return "infra.remoting.request"; + } + return super.getName(); + } +} diff --git a/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/DefaultChannelResponderObservationConvention.java b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/DefaultChannelResponderObservationConvention.java new file mode 100644 index 0000000..76ee3b1 --- /dev/null +++ b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/DefaultChannelResponderObservationConvention.java @@ -0,0 +1,60 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.remoting.micrometer.observation; + +import infra.remoting.frame.FrameType; +import io.micrometer.common.KeyValues; +import io.micrometer.common.util.StringUtils; +import io.micrometer.observation.Observation; + +/** + * Default {@link ChannelRequesterObservationConvention} implementation. + * + * @author Marcin Grzejszczak + */ +public class DefaultChannelResponderObservationConvention + extends DefaultChannelObservationConvention implements ChannelResponderObservationConvention { + + public DefaultChannelResponderObservationConvention(ChannelContext channelContext) { + super(channelContext); + } + + @Override + public KeyValues getLowCardinalityKeyValues(ChannelContext context) { + KeyValues tags = KeyValues.of( + RemotingObservationDocumentation.ResponderTags.REQUEST_TYPE.withValue( + context.frameType.name())); + if (StringUtils.isNotBlank(context.route)) { + tags = tags.and(RemotingObservationDocumentation.ResponderTags.ROUTE.withValue(context.route)); + } + return tags; + } + + @Override + public boolean supportsContext(Observation.Context context) { + return context instanceof ChannelContext; + } + + @Override + public String getName() { + if (getChannelContext().frameType == FrameType.REQUEST_RESPONSE) { + return "infra.remoting.response"; + } + return super.getName(); + } +} diff --git a/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/ObservationRequesterChannel.java b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/ObservationRequesterChannel.java new file mode 100644 index 0000000..f0bf43a --- /dev/null +++ b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/ObservationRequesterChannel.java @@ -0,0 +1,185 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.remoting.micrometer.observation; + +import org.reactivestreams.Publisher; + +import java.util.function.Function; + +import infra.lang.Nullable; +import infra.remoting.Channel; +import infra.remoting.Payload; +import infra.remoting.frame.FrameType; +import infra.remoting.util.ChannelWrapper; +import io.micrometer.common.util.StringUtils; +import io.micrometer.observation.Observation; +import io.micrometer.observation.ObservationRegistry; +import io.micrometer.observation.docs.ObservationDocumentation; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; +import reactor.util.context.ContextView; + +/** + * Tracing representation of a {@link ChannelWrapper} for the requester. + * + * @author Marcin Grzejszczak + * @author Oleh Dokuka + * @author 海子 Yang + */ +public class ObservationRequesterChannel extends ChannelWrapper { + + /** + * Aligned with ObservationThreadLocalAccessor#KEY + */ + private static final String MICROMETER_OBSERVATION_KEY = "micrometer.observation"; + + private final ObservationRegistry observationRegistry; + + @Nullable + private final ChannelRequesterObservationConvention observationConvention; + + public ObservationRequesterChannel(Channel source, ObservationRegistry observationRegistry) { + this(source, observationRegistry, null); + } + + public ObservationRequesterChannel(Channel source, ObservationRegistry observationRegistry, + @Nullable ChannelRequesterObservationConvention observationConvention) { + super(source); + this.observationRegistry = observationRegistry; + this.observationConvention = observationConvention; + } + + @Override + public Mono fireAndForget(Payload payload) { + return setObservation( + super::fireAndForget, + payload, + FrameType.REQUEST_FNF, + RemotingObservationDocumentation.REQUESTER_FNF); + } + + @Override + public Mono requestResponse(Payload payload) { + return setObservation( + super::requestResponse, + payload, + FrameType.REQUEST_RESPONSE, + RemotingObservationDocumentation.REQUESTER_REQUEST_RESPONSE); + } + + Mono setObservation(Function> input, Payload payload, + FrameType frameType, ObservationDocumentation observation) { + return Mono.deferContextual( + contextView -> observe(input, payload, frameType, observation, contextView)); + } + + private String route(Payload payload) { + return null; + } + + private Mono observe( + Function> input, + Payload payload, + FrameType frameType, + ObservationDocumentation obs, + ContextView contextView) { + String route = route(payload); + ChannelContext channelContext = + new ChannelContext( + payload, payload.sliceMetadata(), frameType, route, ChannelContext.Side.REQUESTER); + Observation parentObservation = contextView.getOrDefault(MICROMETER_OBSERVATION_KEY, null); + Observation observation = obs.observation(this.observationConvention, + new DefaultChannelRequesterObservationConvention(channelContext), + () -> channelContext, observationRegistry) + .parentObservation(parentObservation); + setContextualName(frameType, route, observation); + observation.start(); + Payload newPayload = payload; + if (channelContext.modifiedPayload != null) { + newPayload = channelContext.modifiedPayload; + } + return input + .apply(newPayload) + .doOnError(observation::error) + .doFinally(signalType -> observation.stop()) + .contextWrite(context -> context.put(MICROMETER_OBSERVATION_KEY, observation)); + } + + @Override + public Flux requestStream(Payload payload) { + return observationFlux( + super::requestStream, + payload, + FrameType.REQUEST_STREAM, + RemotingObservationDocumentation.REQUESTER_REQUEST_STREAM); + } + + @Override + public Flux requestChannel(Publisher inbound) { + return Flux.from(inbound) + .switchOnFirst( + (firstSignal, flux) -> { + final Payload firstPayload = firstSignal.get(); + if (firstPayload != null) { + return observationFlux( + p -> super.requestChannel(flux.skip(1).startWith(p)), + firstPayload, + FrameType.REQUEST_CHANNEL, + RemotingObservationDocumentation.REQUESTER_REQUEST_CHANNEL); + } + return flux; + }); + } + + private Flux observationFlux(Function> input, + Payload payload, FrameType frameType, ObservationDocumentation obs) { + return Flux.deferContextual(contextView -> { + String route = route(payload); + ChannelContext channelContext = + new ChannelContext( + payload, + payload.sliceMetadata(), + frameType, + route, + ChannelContext.Side.REQUESTER); + Observation parentObservation = + contextView.getOrDefault(MICROMETER_OBSERVATION_KEY, null); + Observation newObservation = + obs.observation(this.observationConvention, + new DefaultChannelRequesterObservationConvention(channelContext), + () -> channelContext, this.observationRegistry) + .parentObservation(parentObservation); + setContextualName(frameType, route, newObservation); + newObservation.start(); + return input + .apply(channelContext.modifiedPayload) + .doOnError(newObservation::error) + .doFinally(signalType -> newObservation.stop()) + .contextWrite(context -> context.put(MICROMETER_OBSERVATION_KEY, newObservation)); + }); + } + + private void setContextualName(FrameType frameType, String route, Observation newObservation) { + if (StringUtils.isNotBlank(route)) { + newObservation.contextualName(frameType.name() + " " + route); + } + else { + newObservation.contextualName(frameType.name()); + } + } +} diff --git a/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/ObservationResponderChannel.java b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/ObservationResponderChannel.java new file mode 100644 index 0000000..4464cfe --- /dev/null +++ b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/ObservationResponderChannel.java @@ -0,0 +1,156 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.remoting.micrometer.observation; + +import org.reactivestreams.Publisher; + +import infra.lang.Nullable; +import infra.remoting.Channel; +import infra.remoting.Payload; +import infra.remoting.frame.FrameType; +import infra.remoting.util.ChannelWrapper; +import io.micrometer.common.util.StringUtils; +import io.micrometer.observation.Observation; +import io.micrometer.observation.ObservationRegistry; +import io.netty.buffer.ByteBuf; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +/** + * Tracing representation of a {@link ChannelWrapper} for the responder. + * + * @author Marcin Grzejszczak + * @author Oleh Dokuka + */ +public class ObservationResponderChannel extends ChannelWrapper { + /** Aligned with ObservationThreadLocalAccessor#KEY */ + private static final String MICROMETER_OBSERVATION_KEY = "micrometer.observation"; + + private final ObservationRegistry observationRegistry; + + @Nullable + private final ChannelResponderObservationConvention observationConvention; + + public ObservationResponderChannel(Channel source, ObservationRegistry observationRegistry) { + this(source, observationRegistry, null); + } + + public ObservationResponderChannel(Channel source, + ObservationRegistry observationRegistry, + @Nullable ChannelResponderObservationConvention observationConvention) { + super(source); + this.observationRegistry = observationRegistry; + this.observationConvention = observationConvention; + } + + @Override + public Mono fireAndForget(Payload payload) { + // called on Netty EventLoop + // there can't be observation in thread local here + ByteBuf sliceMetadata = payload.sliceMetadata(); + String route = route(payload, sliceMetadata); + ChannelContext channelContext = new ChannelContext(payload, + payload.sliceMetadata(), FrameType.REQUEST_FNF, route, + ChannelContext.Side.RESPONDER); + Observation newObservation = startObservation(RemotingObservationDocumentation.RESPONDER_FNF, channelContext); + return super.fireAndForget(channelContext.modifiedPayload) + .doOnError(newObservation::error) + .doFinally(signalType -> newObservation.stop()) + .contextWrite(context -> context.put(MICROMETER_OBSERVATION_KEY, newObservation)); + } + + private Observation startObservation( + RemotingObservationDocumentation observation, ChannelContext channelContext) { + return observation.start(this.observationConvention, + new DefaultChannelResponderObservationConvention(channelContext), + () -> channelContext, this.observationRegistry); + } + + @Override + public Mono requestResponse(Payload payload) { + ByteBuf sliceMetadata = payload.sliceMetadata(); + String route = route(payload, sliceMetadata); + ChannelContext channelContext = + new ChannelContext( + payload, + payload.sliceMetadata(), + FrameType.REQUEST_RESPONSE, + route, + ChannelContext.Side.RESPONDER); + Observation newObservation = + startObservation( + RemotingObservationDocumentation.RESPONDER_REQUEST_RESPONSE, channelContext); + return super.requestResponse(channelContext.modifiedPayload) + .doOnError(newObservation::error) + .doFinally(signalType -> newObservation.stop()) + .contextWrite(context -> context.put(MICROMETER_OBSERVATION_KEY, newObservation)); + } + + @Override + public Flux requestStream(Payload payload) { + ByteBuf sliceMetadata = payload.sliceMetadata(); + String route = route(payload, sliceMetadata); + ChannelContext channelContext = + new ChannelContext( + payload, sliceMetadata, FrameType.REQUEST_STREAM, route, ChannelContext.Side.RESPONDER); + Observation newObservation = + startObservation( + RemotingObservationDocumentation.RESPONDER_REQUEST_STREAM, channelContext); + return super.requestStream(channelContext.modifiedPayload) + .doOnError(newObservation::error) + .doFinally(signalType -> newObservation.stop()) + .contextWrite(context -> context.put(MICROMETER_OBSERVATION_KEY, newObservation)); + } + + @Override + public Flux requestChannel(Publisher payloads) { + return Flux.from(payloads) + .switchOnFirst( + (firstSignal, flux) -> { + final Payload firstPayload = firstSignal.get(); + if (firstPayload != null) { + ByteBuf sliceMetadata = firstPayload.sliceMetadata(); + String route = route(firstPayload, sliceMetadata); + ChannelContext channelContext = + new ChannelContext( + firstPayload, + firstPayload.sliceMetadata(), + FrameType.REQUEST_CHANNEL, + route, + ChannelContext.Side.RESPONDER); + Observation newObservation = + startObservation( + RemotingObservationDocumentation.RESPONDER_REQUEST_CHANNEL, + channelContext); + if (StringUtils.isNotBlank(route)) { + newObservation.contextualName(channelContext.frameType.name() + " " + route); + } + return super.requestChannel(flux.skip(1).startWith(channelContext.modifiedPayload)) + .doOnError(newObservation::error) + .doFinally(signalType -> newObservation.stop()) + .contextWrite( + context -> context.put(MICROMETER_OBSERVATION_KEY, newObservation)); + } + return flux; + }); + } + + private String route(Payload payload, ByteBuf headers) { + return null; + } +} diff --git a/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/PayloadUtils.java b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/PayloadUtils.java new file mode 100644 index 0000000..421c822 --- /dev/null +++ b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/PayloadUtils.java @@ -0,0 +1,54 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.remoting.micrometer.observation; + +import java.util.Set; + +import infra.remoting.Payload; +import infra.remoting.util.ByteBufPayload; +import infra.remoting.util.DefaultPayload; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.CompositeByteBuf; +import io.netty.buffer.Unpooled; + +final class PayloadUtils { + + private PayloadUtils() { + throw new IllegalStateException("Can't instantiate a utility class"); + } + + static ByteBuf cleanTracingMetadata(Payload payload, Set fields) { + return Unpooled.EMPTY_BUFFER; + } + + static Payload payload(Payload payload, ByteBuf metadata) { + final Payload newPayload; + try { + if (payload instanceof ByteBufPayload) { + newPayload = ByteBufPayload.create(payload.data().retain(), metadata); + } + else { + newPayload = DefaultPayload.create(payload.data().retain(), metadata); + } + } + finally { + payload.release(); + } + return newPayload; + } +} diff --git a/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/RemotingObservationDocumentation.java b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/RemotingObservationDocumentation.java new file mode 100644 index 0000000..2727cf9 --- /dev/null +++ b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/RemotingObservationDocumentation.java @@ -0,0 +1,229 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.remoting.micrometer.observation; + +import io.micrometer.common.docs.KeyName; +import io.micrometer.observation.Observation; +import io.micrometer.observation.ObservationConvention; +import io.micrometer.observation.docs.ObservationDocumentation; + +enum RemotingObservationDocumentation implements ObservationDocumentation { + + /** + * Observation created on the responder side. + */ + RESPONDER { + @Override + public Class> getDefaultConvention() { + return DefaultChannelResponderObservationConvention.class; + } + }, + + /** + * Observation created on the requester side for Fire and Forget frame type. + */ + REQUESTER_FNF { + @Override + public Class> getDefaultConvention() { + return DefaultChannelRequesterObservationConvention.class; + } + + @Override + public KeyName[] getLowCardinalityKeyNames() { + return RequesterTags.values(); + } + + @Override + public String getPrefix() { + return "infra.remoting."; + } + }, + + /** Observation created on the responder side for Fire and Forget frame type. */ + RESPONDER_FNF { + @Override + public Class> getDefaultConvention() { + return DefaultChannelResponderObservationConvention.class; + } + + @Override + public KeyName[] getLowCardinalityKeyNames() { + return ResponderTags.values(); + } + + @Override + public String getPrefix() { + return "infra.remoting."; + } + }, + + /** Observation created on the requester side for Request Response frame type. */ + REQUESTER_REQUEST_RESPONSE { + @Override + public Class> + getDefaultConvention() { + return DefaultChannelRequesterObservationConvention.class; + } + + @Override + public KeyName[] getLowCardinalityKeyNames() { + return RequesterTags.values(); + } + + @Override + public String getPrefix() { + return "infra.remoting."; + } + }, + + /** Observation created on the responder side for Request Response frame type. */ + RESPONDER_REQUEST_RESPONSE { + @Override + public Class> getDefaultConvention() { + return DefaultChannelResponderObservationConvention.class; + } + + @Override + public KeyName[] getLowCardinalityKeyNames() { + return ResponderTags.values(); + } + + @Override + public String getPrefix() { + return "infra.remoting."; + } + }, + + /** Observation created on the requester side for Request Stream frame type. */ + REQUESTER_REQUEST_STREAM { + @Override + public Class> getDefaultConvention() { + return DefaultChannelRequesterObservationConvention.class; + } + + @Override + public KeyName[] getLowCardinalityKeyNames() { + return RequesterTags.values(); + } + + @Override + public String getPrefix() { + return "infra.remoting."; + } + }, + + /** Observation created on the responder side for Request Stream frame type. */ + RESPONDER_REQUEST_STREAM { + @Override + public Class> getDefaultConvention() { + return DefaultChannelResponderObservationConvention.class; + } + + @Override + public KeyName[] getLowCardinalityKeyNames() { + return ResponderTags.values(); + } + + @Override + public String getPrefix() { + return "infra.remoting."; + } + }, + + /** Observation created on the requester side for Request Channel frame type. */ + REQUESTER_REQUEST_CHANNEL { + @Override + public Class> getDefaultConvention() { + return DefaultChannelRequesterObservationConvention.class; + } + + @Override + public KeyName[] getLowCardinalityKeyNames() { + return RequesterTags.values(); + } + + @Override + public String getPrefix() { + return "infra.remoting."; + } + }, + + /** Observation created on the responder side for Request Channel frame type. */ + RESPONDER_REQUEST_CHANNEL { + @Override + public Class> getDefaultConvention() { + return DefaultChannelResponderObservationConvention.class; + } + + @Override + public KeyName[] getLowCardinalityKeyNames() { + return ResponderTags.values(); + } + + @Override + public String getPrefix() { + return "infra.remoting."; + } + }; + + enum RequesterTags implements KeyName { + + /** Name of the route. */ + ROUTE { + @Override + public String asString() { + return "infra.remoting.route"; + } + }, + + /** Name of the request type. */ + REQUEST_TYPE { + @Override + public String asString() { + return "infra.remoting.request-type"; + } + }, + + /** Name of the content type. */ + CONTENT_TYPE { + @Override + public String asString() { + return "infra.remoting.content-type"; + } + } + } + + enum ResponderTags implements KeyName { + + /** Name of the route. */ + ROUTE { + @Override + public String asString() { + return "infra.remoting.route"; + } + }, + + /** Name of the request type. */ + REQUEST_TYPE { + @Override + public String asString() { + return "infra.remoting.request-type"; + } + } + } +} diff --git a/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/package-info.java b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/package-info.java new file mode 100644 index 0000000..036d945 --- /dev/null +++ b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/package-info.java @@ -0,0 +1,28 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +/** + * Transparent metrics exposure for Micrometer. + * + * @see Micrometer + */ +@NonNullApi +@NonNullFields +package infra.remoting.micrometer; + +import infra.lang.NonNullFields; +import reactor.util.annotation.NonNullApi; diff --git a/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/MicrometerChannelDecoratorTests.java b/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/MicrometerChannelDecoratorTests.java new file mode 100644 index 0000000..d4b21ab --- /dev/null +++ b/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/MicrometerChannelDecoratorTests.java @@ -0,0 +1,59 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.remoting.micrometer; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import infra.remoting.Channel; +import io.micrometer.core.instrument.simple.SimpleMeterRegistry; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatNullPointerException; +import static org.mockito.Mockito.RETURNS_SMART_NULLS; +import static org.mockito.Mockito.mock; + +final class MicrometerChannelDecoratorTests { + + private final Channel delegate = mock(Channel.class, RETURNS_SMART_NULLS); + + private final SimpleMeterRegistry meterRegistry = new SimpleMeterRegistry(); + + @DisplayName("creates Micrometer") + @Test + void apply() { + assertThat(new MicrometerChannelDecorator(meterRegistry).decorate(delegate)) + .isInstanceOf(MicrometerChannel.class); + } + + @DisplayName("apply throws NullPointerException with null delegate") + @Test + void applyNullDelegate() { + assertThatNullPointerException() + .isThrownBy(() -> new MicrometerChannelDecorator(meterRegistry).decorate(null)) + .withMessage("delegate is required"); + } + + @DisplayName("constructor throws NullPointerException with null meterRegistry") + @Test + void constructorNullMeterRegistry() { + assertThatNullPointerException() + .isThrownBy(() -> new MicrometerChannelDecorator(null)) + .withMessage("meterRegistry is required"); + } +} diff --git a/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/MicrometerChannelTests.java b/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/MicrometerChannelTests.java new file mode 100644 index 0000000..ca0d53c --- /dev/null +++ b/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/MicrometerChannelTests.java @@ -0,0 +1,148 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.remoting.micrometer; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import infra.remoting.Channel; +import infra.remoting.Payload; +import infra.remoting.util.DefaultPayload; +import io.micrometer.core.instrument.Counter; +import io.micrometer.core.instrument.Tag; +import io.micrometer.core.instrument.Timer; +import io.micrometer.core.instrument.simple.SimpleMeterRegistry; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; +import reactor.core.publisher.SignalType; +import reactor.test.StepVerifier; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatNullPointerException; +import static org.mockito.Mockito.RETURNS_SMART_NULLS; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +final class MicrometerChannelTests { + + private final Channel delegate = mock(Channel.class, RETURNS_SMART_NULLS); + + private final SimpleMeterRegistry meterRegistry = new SimpleMeterRegistry(); + + @DisplayName("constructor throws NullPointerException with null delegate") + @Test + void constructorNullDelegate() { + assertThatNullPointerException() + .isThrownBy(() -> new MicrometerChannel(null, meterRegistry)) + .withMessage("delegate is required"); + } + + @DisplayName("constructor throws NullPointerException with null meterRegistry") + @Test + void constructorNullMeterRegistry() { + assertThatNullPointerException() + .isThrownBy(() -> new MicrometerChannel(delegate, null)) + .withMessage("meterRegistry is required"); + } + + @DisplayName("fireAndForget gathers metrics") + @Test + void fireAndForget() { + Payload payload = DefaultPayload.create("test-metadata", "test-data"); + when(delegate.fireAndForget(payload)).thenReturn(Mono.empty()); + + new MicrometerChannel(delegate, meterRegistry, Tag.of("test-key", "test-value")) + .fireAndForget(payload) + .as(StepVerifier::create) + .verifyComplete(); + + assertThat(findCounter("request.fnf", SignalType.ON_COMPLETE).count()).isEqualTo(1); + } + + @DisplayName("metadataPush gathers metrics") + @Test + void metadataPush() { + Payload payload = DefaultPayload.create("test-metadata", "test-data"); + when(delegate.metadataPush(payload)).thenReturn(Mono.empty()); + + new MicrometerChannel(delegate, meterRegistry, Tag.of("test-key", "test-value")) + .metadataPush(payload) + .as(StepVerifier::create) + .verifyComplete(); + + assertThat(findCounter("metadata.push", SignalType.ON_COMPLETE).count()).isEqualTo(1); + } + + @DisplayName("requestChannel gathers metrics") + @Test + void requestChannel() { + Mono payload = Mono.just(DefaultPayload.create("test-metadata", "test-data")); + when(delegate.requestChannel(payload)).thenReturn(Flux.empty()); + + new MicrometerChannel(delegate, meterRegistry, Tag.of("test-key", "test-value")) + .requestChannel(payload) + .as(StepVerifier::create) + .verifyComplete(); + + assertThat(findCounter("request.channel", SignalType.ON_COMPLETE).count()).isEqualTo(1); + } + + @DisplayName("requestResponse gathers metrics") + @Test + void requestResponse() { + Payload payload = DefaultPayload.create("test-metadata", "test-data"); + when(delegate.requestResponse(payload)).thenReturn(Mono.empty()); + + new MicrometerChannel(delegate, meterRegistry, Tag.of("test-key", "test-value")) + .requestResponse(payload) + .as(StepVerifier::create) + .verifyComplete(); + + assertThat(findTimer("request.response", SignalType.ON_COMPLETE).count()).isEqualTo(1); + } + + @DisplayName("requestStream gathers metrics") + @Test + void requestStream() { + Payload payload = DefaultPayload.create("test-metadata", "test-data"); + when(delegate.requestStream(payload)).thenReturn(Flux.empty()); + + new MicrometerChannel(delegate, meterRegistry, Tag.of("test-key", "test-value")) + .requestStream(payload) + .as(StepVerifier::create) + .verifyComplete(); + + assertThat(findCounter("request.stream", SignalType.ON_COMPLETE).count()).isEqualTo(1); + } + + private Counter findCounter(String interactionModel, SignalType signalType) { + return meterRegistry + .get(String.format("infra.remoting.%s", interactionModel)) + .tag("signal.type", signalType.name()) + .tag("test-key", "test-value") + .counter(); + } + + private Timer findTimer(String interactionModel, SignalType signalType) { + return meterRegistry + .get(String.format("infra.remoting.%s", interactionModel)) + .tag("signal.type", signalType.name()) + .tag("test-key", "test-value") + .timer(); + } +} diff --git a/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/MicrometerDuplexConnectionDecoratorTests.java b/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/MicrometerDuplexConnectionDecoratorTests.java new file mode 100644 index 0000000..e5c23c8 --- /dev/null +++ b/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/MicrometerDuplexConnectionDecoratorTests.java @@ -0,0 +1,70 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.remoting.micrometer; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import infra.remoting.DuplexConnection; +import io.micrometer.core.instrument.simple.SimpleMeterRegistry; + +import static infra.remoting.plugins.ConnectionDecorator.Type.CLIENT; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatNullPointerException; +import static org.mockito.Mockito.RETURNS_SMART_NULLS; +import static org.mockito.Mockito.mock; + +final class MicrometerDuplexConnectionDecoratorTests { + + private final DuplexConnection delegate = mock(DuplexConnection.class, RETURNS_SMART_NULLS); + + private final SimpleMeterRegistry meterRegistry = new SimpleMeterRegistry(); + + @DisplayName("creates MicrometerDuplexConnection") + @Test + void apply() { + assertThat(new MicrometerDuplexConnectionDecorator(meterRegistry).decorate(CLIENT, delegate)) + .isInstanceOf(MicrometerDuplexConnection.class); + } + + @DisplayName("apply throws NullPointerException with null connectionType") + @Test + void applyNullConnectionType() { + assertThatNullPointerException() + .isThrownBy( + () -> new MicrometerDuplexConnectionDecorator(meterRegistry).decorate(null, delegate)) + .withMessage("connectionType is required"); + } + + @DisplayName("apply throws NullPointerException with null delegate") + @Test + void applyNullDelegate() { + assertThatNullPointerException() + .isThrownBy( + () -> new MicrometerDuplexConnectionDecorator(meterRegistry).decorate(CLIENT, null)) + .withMessage("delegate is required"); + } + + @DisplayName("constructor throws NullPointer exception with null meterRegistry") + @Test + void constructorNullMeterRegistry() { + assertThatNullPointerException() + .isThrownBy(() -> new MicrometerDuplexConnectionDecorator(null)) + .withMessage("meterRegistry is required"); + } +} diff --git a/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/MicrometerDuplexConnectionTests.java b/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/MicrometerDuplexConnectionTests.java new file mode 100644 index 0000000..9661084 --- /dev/null +++ b/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/MicrometerDuplexConnectionTests.java @@ -0,0 +1,228 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.remoting.micrometer; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.Mockito; + +import infra.remoting.DuplexConnection; +import infra.remoting.frame.FrameType; +import infra.remoting.plugins.ConnectionDecorator.Type; +import io.micrometer.core.instrument.Counter; +import io.micrometer.core.instrument.Tag; +import io.micrometer.core.instrument.simple.SimpleMeterRegistry; +import io.netty.buffer.ByteBuf; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; +import reactor.core.publisher.Operators; +import reactor.test.StepVerifier; + +import static infra.remoting.frame.FrameType.CANCEL; +import static infra.remoting.frame.FrameType.COMPLETE; +import static infra.remoting.frame.FrameType.ERROR; +import static infra.remoting.frame.FrameType.KEEPALIVE; +import static infra.remoting.frame.FrameType.LEASE; +import static infra.remoting.frame.FrameType.METADATA_PUSH; +import static infra.remoting.frame.FrameType.REQUEST_CHANNEL; +import static infra.remoting.frame.FrameType.REQUEST_FNF; +import static infra.remoting.frame.FrameType.REQUEST_N; +import static infra.remoting.frame.FrameType.REQUEST_RESPONSE; +import static infra.remoting.frame.FrameType.REQUEST_STREAM; +import static infra.remoting.frame.FrameType.SETUP; +import static infra.remoting.plugins.ConnectionDecorator.Type.CLIENT; +import static infra.remoting.plugins.ConnectionDecorator.Type.SERVER; +import static infra.remoting.test.TestFrames.createTestCancelFrame; +import static infra.remoting.test.TestFrames.createTestErrorFrame; +import static infra.remoting.test.TestFrames.createTestKeepaliveFrame; +import static infra.remoting.test.TestFrames.createTestLeaseFrame; +import static infra.remoting.test.TestFrames.createTestMetadataPushFrame; +import static infra.remoting.test.TestFrames.createTestPayloadFrame; +import static infra.remoting.test.TestFrames.createTestRequestChannelFrame; +import static infra.remoting.test.TestFrames.createTestRequestFireAndForgetFrame; +import static infra.remoting.test.TestFrames.createTestRequestNFrame; +import static infra.remoting.test.TestFrames.createTestRequestResponseFrame; +import static infra.remoting.test.TestFrames.createTestRequestStreamFrame; +import static infra.remoting.test.TestFrames.createTestSetupFrame; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatNullPointerException; +import static org.mockito.Mockito.RETURNS_SMART_NULLS; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +final class MicrometerDuplexConnectionTests { + + private final DuplexConnection delegate = mock(DuplexConnection.class, RETURNS_SMART_NULLS); + + private final SimpleMeterRegistry meterRegistry = new SimpleMeterRegistry(); + + @DisplayName("constructor throws NullPointerException with null connectionType") + @Test + void constructorNullConnectionType() { + assertThatNullPointerException() + .isThrownBy(() -> new MicrometerDuplexConnection(null, delegate, meterRegistry)) + .withMessage("connectionType is required"); + } + + @DisplayName("constructor throws NullPointerException with null delegate") + @Test + void constructorNullDelegate() { + assertThatNullPointerException() + .isThrownBy(() -> new MicrometerDuplexConnection(CLIENT, null, meterRegistry)) + .withMessage("delegate is required"); + } + + @DisplayName("constructor throws NullPointerException with null meterRegistry") + @Test + void constructorNullMeterRegistry() { + + assertThatNullPointerException() + .isThrownBy(() -> new MicrometerDuplexConnection(CLIENT, delegate, null)) + .withMessage("meterRegistry is required"); + } + + @DisplayName("dispose gathers metrics") + @Test + void dispose() { + new MicrometerDuplexConnection( + CLIENT, delegate, meterRegistry, Tag.of("test-key", "test-value")) + .dispose(); + + assertThat( + meterRegistry + .get("infra.remoting.duplex.connection.dispose") + .tag("connection.type", CLIENT.name()) + .tag("test-key", "test-value") + .counter() + .count()) + .isEqualTo(1); + } + + @DisplayName("onClose gathers metrics") + @Test + void onClose() { + when(delegate.onClose()).thenReturn(Mono.empty()); + + new MicrometerDuplexConnection( + CLIENT, delegate, meterRegistry, Tag.of("test-key", "test-value")) + .onClose() + .subscribe(Operators.drainSubscriber()); + + assertThat( + meterRegistry + .get("infra.remoting.duplex.connection.close") + .tag("connection.type", CLIENT.name()) + .tag("test-key", "test-value") + .counter() + .count()) + .isEqualTo(1); + } + + @DisplayName("receive gathers metrics") + @Test + void receive() { + Flux frames = + Flux.just( + createTestCancelFrame(), + createTestErrorFrame(), + createTestKeepaliveFrame(), + createTestLeaseFrame(), + createTestMetadataPushFrame(), + createTestPayloadFrame(), + createTestRequestChannelFrame(), + createTestRequestFireAndForgetFrame(), + createTestRequestNFrame(), + createTestRequestResponseFrame(), + createTestRequestStreamFrame(), + createTestSetupFrame()); + + when(delegate.receive()).thenReturn(frames); + + new MicrometerDuplexConnection( + CLIENT, delegate, meterRegistry, Tag.of("test-key", "test-value")) + .receive() + .as(StepVerifier::create) + .expectNextCount(12) + .verifyComplete(); + + assertThat(findCounter(CLIENT, CANCEL).count()).isEqualTo(1); + assertThat(findCounter(CLIENT, COMPLETE).count()).isEqualTo(1); + assertThat(findCounter(CLIENT, ERROR).count()).isEqualTo(1); + assertThat(findCounter(CLIENT, KEEPALIVE).count()).isEqualTo(1); + assertThat(findCounter(CLIENT, LEASE).count()).isEqualTo(1); + assertThat(findCounter(CLIENT, METADATA_PUSH).count()).isEqualTo(1); + assertThat(findCounter(CLIENT, REQUEST_CHANNEL).count()).isEqualTo(1); + assertThat(findCounter(CLIENT, REQUEST_FNF).count()).isEqualTo(1); + assertThat(findCounter(CLIENT, REQUEST_N).count()).isEqualTo(1); + assertThat(findCounter(CLIENT, REQUEST_RESPONSE).count()).isEqualTo(1); + assertThat(findCounter(CLIENT, REQUEST_STREAM).count()).isEqualTo(1); + assertThat(findCounter(CLIENT, SETUP).count()).isEqualTo(1); + } + + @DisplayName("send gathers metrics") + @SuppressWarnings("unchecked") + @Test + void send() { + ArgumentCaptor captor = ArgumentCaptor.forClass(ByteBuf.class); + doNothing().when(delegate).sendFrame(Mockito.anyInt(), captor.capture()); + + final MicrometerDuplexConnection micrometerDuplexConnection = + new MicrometerDuplexConnection( + SERVER, delegate, meterRegistry, Tag.of("test-key", "test-value")); + micrometerDuplexConnection.sendFrame(1, createTestCancelFrame()); + micrometerDuplexConnection.sendFrame(1, createTestErrorFrame()); + micrometerDuplexConnection.sendFrame(1, createTestKeepaliveFrame()); + micrometerDuplexConnection.sendFrame(1, createTestLeaseFrame()); + micrometerDuplexConnection.sendFrame(1, createTestMetadataPushFrame()); + micrometerDuplexConnection.sendFrame(1, createTestPayloadFrame()); + micrometerDuplexConnection.sendFrame(1, createTestRequestChannelFrame()); + micrometerDuplexConnection.sendFrame(1, createTestRequestFireAndForgetFrame()); + micrometerDuplexConnection.sendFrame(1, createTestRequestNFrame()); + micrometerDuplexConnection.sendFrame(1, createTestRequestResponseFrame()); + micrometerDuplexConnection.sendFrame(1, createTestRequestStreamFrame()); + micrometerDuplexConnection.sendFrame(1, createTestSetupFrame()); + + StepVerifier.create(Flux.fromIterable(captor.getAllValues())) + .expectNextCount(12) + .verifyComplete(); + + assertThat(findCounter(SERVER, CANCEL).count()).isEqualTo(1); + assertThat(findCounter(SERVER, COMPLETE).count()).isEqualTo(1); + assertThat(findCounter(SERVER, ERROR).count()).isEqualTo(1); + assertThat(findCounter(SERVER, KEEPALIVE).count()).isEqualTo(1); + assertThat(findCounter(SERVER, LEASE).count()).isEqualTo(1); + assertThat(findCounter(SERVER, METADATA_PUSH).count()).isEqualTo(1); + assertThat(findCounter(SERVER, REQUEST_CHANNEL).count()).isEqualTo(1); + assertThat(findCounter(SERVER, REQUEST_FNF).count()).isEqualTo(1); + assertThat(findCounter(SERVER, REQUEST_N).count()).isEqualTo(1); + assertThat(findCounter(SERVER, REQUEST_RESPONSE).count()).isEqualTo(1); + assertThat(findCounter(SERVER, REQUEST_STREAM).count()).isEqualTo(1); + assertThat(findCounter(SERVER, SETUP).count()).isEqualTo(1); + } + + private Counter findCounter(Type connectionType, FrameType frameType) { + return meterRegistry + .get("infra.remoting.frame") + .tag("connection.type", connectionType.name()) + .tag("frame.type", frameType.name()) + .tag("test-key", "test-value") + .counter(); + } +} diff --git a/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/IntegrationTests.java b/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/IntegrationTests.java new file mode 100644 index 0000000..55b8bb5 --- /dev/null +++ b/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/IntegrationTests.java @@ -0,0 +1,196 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.remoting.micrometer.integration; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.Timeout; +import org.reactivestreams.Publisher; +import org.reactivestreams.Subscriber; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.atomic.AtomicInteger; + +import infra.remoting.Channel; +import infra.remoting.Payload; +import infra.remoting.core.ChannelConnector; +import infra.remoting.core.RemotingServer; +import infra.remoting.plugins.ChannelAcceptorInterceptor; +import infra.remoting.plugins.ChannelDecorator; +import infra.remoting.plugins.ConnectionDecorator; +import infra.remoting.test.TestSubscriber; +import infra.remoting.transport.netty.client.TcpClientTransport; +import infra.remoting.transport.netty.server.CloseableChannel; +import infra.remoting.transport.netty.server.TcpServerTransport; +import infra.remoting.util.ChannelWrapper; +import infra.remoting.util.DefaultPayload; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; + +public class IntegrationTests { + + private static final ChannelDecorator requesterInterceptor; + private static final ChannelDecorator responderInterceptor; + private static final ChannelAcceptorInterceptor clientAcceptorInterceptor; + private static final ChannelAcceptorInterceptor serverAcceptorInterceptor; + private static final ConnectionDecorator CONNECTION_DECORATOR; + + private static volatile boolean calledRequester = false; + private static volatile boolean calledResponder = false; + private static volatile boolean calledClientAcceptor = false; + private static volatile boolean calledServerAcceptor = false; + private static volatile boolean calledFrame = false; + + static { + requesterInterceptor = channel -> + new ChannelWrapper(channel) { + @Override + public Mono requestResponse(Payload payload) { + calledRequester = true; + return channel.requestResponse(payload); + } + }; + + responderInterceptor = channel -> + new ChannelWrapper(channel) { + @Override + public Mono requestResponse(Payload payload) { + calledResponder = true; + return channel.requestResponse(payload); + } + }; + + clientAcceptorInterceptor = acceptor -> + (setup, channel) -> { + calledClientAcceptor = true; + return acceptor.accept(setup, channel); + }; + + serverAcceptorInterceptor = acceptor -> (setup, channel) -> { + calledServerAcceptor = true; + return acceptor.accept(setup, channel); + }; + + CONNECTION_DECORATOR = (type, connection) -> { + calledFrame = true; + return connection; + }; + } + + private CloseableChannel server; + private Channel client; + private AtomicInteger requestCount; + private CountDownLatch disconnectionCounter; + private AtomicInteger errorCount; + + @BeforeEach + public void startup() { + errorCount = new AtomicInteger(); + requestCount = new AtomicInteger(); + disconnectionCounter = new CountDownLatch(1); + + server = RemotingServer.create((setup, channel) -> { + channel.onClose() + .doFinally(signalType -> disconnectionCounter.countDown()) + .subscribe(); + + return Mono.just(new Channel() { + @Override + public Mono requestResponse(Payload payload) { + return Mono.just(DefaultPayload.create("RESPONSE", "METADATA")) + .doOnSubscribe(s -> requestCount.incrementAndGet()); + } + + @Override + public Flux requestStream(Payload payload) { + return Flux.range(1, 10_000) + .map(i -> DefaultPayload.create("data -> " + i)); + } + + @Override + public Flux requestChannel(Publisher payloads) { + return Flux.from(payloads); + } + }); + }) + .interceptors(registry -> registry + .forResponder(responderInterceptor) + .forChannelAcceptor(serverAcceptorInterceptor) + .forConnection(CONNECTION_DECORATOR)) + .bind(TcpServerTransport.create("localhost", 0)) + .block(); + + client = ChannelConnector.create() + .interceptors(registry -> registry + .forRequester(requesterInterceptor) + .forChannelAcceptor(clientAcceptorInterceptor) + .forConnection(CONNECTION_DECORATOR)) + .connect(TcpClientTransport.create(server.address())) + .block(); + } + + @AfterEach + public void teardown() { + server.dispose(); + } + + @Test + @Timeout(5_000L) + public void testRequest() { + client.requestResponse(DefaultPayload.create("REQUEST", "META")).block(); + assertThat(requestCount).as("Server did not see the request.").hasValue(1); + + assertThat(calledRequester).isTrue(); + assertThat(calledResponder).isTrue(); + assertThat(calledClientAcceptor).isTrue(); + assertThat(calledServerAcceptor).isTrue(); + assertThat(calledFrame).isTrue(); + } + + @Test + @Timeout(5_000L) + public void testStream() { + Subscriber subscriber = TestSubscriber.createCancelling(); + client.requestStream(DefaultPayload.create("start")).subscribe(subscriber); + + verify(subscriber).onSubscribe(any()); + verifyNoMoreInteractions(subscriber); + } + + @Test + @Timeout(5_000L) + public void testClose() throws InterruptedException { + client.dispose(); + disconnectionCounter.await(); + } + + @Test // (timeout = 5_000L) + public void testCallRequestWithErrorAndThenRequest() { + assertThatThrownBy(client.requestChannel(Mono.error(new Throwable("test")))::blockLast) + .hasMessage("java.lang.Throwable: test"); + + testRequest(); + } +} diff --git a/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/InteractionsLoadTests.java b/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/InteractionsLoadTests.java new file mode 100644 index 0000000..2be1db5 --- /dev/null +++ b/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/InteractionsLoadTests.java @@ -0,0 +1,110 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.remoting.micrometer.integration; + +import org.junit.jupiter.api.Test; +import org.reactivestreams.Publisher; + +import java.time.Duration; +import java.util.function.Supplier; + +import infra.remoting.Channel; +import infra.remoting.ChannelAcceptor; +import infra.remoting.Payload; +import infra.remoting.core.ChannelConnector; +import infra.remoting.core.RemotingServer; +import infra.remoting.test.SlowTest; +import infra.remoting.transport.netty.client.TcpClientTransport; +import infra.remoting.transport.netty.server.CloseableChannel; +import infra.remoting.transport.netty.server.TcpServerTransport; +import infra.remoting.util.DefaultPayload; +import reactor.core.publisher.Flux; + +public class InteractionsLoadTests { + + @Test + @SlowTest + public void channel() { + CloseableChannel server = RemotingServer.create(ChannelAcceptor.with(new EchoChannel())) + .bind(TcpServerTransport.create("localhost", 0)) + .block(Duration.ofSeconds(10)); + + Channel clientChannel = ChannelConnector.connectWith(TcpClientTransport.create(server.address())) + .block(Duration.ofSeconds(10)); + + int concurrency = 16; + Flux.range(1, concurrency) + .flatMap(v -> clientChannel + .requestChannel(input().onBackpressureDrop().map(iv -> DefaultPayload.create("foo"))) + .limitRate(10000), + concurrency) + .timeout(Duration.ofSeconds(5)) + .doOnNext(p -> { + String data = p.getDataUtf8(); + if (!data.equals("bar")) { + throw new IllegalStateException("Channel Client Bad message: " + data); + } + }) + .window(Duration.ofSeconds(1)) + .flatMap(Flux::count) + .doOnNext(d -> System.out.println("Got: " + d)) + .take(Duration.ofMinutes(1)) + .doOnTerminate(server::dispose) + .subscribe(); + + server.onClose().block(); + } + + private static Flux input() { + Flux interval = Flux.interval(Duration.ofMillis(1)).onBackpressureDrop(); + for (int i = 0; i < 10; i++) { + interval = interval.mergeWith(interval); + } + return interval; + } + + private static class EchoChannel implements Channel { + + @Override + public Flux requestChannel(Publisher payloads) { + return Flux.from(payloads) + .map(p -> { + String data = p.getDataUtf8(); + if (!data.equals("foo")) { + throw new IllegalStateException("Channel Server Bad message: " + data); + } + return DefaultPayload.create("bar"); + }); + } + + @Override + public Flux requestStream(Payload payload) { + return Flux.just(payload) + .map(Payload::getDataUtf8) + .doOnNext((data) -> { + if (!data.equals("foo")) { + throw new IllegalStateException("Stream Server Bad message: " + data); + } + }) + .flatMap(data -> { + Supplier p = () -> DefaultPayload.create("bar"); + return Flux.range(1, 100).map(v -> p.get()); + }); + } + } +} diff --git a/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/StreamingTests.java b/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/StreamingTests.java new file mode 100644 index 0000000..14d746d --- /dev/null +++ b/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/StreamingTests.java @@ -0,0 +1,123 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.remoting.micrometer.integration; + +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.time.Duration; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.Function; + +import infra.remoting.ChannelAcceptor; +import infra.remoting.Closeable; +import infra.remoting.Payload; +import infra.remoting.core.ChannelConnector; +import infra.remoting.core.RemotingServer; +import infra.remoting.exceptions.ApplicationErrorException; +import infra.remoting.transport.local.LocalClientTransport; +import infra.remoting.transport.local.LocalServerTransport; +import infra.remoting.util.DefaultPayload; +import reactor.core.publisher.Flux; + +class StreamingTests { + LocalServerTransport serverTransport = LocalServerTransport.create("test"); + + @Test + public void testRangeButThrowException() { + Closeable server = null; + try { + server = RemotingServer.create(ChannelAcceptor.forRequestStream(payload -> + Flux.range(1, 1000) + .doOnNext(i -> { + if (i > 3) { + throw new RuntimeException("BOOM!"); + } + }) + .map((Function) l -> DefaultPayload.create("l -> " + l)) + .cast(Payload.class))) + .bind(serverTransport) + .block(); + + Assertions.assertThatThrownBy( + Flux.range(1, 6).flatMap(i -> consumer("connection number -> " + i))::blockLast) + .isInstanceOf(ApplicationErrorException.class); + + } + finally { + server.dispose(); + } + } + + @Test + public void testRangeOfConsumers() { + Closeable server = null; + try { + server = + RemotingServer.create( + ChannelAcceptor.forRequestStream( + payload -> + Flux.range(1, 1000) + .map((Function) l -> DefaultPayload.create("l -> " + l)) + .cast(Payload.class))) + .bind(serverTransport) + .block(); + + Flux.range(1, 6).flatMap(i -> consumer("connection number -> " + i)).blockLast(); + } + finally { + server.dispose(); + } + } + + private Flux consumer(String s) { + return ChannelConnector.connectWith(LocalClientTransport.create("test")) + .flatMapMany(channel -> { + AtomicInteger count = new AtomicInteger(); + return Flux.range(1, 100) + .flatMap( + i -> channel.requestStream(DefaultPayload.create("i -> " + i)).take(100), 1); + }); + } + + @Test + public void testSingleConsumer() { + Closeable server = null; + try { + server = + RemotingServer.create(ChannelAcceptor.forRequestStream(payload -> Flux.range(1, 10_000) + .map((Function) l -> DefaultPayload.create("l -> " + l)) + .cast(Payload.class))) + .bind(serverTransport) + .block(); + + consumer("1").blockLast(); + + } + finally { + server.dispose(); + } + } + + @Test + public void testFluxOnly() { + Flux longFlux = Flux.interval(Duration.ofMillis(1)).onBackpressureDrop(); + + Flux.range(1, 60).flatMap(i -> longFlux.take(1000)).blockLast(); + } +} diff --git a/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/TcpIntegrationTests.java b/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/TcpIntegrationTests.java new file mode 100644 index 0000000..106fee5 --- /dev/null +++ b/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/TcpIntegrationTests.java @@ -0,0 +1,197 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.remoting.micrometer.integration; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.Timeout; + +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CountDownLatch; + +import infra.remoting.Channel; +import infra.remoting.Payload; +import infra.remoting.core.ChannelConnector; +import infra.remoting.core.RemotingServer; +import infra.remoting.transport.netty.client.TcpClientTransport; +import infra.remoting.transport.netty.server.CloseableChannel; +import infra.remoting.transport.netty.server.TcpServerTransport; +import infra.remoting.util.ChannelWrapper; +import infra.remoting.util.DefaultPayload; +import infra.remoting.util.EmptyPayload; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; +import reactor.core.publisher.Sinks; +import reactor.core.scheduler.Schedulers; + +import static org.assertj.core.api.Assertions.assertThat; + +public class TcpIntegrationTests { + private Channel handler; + + private CloseableChannel server; + + @BeforeEach + public void startup() { + server = RemotingServer.create((setup, sendingSocket) -> Mono.just(new ChannelWrapper(handler))) + .bind(TcpServerTransport.create("localhost", 0)) + .block(); + } + + private Channel buildClient() { + return ChannelConnector.connectWith(TcpClientTransport.create(server.address())).block(); + } + + @AfterEach + public void cleanup() { + server.dispose(); + } + + @Test + @Timeout(15_000L) + public void testCompleteWithoutNext() { + handler = + new Channel() { + @Override + public Flux requestStream(Payload payload) { + return Flux.empty(); + } + }; + Channel client = buildClient(); + Boolean hasElements = + client.requestStream(DefaultPayload.create("REQUEST", "META")).log().hasElements().block(); + + assertThat(hasElements).isFalse(); + } + + @Test + @Timeout(15_000L) + public void testSingleStream() { + handler = + new Channel() { + @Override + public Flux requestStream(Payload payload) { + return Flux.just(DefaultPayload.create("RESPONSE", "METADATA")); + } + }; + + Channel client = buildClient(); + + Payload result = client.requestStream(DefaultPayload.create("REQUEST", "META")).blockLast(); + + assertThat(result.getDataUtf8()).isEqualTo("RESPONSE"); + } + + @Test + @Timeout(15_000L) + public void testZeroPayload() { + handler = + new Channel() { + @Override + public Flux requestStream(Payload payload) { + return Flux.just(EmptyPayload.INSTANCE); + } + }; + + Channel client = buildClient(); + + Payload result = client.requestStream(DefaultPayload.create("REQUEST", "META")).blockFirst(); + + assertThat(result.getDataUtf8()).isEmpty(); + } + + @Test + @Timeout(15_000L) + public void testRequestResponseErrors() { + handler = + new Channel() { + boolean first = true; + + @Override + public Mono requestResponse(Payload payload) { + if (first) { + first = false; + return Mono.error(new RuntimeException("EX")); + } + else { + return Mono.just(DefaultPayload.create("SUCCESS")); + } + } + }; + + Channel client = buildClient(); + + Payload response1 = + client + .requestResponse(DefaultPayload.create("REQUEST", "META")) + .onErrorReturn(DefaultPayload.create("ERROR")) + .block(); + Payload response2 = + client + .requestResponse(DefaultPayload.create("REQUEST", "META")) + .onErrorReturn(DefaultPayload.create("ERROR")) + .block(); + + assertThat(response1.getDataUtf8()).isEqualTo("ERROR"); + assertThat(response2.getDataUtf8()).isEqualTo("SUCCESS"); + } + + @Test + @Timeout(15_000L) + public void testTwoConcurrentStreams() throws InterruptedException { + ConcurrentHashMap> map = new ConcurrentHashMap<>(); + Sinks.Many processor1 = Sinks.many().unicast().onBackpressureBuffer(); + map.put("REQUEST1", processor1); + Sinks.Many processor2 = Sinks.many().unicast().onBackpressureBuffer(); + map.put("REQUEST2", processor2); + + handler = new Channel() { + @Override + public Flux requestStream(Payload payload) { + return map.get(payload.getDataUtf8()).asFlux(); + } + }; + + Channel client = buildClient(); + + Flux response1 = client.requestStream(DefaultPayload.create("REQUEST1")); + Flux response2 = client.requestStream(DefaultPayload.create("REQUEST2")); + + CountDownLatch nextCountdown = new CountDownLatch(2); + CountDownLatch completeCountdown = new CountDownLatch(2); + + response1 + .subscribeOn(Schedulers.newSingle("1")) + .subscribe(c -> nextCountdown.countDown(), t -> { }, completeCountdown::countDown); + + response2 + .subscribeOn(Schedulers.newSingle("2")) + .subscribe(c -> nextCountdown.countDown(), t -> { }, completeCountdown::countDown); + + processor1.tryEmitNext(DefaultPayload.create("RESPONSE1A")); + processor2.tryEmitNext(DefaultPayload.create("RESPONSE2A")); + + nextCountdown.await(); + + processor1.tryEmitComplete(); + processor2.tryEmitComplete(); + + completeCountdown.await(); + } +} diff --git a/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/observation/ByteBufGetter.java b/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/observation/ByteBufGetter.java new file mode 100644 index 0000000..f2536f2 --- /dev/null +++ b/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/observation/ByteBufGetter.java @@ -0,0 +1,38 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.remoting.micrometer.integration.observation; + +import java.util.Map; + +import io.micrometer.tracing.propagation.Propagator; +import io.netty.buffer.ByteBuf; + +public class ByteBufGetter implements Propagator.Getter { + + private final Map map; + + public ByteBufGetter(Map map) { + this.map = map; + } + + @Override + public String get(ByteBuf carrier, String key) { + return map.get(key); + } + +} diff --git a/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/observation/ByteBufSetter.java b/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/observation/ByteBufSetter.java new file mode 100644 index 0000000..6223e5d --- /dev/null +++ b/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/observation/ByteBufSetter.java @@ -0,0 +1,35 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.remoting.micrometer.integration.observation; + +import java.util.HashMap; +import java.util.Map; + +import io.micrometer.tracing.propagation.Propagator; +import io.netty.buffer.ByteBuf; + +public class ByteBufSetter implements Propagator.Setter { + + final Map map = new HashMap<>(); + + @Override + public void set(ByteBuf carrier, String key, String value) { + map.put(key, value); + } + +} diff --git a/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/observation/ObservationIntegrationTests.java b/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/observation/ObservationIntegrationTests.java new file mode 100644 index 0000000..746d1d9 --- /dev/null +++ b/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/observation/ObservationIntegrationTests.java @@ -0,0 +1,233 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.remoting.micrometer.integration.observation; + +import org.awaitility.Awaitility; +import org.junit.jupiter.api.AfterEach; +import org.reactivestreams.Publisher; + +import java.time.Duration; +import java.util.Deque; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.BiConsumer; + +import infra.remoting.Channel; +import infra.remoting.Payload; +import infra.remoting.core.ChannelConnector; +import infra.remoting.core.RemotingServer; +import infra.remoting.micrometer.observation.ChannelRequesterTracingObservationHandler; +import infra.remoting.micrometer.observation.ChannelResponderTracingObservationHandler; +import infra.remoting.micrometer.observation.ObservationRequesterChannel; +import infra.remoting.micrometer.observation.ObservationResponderChannel; +import infra.remoting.plugins.ChannelDecorator; +import infra.remoting.transport.netty.client.TcpClientTransport; +import infra.remoting.transport.netty.server.CloseableChannel; +import infra.remoting.transport.netty.server.TcpServerTransport; +import infra.remoting.util.DefaultPayload; +import io.micrometer.core.instrument.MeterRegistry; +import io.micrometer.core.instrument.Tag; +import io.micrometer.core.instrument.Tags; +import io.micrometer.core.instrument.observation.DefaultMeterObservationHandler; +import io.micrometer.core.instrument.simple.SimpleMeterRegistry; +import io.micrometer.core.tck.MeterRegistryAssert; +import io.micrometer.observation.Observation; +import io.micrometer.observation.ObservationHandler; +import io.micrometer.observation.ObservationRegistry; +import io.micrometer.tracing.test.SampleTestRunner; +import io.micrometer.tracing.test.reporter.BuildingBlocks; +import io.micrometer.tracing.test.simple.SpansAssert; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +import static org.assertj.core.api.Assertions.assertThat; + +public class ObservationIntegrationTests extends SampleTestRunner { + private static final MeterRegistry registry = new SimpleMeterRegistry(); + private static final ObservationRegistry observationRegistry = ObservationRegistry.create(); + + static { + observationRegistry + .observationConfig() + .observationHandler(new DefaultMeterObservationHandler(registry)); + } + + private final ChannelDecorator requesterInterceptor; + private final ChannelDecorator responderInterceptor; + + ObservationIntegrationTests() { + super(SampleRunnerConfig.builder().build()); + requesterInterceptor = channel -> new ObservationRequesterChannel(channel, observationRegistry); + responderInterceptor = channel -> new ObservationResponderChannel(channel, observationRegistry); + } + + private CloseableChannel server; + private Channel client; + private AtomicInteger counter; + + @Override + public BiConsumer>> customizeObservationHandlers() { + return (buildingBlocks, observationHandlers) -> { + ByteBufSetter setter = new ByteBufSetter(); + observationHandlers.addFirst( + new ChannelRequesterTracingObservationHandler( + buildingBlocks.getTracer(), + buildingBlocks.getPropagator(), + setter + )); + observationHandlers.addFirst( + new ChannelResponderTracingObservationHandler( + buildingBlocks.getTracer(), + buildingBlocks.getPropagator(), + new ByteBufGetter(setter.map))); + }; + } + + @AfterEach + public void teardown() { + if (server != null) { + server.dispose(); + } + } + + private void testRequest() { + counter.set(0); + client.requestResponse(DefaultPayload.create("REQUEST", "META")).block(); + assertThat(counter).as("Server did not see the request.").hasValue(1); + } + + private void testStream() { + counter.set(0); + client.requestStream(DefaultPayload.create("start")).blockLast(); + + assertThat(counter).as("Server did not see the request.").hasValue(1); + } + + private void testRequestChannel() { + counter.set(0); + client.requestChannel(Mono.just(DefaultPayload.create("start"))).blockFirst(); + assertThat(counter).as("Server did not see the request.").hasValue(1); + } + + private void testFireAndForget() { + counter.set(0); + client.fireAndForget(DefaultPayload.create("start")).subscribe(); + Awaitility.await().atMost(Duration.ofSeconds(50)).until(() -> counter.get() == 1); + assertThat(counter).as("Server did not see the request.").hasValue(1); + } + + @Override + public SampleTestRunnerConsumer yourCode() { + return (bb, meterRegistry) -> { + counter = new AtomicInteger(); + server = RemotingServer.create((setup, sendingSocket) -> { + sendingSocket.onClose().subscribe(); + + return Mono.just( + new Channel() { + @Override + public Mono requestResponse(Payload payload) { + payload.release(); + counter.incrementAndGet(); + return Mono.just(DefaultPayload.create("RESPONSE", "METADATA")); + } + + @Override + public Flux requestStream(Payload payload) { + payload.release(); + counter.incrementAndGet(); + return Flux.range(1, 10_000) + .map(i -> DefaultPayload.create("data -> " + i)); + } + + @Override + public Flux requestChannel(Publisher payloads) { + counter.incrementAndGet(); + return Flux.from(payloads); + } + + @Override + public Mono fireAndForget(Payload payload) { + payload.release(); + counter.incrementAndGet(); + return Mono.empty(); + } + }); + }) + .interceptors(registry -> registry.forResponder(responderInterceptor)) + .bind(TcpServerTransport.create("localhost", 0)) + .block(); + + client = ChannelConnector.create() + .interceptors(registry -> registry.forRequester(requesterInterceptor)) + .connect(TcpClientTransport.create(server.address())) + .block(); + + testRequest(); + + testStream(); + + testRequestChannel(); + + testFireAndForget(); + + SpansAssert.assertThat(bb.getFinishedSpans()) + .haveSameTraceId() + // "request_*" + "handle" x 4 + .hasNumberOfSpansEqualTo(8) + .hasNumberOfSpansWithNameEqualTo("handle", 4) + .forAllSpansWithNameEqualTo("handle", span -> span.hasTagWithKey("infra.remoting.request-type")) + .hasASpanWithNameIgnoreCase("request_stream") + .thenASpanWithNameEqualToIgnoreCase("request_stream") + .hasTag("infra.remoting.request-type", "REQUEST_STREAM") + .backToSpans() + .hasASpanWithNameIgnoreCase("request_channel") + .thenASpanWithNameEqualToIgnoreCase("request_channel") + .hasTag("infra.remoting.request-type", "REQUEST_CHANNEL") + .backToSpans() + .hasASpanWithNameIgnoreCase("request_fnf") + .thenASpanWithNameEqualToIgnoreCase("request_fnf") + .hasTag("infra.remoting.request-type", "REQUEST_FNF") + .backToSpans() + .hasASpanWithNameIgnoreCase("request_response") + .thenASpanWithNameEqualToIgnoreCase("request_response") + .hasTag("infra.remoting.request-type", "REQUEST_RESPONSE"); + + MeterRegistryAssert.assertThat(registry) + .hasTimerWithNameAndTags("infra.remoting.response", + Tags.of(Tag.of("error", "none"), Tag.of("infra.remoting.request-type", "REQUEST_RESPONSE"))) + .hasTimerWithNameAndTags("infra.remoting.fnf", + Tags.of(Tag.of("error", "none"), Tag.of("infra.remoting.request-type", "REQUEST_FNF"))) + .hasTimerWithNameAndTags("infra.remoting.request", + Tags.of(Tag.of("error", "none"), Tag.of("infra.remoting.request-type", "REQUEST_RESPONSE"))) + .hasTimerWithNameAndTags("infra.remoting.channel", + Tags.of(Tag.of("error", "none"), Tag.of("infra.remoting.request-type", "REQUEST_CHANNEL"))) + .hasTimerWithNameAndTags("infra.remoting.stream", + Tags.of(Tag.of("error", "none"), Tag.of("infra.remoting.request-type", "REQUEST_STREAM"))); + }; + } + + @Override + protected MeterRegistry getMeterRegistry() { + return registry; + } + + @Override + protected ObservationRegistry getObservationRegistry() { + return observationRegistry; + } +} diff --git a/today-remoting-micrometer/src/test/resources/logback-test.xml b/today-remoting-micrometer/src/test/resources/logback-test.xml new file mode 100644 index 0000000..2cc1ec3 --- /dev/null +++ b/today-remoting-micrometer/src/test/resources/logback-test.xml @@ -0,0 +1,33 @@ + + + + + + + + %date{HH:mm:ss.SSS} %-10thread %-42logger %msg%n + + + + + + + + + + diff --git a/today-remoting-transport-tcp/src/test/java/infra/remoting/integration/FragmentTests.java b/today-remoting-transport-tcp/src/test/java/infra/remoting/integration/FragmentTests.java index b21ebda..93930a9 100644 --- a/today-remoting-transport-tcp/src/test/java/infra/remoting/integration/FragmentTests.java +++ b/today-remoting-transport-tcp/src/test/java/infra/remoting/integration/FragmentTests.java @@ -33,7 +33,7 @@ import infra.remoting.transport.netty.server.CloseableChannel; import infra.remoting.transport.netty.server.TcpServerTransport; import infra.remoting.util.DefaultPayload; -import infra.remoting.util.ChannelDecorator; +import infra.remoting.util.ChannelWrapper; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; @@ -66,7 +66,7 @@ public void startup(int frameSize) { TcpServerTransport serverTransport = TcpServerTransport.create("localhost", randomPort); server = - RemotingServer.create((setup, sendingSocket) -> Mono.just(new ChannelDecorator(handler))) + RemotingServer.create((setup, channel) -> Mono.just(new ChannelWrapper(handler))) .fragment(frameSize) .bind(serverTransport) .block(); diff --git a/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/SetupRejectionTests.java b/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/SetupRejectionTests.java index 423dd94..3912086 100644 --- a/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/SetupRejectionTests.java +++ b/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/SetupRejectionTests.java @@ -124,8 +124,8 @@ public RejectingAcceptor(String msg) { } @Override - public Mono accept(ConnectionSetupPayload setup, Channel sendingSocket) { - requesters.tryEmitNext(sendingSocket); + public Mono accept(ConnectionSetupPayload setup, Channel channel) { + requesters.tryEmitNext(channel); return Mono.error(new RuntimeException(msg)); } diff --git a/today-remoting/build.gradle b/today-remoting/build.gradle index e3f031c..343edf2 100644 --- a/today-remoting/build.gradle +++ b/today-remoting/build.gradle @@ -10,8 +10,11 @@ dependencies { testImplementation(project(":today-remoting-transport-local")) + testImplementation(project(":today-remoting-transport-tcp")) + testImplementation 'io.projectreactor:reactor-test' testImplementation 'org.awaitility:awaitility' + testImplementation 'com.netflix.concurrency-limits:concurrency-limits-core:0.3.6' testFixturesApi "cn.taketoday:today-core" testFixturesApi 'org.assertj:assertj-core' diff --git a/today-remoting/src/main/java/infra/remoting/ChannelAcceptor.java b/today-remoting/src/main/java/infra/remoting/ChannelAcceptor.java index 27b19b5..e40daa8 100644 --- a/today-remoting/src/main/java/infra/remoting/ChannelAcceptor.java +++ b/today-remoting/src/main/java/infra/remoting/ChannelAcceptor.java @@ -38,20 +38,20 @@ public interface ChannelAcceptor { * * @param setup the {@code setup} received from a client in a server scenario, or in a client * scenario this is the setup about to be sent to the server. - * @param sendingSocket socket for sending requests to the remote peer. + * @param channel socket for sending requests to the remote peer. * @return {@code Channel} to accept requests with. * @throws SetupException If the acceptor needs to reject the setup of this socket. */ - Mono accept(ConnectionSetupPayload setup, Channel sendingSocket); + Mono accept(ConnectionSetupPayload setup, Channel channel); /** - * Create a {@code SocketAcceptor} that handles requests with the given {@code Channel}. + * Create a {@code ChannelAcceptor} that handles requests with the given {@code Channel}. */ static ChannelAcceptor with(Channel channel) { return (setup, sendingChannel) -> Mono.just(channel); } - /** Create a {@code SocketAcceptor} for fire-and-forget interactions with the given handler. */ + /** Create a {@code ChannelAcceptor} for fire-and-forget interactions with the given handler. */ static ChannelAcceptor forFireAndForget(Function> handler) { return with( new Channel() { @@ -62,7 +62,7 @@ public Mono fireAndForget(Payload payload) { }); } - /** Create a {@code SocketAcceptor} for request-response interactions with the given handler. */ + /** Create a {@code ChannelAcceptor} for request-response interactions with the given handler. */ static ChannelAcceptor forRequestResponse(Function> handler) { return with( new Channel() { @@ -73,7 +73,7 @@ public Mono requestResponse(Payload payload) { }); } - /** Create a {@code SocketAcceptor} for request-stream interactions with the given handler. */ + /** Create a {@code ChannelAcceptor} for request-stream interactions with the given handler. */ static ChannelAcceptor forRequestStream(Function> handler) { return with( new Channel() { @@ -84,7 +84,7 @@ public Flux requestStream(Payload payload) { }); } - /** Create a {@code SocketAcceptor} for request-channel interactions with the given handler. */ + /** Create a {@code ChannelAcceptor} for request-channel interactions with the given handler. */ static ChannelAcceptor forRequestChannel(Function, Flux> handler) { return with( new Channel() { diff --git a/today-remoting/src/main/java/infra/remoting/core/ChannelConnector.java b/today-remoting/src/main/java/infra/remoting/core/ChannelConnector.java index 53dc575..67b3c8c 100644 --- a/today-remoting/src/main/java/infra/remoting/core/ChannelConnector.java +++ b/today-remoting/src/main/java/infra/remoting/core/ChannelConnector.java @@ -33,10 +33,10 @@ import infra.remoting.frame.decoder.PayloadDecoder; import infra.remoting.keepalive.KeepAliveHandler; import infra.remoting.lease.TrackingLeaseSender; -import infra.remoting.plugins.ConnectionInterceptor; +import infra.remoting.plugins.ConnectionDecorator; import infra.remoting.plugins.InitializingInterceptorRegistry; import infra.remoting.plugins.InterceptorRegistry; -import infra.remoting.plugins.RateLimitInterceptor; +import infra.remoting.plugins.RateLimitDecorator; import infra.remoting.resume.ClientChannelSession; import infra.remoting.resume.ResumableDuplexConnection; import infra.remoting.resume.ResumableFramesStore; @@ -118,28 +118,6 @@ public class ChannelConnector { private ChannelConnector() { } - /** - * Static factory method to create an {@code ChannelConnector} instance and customize default - * settings before connecting. To connect only, use {@link #connectWith(ClientTransport)}. - */ - public static ChannelConnector create() { - return new ChannelConnector(); - } - - /** - * Static factory method to connect with default settings, effectively a shortcut for: - * - *

    -   * ChannelConnector.create().connect(transport);
    -   * 
    - * - * @param transport the transport of choice to connect with - * @return a {@code Mono} with the connected Channel - */ - public static Mono connectWith(ClientTransport transport) { - return ChannelConnector.create().connect(() -> transport); - } - /** * Provide a {@code Mono} from which to obtain the {@code Payload} for the initial SETUP frame. * Data and metadata should be formatted according to the MIME types specified via {@link @@ -256,7 +234,7 @@ public ChannelConnector keepAlive(Duration interval, Duration maxLifeTime) { * * @param configurer a configurer to customize interception with. * @return the same instance for method chaining - * @see RateLimitInterceptor + * @see RateLimitDecorator */ public ChannelConnector interceptors(Consumer configurer) { configurer.accept(this.interceptors); @@ -300,7 +278,7 @@ public ChannelConnector interceptors(Consumer configurer) { * @param acceptor the acceptor to use for responding to server requests * @return the same instance for method chaining */ - public ChannelConnector acceptor(ChannelAcceptor acceptor) { + public ChannelConnector acceptor(@Nullable ChannelAcceptor acceptor) { this.acceptor = acceptor; return this; } @@ -537,7 +515,7 @@ public Mono connect(Supplier transportSupplier) { return ct; }) .flatMap(transport -> transport.connect()) - .map(sourceConnection -> interceptors.initConnection(ConnectionInterceptor.Type.SOURCE, sourceConnection)) + .map(sourceConnection -> interceptors.initConnection(ConnectionDecorator.Type.SOURCE, sourceConnection)) .map(con -> LoggingDuplexConnection.wrapIfEnabled(con)); return connectionMono @@ -652,4 +630,27 @@ public Mono connect(Supplier transportSupplier) { } }); } + + /** + * Static factory method to create an {@code ChannelConnector} instance and customize default + * settings before connecting. To connect only, use {@link #connectWith(ClientTransport)}. + */ + public static ChannelConnector create() { + return new ChannelConnector(); + } + + /** + * Static factory method to connect with default settings, effectively a shortcut for: + * + *
    {@code
    +   * ChannelConnector.create().connect(transport);
    +   * }
    + * + * @param transport the transport of choice to connect with + * @return a {@code Mono} with the connected Channel + */ + public static Mono connectWith(ClientTransport transport) { + return ChannelConnector.create().connect(() -> transport); + } + } diff --git a/today-remoting/src/main/java/infra/remoting/core/ClientServerInputMultiplexer.java b/today-remoting/src/main/java/infra/remoting/core/ClientServerInputMultiplexer.java index 1bfca28..5c8e0de 100644 --- a/today-remoting/src/main/java/infra/remoting/core/ClientServerInputMultiplexer.java +++ b/today-remoting/src/main/java/infra/remoting/core/ClientServerInputMultiplexer.java @@ -26,7 +26,7 @@ import infra.remoting.DuplexConnection; import infra.remoting.ProtocolErrorException; import infra.remoting.frame.FrameHeaderCodec; -import infra.remoting.plugins.ConnectionInterceptor.Type; +import infra.remoting.plugins.ConnectionDecorator.Type; import infra.remoting.plugins.InitializingInterceptorRegistry; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufAllocator; diff --git a/today-remoting/src/main/java/infra/remoting/core/FireAndForgetResponderSubscriber.java b/today-remoting/src/main/java/infra/remoting/core/FireAndForgetResponderSubscriber.java index 4e74534..a13dc2a 100644 --- a/today-remoting/src/main/java/infra/remoting/core/FireAndForgetResponderSubscriber.java +++ b/today-remoting/src/main/java/infra/remoting/core/FireAndForgetResponderSubscriber.java @@ -145,7 +145,7 @@ public void handleNext(ByteBuf followingFrame, boolean hasFollows, boolean isLas Payload payload; try { - payload = this.payloadDecoder.apply(frames); + payload = this.payloadDecoder.decode(frames); frames.release(); } catch (Throwable t) { diff --git a/today-remoting/src/main/java/infra/remoting/core/FragmentationUtils.java b/today-remoting/src/main/java/infra/remoting/core/FragmentationUtils.java index 775c825..cb95cea 100644 --- a/today-remoting/src/main/java/infra/remoting/core/FragmentationUtils.java +++ b/today-remoting/src/main/java/infra/remoting/core/FragmentationUtils.java @@ -37,9 +37,9 @@ class FragmentationUtils { static final int FRAME_OFFSET = // 9 bytes in total FrameLengthCodec.FRAME_LENGTH_SIZE // includes encoded frame length bytes size + FrameHeaderCodec.size(); // includes encoded frame headers info bytes size + static final int FRAME_OFFSET_WITH_METADATA = // 12 bytes in total - FRAME_OFFSET - + FrameLengthCodec.FRAME_LENGTH_SIZE; // include encoded metadata length bytes size + FRAME_OFFSET + FrameLengthCodec.FRAME_LENGTH_SIZE; // include encoded metadata length bytes size static final int FRAME_OFFSET_WITH_INITIAL_REQUEST_N = // 13 bytes in total FRAME_OFFSET + Integer.BYTES; // includes extra space for initialRequestN bytes size @@ -47,36 +47,24 @@ class FragmentationUtils { FRAME_OFFSET_WITH_METADATA + Integer.BYTES; // includes extra space for initialRequestN bytes size - static boolean isFragmentable( - int mtu, ByteBuf data, @Nullable ByteBuf metadata, boolean hasInitialRequestN) { + static boolean isFragmentable(int mtu, ByteBuf data, @Nullable ByteBuf metadata, boolean hasInitialRequestN) { if (mtu == 0) { return false; } if (metadata != null) { - int remaining = - mtu - - (hasInitialRequestN - ? FRAME_OFFSET_WITH_METADATA_AND_INITIAL_REQUEST_N - : FRAME_OFFSET_WITH_METADATA); + int remaining = mtu - (hasInitialRequestN + ? FRAME_OFFSET_WITH_METADATA_AND_INITIAL_REQUEST_N + : FRAME_OFFSET_WITH_METADATA); return (metadata.readableBytes() + data.readableBytes()) > remaining; } - else { - int remaining = - mtu - (hasInitialRequestN ? FRAME_OFFSET_WITH_INITIAL_REQUEST_N : FRAME_OFFSET); - - return data.readableBytes() > remaining; - } + int remaining = mtu - (hasInitialRequestN ? FRAME_OFFSET_WITH_INITIAL_REQUEST_N : FRAME_OFFSET); + return data.readableBytes() > remaining; } - static ByteBuf encodeFollowsFragment( - ByteBufAllocator allocator, - int mtu, - int streamId, - boolean complete, - ByteBuf metadata, - ByteBuf data) { + static ByteBuf encodeFollowsFragment(ByteBufAllocator allocator, + int mtu, int streamId, boolean complete, ByteBuf metadata, ByteBuf data) { // subtract the header bytes + frame length size int remaining = mtu - FRAME_OFFSET; @@ -108,14 +96,8 @@ static ByteBuf encodeFollowsFragment( allocator, streamId, follows, (!follows && complete), true, metadataFragment, dataFragment); } - static ByteBuf encodeFirstFragment( - ByteBufAllocator allocator, - int mtu, - FrameType frameType, - int streamId, - boolean hasMetadata, - ByteBuf metadata, - ByteBuf data) { + static ByteBuf encodeFirstFragment(ByteBufAllocator allocator, int mtu, + FrameType frameType, int streamId, boolean hasMetadata, ByteBuf metadata, ByteBuf data) { // subtract the header bytes + frame length size int remaining = mtu - FRAME_OFFSET; @@ -144,37 +126,24 @@ static ByteBuf encodeFirstFragment( throw e; } - switch (frameType) { - case REQUEST_FNF: - return RequestFireAndForgetFrameCodec.encode( - allocator, streamId, true, metadataFragment, dataFragment); - case REQUEST_RESPONSE: - return RequestResponseFrameCodec.encode( - allocator, streamId, true, metadataFragment, dataFragment); + return switch (frameType) { + case REQUEST_FNF -> RequestFireAndForgetFrameCodec.encode( + allocator, streamId, true, metadataFragment, dataFragment); + case REQUEST_RESPONSE -> RequestResponseFrameCodec.encode( + allocator, streamId, true, metadataFragment, dataFragment); // Payload and synthetic types from the responder side - case PAYLOAD: - return PayloadFrameCodec.encode( - allocator, streamId, true, false, false, metadataFragment, dataFragment); - case NEXT: - // see https://github.com/today-tech/today-cloud/blob/master/today-remoting/Protocol.md#handling-the-unexpected - // point 7 - case NEXT_COMPLETE: - return PayloadFrameCodec.encode( - allocator, streamId, true, false, true, metadataFragment, dataFragment); - default: - throw new IllegalStateException("unsupported fragment type: " + frameType); - } + case PAYLOAD -> PayloadFrameCodec.encode( + allocator, streamId, true, false, false, metadataFragment, dataFragment); + // see https://github.com/today-tech/today-cloud/blob/master/today-remoting/Protocol.md#handling-the-unexpected + // point 7 + case NEXT, NEXT_COMPLETE -> PayloadFrameCodec.encode( + allocator, streamId, true, false, true, metadataFragment, dataFragment); + default -> throw new IllegalStateException("unsupported fragment type: " + frameType); + }; } - static ByteBuf encodeFirstFragment( - ByteBufAllocator allocator, - int mtu, - long initialRequestN, - FrameType frameType, - int streamId, - boolean hasMetadata, - ByteBuf metadata, - ByteBuf data) { + static ByteBuf encodeFirstFragment(ByteBufAllocator allocator, int mtu, long initialRequestN, + FrameType frameType, int streamId, boolean hasMetadata, ByteBuf metadata, ByteBuf data) { // subtract the header bytes + frame length bytes + initial requestN bytes int remaining = mtu - FRAME_OFFSET_WITH_INITIAL_REQUEST_N; @@ -203,25 +172,20 @@ static ByteBuf encodeFirstFragment( throw e; } - switch (frameType) { + return switch (frameType) { // Requester Side - case REQUEST_STREAM: - return RequestStreamFrameCodec.encode( - allocator, streamId, true, initialRequestN, metadataFragment, dataFragment); - case REQUEST_CHANNEL: - return RequestChannelFrameCodec.encode( - allocator, streamId, true, false, initialRequestN, metadataFragment, dataFragment); - default: - throw new IllegalStateException("unsupported fragment type: " + frameType); - } + case REQUEST_STREAM -> RequestStreamFrameCodec.encode( + allocator, streamId, true, initialRequestN, metadataFragment, dataFragment); + case REQUEST_CHANNEL -> RequestChannelFrameCodec.encode( + allocator, streamId, true, false, initialRequestN, metadataFragment, dataFragment); + default -> throw new IllegalStateException("unsupported fragment type: " + frameType); + }; } static int assertMtu(int mtu) { if (mtu > 0 && mtu < MIN_MTU_SIZE || mtu < 0) { - String msg = - String.format( - "The smallest allowed mtu size is %d bytes, provided: %d", MIN_MTU_SIZE, mtu); - throw new IllegalArgumentException(msg); + throw new IllegalArgumentException("The smallest allowed mtu size is %d bytes, provided: %d" + .formatted(MIN_MTU_SIZE, mtu)); } else { return mtu; diff --git a/today-remoting/src/main/java/infra/remoting/core/ReassemblyUtils.java b/today-remoting/src/main/java/infra/remoting/core/ReassemblyUtils.java index e563238..633c9f3 100644 --- a/today-remoting/src/main/java/infra/remoting/core/ReassemblyUtils.java +++ b/today-remoting/src/main/java/infra/remoting/core/ReassemblyUtils.java @@ -84,7 +84,7 @@ static void handleNextSupport( if (!hasFollows && !isReassembling(state)) { Payload payload; try { - payload = payloadDecoder.apply(frame); + payload = payloadDecoder.decode(frame); } catch (Throwable t) { // sends cancel frame to prevent any further frames @@ -145,7 +145,7 @@ static void handleNextSupport( Payload payload; try { - payload = payloadDecoder.apply(frames); + payload = payloadDecoder.decode(frames); frames.release(); } catch (Throwable t) { diff --git a/today-remoting/src/main/java/infra/remoting/core/RemotingServer.java b/today-remoting/src/main/java/infra/remoting/core/RemotingServer.java index 982f4dd..683e588 100644 --- a/today-remoting/src/main/java/infra/remoting/core/RemotingServer.java +++ b/today-remoting/src/main/java/infra/remoting/core/RemotingServer.java @@ -35,10 +35,10 @@ import infra.remoting.frame.SetupFrameCodec; import infra.remoting.frame.decoder.PayloadDecoder; import infra.remoting.lease.TrackingLeaseSender; -import infra.remoting.plugins.ConnectionInterceptor; +import infra.remoting.plugins.ConnectionDecorator; import infra.remoting.plugins.InitializingInterceptorRegistry; import infra.remoting.plugins.InterceptorRegistry; -import infra.remoting.plugins.RateLimitInterceptor; +import infra.remoting.plugins.RateLimitDecorator; import infra.remoting.resume.SessionManager; import infra.remoting.transport.ConnectionAcceptor; import infra.remoting.transport.ServerTransport; @@ -59,7 +59,7 @@ * *
    {@code
      * CloseableChannel closeable =
    - *         RemotingServer.create(SocketAcceptor.with(new Channel() {...}))
    + *         RemotingServer.create(ChannelAcceptor.with(new Channel() {...}))
      *                 .bind(TcpServerTransport.create("localhost", 7000))
      *                 .block();
      * }
    @@ -94,7 +94,7 @@ public static RemotingServer create() { /** * Static factory method to create an {@code RemotingServer} instance with the given {@code - * SocketAcceptor}. Effectively a shortcut for: + * ChannelAcceptor}. Effectively a shortcut for: * *
        * RemotingServer.create().acceptor(...);
    @@ -123,7 +123,7 @@ public static RemotingServer create(ChannelAcceptor acceptor) {
        * 

    A shortcut to provide the handling Channel only: * *

    {@code
    -   * RemotingServer.create(SocketAcceptor.with(new Channel() {...}))
    +   * RemotingServer.create(ChannelAcceptor.with(new Channel() {...}))
        *         .bind(TcpServerTransport.create("localhost", 7000))
        *         .subscribe();
        * }
    @@ -131,7 +131,7 @@ public static RemotingServer create(ChannelAcceptor acceptor) { *

    A shortcut to handle request-response interactions only: * *

    {@code
    -   * RemotingServer.create(SocketAcceptor.forRequestResponse(payload -> ...))
    +   * RemotingServer.create(ChannelAcceptor.forRequestResponse(payload -> ...))
        *         .bind(TcpServerTransport.create("localhost", 7000))
        *         .subscribe();
        * }
    @@ -160,7 +160,7 @@ public RemotingServer acceptor(ChannelAcceptor acceptor) { * * @param configurer a configurer to customize interception with. * @return the same instance for method chaining - * @see RateLimitInterceptor + * @see RateLimitDecorator */ public RemotingServer interceptors(Consumer configurer) { configurer.accept(this.interceptors); @@ -196,7 +196,7 @@ public RemotingServer resume(Resume resume) { *

    Example usage: * *

    {@code
    -   * RemotingServer.create(SocketAcceptor.with(new Channel() {...}))
    +   * RemotingServer.create(ChannelAcceptor.with(new Channel() {...}))
        *         .lease(spec ->
        *            spec.sender(() -> Flux.interval(ofSeconds(1))
        *                                  .map(__ -> Lease.create(ofSeconds(1), 1)))
    @@ -353,7 +353,7 @@ public Mono accept(DuplexConnection connection) {
       }
     
       private Mono acceptor(ServerSetup serverSetup, DuplexConnection sourceConnection, int maxFrameLength) {
    -    final DuplexConnection interceptedConnection = interceptors.initConnection(ConnectionInterceptor.Type.SOURCE, sourceConnection);
    +    final DuplexConnection interceptedConnection = interceptors.initConnection(ConnectionDecorator.Type.SOURCE, sourceConnection);
         return serverSetup
                 .init(LoggingDuplexConnection.wrapIfEnabled(interceptedConnection))
                 .flatMap(tuple2 -> {
    diff --git a/today-remoting/src/main/java/infra/remoting/core/RequestChannelRequesterFlux.java b/today-remoting/src/main/java/infra/remoting/core/RequestChannelRequesterFlux.java
    index c2c53d4..ed6b912 100644
    --- a/today-remoting/src/main/java/infra/remoting/core/RequestChannelRequesterFlux.java
    +++ b/today-remoting/src/main/java/infra/remoting/core/RequestChannelRequesterFlux.java
    @@ -14,6 +14,7 @@
      * You should have received a copy of the GNU General Public License
      * along with this program.  If not, see [http://www.gnu.org/licenses/]
      */
    +
     package infra.remoting.core;
     
     import org.reactivestreams.Publisher;
    @@ -70,11 +71,7 @@
     import static infra.remoting.core.StateUtils.markTerminated;
     
     final class RequestChannelRequesterFlux extends Flux
    -        implements RequesterFrameHandler,
    -        LeasePermitHandler,
    -        CoreSubscriber,
    -        Subscription,
    -        Scannable {
    +        implements RequesterFrameHandler, LeasePermitHandler, CoreSubscriber, Subscription, Scannable {
     
       final ChannelSupport channel;
     
    diff --git a/today-remoting/src/main/java/infra/remoting/core/RequestChannelResponderSubscriber.java b/today-remoting/src/main/java/infra/remoting/core/RequestChannelResponderSubscriber.java
    index ca6dc26..a52f706 100644
    --- a/today-remoting/src/main/java/infra/remoting/core/RequestChannelResponderSubscriber.java
    +++ b/today-remoting/src/main/java/infra/remoting/core/RequestChannelResponderSubscriber.java
    @@ -14,6 +14,7 @@
      * You should have received a copy of the GNU General Public License
      * along with this program.  If not, see [http://www.gnu.org/licenses/]
      */
    +
     package infra.remoting.core;
     
     import org.reactivestreams.Subscription;
    @@ -22,9 +23,6 @@
     import java.util.concurrent.atomic.AtomicLongFieldUpdater;
     import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
     
    -import infra.lang.Nullable;
    -import infra.logging.Logger;
    -import infra.logging.LoggerFactory;
     import infra.remoting.Channel;
     import infra.remoting.DuplexConnection;
     import infra.remoting.Payload;
    @@ -34,8 +32,6 @@
     import infra.remoting.frame.FrameType;
     import infra.remoting.frame.PayloadFrameCodec;
     import infra.remoting.frame.RequestNFrameCodec;
    -import infra.remoting.frame.decoder.PayloadDecoder;
    -import infra.remoting.plugins.RequestInterceptor;
     import io.netty.buffer.ByteBuf;
     import io.netty.buffer.ByteBufAllocator;
     import io.netty.buffer.CompositeByteBuf;
    @@ -69,23 +65,15 @@
     import static infra.remoting.core.StateUtils.markTerminated;
     import static reactor.core.Exceptions.TERMINATED;
     
    -final class RequestChannelResponderSubscriber extends Flux
    -        implements ResponderFrameHandler, Subscription, CoreSubscriber {
    -
    -  static final Logger logger = LoggerFactory.getLogger(RequestChannelResponderSubscriber.class);
    +final class RequestChannelResponderSubscriber extends Flux implements ResponderFrameHandler, Subscription, CoreSubscriber {
     
       final int streamId;
    -  final ByteBufAllocator allocator;
    -  final PayloadDecoder payloadDecoder;
    -  final int mtu;
    -  final int maxFrameLength;
    -  final int maxInboundPayloadSize;
    -  final ChannelSupport channelSupport;
    +
    +  final ChannelSupport channel;
    +
       final DuplexConnection connection;
    -  final long firstRequest;
     
    -  @Nullable
    -  final RequestInterceptor requestInterceptor;
    +  final long firstRequest;
     
       final Channel handler;
     
    @@ -111,44 +99,24 @@ final class RequestChannelResponderSubscriber extends Flux
       long requested;
       long produced;
     
    -  public RequestChannelResponderSubscriber(
    -          int streamId,
    -          long firstRequestN,
    -          ByteBuf firstFrame,
    -          ChannelSupport channelSupport,
    -          Channel handler) {
    +  public RequestChannelResponderSubscriber(int streamId, long firstRequestN,
    +          ByteBuf firstFrame, ChannelSupport channel, Channel handler) {
         this.streamId = streamId;
    -    this.allocator = channelSupport.getAllocator();
    -    this.mtu = channelSupport.getMtu();
    -    this.maxFrameLength = channelSupport.getMaxFrameLength();
    -    this.maxInboundPayloadSize = channelSupport.getMaxInboundPayloadSize();
    -    this.channelSupport = channelSupport;
    -    this.connection = channelSupport.getDuplexConnection();
    -    this.payloadDecoder = channelSupport.getPayloadDecoder();
    -    this.requestInterceptor = channelSupport.getRequestInterceptor();
    +    this.channel = channel;
    +    this.connection = channel.getDuplexConnection();
         this.handler = handler;
         this.firstRequest = firstRequestN;
     
    -    this.frames =
    -            ReassemblyUtils.addFollowingFrame(
    -                    allocator.compositeBuffer(), firstFrame, true, maxInboundPayloadSize);
    +    this.frames = ReassemblyUtils.addFollowingFrame(
    +            channel.allocator.compositeBuffer(), firstFrame, true, channel.maxInboundPayloadSize);
         STATE.lazySet(this, REASSEMBLING_FLAG);
       }
     
    -  public RequestChannelResponderSubscriber(
    -          int streamId,
    -          long firstRequestN,
    -          Payload firstPayload,
    -          ChannelSupport channelSupport) {
    +  public RequestChannelResponderSubscriber(int streamId, long firstRequestN,
    +          Payload firstPayload, ChannelSupport channel) {
         this.streamId = streamId;
    -    this.allocator = channelSupport.getAllocator();
    -    this.mtu = channelSupport.getMtu();
    -    this.maxFrameLength = channelSupport.getMaxFrameLength();
    -    this.maxInboundPayloadSize = channelSupport.getMaxInboundPayloadSize();
    -    this.channelSupport = channelSupport;
    -    this.connection = channelSupport.getDuplexConnection();
    -    this.payloadDecoder = channelSupport.getPayloadDecoder();
    -    this.requestInterceptor = channelSupport.getRequestInterceptor();
    +    this.channel = channel;
    +    this.connection = channel.getDuplexConnection();
         this.firstRequest = firstRequestN;
         this.firstPayload = firstPayload;
     
    @@ -168,16 +136,13 @@ public void subscribe(CoreSubscriber actual) {
             Operators.error(actual, t);
           }
           else {
    -        Operators.error(
    -                actual,
    -                new CancellationException("RequestChannelSubscriber has already been terminated"));
    +        Operators.error(actual, new CancellationException("RequestChannelSubscriber has already been terminated"));
           }
           return;
         }
     
         if (isSubscribed(previousState)) {
    -      Operators.error(
    -              actual, new IllegalStateException("RequestChannelSubscriber allows only one Subscriber"));
    +      Operators.error(actual, new IllegalStateException("RequestChannelSubscriber allows only one Subscriber"));
           return;
         }
     
    @@ -259,7 +224,7 @@ public void request(long n) {
           if (isFirstFrameSent(previousState)
                   && !isMaxAllowedRequestN(StateUtils.extractRequestN(previousState))) {
             final int streamId = this.streamId;
    -        final ByteBuf requestNFrame = RequestNFrameCodec.encode(this.allocator, streamId, n);
    +        final ByteBuf requestNFrame = RequestNFrameCodec.encode(channel.allocator, streamId, n);
             this.connection.sendFrame(streamId, requestNFrame);
           }
           return;
    @@ -305,7 +270,7 @@ else if (this.inboundDone) {
         long requestN = StateUtils.extractRequestN(previousState);
         if (isMaxAllowedRequestN(requestN)) {
           final int streamId = this.streamId;
    -      final ByteBuf requestNFrame = RequestNFrameCodec.encode(allocator, streamId, requestN);
    +      final ByteBuf requestNFrame = RequestNFrameCodec.encode(channel.allocator, streamId, requestN);
           this.connection.sendFrame(streamId, requestNFrame);
         }
         else {
    @@ -313,7 +278,7 @@ else if (this.inboundDone) {
           if (firstRequestN > 0) {
             final int streamId = this.streamId;
             final ByteBuf requestNFrame =
    -                RequestNFrameCodec.encode(this.allocator, streamId, firstRequestN);
    +                RequestNFrameCodec.encode(channel.allocator, streamId, firstRequestN);
             this.connection.sendFrame(streamId, requestNFrame);
           }
         }
    @@ -338,14 +303,14 @@ public void cancel() {
     
         final boolean isOutboundTerminated = isOutboundTerminated(previousState);
         if (isOutboundTerminated) {
    -      this.channelSupport.remove(streamId, this);
    +      channel.remove(streamId, this);
         }
     
    -    final ByteBuf cancelFrame = CancelFrameCodec.encode(this.allocator, streamId);
    +    final ByteBuf cancelFrame = CancelFrameCodec.encode(channel.allocator, streamId);
         this.connection.sendFrame(streamId, cancelFrame);
     
         if (isOutboundTerminated) {
    -      final RequestInterceptor interceptor = requestInterceptor;
    +      final var interceptor = channel.requestInterceptor;
           if (interceptor != null) {
             interceptor.onTerminate(streamId, FrameType.REQUEST_CHANNEL, null);
           }
    @@ -360,7 +325,7 @@ public final void handleCancel() {
           // and fragmentation of the first frame was cancelled before
           lazyTerminate(STATE, this);
     
    -      this.channelSupport.remove(this.streamId, this);
    +      this.channel.remove(this.streamId, this);
     
           final CompositeByteBuf frames = this.frames;
           if (frames != null) {
    @@ -373,7 +338,7 @@ public final void handleCancel() {
             firstPayload.release();
           }
     
    -      final RequestInterceptor interceptor = this.requestInterceptor;
    +      final var interceptor = channel.requestInterceptor;
           if (interceptor != null) {
             interceptor.onCancel(this.streamId, FrameType.REQUEST_CHANNEL);
           }
    @@ -385,7 +350,7 @@ public final void handleCancel() {
           return;
         }
     
    -    final RequestInterceptor interceptor = this.requestInterceptor;
    +    final var interceptor = channel.requestInterceptor;
         if (interceptor != null) {
           interceptor.onCancel(this.streamId, FrameType.REQUEST_CHANNEL);
         }
    @@ -400,7 +365,7 @@ final long tryTerminate(boolean isFromInbound) {
           return previousState;
         }
     
    -    this.channelSupport.remove(this.streamId, this);
    +    this.channel.remove(this.streamId, this);
     
         if (isReassembling(previousState)) {
           final CompositeByteBuf frames = this.frames;
    @@ -475,12 +440,12 @@ final void handlePayload(Payload p) {
               return;
             }
     
    -        this.channelSupport.remove(this.streamId, this);
    +        this.channel.remove(this.streamId, this);
     
             this.connection.sendFrame(
                     streamId,
                     ErrorFrameCodec.encode(
    -                        this.allocator, streamId, new CanceledException(cause.getMessage())));
    +                        channel.allocator, streamId, new CanceledException(cause.getMessage())));
     
             if (!isSubscribed(previousState)) {
               final Payload firstPayload = this.firstPayload;
    @@ -500,7 +465,7 @@ else if (isFirstFrameSent(previousState) && !isInboundTerminated(previousState))
             // needs for disconnected upstream and downstream case
             this.outboundSubscription.cancel();
     
    -        final RequestInterceptor interceptor = requestInterceptor;
    +        final var interceptor = channel.requestInterceptor;
             if (interceptor != null) {
               interceptor.onTerminate(this.streamId, FrameType.REQUEST_CHANNEL, cause);
             }
    @@ -531,7 +496,7 @@ public final void handleError(Throwable t) {
           return;
         }
     
    -    this.channelSupport.remove(this.streamId, this);
    +    this.channel.remove(this.streamId, this);
     
         if (isReassembling(previousState)) {
           final CompositeByteBuf frames = this.frames;
    @@ -557,7 +522,7 @@ else if (isFirstFrameSent(previousState) && !isInboundTerminated(previousState))
         // needs for disconnected upstream and downstream case
         this.outboundSubscription.cancel();
     
    -    final RequestInterceptor interceptor = requestInterceptor;
    +    final var interceptor = channel.requestInterceptor;
         if (interceptor != null) {
           interceptor.onTerminate(this.streamId, FrameType.REQUEST_CHANNEL, t);
         }
    @@ -575,7 +540,7 @@ public void handleComplete() {
     
         final boolean isOutboundTerminated = isOutboundTerminated(previousState);
         if (isOutboundTerminated) {
    -      this.channelSupport.remove(this.streamId, this);
    +      this.channel.remove(this.streamId, this);
         }
     
         if (isFirstFrameSent(previousState)) {
    @@ -583,7 +548,7 @@ public void handleComplete() {
         }
     
         if (isOutboundTerminated) {
    -      final RequestInterceptor interceptor = this.requestInterceptor;
    +      final var interceptor = channel.requestInterceptor;
           if (interceptor != null) {
             interceptor.onTerminate(this.streamId, FrameType.REQUEST_CHANNEL, null);
           }
    @@ -600,7 +565,7 @@ public void handleNext(ByteBuf frame, boolean hasFollows, boolean isLastPayload)
         if (!hasFollows && !isReassembling(state)) {
           Payload payload;
           try {
    -        payload = this.payloadDecoder.apply(frame);
    +        payload = channel.payloadDecoder.decode(frame);
           }
           catch (Throwable t) {
             long previousState = this.tryTerminate(true);
    @@ -609,7 +574,7 @@ public void handleNext(ByteBuf frame, boolean hasFollows, boolean isLastPayload)
               return;
             }
             else if (isOutboundTerminated(previousState)) {
    -          final RequestInterceptor interceptor = this.requestInterceptor;
    +          final var interceptor = channel.requestInterceptor;
               if (interceptor != null) {
                 interceptor.onTerminate(this.streamId, FrameType.REQUEST_CHANNEL, t);
               }
    @@ -622,10 +587,10 @@ else if (isOutboundTerminated(previousState)) {
             // send error to terminate interaction
             final int streamId = this.streamId;
             final ByteBuf errorFrame =
    -                ErrorFrameCodec.encode(this.allocator, streamId, new CanceledException(t.getMessage()));
    +                ErrorFrameCodec.encode(channel.allocator, streamId, new CanceledException(t.getMessage()));
             this.connection.sendFrame(streamId, errorFrame);
     
    -        final RequestInterceptor interceptor = requestInterceptor;
    +        final var interceptor = channel.requestInterceptor;
             if (interceptor != null) {
               interceptor.onTerminate(streamId, FrameType.REQUEST_CHANNEL, t);
             }
    @@ -641,9 +606,8 @@ else if (isOutboundTerminated(previousState)) {
     
         CompositeByteBuf frames = this.frames;
         if (frames == null) {
    -      frames =
    -              ReassemblyUtils.addFollowingFrame(
    -                      this.allocator.compositeBuffer(), frame, hasFollows, this.maxInboundPayloadSize);
    +      frames = ReassemblyUtils.addFollowingFrame(
    +              channel.allocator.compositeBuffer(), frame, hasFollows, channel.maxInboundPayloadSize);
           this.frames = frames;
     
           long previousState = markReassembling(STATE, this);
    @@ -655,9 +619,7 @@ else if (isOutboundTerminated(previousState)) {
         }
         else {
           try {
    -        frames =
    -                ReassemblyUtils.addFollowingFrame(
    -                        frames, frame, hasFollows, this.maxInboundPayloadSize);
    +        frames = ReassemblyUtils.addFollowingFrame(frames, frame, hasFollows, channel.maxInboundPayloadSize);
           }
           catch (IllegalStateException e) {
             if (isTerminated(this.state)) {
    @@ -670,7 +632,7 @@ else if (isOutboundTerminated(previousState)) {
               return;
             }
             else if (isOutboundTerminated(previousState)) {
    -          final RequestInterceptor interceptor = this.requestInterceptor;
    +          final var interceptor = channel.requestInterceptor;
               if (interceptor != null) {
                 interceptor.onTerminate(this.streamId, FrameType.REQUEST_CHANNEL, e);
               }
    @@ -682,14 +644,11 @@ else if (isOutboundTerminated(previousState)) {
             this.outboundDone = true;
             // send error to terminate interaction
             final int streamId = this.streamId;
    -        final ByteBuf errorFrame =
    -                ErrorFrameCodec.encode(
    -                        this.allocator,
    -                        streamId,
    -                        new CanceledException("Failed to reassemble payload. Cause: " + e.getMessage()));
    -        this.connection.sendFrame(streamId, errorFrame);
    +        final ByteBuf errorFrame = ErrorFrameCodec.encode(channel.allocator, streamId,
    +                new CanceledException("Failed to reassemble payload. Cause: " + e.getMessage()));
    +        connection.sendFrame(streamId, errorFrame);
     
    -        final RequestInterceptor interceptor = this.requestInterceptor;
    +        final var interceptor = channel.requestInterceptor;
             if (interceptor != null) {
               interceptor.onTerminate(streamId, FrameType.REQUEST_CHANNEL, e);
             }
    @@ -708,19 +667,19 @@ else if (isOutboundTerminated(previousState)) {
     
           Payload payload;
           try {
    -        payload = this.payloadDecoder.apply(frames);
    +        payload = channel.payloadDecoder.decode(frames);
             frames.release();
           }
           catch (Throwable t) {
             ReferenceCountUtil.safeRelease(frames);
     
    -        previousState = this.tryTerminate(true);
    +        previousState = tryTerminate(true);
             if (isTerminated(previousState)) {
               Operators.onErrorDropped(t, this.inboundSubscriber.currentContext());
               return;
             }
             else if (isOutboundTerminated(previousState)) {
    -          final RequestInterceptor interceptor = this.requestInterceptor;
    +          final var interceptor = channel.requestInterceptor;
               if (interceptor != null) {
                 interceptor.onTerminate(this.streamId, FrameType.REQUEST_CHANNEL, t);
               }
    @@ -731,14 +690,11 @@ else if (isOutboundTerminated(previousState)) {
     
             // send error to terminate interaction
             final int streamId = this.streamId;
    -        final ByteBuf errorFrame =
    -                ErrorFrameCodec.encode(
    -                        this.allocator,
    -                        streamId,
    -                        new CanceledException("Failed to reassemble payload. Cause: " + t.getMessage()));
    +        final ByteBuf errorFrame = ErrorFrameCodec.encode(channel.allocator, streamId,
    +                new CanceledException("Failed to reassemble payload. Cause: " + t.getMessage()));
             this.connection.sendFrame(streamId, errorFrame);
     
    -        final RequestInterceptor interceptor = requestInterceptor;
    +        final var interceptor = channel.requestInterceptor;
             if (interceptor != null) {
               interceptor.onTerminate(streamId, FrameType.REQUEST_CHANNEL, t);
             }
    @@ -769,12 +725,12 @@ public void onNext(Payload p) {
         }
     
         final int streamId = this.streamId;
    -    final DuplexConnection connection = this.connection;
    -    final ByteBufAllocator allocator = this.allocator;
    +    final DuplexConnection connection = channel.connection;
    +    final ByteBufAllocator allocator = channel.allocator;
     
    -    final int mtu = this.mtu;
    +    final int mtu = channel.mtu;
         try {
    -      if (!isValid(mtu, this.maxFrameLength, p, false)) {
    +      if (!isValid(mtu, channel.maxFrameLength, p, false)) {
             p.release();
     
             // FIXME: must be scheduled on the connection event-loop to achieve serial
    @@ -783,16 +739,16 @@ public void onNext(Payload p) {
             if (isTerminated(previousState)) {
               Operators.onErrorDropped(
                       new IllegalArgumentException(
    -                          String.format(INVALID_PAYLOAD_ERROR_MESSAGE, this.maxFrameLength)),
    +                          String.format(INVALID_PAYLOAD_ERROR_MESSAGE, channel.maxFrameLength)),
                       this.inboundSubscriber.currentContext());
               return;
             }
             else if (isOutboundTerminated(previousState)) {
               final IllegalArgumentException e =
                       new IllegalArgumentException(
    -                          String.format(INVALID_PAYLOAD_ERROR_MESSAGE, this.maxFrameLength));
    +                          String.format(INVALID_PAYLOAD_ERROR_MESSAGE, channel.maxFrameLength));
     
    -          final RequestInterceptor interceptor = this.requestInterceptor;
    +          final var interceptor = channel.requestInterceptor;
               if (interceptor != null) {
                 interceptor.onTerminate(streamId, FrameType.REQUEST_CHANNEL, e);
               }
    @@ -803,11 +759,11 @@ else if (isOutboundTerminated(previousState)) {
     
             final CanceledException e =
                     new CanceledException(
    -                        String.format(INVALID_PAYLOAD_ERROR_MESSAGE, this.maxFrameLength));
    +                        String.format(INVALID_PAYLOAD_ERROR_MESSAGE, channel.maxFrameLength));
             final ByteBuf errorFrame = ErrorFrameCodec.encode(allocator, streamId, e);
             connection.sendFrame(streamId, errorFrame);
     
    -        final RequestInterceptor interceptor = this.requestInterceptor;
    +        final var interceptor = channel.requestInterceptor;
             if (interceptor != null) {
               interceptor.onTerminate(streamId, FrameType.REQUEST_CHANNEL, e);
             }
    @@ -824,7 +780,7 @@ else if (isOutboundTerminated(previousState)) {
             return;
           }
           else if (isOutboundTerminated(previousState)) {
    -        final RequestInterceptor interceptor = this.requestInterceptor;
    +        final var interceptor = channel.requestInterceptor;
             if (interceptor != null) {
               interceptor.onTerminate(streamId, FrameType.REQUEST_CHANNEL, e);
             }
    @@ -833,14 +789,11 @@ else if (isOutboundTerminated(previousState)) {
             return;
           }
     
    -      final ByteBuf errorFrame =
    -              ErrorFrameCodec.encode(
    -                      allocator,
    -                      streamId,
    -                      new CanceledException("Failed to validate payload. Cause:" + e.getMessage()));
    +      final ByteBuf errorFrame = ErrorFrameCodec.encode(allocator, streamId,
    +              new CanceledException("Failed to validate payload. Cause:" + e.getMessage()));
           connection.sendFrame(streamId, errorFrame);
     
    -      final RequestInterceptor interceptor = requestInterceptor;
    +      final var interceptor = channel.requestInterceptor;
           if (interceptor != null) {
             interceptor.onTerminate(streamId, FrameType.REQUEST_CHANNEL, e);
           }
    @@ -854,7 +807,7 @@ else if (isOutboundTerminated(previousState)) {
           // FIXME: must be scheduled on the connection event-loop to achieve serial
           //  behaviour on the inbound subscriber
           long previousState = this.tryTerminate(false);
    -      final RequestInterceptor interceptor = requestInterceptor;
    +      final var interceptor = channel.requestInterceptor;
           if (interceptor != null && !isTerminated(previousState)) {
             interceptor.onTerminate(streamId, FrameType.REQUEST_CHANNEL, t);
           }
    @@ -868,11 +821,8 @@ public void onError(Throwable t) {
           return;
         }
     
    -    boolean wasThrowableAdded =
    -            Exceptions.addThrowable(
    -                    INBOUND_ERROR,
    -                    this,
    -                    new CancellationException("Outbound has terminated with an error"));
    +    boolean wasThrowableAdded = Exceptions.addThrowable(INBOUND_ERROR, this,
    +            new CancellationException("Outbound has terminated with an error"));
         this.outboundDone = true;
     
         long previousState = markTerminated(STATE, this);
    @@ -883,7 +833,7 @@ public void onError(Throwable t) {
     
         final int streamId = this.streamId;
     
    -    this.channelSupport.remove(streamId, this);
    +    this.channel.remove(streamId, this);
     
         if (isReassembling(previousState)) {
           final CompositeByteBuf frames = this.frames;
    @@ -913,10 +863,10 @@ && isFirstFrameSent(previousState)
           }
         }
     
    -    final ByteBuf errorFrame = ErrorFrameCodec.encode(this.allocator, streamId, t);
    +    final ByteBuf errorFrame = ErrorFrameCodec.encode(channel.allocator, streamId, t);
         this.connection.sendFrame(streamId, errorFrame);
     
    -    final RequestInterceptor interceptor = this.requestInterceptor;
    +    final var interceptor = channel.requestInterceptor;
         if (interceptor != null) {
           interceptor.onTerminate(streamId, FrameType.REQUEST_CHANNEL, t);
         }
    @@ -939,14 +889,14 @@ public void onComplete() {
     
         final boolean isInboundTerminated = isInboundTerminated(previousState);
         if (isInboundTerminated) {
    -      this.channelSupport.remove(streamId, this);
    +      this.channel.remove(streamId, this);
         }
     
    -    final ByteBuf completeFrame = PayloadFrameCodec.encodeComplete(this.allocator, streamId);
    -    this.connection.sendFrame(streamId, completeFrame);
    +    final ByteBuf completeFrame = PayloadFrameCodec.encodeComplete(channel.allocator, streamId);
    +    connection.sendFrame(streamId, completeFrame);
     
         if (isInboundTerminated) {
    -      final RequestInterceptor interceptor = this.requestInterceptor;
    +      final var interceptor = channel.requestInterceptor;
           if (interceptor != null) {
             interceptor.onTerminate(streamId, FrameType.REQUEST_CHANNEL, null);
           }
    diff --git a/today-remoting/src/main/java/infra/remoting/core/RequestResponseResponderSubscriber.java b/today-remoting/src/main/java/infra/remoting/core/RequestResponseResponderSubscriber.java
    index fb7d5ac..894f223 100644
    --- a/today-remoting/src/main/java/infra/remoting/core/RequestResponseResponderSubscriber.java
    +++ b/today-remoting/src/main/java/infra/remoting/core/RequestResponseResponderSubscriber.java
    @@ -14,6 +14,7 @@
      * You should have received a copy of the GNU General Public License
      * along with this program.  If not, see [http://www.gnu.org/licenses/]
      */
    +
     package infra.remoting.core;
     
     import org.reactivestreams.Subscription;
    @@ -30,7 +31,6 @@
     import infra.remoting.frame.ErrorFrameCodec;
     import infra.remoting.frame.FrameType;
     import infra.remoting.frame.PayloadFrameCodec;
    -import infra.remoting.frame.decoder.PayloadDecoder;
     import infra.remoting.plugins.RequestInterceptor;
     import io.netty.buffer.ByteBuf;
     import io.netty.buffer.ByteBufAllocator;
    @@ -52,17 +52,10 @@ final class RequestResponseResponderSubscriber
       static final Logger logger = LoggerFactory.getLogger(RequestResponseResponderSubscriber.class);
     
       final int streamId;
    -  final ByteBufAllocator allocator;
    -  final PayloadDecoder payloadDecoder;
    -  final int mtu;
    -  final int maxFrameLength;
    -  final int maxInboundPayloadSize;
    -  final ChannelSupport channelSupport;
    -  final DuplexConnection connection;
    -  final Channel handler;
     
    -  @Nullable
    -  final RequestInterceptor requestInterceptor;
    +  final ChannelSupport channel;
    +
    +  final Channel handler;
     
       boolean done;
       CompositeByteBuf frames;
    @@ -72,39 +65,18 @@ final class RequestResponseResponderSubscriber
               AtomicReferenceFieldUpdater.newUpdater(
                       RequestResponseResponderSubscriber.class, Subscription.class, "s");
     
    -  public RequestResponseResponderSubscriber(
    -          int streamId,
    -          ByteBuf firstFrame,
    -          ChannelSupport channelSupport,
    -          Channel handler) {
    +  public RequestResponseResponderSubscriber(int streamId, ByteBuf firstFrame, ChannelSupport channel, Channel handler) {
         this.streamId = streamId;
    -    this.allocator = channelSupport.getAllocator();
    -    this.mtu = channelSupport.getMtu();
    -    this.maxFrameLength = channelSupport.getMaxFrameLength();
    -    this.maxInboundPayloadSize = channelSupport.getMaxInboundPayloadSize();
    -    this.channelSupport = channelSupport;
    -    this.connection = channelSupport.getDuplexConnection();
    -    this.payloadDecoder = channelSupport.getPayloadDecoder();
    -    this.requestInterceptor = channelSupport.getRequestInterceptor();
    +    this.channel = channel;
         this.handler = handler;
     
    -    this.frames =
    -            ReassemblyUtils.addFollowingFrame(
    -                    allocator.compositeBuffer(), firstFrame, true, maxInboundPayloadSize);
    +    this.frames = ReassemblyUtils.addFollowingFrame(
    +            channel.allocator.compositeBuffer(), firstFrame, true, channel.maxInboundPayloadSize);
       }
     
    -  public RequestResponseResponderSubscriber(
    -          int streamId, ChannelSupport channelSupport) {
    +  public RequestResponseResponderSubscriber(int streamId, ChannelSupport channel) {
         this.streamId = streamId;
    -    this.allocator = channelSupport.getAllocator();
    -    this.mtu = channelSupport.getMtu();
    -    this.maxFrameLength = channelSupport.getMaxFrameLength();
    -    this.maxInboundPayloadSize = channelSupport.getMaxInboundPayloadSize();
    -    this.channelSupport = channelSupport;
    -    this.connection = channelSupport.getDuplexConnection();
    -    this.requestInterceptor = channelSupport.getRequestInterceptor();
    -
    -    this.payloadDecoder = null;
    +    this.channel = channel;
         this.handler = null;
         this.frames = null;
       }
    @@ -138,38 +110,37 @@ public void onNext(@Nullable Payload p) {
         this.done = true;
     
         final int streamId = this.streamId;
    -    final DuplexConnection connection = this.connection;
    -    final ByteBufAllocator allocator = this.allocator;
    +    final ChannelSupport channel = this.channel;
    +    final DuplexConnection connection = channel.connection;
    +    final ByteBufAllocator allocator = channel.allocator;
     
    -    this.channelSupport.remove(streamId, this);
    +    channel.remove(streamId, this);
     
         if (p == null) {
           final ByteBuf completeFrame = PayloadFrameCodec.encodeComplete(allocator, streamId);
           connection.sendFrame(streamId, completeFrame);
     
    -      final RequestInterceptor requestInterceptor = this.requestInterceptor;
    -      if (requestInterceptor != null) {
    -        requestInterceptor.onTerminate(streamId, FrameType.REQUEST_RESPONSE, null);
    +      final RequestInterceptor interceptor = channel.requestInterceptor;
    +      if (interceptor != null) {
    +        interceptor.onTerminate(streamId, FrameType.REQUEST_RESPONSE, null);
           }
           return;
         }
     
    -    final int mtu = this.mtu;
    +    final int mtu = channel.mtu;
         try {
    -      if (!isValid(mtu, this.maxFrameLength, p, false)) {
    +      if (!isValid(mtu, channel.maxFrameLength, p, false)) {
             currentSubscription.cancel();
     
             p.release();
     
    -        final CanceledException e =
    -                new CanceledException(
    -                        String.format(INVALID_PAYLOAD_ERROR_MESSAGE, this.maxFrameLength));
    +        final CanceledException e = new CanceledException(String.format(INVALID_PAYLOAD_ERROR_MESSAGE, channel.maxFrameLength));
             final ByteBuf errorFrame = ErrorFrameCodec.encode(allocator, streamId, e);
             connection.sendFrame(streamId, errorFrame);
     
    -        final RequestInterceptor requestInterceptor = this.requestInterceptor;
    -        if (requestInterceptor != null) {
    -          requestInterceptor.onTerminate(streamId, FrameType.REQUEST_RESPONSE, e);
    +        final var interceptor = channel.requestInterceptor;
    +        if (interceptor != null) {
    +          interceptor.onTerminate(streamId, FrameType.REQUEST_RESPONSE, e);
             }
             return;
           }
    @@ -177,16 +148,13 @@ public void onNext(@Nullable Payload p) {
         catch (IllegalReferenceCountException e) {
           currentSubscription.cancel();
     
    -      final ByteBuf errorFrame =
    -              ErrorFrameCodec.encode(
    -                      allocator,
    -                      streamId,
    -                      new CanceledException("Failed to validate payload. Cause" + e.getMessage()));
    +      final ByteBuf errorFrame = ErrorFrameCodec.encode(allocator, streamId,
    +              new CanceledException("Failed to validate payload. Cause" + e.getMessage()));
           connection.sendFrame(streamId, errorFrame);
     
    -      final RequestInterceptor requestInterceptor = this.requestInterceptor;
    -      if (requestInterceptor != null) {
    -        requestInterceptor.onTerminate(streamId, FrameType.REQUEST_RESPONSE, e);
    +      final var interceptor = channel.requestInterceptor;
    +      if (interceptor != null) {
    +        interceptor.onTerminate(streamId, FrameType.REQUEST_RESPONSE, e);
           }
           return;
         }
    @@ -194,17 +162,17 @@ public void onNext(@Nullable Payload p) {
         try {
           sendReleasingPayload(streamId, FrameType.NEXT_COMPLETE, mtu, p, connection, allocator, false);
     
    -      final RequestInterceptor requestInterceptor = this.requestInterceptor;
    -      if (requestInterceptor != null) {
    -        requestInterceptor.onTerminate(streamId, FrameType.REQUEST_RESPONSE, null);
    +      final var interceptor = channel.requestInterceptor;
    +      if (interceptor != null) {
    +        interceptor.onTerminate(streamId, FrameType.REQUEST_RESPONSE, null);
           }
         }
         catch (Throwable t) {
           currentSubscription.cancel();
     
    -      final RequestInterceptor requestInterceptor = this.requestInterceptor;
    -      if (requestInterceptor != null) {
    -        requestInterceptor.onTerminate(streamId, FrameType.REQUEST_RESPONSE, t);
    +      final var interceptor = channel.requestInterceptor;
    +      if (interceptor != null) {
    +        interceptor.onTerminate(streamId, FrameType.REQUEST_RESPONSE, t);
           }
         }
       }
    @@ -226,15 +194,16 @@ public void onError(Throwable t) {
         this.done = true;
     
         final int streamId = this.streamId;
    +    final ChannelSupport channel = this.channel;
     
    -    this.channelSupport.remove(streamId, this);
    +    channel.remove(streamId, this);
     
    -    final ByteBuf errorFrame = ErrorFrameCodec.encode(this.allocator, streamId, t);
    -    this.connection.sendFrame(streamId, errorFrame);
    +    final ByteBuf errorFrame = ErrorFrameCodec.encode(channel.allocator, streamId, t);
    +    channel.connection.sendFrame(streamId, errorFrame);
     
    -    final RequestInterceptor requestInterceptor = this.requestInterceptor;
    -    if (requestInterceptor != null) {
    -      requestInterceptor.onTerminate(streamId, FrameType.REQUEST_RESPONSE, t);
    +    final var interceptor = channel.requestInterceptor;
    +    if (interceptor != null) {
    +      interceptor.onTerminate(streamId, FrameType.REQUEST_RESPONSE, t);
         }
       }
     
    @@ -250,13 +219,14 @@ public void handleCancel() {
           return;
         }
     
    +    final ChannelSupport channel = this.channel;
         if (currentSubscription == null) {
           // if subscription is null, it means that streams has not yet reassembled all the fragments
           // and fragmentation of the first frame was cancelled before
           S.lazySet(this, Operators.cancelledSubscription());
     
           final int streamId = this.streamId;
    -      this.channelSupport.remove(streamId, this);
    +      channel.remove(streamId, this);
     
           final CompositeByteBuf frames = this.frames;
           if (frames != null) {
    @@ -264,9 +234,9 @@ public void handleCancel() {
             frames.release();
           }
     
    -      final RequestInterceptor requestInterceptor = this.requestInterceptor;
    -      if (requestInterceptor != null) {
    -        requestInterceptor.onCancel(streamId, FrameType.REQUEST_RESPONSE);
    +      final var interceptor = channel.requestInterceptor;
    +      if (interceptor != null) {
    +        interceptor.onCancel(streamId, FrameType.REQUEST_RESPONSE);
           }
           return;
         }
    @@ -276,13 +246,13 @@ public void handleCancel() {
         }
     
         final int streamId = this.streamId;
    -    this.channelSupport.remove(streamId, this);
    +    channel.remove(streamId, this);
     
         currentSubscription.cancel();
     
    -    final RequestInterceptor requestInterceptor = this.requestInterceptor;
    -    if (requestInterceptor != null) {
    -      requestInterceptor.onCancel(streamId, FrameType.REQUEST_RESPONSE);
    +    final var interceptor = channel.requestInterceptor;
    +    if (interceptor != null) {
    +      interceptor.onCancel(streamId, FrameType.REQUEST_RESPONSE);
         }
       }
     
    @@ -293,13 +263,14 @@ public void handleNext(ByteBuf frame, boolean hasFollows, boolean isLastPayload)
           return;
         }
     
    +    final ChannelSupport channel = this.channel;
         try {
    -      ReassemblyUtils.addFollowingFrame(frames, frame, hasFollows, this.maxInboundPayloadSize);
    +      ReassemblyUtils.addFollowingFrame(frames, frame, hasFollows, channel.maxInboundPayloadSize);
         }
         catch (IllegalStateException t) {
           S.lazySet(this, Operators.cancelledSubscription());
     
    -      this.channelSupport.remove(this.streamId, this);
    +      channel.remove(this.streamId, this);
     
           this.frames = null;
           frames.release();
    @@ -308,16 +279,13 @@ public void handleNext(ByteBuf frame, boolean hasFollows, boolean isLastPayload)
     
           // sends error frame from the responder side to tell that something went wrong
           final int streamId = this.streamId;
    -      final ByteBuf errorFrame =
    -              ErrorFrameCodec.encode(
    -                      this.allocator,
    -                      streamId,
    -                      new CanceledException("Failed to reassemble payload. Cause: " + t.getMessage()));
    -      this.connection.sendFrame(streamId, errorFrame);
    -
    -      final RequestInterceptor requestInterceptor = this.requestInterceptor;
    -      if (requestInterceptor != null) {
    -        requestInterceptor.onTerminate(streamId, FrameType.REQUEST_RESPONSE, t);
    +      final ByteBuf errorFrame = ErrorFrameCodec.encode(channel.allocator, streamId,
    +              new CanceledException("Failed to reassemble payload. Cause: " + t.getMessage()));
    +      channel.connection.sendFrame(streamId, errorFrame);
    +
    +      final var interceptor = channel.requestInterceptor;
    +      if (interceptor != null) {
    +        interceptor.onTerminate(streamId, FrameType.REQUEST_RESPONSE, t);
           }
           return;
         }
    @@ -326,30 +294,27 @@ public void handleNext(ByteBuf frame, boolean hasFollows, boolean isLastPayload)
           this.frames = null;
           Payload payload;
           try {
    -        payload = this.payloadDecoder.apply(frames);
    +        payload = channel.payloadDecoder.decode(frames);
             frames.release();
           }
           catch (Throwable t) {
             S.lazySet(this, Operators.cancelledSubscription());
     
             final int streamId = this.streamId;
    -        this.channelSupport.remove(streamId, this);
    +        channel.remove(streamId, this);
     
             ReferenceCountUtil.safeRelease(frames);
     
             logger.debug("Reassembly has failed", t);
     
             // sends error frame from the responder side to tell that something went wrong
    -        final ByteBuf errorFrame =
    -                ErrorFrameCodec.encode(
    -                        this.allocator,
    -                        streamId,
    -                        new CanceledException("Failed to reassemble payload. Cause: " + t.getMessage()));
    -        this.connection.sendFrame(streamId, errorFrame);
    -
    -        final RequestInterceptor requestInterceptor = this.requestInterceptor;
    -        if (requestInterceptor != null) {
    -          requestInterceptor.onTerminate(streamId, FrameType.REQUEST_RESPONSE, t);
    +        final ByteBuf errorFrame = ErrorFrameCodec.encode(channel.allocator, streamId,
    +                new CanceledException("Failed to reassemble payload. Cause: " + t.getMessage()));
    +        channel.connection.sendFrame(streamId, errorFrame);
    +
    +        final var interceptor = channel.requestInterceptor;
    +        if (interceptor != null) {
    +          interceptor.onTerminate(streamId, FrameType.REQUEST_RESPONSE, t);
             }
             return;
           }
    diff --git a/today-remoting/src/main/java/infra/remoting/core/RequestStreamResponderSubscriber.java b/today-remoting/src/main/java/infra/remoting/core/RequestStreamResponderSubscriber.java
    index c948d59..136f69c 100644
    --- a/today-remoting/src/main/java/infra/remoting/core/RequestStreamResponderSubscriber.java
    +++ b/today-remoting/src/main/java/infra/remoting/core/RequestStreamResponderSubscriber.java
    @@ -14,13 +14,13 @@
      * You should have received a copy of the GNU General Public License
      * along with this program.  If not, see [http://www.gnu.org/licenses/]
      */
    +
     package infra.remoting.core;
     
     import org.reactivestreams.Subscription;
     
     import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
     
    -import infra.lang.Nullable;
     import infra.logging.Logger;
     import infra.logging.LoggerFactory;
     import infra.remoting.Channel;
    @@ -30,8 +30,6 @@
     import infra.remoting.frame.ErrorFrameCodec;
     import infra.remoting.frame.FrameType;
     import infra.remoting.frame.PayloadFrameCodec;
    -import infra.remoting.frame.decoder.PayloadDecoder;
    -import infra.remoting.plugins.RequestInterceptor;
     import io.netty.buffer.ByteBuf;
     import io.netty.buffer.ByteBufAllocator;
     import io.netty.buffer.CompositeByteBuf;
    @@ -46,23 +44,14 @@
     import static infra.remoting.core.PayloadValidationUtils.isValid;
     import static infra.remoting.core.SendUtils.sendReleasingPayload;
     
    -final class RequestStreamResponderSubscriber
    -        implements ResponderFrameHandler, CoreSubscriber {
    +final class RequestStreamResponderSubscriber implements ResponderFrameHandler, CoreSubscriber {
     
       static final Logger logger = LoggerFactory.getLogger(RequestStreamResponderSubscriber.class);
     
       final int streamId;
       final long firstRequest;
    -  final ByteBufAllocator allocator;
    -  final PayloadDecoder payloadDecoder;
    -  final int mtu;
    -  final int maxFrameLength;
    -  final int maxInboundPayloadSize;
    -  final ChannelSupport channelSupport;
    -  final DuplexConnection connection;
     
    -  @Nullable
    -  final RequestInterceptor requestInterceptor;
    +  final ChannelSupport channel;
     
       final Channel handler;
     
    @@ -74,41 +63,21 @@ final class RequestStreamResponderSubscriber
       CompositeByteBuf frames;
       boolean done;
     
    -  public RequestStreamResponderSubscriber(
    -          int streamId,
    -          long firstRequest,
    -          ByteBuf firstFrame,
    -          ChannelSupport channelSupport,
    -          Channel handler) {
    +  public RequestStreamResponderSubscriber(int streamId, long firstRequest,
    +          ByteBuf firstFrame, ChannelSupport channel, Channel handler) {
         this.streamId = streamId;
         this.firstRequest = firstRequest;
    -    this.allocator = channelSupport.getAllocator();
    -    this.mtu = channelSupport.getMtu();
    -    this.maxFrameLength = channelSupport.getMaxFrameLength();
    -    this.maxInboundPayloadSize = channelSupport.getMaxInboundPayloadSize();
    -    this.channelSupport = channelSupport;
    -    this.connection = channelSupport.getDuplexConnection();
    -    this.payloadDecoder = channelSupport.getPayloadDecoder();
    -    this.requestInterceptor = channelSupport.getRequestInterceptor();
    +    this.channel = channel;
         this.handler = handler;
    -    this.frames =
    -            ReassemblyUtils.addFollowingFrame(
    -                    allocator.compositeBuffer(), firstFrame, true, maxInboundPayloadSize);
    +    this.frames = ReassemblyUtils.addFollowingFrame(
    +            channel.allocator.compositeBuffer(), firstFrame, true, channel.maxInboundPayloadSize);
       }
     
    -  public RequestStreamResponderSubscriber(
    -          int streamId, long firstRequest, ChannelSupport channelSupport) {
    +  public RequestStreamResponderSubscriber(int streamId, long firstRequest, ChannelSupport channel) {
         this.streamId = streamId;
         this.firstRequest = firstRequest;
    -    this.allocator = channelSupport.getAllocator();
    -    this.mtu = channelSupport.getMtu();
    -    this.maxFrameLength = channelSupport.getMaxFrameLength();
    -    this.maxInboundPayloadSize = channelSupport.getMaxInboundPayloadSize();
    -    this.channelSupport = channelSupport;
    -    this.connection = channelSupport.getDuplexConnection();
    -    this.requestInterceptor = channelSupport.getRequestInterceptor();
    -
    -    this.payloadDecoder = null;
    +    this.channel = channel;
    +
         this.handler = null;
         this.frames = null;
       }
    @@ -130,29 +99,28 @@ public void onNext(Payload p) {
         }
     
         final int streamId = this.streamId;
    -    final DuplexConnection sender = this.connection;
    -    final ByteBufAllocator allocator = this.allocator;
    +    final DuplexConnection sender = channel.connection;
    +    final ByteBufAllocator allocator = channel.allocator;
     
    -    final int mtu = this.mtu;
    +    final int mtu = channel.mtu;
         try {
    -      if (!isValid(mtu, this.maxFrameLength, p, false)) {
    +      if (!isValid(mtu, channel.maxFrameLength, p, false)) {
             p.release();
     
             if (!this.tryTerminateOnError()) {
               return;
             }
     
    -        final CanceledException e =
    -                new CanceledException(
    -                        String.format(INVALID_PAYLOAD_ERROR_MESSAGE, this.maxFrameLength));
    +        final CanceledException e = new CanceledException(
    +                String.format(INVALID_PAYLOAD_ERROR_MESSAGE, channel.maxFrameLength));
             final ByteBuf errorFrame = ErrorFrameCodec.encode(allocator, streamId, e);
             sender.sendFrame(streamId, errorFrame);
     
    -        this.channelSupport.remove(streamId, this);
    +        this.channel.remove(streamId, this);
     
    -        final RequestInterceptor requestInterceptor = this.requestInterceptor;
    -        if (requestInterceptor != null) {
    -          requestInterceptor.onTerminate(streamId, FrameType.REQUEST_STREAM, e);
    +        final var interceptor = channel.requestInterceptor;
    +        if (interceptor != null) {
    +          interceptor.onTerminate(streamId, FrameType.REQUEST_STREAM, e);
             }
             return;
           }
    @@ -162,18 +130,15 @@ public void onNext(Payload p) {
             return;
           }
     
    -      final ByteBuf errorFrame =
    -              ErrorFrameCodec.encode(
    -                      allocator,
    -                      streamId,
    -                      new CanceledException("Failed to validate payload. Cause" + e.getMessage()));
    +      final ByteBuf errorFrame = ErrorFrameCodec.encode(allocator, streamId,
    +              new CanceledException("Failed to validate payload. Cause" + e.getMessage()));
           sender.sendFrame(streamId, errorFrame);
     
    -      this.channelSupport.remove(streamId, this);
    +      this.channel.remove(streamId, this);
     
    -      final RequestInterceptor requestInterceptor = this.requestInterceptor;
    -      if (requestInterceptor != null) {
    -        requestInterceptor.onTerminate(streamId, FrameType.REQUEST_STREAM, e);
    +      final var interceptor = channel.requestInterceptor;
    +      if (interceptor != null) {
    +        interceptor.onTerminate(streamId, FrameType.REQUEST_STREAM, e);
           }
           return;
         }
    @@ -186,11 +151,11 @@ public void onNext(Payload p) {
             return;
           }
     
    -      this.channelSupport.remove(streamId, this);
    +      this.channel.remove(streamId, this);
     
    -      final RequestInterceptor requestInterceptor = this.requestInterceptor;
    -      if (requestInterceptor != null) {
    -        requestInterceptor.onTerminate(streamId, FrameType.REQUEST_STREAM, t);
    +      final var interceptor = channel.requestInterceptor;
    +      if (interceptor != null) {
    +        interceptor.onTerminate(streamId, FrameType.REQUEST_STREAM, t);
           }
         }
       }
    @@ -233,14 +198,14 @@ public void onError(Throwable t) {
     
         final int streamId = this.streamId;
     
    -    final ByteBuf errorFrame = ErrorFrameCodec.encode(this.allocator, streamId, t);
    -    this.connection.sendFrame(streamId, errorFrame);
    +    final ByteBuf errorFrame = ErrorFrameCodec.encode(channel.allocator, streamId, t);
    +    channel.connection.sendFrame(streamId, errorFrame);
     
    -    this.channelSupport.remove(streamId, this);
    +    this.channel.remove(streamId, this);
     
    -    final RequestInterceptor requestInterceptor = this.requestInterceptor;
    -    if (requestInterceptor != null) {
    -      requestInterceptor.onTerminate(streamId, FrameType.REQUEST_STREAM, t);
    +    final var interceptor = channel.requestInterceptor;
    +    if (interceptor != null) {
    +      interceptor.onTerminate(streamId, FrameType.REQUEST_STREAM, t);
         }
       }
     
    @@ -258,14 +223,14 @@ public void onComplete() {
     
         final int streamId = this.streamId;
     
    -    final ByteBuf completeFrame = PayloadFrameCodec.encodeComplete(this.allocator, streamId);
    -    this.connection.sendFrame(streamId, completeFrame);
    +    final ByteBuf completeFrame = PayloadFrameCodec.encodeComplete(channel.allocator, streamId);
    +    channel.connection.sendFrame(streamId, completeFrame);
     
    -    this.channelSupport.remove(streamId, this);
    +    this.channel.remove(streamId, this);
     
    -    final RequestInterceptor requestInterceptor = this.requestInterceptor;
    -    if (requestInterceptor != null) {
    -      requestInterceptor.onTerminate(streamId, FrameType.REQUEST_STREAM, null);
    +    final var interceptor = channel.requestInterceptor;
    +    if (interceptor != null) {
    +      interceptor.onTerminate(streamId, FrameType.REQUEST_STREAM, null);
         }
       }
     
    @@ -287,7 +252,7 @@ public final void handleCancel() {
           S.lazySet(this, Operators.cancelledSubscription());
     
           final int streamId = this.streamId;
    -      this.channelSupport.remove(streamId, this);
    +      this.channel.remove(streamId, this);
     
           final CompositeByteBuf frames = this.frames;
           if (frames != null) {
    @@ -295,9 +260,9 @@ public final void handleCancel() {
             frames.release();
           }
     
    -      final RequestInterceptor requestInterceptor = this.requestInterceptor;
    -      if (requestInterceptor != null) {
    -        requestInterceptor.onCancel(streamId, FrameType.REQUEST_STREAM);
    +      final var interceptor = channel.requestInterceptor;
    +      if (interceptor != null) {
    +        interceptor.onCancel(streamId, FrameType.REQUEST_STREAM);
           }
           return;
         }
    @@ -307,13 +272,13 @@ public final void handleCancel() {
         }
     
         final int streamId = this.streamId;
    -    this.channelSupport.remove(streamId, this);
    +    this.channel.remove(streamId, this);
     
         currentSubscription.cancel();
     
    -    final RequestInterceptor requestInterceptor = this.requestInterceptor;
    -    if (requestInterceptor != null) {
    -      requestInterceptor.onCancel(streamId, FrameType.REQUEST_STREAM);
    +    final var interceptor = channel.requestInterceptor;
    +    if (interceptor != null) {
    +      interceptor.onCancel(streamId, FrameType.REQUEST_STREAM);
         }
       }
     
    @@ -325,8 +290,7 @@ public void handleNext(ByteBuf followingFrame, boolean hasFollows, boolean isLas
         }
     
         try {
    -      ReassemblyUtils.addFollowingFrame(
    -              frames, followingFrame, hasFollows, this.maxInboundPayloadSize);
    +      ReassemblyUtils.addFollowingFrame(frames, followingFrame, hasFollows, channel.maxInboundPayloadSize);
         }
         catch (IllegalStateException e) {
           // if subscription is null, it means that streams has not yet reassembled all the fragments
    @@ -339,18 +303,15 @@ public void handleNext(ByteBuf followingFrame, boolean hasFollows, boolean isLas
           frames.release();
     
           // sends error frame from the responder side to tell that something went wrong
    -      final ByteBuf errorFrame =
    -              ErrorFrameCodec.encode(
    -                      this.allocator,
    -                      streamId,
    -                      new CanceledException("Failed to reassemble payload. Cause: " + e.getMessage()));
    -      this.connection.sendFrame(streamId, errorFrame);
    -
    -      this.channelSupport.remove(streamId, this);
    -
    -      final RequestInterceptor requestInterceptor = this.requestInterceptor;
    -      if (requestInterceptor != null) {
    -        requestInterceptor.onTerminate(streamId, FrameType.REQUEST_STREAM, e);
    +      final ByteBuf errorFrame = ErrorFrameCodec.encode(channel.allocator, streamId,
    +              new CanceledException("Failed to reassemble payload. Cause: " + e.getMessage()));
    +      channel.connection.sendFrame(streamId, errorFrame);
    +
    +      this.channel.remove(streamId, this);
    +
    +      final var interceptor = channel.requestInterceptor;
    +      if (interceptor != null) {
    +        interceptor.onTerminate(streamId, FrameType.REQUEST_STREAM, e);
           }
     
           logger.debug("Reassembly has failed", e);
    @@ -361,7 +322,7 @@ public void handleNext(ByteBuf followingFrame, boolean hasFollows, boolean isLas
           this.frames = null;
           Payload payload;
           try {
    -        payload = this.payloadDecoder.apply(frames);
    +        payload = channel.payloadDecoder.decode(frames);
             frames.release();
           }
           catch (Throwable t) {
    @@ -373,18 +334,15 @@ public void handleNext(ByteBuf followingFrame, boolean hasFollows, boolean isLas
             ReferenceCountUtil.safeRelease(frames);
     
             // sends error frame from the responder side to tell that something went wrong
    -        final ByteBuf errorFrame =
    -                ErrorFrameCodec.encode(
    -                        this.allocator,
    -                        streamId,
    -                        new CanceledException("Failed to reassemble payload. Cause: " + t.getMessage()));
    -        this.connection.sendFrame(streamId, errorFrame);
    -
    -        this.channelSupport.remove(streamId, this);
    -
    -        final RequestInterceptor requestInterceptor = this.requestInterceptor;
    -        if (requestInterceptor != null) {
    -          requestInterceptor.onTerminate(streamId, FrameType.REQUEST_STREAM, t);
    +        final ByteBuf errorFrame = ErrorFrameCodec.encode(channel.allocator, streamId,
    +                new CanceledException("Failed to reassemble payload. Cause: " + t.getMessage()));
    +        channel.connection.sendFrame(streamId, errorFrame);
    +
    +        this.channel.remove(streamId, this);
    +
    +        final var interceptor = channel.requestInterceptor;
    +        if (interceptor != null) {
    +          interceptor.onTerminate(streamId, FrameType.REQUEST_STREAM, t);
             }
     
             logger.debug("Reassembly has failed", t);
    diff --git a/today-remoting/src/main/java/infra/remoting/core/ResponderChannel.java b/today-remoting/src/main/java/infra/remoting/core/ResponderChannel.java
    index a8a7848..3a9185b 100644
    --- a/today-remoting/src/main/java/infra/remoting/core/ResponderChannel.java
    +++ b/today-remoting/src/main/java/infra/remoting/core/ResponderChannel.java
    @@ -230,7 +230,7 @@ final void handleFrame(ByteBuf frame) {
                       streamId, frame, channelInitialRequestN, FrameHeaderCodec.hasComplete(frame));
               break;
             case METADATA_PUSH:
    -          handleMetadataPush(metadataPush(getPayloadDecoder().apply(frame)));
    +          handleMetadataPush(metadataPush(payloadDecoder.decode(frame)));
               break;
             case CANCEL:
               receiver = get(streamId);
    @@ -313,11 +313,11 @@ final void handleFireAndForget(int streamId, ByteBuf frame) {
               requestInterceptor.onStart(
                       streamId, FrameType.REQUEST_FNF, RequestFireAndForgetFrameCodec.metadata(frame));
     
    -          fireAndForget(getPayloadDecoder().apply(frame))
    +          fireAndForget(payloadDecoder.decode(frame))
                       .subscribe(new FireAndForgetResponderSubscriber(streamId, this));
             }
             else {
    -          fireAndForget(getPayloadDecoder().apply(frame))
    +          fireAndForget(payloadDecoder.decode(frame))
                       .subscribe(FireAndForgetResponderSubscriber.INSTANCE);
             }
           }
    @@ -346,7 +346,7 @@ final void handleRequestResponse(int streamId, ByteBuf frame) {
           else {
             var subscriber = new RequestResponseResponderSubscriber(streamId, this);
             if (add(streamId, subscriber)) {
    -          requestResponse(getPayloadDecoder().apply(frame)).subscribe(subscriber);
    +          requestResponse(payloadDecoder.decode(frame)).subscribe(subscriber);
             }
           }
         }
    @@ -377,7 +377,7 @@ final void handleStream(int streamId, ByteBuf frame, long initialRequestN) {
                     new RequestStreamResponderSubscriber(streamId, initialRequestN, this);
     
             if (add(streamId, subscriber)) {
    -          requestStream(getPayloadDecoder().apply(frame)).subscribe(subscriber);
    +          requestStream(payloadDecoder.decode(frame)).subscribe(subscriber);
             }
           }
         }
    @@ -407,7 +407,7 @@ final void handleChannel(int streamId, ByteBuf frame, long initialRequestN, bool
             add(streamId, subscriber);
           }
           else {
    -        final Payload firstPayload = getPayloadDecoder().apply(frame);
    +        final Payload firstPayload = payloadDecoder.decode(frame);
             RequestChannelResponderSubscriber subscriber =
                     new RequestChannelResponderSubscriber(streamId, initialRequestN, firstPayload, this);
     
    diff --git a/today-remoting/src/main/java/infra/remoting/frame/decoder/DefaultPayloadDecoder.java b/today-remoting/src/main/java/infra/remoting/frame/decoder/DefaultPayloadDecoder.java
    index 3c1b604..a853af6 100644
    --- a/today-remoting/src/main/java/infra/remoting/frame/decoder/DefaultPayloadDecoder.java
    +++ b/today-remoting/src/main/java/infra/remoting/frame/decoder/DefaultPayloadDecoder.java
    @@ -32,11 +32,13 @@
     import io.netty.buffer.ByteBuf;
     import io.netty.buffer.Unpooled;
     
    -/** Default Frame decoder that copies the frames contents for easy of use. */
    +/**
    + * Default Frame decoder that copies the frames contents for easy of use.
    + */
     class DefaultPayloadDecoder implements PayloadDecoder {
     
       @Override
    -  public Payload apply(ByteBuf byteBuf) {
    +  public Payload decode(ByteBuf byteBuf) {
         ByteBuf d;
         FrameType type = FrameHeaderCodec.frameType(byteBuf);
         ByteBuf m = switch (type) {
    diff --git a/today-remoting/src/main/java/infra/remoting/frame/decoder/PayloadDecoder.java b/today-remoting/src/main/java/infra/remoting/frame/decoder/PayloadDecoder.java
    index 25d0a6e..d2e4717 100644
    --- a/today-remoting/src/main/java/infra/remoting/frame/decoder/PayloadDecoder.java
    +++ b/today-remoting/src/main/java/infra/remoting/frame/decoder/PayloadDecoder.java
    @@ -17,12 +17,15 @@
     
     package infra.remoting.frame.decoder;
     
    -import java.util.function.Function;
    -
     import infra.remoting.Payload;
     import io.netty.buffer.ByteBuf;
     
    -public interface PayloadDecoder extends Function {
    +public interface PayloadDecoder {
    +
       PayloadDecoder DEFAULT = new DefaultPayloadDecoder();
    +
       PayloadDecoder ZERO_COPY = new ZeroCopyPayloadDecoder();
    +
    +  Payload decode(ByteBuf byteBuf);
    +
     }
    diff --git a/today-remoting/src/main/java/infra/remoting/frame/decoder/ZeroCopyPayloadDecoder.java b/today-remoting/src/main/java/infra/remoting/frame/decoder/ZeroCopyPayloadDecoder.java
    index d5c4f77..6b2f0f4 100644
    --- a/today-remoting/src/main/java/infra/remoting/frame/decoder/ZeroCopyPayloadDecoder.java
    +++ b/today-remoting/src/main/java/infra/remoting/frame/decoder/ZeroCopyPayloadDecoder.java
    @@ -35,40 +35,39 @@
      * for releasing the payload to free memory when they no long need it.
      */
     public class ZeroCopyPayloadDecoder implements PayloadDecoder {
    +
       @Override
    -  public Payload apply(ByteBuf byteBuf) {
    +  public Payload decode(ByteBuf byteBuf) {
         ByteBuf m;
         ByteBuf d;
         FrameType type = FrameHeaderCodec.frameType(byteBuf);
    -    switch (type) {
    -      case REQUEST_FNF:
    +    m = switch (type) {
    +      case REQUEST_FNF -> {
             d = RequestFireAndForgetFrameCodec.data(byteBuf);
    -        m = RequestFireAndForgetFrameCodec.metadata(byteBuf);
    -        break;
    -      case REQUEST_RESPONSE:
    +        yield RequestFireAndForgetFrameCodec.metadata(byteBuf);
    +      }
    +      case REQUEST_RESPONSE -> {
             d = RequestResponseFrameCodec.data(byteBuf);
    -        m = RequestResponseFrameCodec.metadata(byteBuf);
    -        break;
    -      case REQUEST_STREAM:
    +        yield RequestResponseFrameCodec.metadata(byteBuf);
    +      }
    +      case REQUEST_STREAM -> {
             d = RequestStreamFrameCodec.data(byteBuf);
    -        m = RequestStreamFrameCodec.metadata(byteBuf);
    -        break;
    -      case REQUEST_CHANNEL:
    +        yield RequestStreamFrameCodec.metadata(byteBuf);
    +      }
    +      case REQUEST_CHANNEL -> {
             d = RequestChannelFrameCodec.data(byteBuf);
    -        m = RequestChannelFrameCodec.metadata(byteBuf);
    -        break;
    -      case NEXT:
    -      case NEXT_COMPLETE:
    +        yield RequestChannelFrameCodec.metadata(byteBuf);
    +      }
    +      case NEXT, NEXT_COMPLETE -> {
             d = PayloadFrameCodec.data(byteBuf);
    -        m = PayloadFrameCodec.metadata(byteBuf);
    -        break;
    -      case METADATA_PUSH:
    +        yield PayloadFrameCodec.metadata(byteBuf);
    +      }
    +      case METADATA_PUSH -> {
             d = Unpooled.EMPTY_BUFFER;
    -        m = MetadataPushFrameCodec.metadata(byteBuf);
    -        break;
    -      default:
    -        throw new IllegalArgumentException("unsupported frame type: " + type);
    -    }
    +        yield MetadataPushFrameCodec.metadata(byteBuf);
    +      }
    +      default -> throw new IllegalArgumentException("unsupported frame type: " + type);
    +    };
     
         return ByteBufPayload.create(d.retain(), m != null ? m.retain() : null);
       }
    diff --git a/today-remoting/src/main/java/infra/remoting/lb/WeightedStatsChannel.java b/today-remoting/src/main/java/infra/remoting/lb/WeightedStatsChannel.java
    index 82ca2a7..1cd8c23 100644
    --- a/today-remoting/src/main/java/infra/remoting/lb/WeightedStatsChannel.java
    +++ b/today-remoting/src/main/java/infra/remoting/lb/WeightedStatsChannel.java
    @@ -18,13 +18,13 @@
     package infra.remoting.lb;
     
     import infra.remoting.Channel;
    -import infra.remoting.util.ChannelDecorator;
    +import infra.remoting.util.ChannelWrapper;
     
     /**
    - * Package private {@code ChannelDecorator} used from {@link WeightedStats#wrap(Channel)} to attach a
    + * Package private {@code ChannelWrapper} used from {@link WeightedStats#wrap(Channel)} to attach a
      * {@link WeightedStats} instance to an {@code Channel}.
      */
    -final class WeightedStatsChannel extends ChannelDecorator implements WeightedStats {
    +final class WeightedStatsChannel extends ChannelWrapper implements WeightedStats {
     
       private final WeightedStats weightedStats;
     
    diff --git a/today-remoting/src/main/java/infra/remoting/plugins/ChannelInterceptor.java b/today-remoting/src/main/java/infra/remoting/plugins/ChannelDecorator.java
    similarity index 80%
    rename from today-remoting/src/main/java/infra/remoting/plugins/ChannelInterceptor.java
    rename to today-remoting/src/main/java/infra/remoting/plugins/ChannelDecorator.java
    index 83de841..e870ee1 100644
    --- a/today-remoting/src/main/java/infra/remoting/plugins/ChannelInterceptor.java
    +++ b/today-remoting/src/main/java/infra/remoting/plugins/ChannelDecorator.java
    @@ -21,12 +21,12 @@
     
     /**
      * Contract to decorate an {@link Channel}, providing a way to intercept interactions. This can be
    - * applied to a {@link InterceptorRegistry#forRequester(ChannelInterceptor) requester} or {@link
    - * InterceptorRegistry#forResponder(ChannelInterceptor) responder} {@code Channel} of a client or
    + * applied to a {@link InterceptorRegistry#forRequester(ChannelDecorator) requester} or {@link
    + * InterceptorRegistry#forResponder(ChannelDecorator) responder} {@code Channel} of a client or
      * server.
      */
     @FunctionalInterface
    -public interface ChannelInterceptor {
    +public interface ChannelDecorator {
     
       Channel decorate(Channel channel);
     
    diff --git a/today-remoting/src/main/java/infra/remoting/plugins/ConnectionInterceptor.java b/today-remoting/src/main/java/infra/remoting/plugins/ConnectionDecorator.java
    similarity index 89%
    rename from today-remoting/src/main/java/infra/remoting/plugins/ConnectionInterceptor.java
    rename to today-remoting/src/main/java/infra/remoting/plugins/ConnectionDecorator.java
    index 38cf839..a2857c6 100644
    --- a/today-remoting/src/main/java/infra/remoting/plugins/ConnectionInterceptor.java
    +++ b/today-remoting/src/main/java/infra/remoting/plugins/ConnectionDecorator.java
    @@ -24,7 +24,7 @@
      * protocol frames at the transport level.
      */
     @FunctionalInterface
    -public interface ConnectionInterceptor {
    +public interface ConnectionDecorator {
     
       enum Type {
         CLIENT,
    @@ -32,6 +32,6 @@ enum Type {
         SOURCE
       }
     
    -  DuplexConnection intercept(Type type, DuplexConnection duplexConnection);
    +  DuplexConnection decorate(Type type, DuplexConnection connection);
     
     }
    diff --git a/today-remoting/src/main/java/infra/remoting/plugins/InitializingInterceptorRegistry.java b/today-remoting/src/main/java/infra/remoting/plugins/InitializingInterceptorRegistry.java
    index 46f03ef..15419fc 100644
    --- a/today-remoting/src/main/java/infra/remoting/plugins/InitializingInterceptorRegistry.java
    +++ b/today-remoting/src/main/java/infra/remoting/plugins/InitializingInterceptorRegistry.java
    @@ -47,22 +47,22 @@ public RequestInterceptor initResponderRequestInterceptor(Channel channelRespond
                         .collect(Collectors.toList()));
       }
     
    -  public DuplexConnection initConnection(ConnectionInterceptor.Type type, DuplexConnection connection) {
    -    for (ConnectionInterceptor interceptor : connectionInterceptors) {
    -      connection = interceptor.intercept(type, connection);
    +  public DuplexConnection initConnection(ConnectionDecorator.Type type, DuplexConnection connection) {
    +    for (ConnectionDecorator interceptor : connectionDecorators) {
    +      connection = interceptor.decorate(type, connection);
         }
         return connection;
       }
     
       public Channel decorateRequester(Channel channel) {
    -    for (ChannelInterceptor interceptor : requesterChannelInterceptors) {
    +    for (ChannelDecorator interceptor : requesterChannelDecorators) {
           channel = interceptor.decorate(channel);
         }
         return channel;
       }
     
       public Channel decorateResponder(Channel channel) {
    -    for (ChannelInterceptor interceptor : responderChannelInterceptors) {
    +    for (ChannelDecorator interceptor : responderChannelDecorators) {
           channel = interceptor.decorate(channel);
         }
         return channel;
    diff --git a/today-remoting/src/main/java/infra/remoting/plugins/InterceptorRegistry.java b/today-remoting/src/main/java/infra/remoting/plugins/InterceptorRegistry.java
    index c02767e..e7408ae 100644
    --- a/today-remoting/src/main/java/infra/remoting/plugins/InterceptorRegistry.java
    +++ b/today-remoting/src/main/java/infra/remoting/plugins/InterceptorRegistry.java
    @@ -28,10 +28,10 @@
      * Provides support for registering interceptors at the following levels:
      *
      * 
      - *
    • {@link #forConnection(ConnectionInterceptor)} -- transport level + *
    • {@link #forConnection(ConnectionDecorator)} -- transport level *
    • {@link #forChannelAcceptor(ChannelAcceptorInterceptor)} -- for accepting new connections - *
    • {@link #forRequester(ChannelInterceptor)} -- for performing of requests - *
    • {@link #forResponder(ChannelInterceptor)} -- for responding to requests + *
    • {@link #forRequester(ChannelDecorator)} -- for performing of requests + *
    • {@link #forResponder(ChannelDecorator)} -- for responding to requests *
    */ public class InterceptorRegistry { @@ -40,13 +40,13 @@ public class InterceptorRegistry { protected final ArrayList> responderRequestInterceptors = new ArrayList<>(); - protected final ArrayList requesterChannelInterceptors = new ArrayList<>(); + protected final ArrayList requesterChannelDecorators = new ArrayList<>(); - protected final ArrayList responderChannelInterceptors = new ArrayList<>(); + protected final ArrayList responderChannelDecorators = new ArrayList<>(); protected final ArrayList channelAcceptorInterceptors = new ArrayList<>(); - protected final ArrayList connectionInterceptors = new ArrayList<>(); + protected final ArrayList connectionDecorators = new ArrayList<>(); /** * Add an {@link RequestInterceptor} that will hook into Requester Channel requests' phases. @@ -71,37 +71,37 @@ public InterceptorRegistry forRequestsInResponder(Function> consumer) { - consumer.accept(requesterChannelInterceptors); + public InterceptorRegistry forRequester(Consumer> consumer) { + consumer.accept(requesterChannelDecorators); return this; } /** - * Add an {@link ChannelInterceptor} that will decorate the Channel used for responding to + * Add an {@link ChannelDecorator} that will decorate the Channel used for responding to * requests. */ - public InterceptorRegistry forResponder(ChannelInterceptor interceptor) { - responderChannelInterceptors.add(interceptor); + public InterceptorRegistry forResponder(ChannelDecorator interceptor) { + responderChannelDecorators.add(interceptor); return this; } /** - * Variant of {@link #forResponder(ChannelInterceptor)} with access to the list of existing + * Variant of {@link #forResponder(ChannelDecorator)} with access to the list of existing * registrations. */ - public InterceptorRegistry forResponder(Consumer> consumer) { - consumer.accept(responderChannelInterceptors); + public InterceptorRegistry forResponder(Consumer> consumer) { + consumer.accept(responderChannelDecorators); return this; } @@ -122,18 +122,18 @@ public InterceptorRegistry forChannelAcceptor(Consumer> consumer) { - consumer.accept(connectionInterceptors); + public InterceptorRegistry forConnection(Consumer> consumer) { + consumer.accept(connectionDecorators); return this; } diff --git a/today-remoting/src/main/java/infra/remoting/plugins/RateLimitInterceptor.java b/today-remoting/src/main/java/infra/remoting/plugins/RateLimitDecorator.java similarity index 85% rename from today-remoting/src/main/java/infra/remoting/plugins/RateLimitInterceptor.java rename to today-remoting/src/main/java/infra/remoting/plugins/RateLimitDecorator.java index 58f7fc8..c8a612f 100644 --- a/today-remoting/src/main/java/infra/remoting/plugins/RateLimitInterceptor.java +++ b/today-remoting/src/main/java/infra/remoting/plugins/RateLimitDecorator.java @@ -21,7 +21,7 @@ import infra.remoting.Channel; import infra.remoting.Payload; -import infra.remoting.util.ChannelDecorator; +import infra.remoting.util.ChannelWrapper; import reactor.core.publisher.Flux; /** @@ -41,7 +41,7 @@ * * @since 1.0 */ -public class RateLimitInterceptor implements ChannelInterceptor { +public class RateLimitDecorator implements ChannelDecorator { private final int highTide; @@ -49,7 +49,7 @@ public class RateLimitInterceptor implements ChannelInterceptor { private final boolean requesterProxy; - private RateLimitInterceptor(int highTide, int lowTide, boolean requesterProxy) { + private RateLimitDecorator(int highTide, int lowTide, boolean requesterProxy) { this.highTide = highTide; this.lowTide = lowTide; this.requesterProxy = requesterProxy; @@ -67,7 +67,7 @@ public Channel decorate(Channel socket) { * @param prefetchRate the prefetch rate to pass to {@link Flux#limitRate(int)} * @return the created interceptor */ - public static RateLimitInterceptor forResponder(int prefetchRate) { + public static RateLimitDecorator forResponder(int prefetchRate) { return forResponder(prefetchRate, prefetchRate); } @@ -79,8 +79,8 @@ public static RateLimitInterceptor forResponder(int prefetchRate) { * @param lowTide the low tide value to pass to {@link Flux#limitRate(int, int)} * @return the created interceptor */ - public static RateLimitInterceptor forResponder(int highTide, int lowTide) { - return new RateLimitInterceptor(highTide, lowTide, false); + public static RateLimitDecorator forResponder(int highTide, int lowTide) { + return new RateLimitDecorator(highTide, lowTide, false); } /** @@ -89,7 +89,7 @@ public static RateLimitInterceptor forResponder(int highTide, int lowTide) { * @param prefetchRate the prefetch rate to pass to {@link Flux#limitRate(int)} * @return the created interceptor */ - public static RateLimitInterceptor forRequester(int prefetchRate) { + public static RateLimitDecorator forRequester(int prefetchRate) { return forRequester(prefetchRate, prefetchRate); } @@ -101,14 +101,14 @@ public static RateLimitInterceptor forRequester(int prefetchRate) { * @param lowTide the low tide value to pass to {@link Flux#limitRate(int, int)} * @return the created interceptor */ - public static RateLimitInterceptor forRequester(int highTide, int lowTide) { - return new RateLimitInterceptor(highTide, lowTide, true); + public static RateLimitDecorator forRequester(int highTide, int lowTide) { + return new RateLimitDecorator(highTide, lowTide, true); } /** * Responder side proxy, limits response streams. */ - private class ResponderChannel extends ChannelDecorator { + private class ResponderChannel extends ChannelWrapper { ResponderChannel(Channel source) { super(source); @@ -128,7 +128,7 @@ public Flux requestChannel(Publisher payloads) { /** * Requester side proxy, limits channel request stream. */ - private class RequesterChannel extends ChannelDecorator { + private class RequesterChannel extends ChannelWrapper { RequesterChannel(Channel source) { super(source); diff --git a/today-remoting/src/main/java/infra/remoting/plugins/RequestInterceptor.java b/today-remoting/src/main/java/infra/remoting/plugins/RequestInterceptor.java index 4154bd3..afb1569 100644 --- a/today-remoting/src/main/java/infra/remoting/plugins/RequestInterceptor.java +++ b/today-remoting/src/main/java/infra/remoting/plugins/RequestInterceptor.java @@ -27,7 +27,7 @@ /** * Class used to track the protocol requests lifecycles. The main difference and advantage of this - * interceptor compares to {@link ChannelInterceptor} is that it allows intercepting the initial and + * interceptor compares to {@link ChannelDecorator} is that it allows intercepting the initial and * terminal phases on every individual request. * *

    Note, if any of the invocations will rise a runtime exception, this exception will be diff --git a/today-remoting/src/main/java/infra/remoting/util/ChannelDecorator.java b/today-remoting/src/main/java/infra/remoting/util/ChannelWrapper.java similarity index 95% rename from today-remoting/src/main/java/infra/remoting/util/ChannelDecorator.java rename to today-remoting/src/main/java/infra/remoting/util/ChannelWrapper.java index b722b34..64fe93f 100644 --- a/today-remoting/src/main/java/infra/remoting/util/ChannelDecorator.java +++ b/today-remoting/src/main/java/infra/remoting/util/ChannelWrapper.java @@ -27,11 +27,11 @@ /** * Wrapper for a Channel. This is useful when we want to override a specific method. */ -public class ChannelDecorator implements Channel { +public class ChannelWrapper implements Channel { protected final Channel delegate; - public ChannelDecorator(Channel delegate) { + public ChannelWrapper(Channel delegate) { this.delegate = delegate; } @@ -79,4 +79,5 @@ public boolean isDisposed() { public Mono onClose() { return delegate.onClose(); } + } diff --git a/today-remoting/src/test/java/infra/remoting/core/DefaultChannelClientTests.java b/today-remoting/src/test/java/infra/remoting/core/DefaultChannelClientTests.java index 114c6e1..4759012 100644 --- a/today-remoting/src/test/java/infra/remoting/core/DefaultChannelClientTests.java +++ b/today-remoting/src/test/java/infra/remoting/core/DefaultChannelClientTests.java @@ -55,7 +55,7 @@ import infra.remoting.internal.subscriber.AssertSubscriber; import infra.remoting.test.util.TestDuplexConnection; import infra.remoting.util.ByteBufPayload; -import infra.remoting.util.ChannelDecorator; +import infra.remoting.util.ChannelWrapper; import reactor.core.Disposable; import reactor.core.publisher.Flux; import reactor.core.publisher.Hooks; @@ -513,7 +513,7 @@ public void shouldReceiveOnCloseNotificationOnDisposeOriginalSource() { new ClientChannelRule() { @Override protected Channel newChannel() { - return new ChannelDecorator(super.newChannel()) { + return new ChannelWrapper(super.newChannel()) { @Override public Mono onClose() { return super.onClose().and(onCloseDelayer.asMono()); diff --git a/today-remoting/src/test/java/infra/remoting/core/SetupRejectionTest.java b/today-remoting/src/test/java/infra/remoting/core/SetupRejectionTest.java index 8de0ab4..c573f07 100644 --- a/today-remoting/src/test/java/infra/remoting/core/SetupRejectionTest.java +++ b/today-remoting/src/test/java/infra/remoting/core/SetupRejectionTest.java @@ -157,8 +157,8 @@ public RejectingAcceptor(String errorMessage) { } @Override - public Mono accept(ConnectionSetupPayload setup, Channel sendingSocket) { - senderChannels.tryEmitNext(sendingSocket); + public Mono accept(ConnectionSetupPayload setup, Channel channel) { + senderChannels.tryEmitNext(channel); return Mono.error(new RuntimeException(errorMessage)); } diff --git a/today-remoting/src/test/java/infra/remoting/examples/tcp/channel/ChannelEchoClient.java b/today-remoting/src/test/java/infra/remoting/examples/tcp/channel/ChannelEchoClient.java new file mode 100644 index 0000000..3dad7cd --- /dev/null +++ b/today-remoting/src/test/java/infra/remoting/examples/tcp/channel/ChannelEchoClient.java @@ -0,0 +1,63 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.remoting.examples.tcp.channel; + +import java.time.Duration; + +import infra.logging.Logger; +import infra.logging.LoggerFactory; +import infra.remoting.Channel; +import infra.remoting.ChannelAcceptor; +import infra.remoting.Payload; +import infra.remoting.core.ChannelConnector; +import infra.remoting.core.RemotingServer; +import infra.remoting.transport.netty.client.TcpClientTransport; +import infra.remoting.transport.netty.server.TcpServerTransport; +import infra.remoting.util.DefaultPayload; +import reactor.core.publisher.Flux; + +public final class ChannelEchoClient { + + private static final Logger logger = LoggerFactory.getLogger(ChannelEchoClient.class); + + public static void main(String[] args) { + + ChannelAcceptor echoAcceptor = + ChannelAcceptor.forRequestChannel( + payloads -> + Flux.from(payloads) + .map(Payload::getDataUtf8) + .map(s -> "Echo: " + s) + .map(DefaultPayload::create)); + + RemotingServer.create(echoAcceptor).bindNow(TcpServerTransport.create("localhost", 7000)); + + Channel socket = + ChannelConnector.connectWith(TcpClientTransport.create("localhost", 7000)).block(); + + socket + .requestChannel( + Flux.interval(Duration.ofMillis(1000)).map(i -> DefaultPayload.create("Hello"))) + .map(Payload::getDataUtf8) + .doOnNext(logger::debug) + .take(10) + .doFinally(signalType -> socket.dispose()) + .then() + .block(); + } +} diff --git a/today-remoting/src/test/java/infra/remoting/examples/tcp/client/ClientExample.java b/today-remoting/src/test/java/infra/remoting/examples/tcp/client/ClientExample.java new file mode 100644 index 0000000..fbea922 --- /dev/null +++ b/today-remoting/src/test/java/infra/remoting/examples/tcp/client/ClientExample.java @@ -0,0 +1,70 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.remoting.examples.tcp.client; + +import java.time.Duration; + +import infra.logging.Logger; +import infra.logging.LoggerFactory; +import infra.remoting.Channel; +import infra.remoting.ChannelAcceptor; +import infra.remoting.Payload; +import infra.remoting.core.ChannelConnector; +import infra.remoting.core.RemotingClient; +import infra.remoting.core.RemotingServer; +import infra.remoting.transport.netty.client.TcpClientTransport; +import infra.remoting.transport.netty.server.TcpServerTransport; +import infra.remoting.util.DefaultPayload; +import reactor.core.publisher.Mono; +import reactor.util.retry.Retry; + +public class ClientExample { + static final Logger logger = LoggerFactory.getLogger(ClientExample.class); + + public static void main(String[] args) { + RemotingServer.create(ChannelAcceptor.forRequestResponse(p -> { + String data = p.getDataUtf8(); + logger.info("Received request data {}", data); + + Payload responsePayload = DefaultPayload.create("Echo: " + data); + p.release(); + + return Mono.just(responsePayload); + })) + .bind(TcpServerTransport.create("localhost", 7000)) + .delaySubscription(Duration.ofSeconds(5)) + .doOnNext(cc -> logger.info("Server started on the address : {}", cc.address())) + .block(); + + Mono source = + ChannelConnector.create() + .reconnect(Retry.backoff(50, Duration.ofMillis(500))) + .connect(TcpClientTransport.create("localhost", 7000)); + + RemotingClient.from(source) + .requestResponse(Mono.just(DefaultPayload.create("Test Request"))) + .doOnSubscribe(s -> logger.info("Executing Request")) + .doOnNext( + d -> { + logger.info("Received response data {}", d.getDataUtf8()); + d.release(); + }) + .repeat(10) + .blockLast(); + } +} diff --git a/today-remoting/src/test/java/infra/remoting/examples/tcp/fnf/TaskProcessingWithServerSideNotificationsExample.java b/today-remoting/src/test/java/infra/remoting/examples/tcp/fnf/TaskProcessingWithServerSideNotificationsExample.java new file mode 100644 index 0000000..ba8698e --- /dev/null +++ b/today-remoting/src/test/java/infra/remoting/examples/tcp/fnf/TaskProcessingWithServerSideNotificationsExample.java @@ -0,0 +1,239 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ +package infra.remoting.examples.tcp.fnf; + +import java.time.Duration; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ThreadLocalRandom; + +import infra.logging.Logger; +import infra.logging.LoggerFactory; +import infra.remoting.Channel; +import infra.remoting.ChannelAcceptor; +import infra.remoting.ConnectionSetupPayload; +import infra.remoting.Payload; +import infra.remoting.core.ChannelConnector; +import infra.remoting.core.RemotingServer; +import infra.remoting.transport.netty.client.TcpClientTransport; +import infra.remoting.transport.netty.server.TcpServerTransport; +import infra.remoting.util.DefaultPayload; +import reactor.core.publisher.BaseSubscriber; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; +import reactor.core.publisher.Sinks; +import reactor.util.concurrent.Queues; + +/** + * An example of long-running tasks processing (a.k.a Kafka style) where a client submits tasks over + * request `FireAndForget` and then receives results over the same method but on it is own side. + * + *

    This example shows a case when the client may disappear, however, another a client can connect + * again and receive undelivered completed tasks remaining for the previous one. + */ +public class TaskProcessingWithServerSideNotificationsExample { + + public static void main(String[] args) throws InterruptedException { + Sinks.Many tasksProcessor = + Sinks.many().unicast().onBackpressureBuffer(Queues.unboundedMultiproducer().get()); + ConcurrentMap> idToCompletedTasksMap = new ConcurrentHashMap<>(); + ConcurrentMap idToChannelMap = new ConcurrentHashMap<>(); + BackgroundWorker backgroundWorker = + new BackgroundWorker(tasksProcessor.asFlux(), idToCompletedTasksMap, idToChannelMap); + + RemotingServer.create(new TasksAcceptor(tasksProcessor, idToCompletedTasksMap, idToChannelMap)) + .bindNow(TcpServerTransport.create(9991)); + + Logger logger = LoggerFactory.getLogger("Channel.Client.ID[Test]"); + + Mono channelMono = + ChannelConnector.create() + .setupPayload(DefaultPayload.create("Test")) + .acceptor( + ChannelAcceptor.forFireAndForget( + p -> { + logger.info("Received Processed Task[{}]", p.getDataUtf8()); + p.release(); + return Mono.empty(); + })) + .connect(TcpClientTransport.create(9991)); + + Channel channelRequester1 = channelMono.block(); + + for (int i = 0; i < 10; i++) { + channelRequester1.fireAndForget(DefaultPayload.create("task" + i)).block(); + } + + Thread.sleep(4000); + + channelRequester1.dispose(); + logger.info("Disposed"); + + Thread.sleep(4000); + + Channel requester2 = channelMono.block(); + + logger.info("Reconnected"); + + Thread.sleep(10000); + } + + static class BackgroundWorker extends BaseSubscriber { + final ConcurrentMap> idToCompletedTasksMap; + final ConcurrentMap idToChannelMap; + + BackgroundWorker( + Flux taskProducer, + ConcurrentMap> idToCompletedTasksMap, + ConcurrentMap idToChannelMap) { + + this.idToCompletedTasksMap = idToCompletedTasksMap; + this.idToChannelMap = idToChannelMap; + + // mimic a long running task processing + taskProducer + .concatMap( + t -> + Mono.delay(Duration.ofMillis(ThreadLocalRandom.current().nextInt(200, 2000))) + .thenReturn(t)) + .subscribe(this); + } + + @Override + protected void hookOnNext(Task task) { + BlockingQueue completedTasksQueue = + idToCompletedTasksMap.computeIfAbsent(task.id, __ -> new LinkedBlockingQueue<>()); + + completedTasksQueue.offer(task); + Channel channel = idToChannelMap.get(task.id); + if (channel != null) { + channel + .fireAndForget(DefaultPayload.create(task.content)) + .subscribe(null, e -> { }, () -> completedTasksQueue.remove(task)); + } + } + } + + static class TasksAcceptor implements ChannelAcceptor { + + static final Logger logger = LoggerFactory.getLogger(TasksAcceptor.class); + + final Sinks.Many tasksToProcess; + final ConcurrentMap> idToCompletedTasksMap; + final ConcurrentMap idToChannelMap; + + TasksAcceptor( + Sinks.Many tasksToProcess, + ConcurrentMap> idToCompletedTasksMap, + ConcurrentMap idToChannelMap) { + this.tasksToProcess = tasksToProcess; + this.idToCompletedTasksMap = idToCompletedTasksMap; + this.idToChannelMap = idToChannelMap; + } + + @Override + public Mono accept(ConnectionSetupPayload setup, Channel channel) { + String id = setup.getDataUtf8(); + logger.info("Accepting a new client connection with ID {}", id); + // sendingChannel represents here an Channel requester to a remote peer + + if (this.idToChannelMap.compute( + id, (__, old) -> old == null || old.isDisposed() ? channel : old) + == channel) { + return Mono.just( + new ChannelTaskHandler(idToChannelMap, tasksToProcess, id, channel)) + .doOnSuccess(__ -> checkTasksToDeliver(channel, id)); + } + + return Mono.error( + new IllegalStateException("There is already a client connected with the same ID")); + } + + private void checkTasksToDeliver(Channel channel, String id) { + logger.info("Accepted a new client connection with ID {}. Checking for remaining tasks", id); + BlockingQueue tasksToDeliver = this.idToCompletedTasksMap.get(id); + + if (tasksToDeliver == null || tasksToDeliver.isEmpty()) { + // means nothing yet to send + return; + } + + logger.info("Found remaining tasks to deliver for client {}", id); + + for (; ; ) { + Task task = tasksToDeliver.poll(); + + if (task == null) { + return; + } + + channel + .fireAndForget(DefaultPayload.create(task.content)) + .subscribe( + null, + e -> { + // offers back a task if it has not been delivered + tasksToDeliver.offer(task); + }); + } + } + + private static class ChannelTaskHandler implements Channel { + + private final String id; + private final Channel channel; + private ConcurrentMap idToChannelMap; + private Sinks.Many tasksToProcess; + + public ChannelTaskHandler( + ConcurrentMap idToChannelMap, + Sinks.Many tasksToProcess, + String id, + Channel sendingSocket) { + this.id = id; + this.channel = sendingSocket; + this.idToChannelMap = idToChannelMap; + this.tasksToProcess = tasksToProcess; + } + + @Override + public Mono fireAndForget(Payload payload) { + logger.info("Received a Task[{}] from Client.ID[{}]", payload.getDataUtf8(), id); + Sinks.EmitResult result = tasksToProcess.tryEmitNext(new Task(id, payload.getDataUtf8())); + payload.release(); + return result.isFailure() ? Mono.error(new Sinks.EmissionException(result)) : Mono.empty(); + } + + @Override + public void dispose() { + idToChannelMap.remove(id, channel); + } + } + } + + static class Task { + final String id; + final String content; + + Task(String id, String content) { + this.id = id; + this.content = content; + } + } +} diff --git a/today-remoting/src/test/java/infra/remoting/examples/tcp/lease/advanced/common/LeaseManager.java b/today-remoting/src/test/java/infra/remoting/examples/tcp/lease/advanced/common/LeaseManager.java new file mode 100644 index 0000000..1454664 --- /dev/null +++ b/today-remoting/src/test/java/infra/remoting/examples/tcp/lease/advanced/common/LeaseManager.java @@ -0,0 +1,164 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.remoting.examples.tcp.lease.advanced.common; + +import java.util.concurrent.BlockingDeque; +import java.util.concurrent.LinkedBlockingDeque; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; + +import infra.logging.Logger; +import infra.logging.LoggerFactory; +import reactor.core.scheduler.Scheduler; +import reactor.core.scheduler.Schedulers; + +public class LeaseManager implements Runnable { + + static final Logger logger = LoggerFactory.getLogger(LeaseManager.class); + + volatile int activeConnectionsCount; + static final AtomicIntegerFieldUpdater ACTIVE_CONNECTIONS_COUNT = + AtomicIntegerFieldUpdater.newUpdater(LeaseManager.class, "activeConnectionsCount"); + + volatile int stateAndInFlight; + static final AtomicIntegerFieldUpdater STATE_AND_IN_FLIGHT = + AtomicIntegerFieldUpdater.newUpdater(LeaseManager.class, "stateAndInFlight"); + + static final int MASK_PAUSED = 0b1_000_0000_0000_0000_0000_0000_0000_0000; + static final int MASK_IN_FLIGHT = 0b0_111_1111_1111_1111_1111_1111_1111_1111; + + final BlockingDeque sendersQueue = new LinkedBlockingDeque<>(); + final Scheduler worker = Schedulers.newSingle(LeaseManager.class.getName()); + + final int capacity; + final int ttl; + + public LeaseManager(int capacity, int ttl) { + this.capacity = capacity; + this.ttl = ttl; + } + + @Override + public void run() { + try { + LimitBasedLeaseSender leaseSender = sendersQueue.poll(); + + if (leaseSender == null) { + return; + } + + if (leaseSender.isDisposed()) { + logger.debug("Connection[" + leaseSender.connectionId + "]: LeaseSender is Disposed"); + worker.schedule(this); + return; + } + + int limit = leaseSender.limitAlgorithm.getLimit(); + + if (limit == 0) { + throw new IllegalStateException("Limit is 0"); + } + + if (pauseIfNoCapacity()) { + sendersQueue.addFirst(leaseSender); + logger.debug("Pause execution. Not enough capacity"); + return; + } + + leaseSender.sendLease(ttl, limit); + sendersQueue.offer(leaseSender); + + int activeConnections = activeConnectionsCount; + int nextDelay = activeConnections == 0 ? ttl : (ttl / activeConnections); + + logger.debug("Next check happens in " + nextDelay + "ms"); + + worker.schedule(this, nextDelay, TimeUnit.MILLISECONDS); + } + catch (Throwable e) { + logger.error("LeaseSender failed to send lease", e); + } + } + + int incrementInFlightAndGet() { + for (; ; ) { + int state = stateAndInFlight; + int paused = state & MASK_PAUSED; + int inFlight = stateAndInFlight & MASK_IN_FLIGHT; + + // assume overflow is impossible due to max concurrency in channel it self + int nextInFlight = inFlight + 1; + + if (STATE_AND_IN_FLIGHT.compareAndSet(this, state, nextInFlight | paused)) { + return nextInFlight; + } + } + } + + void decrementInFlight() { + for (; ; ) { + int state = stateAndInFlight; + int paused = state & MASK_PAUSED; + int inFlight = stateAndInFlight & MASK_IN_FLIGHT; + + // assume overflow is impossible due to max concurrency in channel it self + int nextInFlight = inFlight - 1; + + if (inFlight == capacity && paused == MASK_PAUSED) { + if (STATE_AND_IN_FLIGHT.compareAndSet(this, state, nextInFlight)) { + logger.debug("Resume execution"); + worker.schedule(this); + return; + } + } + else { + if (STATE_AND_IN_FLIGHT.compareAndSet(this, state, nextInFlight | paused)) { + return; + } + } + } + } + + boolean pauseIfNoCapacity() { + int capacity = this.capacity; + for (; ; ) { + int inFlight = stateAndInFlight; + + if (inFlight < capacity) { + return false; + } + + if (STATE_AND_IN_FLIGHT.compareAndSet(this, inFlight, inFlight | MASK_PAUSED)) { + return true; + } + } + } + + void unregister() { + ACTIVE_CONNECTIONS_COUNT.decrementAndGet(this); + } + + void register(LimitBasedLeaseSender sender) { + sendersQueue.offer(sender); + final int activeCount = ACTIVE_CONNECTIONS_COUNT.getAndIncrement(this); + + if (activeCount == 0) { + worker.schedule(this); + } + } +} diff --git a/today-remoting/src/test/java/infra/remoting/examples/tcp/lease/advanced/common/LimitBasedLeaseSender.java b/today-remoting/src/test/java/infra/remoting/examples/tcp/lease/advanced/common/LimitBasedLeaseSender.java new file mode 100644 index 0000000..3c5a3f4 --- /dev/null +++ b/today-remoting/src/test/java/infra/remoting/examples/tcp/lease/advanced/common/LimitBasedLeaseSender.java @@ -0,0 +1,75 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.remoting.examples.tcp.lease.advanced.common; + +import com.netflix.concurrency.limits.Limit; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.time.Duration; + +import infra.remoting.lease.Lease; +import infra.remoting.lease.TrackingLeaseSender; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Sinks; +import reactor.util.concurrent.Queues; + +public class LimitBasedLeaseSender extends LimitBasedStatsCollector implements TrackingLeaseSender { + + static final Logger logger = LoggerFactory.getLogger(LimitBasedLeaseSender.class); + + final String connectionId; + final Sinks.Many sink = + Sinks.many().unicast().onBackpressureBuffer(Queues.one().get()); + + public LimitBasedLeaseSender( + String connectionId, LeaseManager leaseManager, Limit limitAlgorithm) { + super(leaseManager, limitAlgorithm); + this.connectionId = connectionId; + } + + @Override + public Flux send() { + logger.info("Received new leased Connection[" + connectionId + "]"); + + leaseManager.register(this); + + return sink.asFlux(); + } + + public void sendLease(int ttl, int amount) { + final Lease nextLease = Lease.create(Duration.ofMillis(ttl), amount); + final Sinks.EmitResult result = sink.tryEmitNext(nextLease); + + if (result.isFailure()) { + logger.warn( + "Connection[" + + connectionId + + "]. Issued Lease: [" + + nextLease + + "] was not sent due to " + + result); + } + else { + if (logger.isDebugEnabled()) { + logger.debug("To Connection[" + connectionId + "]: Issued Lease: [" + nextLease + "]"); + } + } + } +} diff --git a/today-remoting/src/test/java/infra/remoting/examples/tcp/lease/advanced/common/LimitBasedStatsCollector.java b/today-remoting/src/test/java/infra/remoting/examples/tcp/lease/advanced/common/LimitBasedStatsCollector.java new file mode 100644 index 0000000..a353e5f --- /dev/null +++ b/today-remoting/src/test/java/infra/remoting/examples/tcp/lease/advanced/common/LimitBasedStatsCollector.java @@ -0,0 +1,92 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.remoting.examples.tcp.lease.advanced.common; + +import com.netflix.concurrency.limits.Limit; + +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.function.LongSupplier; + +import infra.remoting.frame.FrameType; +import infra.remoting.plugins.RequestInterceptor; +import io.netty.buffer.ByteBuf; +import reactor.util.annotation.Nullable; + +public class LimitBasedStatsCollector extends AtomicBoolean implements RequestInterceptor { + + final LeaseManager leaseManager; + final Limit limitAlgorithm; + + final ConcurrentMap inFlightMap = new ConcurrentHashMap<>(); + final ConcurrentMap timeMap = new ConcurrentHashMap<>(); + + final LongSupplier clock = System::nanoTime; + + public LimitBasedStatsCollector(LeaseManager leaseManager, Limit limitAlgorithm) { + this.leaseManager = leaseManager; + this.limitAlgorithm = limitAlgorithm; + } + + @Override + public void onStart(int streamId, FrameType requestType, @Nullable ByteBuf metadata) { + long startTime = clock.getAsLong(); + + int currentInFlight = leaseManager.incrementInFlightAndGet(); + + inFlightMap.put(streamId, currentInFlight); + timeMap.put(streamId, startTime); + } + + @Override + public void onReject( + Throwable rejectionReason, FrameType requestType, @Nullable ByteBuf metadata) { } + + @Override + public void onTerminate(int streamId, FrameType requestType, @Nullable Throwable t) { + leaseManager.decrementInFlight(); + + Long startTime = timeMap.remove(streamId); + Integer currentInflight = inFlightMap.remove(streamId); + + limitAlgorithm.onSample(startTime, clock.getAsLong() - startTime, currentInflight, t != null); + } + + @Override + public void onCancel(int streamId, FrameType requestType) { + leaseManager.decrementInFlight(); + + Long startTime = timeMap.remove(streamId); + Integer currentInflight = inFlightMap.remove(streamId); + + limitAlgorithm.onSample(startTime, clock.getAsLong() - startTime, currentInflight, true); + } + + @Override + public boolean isDisposed() { + return get(); + } + + @Override + public void dispose() { + if (!getAndSet(true)) { + leaseManager.unregister(); + } + } +} diff --git a/today-remoting/src/test/java/infra/remoting/examples/tcp/lease/advanced/controller/Task.java b/today-remoting/src/test/java/infra/remoting/examples/tcp/lease/advanced/controller/Task.java new file mode 100644 index 0000000..1b5ebea --- /dev/null +++ b/today-remoting/src/test/java/infra/remoting/examples/tcp/lease/advanced/controller/Task.java @@ -0,0 +1,45 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.remoting.examples.tcp.lease.advanced.controller; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +// emulating a worker that process data from the queue +public class Task implements Runnable { + private static final Logger logger = LoggerFactory.getLogger(Task.class); + + final String message; + final int processingTime; + + Task(String message, int processingTime) { + this.message = message; + this.processingTime = processingTime; + } + + @Override + public void run() { + logger.info("Processing Task[{}]", message); + try { + Thread.sleep(processingTime); // emulating processing + } + catch (InterruptedException e) { + throw new RuntimeException(e); + } + } +} diff --git a/today-remoting/src/test/java/infra/remoting/examples/tcp/lease/advanced/controller/TasksHandlingChannel.java b/today-remoting/src/test/java/infra/remoting/examples/tcp/lease/advanced/controller/TasksHandlingChannel.java new file mode 100644 index 0000000..20f5cd3 --- /dev/null +++ b/today-remoting/src/test/java/infra/remoting/examples/tcp/lease/advanced/controller/TasksHandlingChannel.java @@ -0,0 +1,62 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.remoting.examples.tcp.lease.advanced.controller; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import infra.remoting.Channel; +import infra.remoting.Payload; +import reactor.core.Disposable; +import reactor.core.publisher.Mono; +import reactor.core.scheduler.Scheduler; + +public class TasksHandlingChannel implements Channel { + + private static final Logger logger = LoggerFactory.getLogger(TasksHandlingChannel.class); + + final Disposable terminatable; + final Scheduler workScheduler; + final int processingTime; + + public TasksHandlingChannel(Disposable terminatable, Scheduler scheduler, int processingTime) { + this.terminatable = terminatable; + this.workScheduler = scheduler; + this.processingTime = processingTime; + } + + @Override + public Mono fireAndForget(Payload payload) { + + // specifically to show that lease can limit rate of fnf requests in + // that example + String message = payload.getDataUtf8(); + payload.release(); + + return Mono.fromRunnable(new Task(message, processingTime)) + // schedule task on specific, limited in size scheduler + .subscribeOn(workScheduler) + // if errors - terminates server + .doOnError( + t -> { + logger.error("Queue has been overflowed. Terminating server"); + terminatable.dispose(); + System.exit(9); + }); + } +} diff --git a/today-remoting/src/test/java/infra/remoting/examples/tcp/lease/advanced/invertmulticlient/RequestingServer.java b/today-remoting/src/test/java/infra/remoting/examples/tcp/lease/advanced/invertmulticlient/RequestingServer.java new file mode 100644 index 0000000..458c2db --- /dev/null +++ b/today-remoting/src/test/java/infra/remoting/examples/tcp/lease/advanced/invertmulticlient/RequestingServer.java @@ -0,0 +1,80 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.remoting.examples.tcp.lease.advanced.invertmulticlient; + +import java.util.Comparator; +import java.util.concurrent.PriorityBlockingQueue; + +import infra.logging.Logger; +import infra.logging.LoggerFactory; +import infra.remoting.Channel; +import infra.remoting.core.RemotingServer; +import infra.remoting.transport.netty.server.CloseableChannel; +import infra.remoting.transport.netty.server.TcpServerTransport; +import infra.remoting.util.ByteBufPayload; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +public class RequestingServer { + + private static final Logger logger = LoggerFactory.getLogger(RequestingServer.class); + + public static void main(String[] args) { + PriorityBlockingQueue channels = + new PriorityBlockingQueue<>( + 16, Comparator.comparingDouble(Channel::availability).reversed()); + + CloseableChannel server = + RemotingServer.create( + (setup, channel) -> { + logger.info("Received new connection"); + return Mono.just(new Channel() { }) + .doAfterTerminate(() -> channels.put(channel)); + }) + .lease(spec -> spec.maxPendingRequests(Integer.MAX_VALUE)) + .bindNow(TcpServerTransport.create("localhost", 7000)); + + logger.info("Server started on port {}", server.address().getPort()); + + // generate stream of fnfs + Flux.generate( + () -> 0L, + (state, sink) -> { + sink.next(state); + return state + 1; + }) + .flatMap( + tick -> { + logger.info("Requesting FireAndForget({})", tick); + + return Mono.fromCallable( + () -> { + Channel channel = channels.take(); + channels.offer(channel); + return channel; + }) + .flatMap( + clientChannel -> + clientChannel.fireAndForget(ByteBufPayload.create("" + tick))) + .retry(); + }) + .blockLast(); + + server.onClose().block(); + } +} diff --git a/today-remoting/src/test/java/infra/remoting/examples/tcp/lease/advanced/invertmulticlient/RespondingClient.java b/today-remoting/src/test/java/infra/remoting/examples/tcp/lease/advanced/invertmulticlient/RespondingClient.java new file mode 100644 index 0000000..847d03c --- /dev/null +++ b/today-remoting/src/test/java/infra/remoting/examples/tcp/lease/advanced/invertmulticlient/RespondingClient.java @@ -0,0 +1,87 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.remoting.examples.tcp.lease.advanced.invertmulticlient; + +import com.netflix.concurrency.limits.limit.VegasLimit; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Objects; +import java.util.UUID; +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +import infra.remoting.Channel; +import infra.remoting.ChannelAcceptor; +import infra.remoting.core.ChannelConnector; +import infra.remoting.examples.tcp.lease.advanced.common.LeaseManager; +import infra.remoting.examples.tcp.lease.advanced.common.LimitBasedLeaseSender; +import infra.remoting.examples.tcp.lease.advanced.controller.TasksHandlingChannel; +import infra.remoting.transport.netty.client.TcpClientTransport; +import reactor.core.Disposable; +import reactor.core.Disposables; +import reactor.core.scheduler.Scheduler; +import reactor.core.scheduler.Schedulers; + +public class RespondingClient { + private static final Logger logger = LoggerFactory.getLogger(RespondingClient.class); + + public static final int PROCESSING_TASK_TIME = 500; + public static final int CONCURRENT_WORKERS_COUNT = 1; + public static final int QUEUE_CAPACITY = 50; + + public static void main(String[] args) { + // Queue for incoming messages represented as Flux + // Imagine that every fireAndForget that is pushed is processed by a worker + BlockingQueue tasksQueue = new ArrayBlockingQueue<>(QUEUE_CAPACITY); + + ThreadPoolExecutor threadPoolExecutor = + new ThreadPoolExecutor(1, CONCURRENT_WORKERS_COUNT, 1, TimeUnit.MINUTES, tasksQueue); + + Scheduler workScheduler = Schedulers.fromExecutorService(threadPoolExecutor); + + LeaseManager periodicLeaseSender = + new LeaseManager(CONCURRENT_WORKERS_COUNT, PROCESSING_TASK_TIME); + + Disposable.Composite disposable = Disposables.composite(); + Channel clientChannel = + ChannelConnector.create() + .acceptor( + ChannelAcceptor.with( + new TasksHandlingChannel(disposable, workScheduler, PROCESSING_TASK_TIME))) + .lease( + (config) -> + config.sender( + new LimitBasedLeaseSender( + UUID.randomUUID().toString(), + periodicLeaseSender, + VegasLimit.newBuilder() + .initialLimit(CONCURRENT_WORKERS_COUNT) + .maxConcurrency(QUEUE_CAPACITY) + .build()))) + .connect(TcpClientTransport.create("localhost", 7000)) + .block(); + + Objects.requireNonNull(clientChannel); + disposable.add(clientChannel); + clientChannel.onClose().block(); + } +} diff --git a/today-remoting/src/test/java/infra/remoting/examples/tcp/lease/advanced/multiclient/RequestingClient.java b/today-remoting/src/test/java/infra/remoting/examples/tcp/lease/advanced/multiclient/RequestingClient.java new file mode 100644 index 0000000..6a236eb --- /dev/null +++ b/today-remoting/src/test/java/infra/remoting/examples/tcp/lease/advanced/multiclient/RequestingClient.java @@ -0,0 +1,59 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.remoting.examples.tcp.lease.advanced.multiclient; + +import java.util.Objects; + +import infra.logging.Logger; +import infra.logging.LoggerFactory; +import infra.remoting.Channel; +import infra.remoting.core.ChannelConnector; +import infra.remoting.transport.netty.client.TcpClientTransport; +import infra.remoting.util.ByteBufPayload; +import reactor.core.publisher.Flux; + +public class RequestingClient { + private static final Logger logger = LoggerFactory.getLogger(RequestingClient.class); + + public static void main(String[] args) { + + Channel clientChannel = + ChannelConnector.create() + .lease() + .connect(TcpClientTransport.create("localhost", 7000)) + .block(); + + Objects.requireNonNull(clientChannel); + + // generate stream of fnfs + Flux.generate( + () -> 0L, + (state, sink) -> { + sink.next(state); + return state + 1; + }) + .concatMap( + tick -> { + logger.info("Requesting FireAndForget({})", tick); + return clientChannel.fireAndForget(ByteBufPayload.create("" + tick)); + }) + .blockLast(); + + clientChannel.onClose().block(); + } +} diff --git a/today-remoting/src/test/java/infra/remoting/examples/tcp/lease/advanced/multiclient/RespondingServer.java b/today-remoting/src/test/java/infra/remoting/examples/tcp/lease/advanced/multiclient/RespondingServer.java new file mode 100644 index 0000000..f490c40 --- /dev/null +++ b/today-remoting/src/test/java/infra/remoting/examples/tcp/lease/advanced/multiclient/RespondingServer.java @@ -0,0 +1,84 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.remoting.examples.tcp.lease.advanced.multiclient; + +import com.netflix.concurrency.limits.limit.VegasLimit; + +import java.util.UUID; +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +import infra.logging.Logger; +import infra.logging.LoggerFactory; +import infra.remoting.ChannelAcceptor; +import infra.remoting.core.RemotingServer; +import infra.remoting.examples.tcp.lease.advanced.common.LeaseManager; +import infra.remoting.examples.tcp.lease.advanced.common.LimitBasedLeaseSender; +import infra.remoting.examples.tcp.lease.advanced.controller.TasksHandlingChannel; +import infra.remoting.transport.netty.server.CloseableChannel; +import infra.remoting.transport.netty.server.TcpServerTransport; +import reactor.core.Disposable; +import reactor.core.Disposables; +import reactor.core.scheduler.Scheduler; +import reactor.core.scheduler.Schedulers; + +public class RespondingServer { + + private static final Logger logger = LoggerFactory.getLogger(RespondingServer.class); + + public static final int TASK_PROCESSING_TIME = 500; + public static final int CONCURRENT_WORKERS_COUNT = 1; + public static final int QUEUE_CAPACITY = 50; + + public static void main(String[] args) { + // Queue for incoming messages represented as Flux + // Imagine that every fireAndForget that is pushed is processed by a worker + BlockingQueue tasksQueue = new ArrayBlockingQueue<>(QUEUE_CAPACITY); + + ThreadPoolExecutor threadPoolExecutor = + new ThreadPoolExecutor(1, CONCURRENT_WORKERS_COUNT, 1, TimeUnit.MINUTES, tasksQueue); + + Scheduler workScheduler = Schedulers.fromExecutorService(threadPoolExecutor); + + LeaseManager leaseManager = new LeaseManager(CONCURRENT_WORKERS_COUNT, TASK_PROCESSING_TIME); + + Disposable.Composite disposable = Disposables.composite(); + CloseableChannel server = + RemotingServer.create( + ChannelAcceptor.with( + new TasksHandlingChannel(disposable, workScheduler, TASK_PROCESSING_TIME))) + .lease( + (config) -> + config.sender( + new LimitBasedLeaseSender( + UUID.randomUUID().toString(), + leaseManager, + VegasLimit.newBuilder() + .initialLimit(CONCURRENT_WORKERS_COUNT) + .maxConcurrency(QUEUE_CAPACITY) + .build()))) + .bindNow(TcpServerTransport.create("localhost", 7000)); + + disposable.add(server); + + logger.info("Server started on port {}", server.address().getPort()); + server.onClose().block(); + } +} diff --git a/today-remoting/src/test/java/infra/remoting/examples/tcp/lease/simple/LeaseExample.java b/today-remoting/src/test/java/infra/remoting/examples/tcp/lease/simple/LeaseExample.java new file mode 100644 index 0000000..575c6d0 --- /dev/null +++ b/today-remoting/src/test/java/infra/remoting/examples/tcp/lease/simple/LeaseExample.java @@ -0,0 +1,161 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.remoting.examples.tcp.lease.simple; + +import java.time.Duration; +import java.util.Objects; +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.BlockingQueue; + +import infra.logging.Logger; +import infra.logging.LoggerFactory; +import infra.remoting.Channel; +import infra.remoting.Payload; +import infra.remoting.core.ChannelConnector; +import infra.remoting.core.RemotingServer; +import infra.remoting.lease.Lease; +import infra.remoting.lease.LeaseSender; +import infra.remoting.transport.netty.client.TcpClientTransport; +import infra.remoting.transport.netty.server.CloseableChannel; +import infra.remoting.transport.netty.server.TcpServerTransport; +import infra.remoting.util.ByteBufPayload; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +public class LeaseExample { + + private static final Logger logger = LoggerFactory.getLogger(LeaseExample.class); + + private static final String SERVER_TAG = "server"; + private static final String CLIENT_TAG = "client"; + + public static void main(String[] args) { + // Queue for incoming messages represented as Flux + // Imagine that every fireAndForget that is pushed is processed by a worker + + int queueCapacity = 50; + BlockingQueue messagesQueue = new ArrayBlockingQueue<>(queueCapacity); + + // emulating a worker that process data from the queue + Thread workerThread = + new Thread( + () -> { + try { + while (!Thread.currentThread().isInterrupted()) { + String message = messagesQueue.take(); + logger.info("Process message {}", message); + Thread.sleep(500); // emulating processing + } + } + catch (InterruptedException e) { + throw new RuntimeException(e); + } + }); + + workerThread.start(); + + CloseableChannel server = RemotingServer.create((setup, sendingSocket) -> + Mono.just(new Channel() { + @Override + public Mono fireAndForget(Payload payload) { + // add element. if overflows errors and terminates execution + // specifically to show that lease can limit rate of fnf requests in + // that example + try { + if (!messagesQueue.offer(payload.getDataUtf8())) { + logger.error("Queue has been overflowed. Terminating execution"); + sendingSocket.dispose(); + workerThread.interrupt(); + } + } + finally { + payload.release(); + } + return Mono.empty(); + } + })) + .lease(leases -> leases.sender(new LeaseCalculator(SERVER_TAG, messagesQueue))) + .bindNow(TcpServerTransport.create("localhost", 7000)); + + Channel clientChannel = + ChannelConnector.create() + .lease((config) -> config.maxPendingRequests(1)) + .connect(TcpClientTransport.create(server.address())) + .block(); + + Objects.requireNonNull(clientChannel); + + // generate stream of fnfs + Flux.generate( + () -> 0L, + (state, sink) -> { + sink.next(state); + return state + 1; + }) + // here we wait for the first lease for the responder side and start execution + // on if there is allowance + .concatMap( + tick -> { + logger.info("Requesting FireAndForget({})", tick); + return clientChannel.fireAndForget(ByteBufPayload.create("" + tick)); + }) + .blockLast(); + + clientChannel.onClose().block(); + server.dispose(); + } + + /** + * This is a class responsible for making decision on whether Responder is ready to receive new + * FireAndForget or not base in the number of messages enqueued.
    + * In the nutshell this is responder-side rate-limiter logic which is created for every new + * connection.
    + * In real-world projects this class has to issue leases based on real metrics + */ + private static class LeaseCalculator implements LeaseSender { + final String tag; + final BlockingQueue queue; + + public LeaseCalculator(String tag, BlockingQueue queue) { + this.tag = tag; + this.queue = queue; + } + + @Override + public Flux send() { + Duration ttlDuration = Duration.ofSeconds(5); + // The interval function is used only for the demo purpose and should not be + // considered as the way to issue leases. + // For advanced RateLimiting with Leasing + // consider adopting https://github.com/Netflix/concurrency-limits#server-limiter + return Flux.interval(Duration.ZERO, ttlDuration.dividedBy(2)) + .handle( + (__, sink) -> { + // put queue.remainingCapacity() + 1 here if you want to observe that app is + // terminated because of the queue overflowing + int requests = queue.remainingCapacity(); + + // reissue new lease only if queue has remaining capacity to + // accept more requests + if (requests > 0) { + sink.next(Lease.create(ttlDuration, requests)); + } + }); + } + } +} diff --git a/today-remoting/src/test/java/infra/remoting/examples/tcp/loadbalancer/RoundRobinLoadbalancerExample.java b/today-remoting/src/test/java/infra/remoting/examples/tcp/loadbalancer/RoundRobinLoadbalancerExample.java new file mode 100644 index 0000000..0d6ba34 --- /dev/null +++ b/today-remoting/src/test/java/infra/remoting/examples/tcp/loadbalancer/RoundRobinLoadbalancerExample.java @@ -0,0 +1,113 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ +package infra.remoting.examples.tcp.loadbalancer; + +import java.time.Duration; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import infra.remoting.ChannelAcceptor; +import infra.remoting.core.RemotingClient; +import infra.remoting.core.RemotingServer; +import infra.remoting.lb.LoadBalanceRemotingClient; +import infra.remoting.lb.LoadBalanceTarget; +import infra.remoting.transport.netty.client.TcpClientTransport; +import infra.remoting.transport.netty.server.CloseableChannel; +import infra.remoting.transport.netty.server.TcpServerTransport; +import infra.remoting.util.DefaultPayload; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +public class RoundRobinLoadbalancerExample { + + public static void main(String[] args) { + CloseableChannel server1 = + RemotingServer.create( + ChannelAcceptor.forRequestResponse( + p -> { + System.out.println("Server 1 got fnf " + p.getDataUtf8()); + return Mono.just(DefaultPayload.create("Server 1 response")) + .delayElement(Duration.ofMillis(100)); + })) + .bindNow(TcpServerTransport.create(8080)); + + CloseableChannel server2 = + RemotingServer.create( + ChannelAcceptor.forRequestResponse( + p -> { + System.out.println("Server 2 got fnf " + p.getDataUtf8()); + return Mono.just(DefaultPayload.create("Server 2 response")) + .delayElement(Duration.ofMillis(100)); + })) + .bindNow(TcpServerTransport.create(8081)); + + CloseableChannel server3 = + RemotingServer.create( + ChannelAcceptor.forRequestResponse( + p -> { + System.out.println("Server 3 got fnf " + p.getDataUtf8()); + return Mono.just(DefaultPayload.create("Server 3 response")) + .delayElement(Duration.ofMillis(100)); + })) + .bindNow(TcpServerTransport.create(8082)); + + LoadBalanceTarget target8080 = LoadBalanceTarget.of("8080", TcpClientTransport.create(8080)); + LoadBalanceTarget target8081 = LoadBalanceTarget.of("8081", TcpClientTransport.create(8081)); + LoadBalanceTarget target8082 = LoadBalanceTarget.of("8082", TcpClientTransport.create(8082)); + + Flux> producer = + Flux.interval(Duration.ofSeconds(5)) + .log() + .map( + i -> { + int val = i.intValue(); + switch (val) { + case 0: + return Collections.emptyList(); + case 1: + return Collections.singletonList(target8080); + case 2: + return Arrays.asList(target8080, target8081); + case 3: + return Arrays.asList(target8080, target8082); + case 4: + return Arrays.asList(target8081, target8082); + case 5: + return Arrays.asList(target8080, target8081, target8082); + case 6: + return Collections.emptyList(); + case 7: + return Collections.emptyList(); + default: + return Arrays.asList(target8080, target8081, target8082); + } + }); + + RemotingClient client = + LoadBalanceRemotingClient.builder(producer).roundRobinLoadBalanceStrategy().build(); + + for (int i = 0; i < 10000; i++) { + try { + client.requestResponse(Mono.just(DefaultPayload.create("test" + i))).block(); + } + catch (Throwable t) { + // no ops + } + } + } +} diff --git a/today-remoting/src/test/java/infra/remoting/examples/tcp/plugins/LimitRateInterceptorExample.java b/today-remoting/src/test/java/infra/remoting/examples/tcp/plugins/LimitRateInterceptorExample.java new file mode 100644 index 0000000..1ab1b78 --- /dev/null +++ b/today-remoting/src/test/java/infra/remoting/examples/tcp/plugins/LimitRateInterceptorExample.java @@ -0,0 +1,102 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.remoting.examples.tcp.plugins; + +import org.reactivestreams.Publisher; + +import java.time.Duration; + +import infra.logging.Logger; +import infra.logging.LoggerFactory; +import infra.remoting.Channel; +import infra.remoting.ChannelAcceptor; +import infra.remoting.Payload; +import infra.remoting.core.ChannelConnector; +import infra.remoting.core.RemotingServer; +import infra.remoting.plugins.RateLimitDecorator; +import infra.remoting.transport.netty.client.TcpClientTransport; +import infra.remoting.transport.netty.server.TcpServerTransport; +import infra.remoting.util.DefaultPayload; +import reactor.core.publisher.Flux; + +public class LimitRateInterceptorExample { + + private static final Logger logger = LoggerFactory.getLogger(LimitRateInterceptorExample.class); + + public static void main(String[] args) { + RemotingServer.create( + ChannelAcceptor.with( + new Channel() { + @Override + public Flux requestStream(Payload payload) { + return Flux.interval(Duration.ofMillis(100)) + .doOnRequest( + e -> logger.debug("Server publisher receives request for " + e)) + .map(aLong -> DefaultPayload.create("Interval: " + aLong)); + } + + @Override + public Flux requestChannel(Publisher payloads) { + return Flux.from(payloads) + .doOnRequest( + e -> logger.debug("Server publisher receives request for " + e)); + } + })) + .interceptors(registry -> registry.forResponder(RateLimitDecorator.forResponder(64))) + .bindNow(TcpServerTransport.create("localhost", 7000)); + + Channel socket = + ChannelConnector.create() + .interceptors(registry -> registry.forRequester(RateLimitDecorator.forRequester(64))) + .connect(TcpClientTransport.create("localhost", 7000)) + .block(); + + logger.debug( + "\n\nStart of requestStream interaction\n" + "----------------------------------\n"); + + socket + .requestStream(DefaultPayload.create("Hello")) + .doOnRequest(e -> logger.debug("Client sends requestN(" + e + ")")) + .map(Payload::getDataUtf8) + .doOnNext(logger::debug) + .take(10) + .then() + .block(); + + logger.debug( + "\n\nStart of requestChannel interaction\n" + "-----------------------------------\n"); + + socket + .requestChannel( + Flux.generate( + () -> 1L, + (s, sink) -> { + sink.next(DefaultPayload.create("Next " + s)); + return ++s; + }) + .doOnRequest(e -> logger.debug("Client publisher receives request for " + e))) + .doOnRequest(e -> logger.debug("Client sends requestN(" + e + ")")) + .map(Payload::getDataUtf8) + .doOnNext(logger::debug) + .take(10) + .then() + .doFinally(signalType -> socket.dispose()) + .then() + .block(); + } +} diff --git a/today-remoting/src/test/java/infra/remoting/examples/tcp/requestresponse/HelloWorldClient.java b/today-remoting/src/test/java/infra/remoting/examples/tcp/requestresponse/HelloWorldClient.java new file mode 100644 index 0000000..e9bb75f --- /dev/null +++ b/today-remoting/src/test/java/infra/remoting/examples/tcp/requestresponse/HelloWorldClient.java @@ -0,0 +1,70 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.remoting.examples.tcp.requestresponse; + +import infra.logging.Logger; +import infra.logging.LoggerFactory; +import infra.remoting.Channel; +import infra.remoting.ChannelAcceptor; +import infra.remoting.Payload; +import infra.remoting.core.ChannelConnector; +import infra.remoting.core.RemotingServer; +import infra.remoting.transport.netty.client.TcpClientTransport; +import infra.remoting.transport.netty.server.TcpServerTransport; +import infra.remoting.util.DefaultPayload; +import reactor.core.publisher.Mono; + +public final class HelloWorldClient { + + private static final Logger logger = LoggerFactory.getLogger(HelloWorldClient.class); + + public static void main(String[] args) { + + Channel channel = new Channel() { + boolean fail = true; + + @Override + public Mono requestResponse(Payload p) { + if (fail) { + fail = false; + return Mono.error(new Throwable("Simulated error")); + } + else { + return Mono.just(p); + } + } + }; + + RemotingServer.create(ChannelAcceptor.with(channel)) + .bindNow(TcpServerTransport.create("localhost", 7000)); + + Channel socket = + ChannelConnector.connectWith(TcpClientTransport.create("localhost", 7000)).block(); + + for (int i = 0; i < 3; i++) { + socket + .requestResponse(DefaultPayload.create("Hello")) + .map(Payload::getDataUtf8) + .onErrorReturn("error") + .doOnNext(logger::debug) + .block(); + } + + socket.dispose(); + } +} diff --git a/today-remoting/src/test/java/infra/remoting/examples/tcp/resume/Files.java b/today-remoting/src/test/java/infra/remoting/examples/tcp/resume/Files.java new file mode 100644 index 0000000..ce2e17d --- /dev/null +++ b/today-remoting/src/test/java/infra/remoting/examples/tcp/resume/Files.java @@ -0,0 +1,166 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.remoting.examples.tcp.resume; + +import org.reactivestreams.Subscriber; +import org.reactivestreams.Subscription; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.BufferedInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +import infra.remoting.Payload; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import reactor.core.publisher.Flux; +import reactor.core.publisher.SynchronousSink; + +class Files { + private static final Logger logger = LoggerFactory.getLogger(Files.class); + + public static Flux fileSource(String fileName, int chunkSizeBytes) { + return Flux.generate( + () -> new FileState(fileName, chunkSizeBytes), FileState::consumeNext, FileState::dispose); + } + + public static Subscriber fileSink(String fileName, int windowSize) { + return new Subscriber() { + Subscription s; + int requests = windowSize; + OutputStream outputStream; + int receivedBytes; + int receivedCount; + + @Override + public void onSubscribe(Subscription s) { + this.s = s; + this.s.request(requests); + } + + @Override + public void onNext(Payload payload) { + ByteBuf data = payload.data(); + receivedBytes += data.readableBytes(); + receivedCount += 1; + logger.debug("Received file chunk: " + receivedCount + ". Total size: " + receivedBytes); + if (outputStream == null) { + outputStream = open(fileName); + } + write(outputStream, data); + payload.release(); + + requests--; + if (requests == windowSize / 2) { + requests += windowSize; + s.request(windowSize); + } + } + + private void write(OutputStream outputStream, ByteBuf byteBuf) { + try { + byteBuf.readBytes(outputStream, byteBuf.readableBytes()); + } + catch (IOException e) { + throw new RuntimeException(e); + } + } + + @Override + public void onError(Throwable t) { + close(outputStream); + } + + @Override + public void onComplete() { + close(outputStream); + } + + private OutputStream open(String filename) { + try { + /*do not buffer for demo purposes*/ + return new FileOutputStream(filename); + } + catch (FileNotFoundException e) { + throw new RuntimeException(e); + } + } + + private void close(OutputStream stream) { + if (stream != null) { + try { + stream.close(); + } + catch (IOException e) { + } + } + } + }; + } + + private static class FileState { + private final String fileName; + private final int chunkSizeBytes; + private BufferedInputStream inputStream; + private byte[] chunkBytes; + + public FileState(String fileName, int chunkSizeBytes) { + this.fileName = fileName; + this.chunkSizeBytes = chunkSizeBytes; + } + + public FileState consumeNext(SynchronousSink sink) { + if (inputStream == null) { + InputStream in = getClass().getClassLoader().getResourceAsStream(fileName); + if (in == null) { + sink.error(new FileNotFoundException(fileName)); + return this; + } + this.inputStream = new BufferedInputStream(in); + this.chunkBytes = new byte[chunkSizeBytes]; + } + try { + int consumedBytes = inputStream.read(chunkBytes); + if (consumedBytes == -1) { + sink.complete(); + } + else { + sink.next(Unpooled.copiedBuffer(chunkBytes, 0, consumedBytes)); + } + } + catch (IOException e) { + sink.error(e); + } + return this; + } + + public void dispose() { + if (inputStream != null) { + try { + inputStream.close(); + } + catch (IOException e) { + } + } + } + } +} diff --git a/today-remoting/src/test/java/infra/remoting/examples/tcp/resume/ResumeFileTransfer.java b/today-remoting/src/test/java/infra/remoting/examples/tcp/resume/ResumeFileTransfer.java new file mode 100644 index 0000000..0d2a673 --- /dev/null +++ b/today-remoting/src/test/java/infra/remoting/examples/tcp/resume/ResumeFileTransfer.java @@ -0,0 +1,116 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.remoting.examples.tcp.resume; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.time.Duration; + +import infra.remoting.Channel; +import infra.remoting.ChannelAcceptor; +import infra.remoting.Payload; +import infra.remoting.core.ChannelConnector; +import infra.remoting.core.RemotingServer; +import infra.remoting.core.Resume; +import infra.remoting.transport.netty.client.TcpClientTransport; +import infra.remoting.transport.netty.server.CloseableChannel; +import infra.remoting.transport.netty.server.TcpServerTransport; +import infra.remoting.util.DefaultPayload; +import reactor.core.publisher.Flux; +import reactor.util.retry.Retry; + +public class ResumeFileTransfer { + + /*amount of file chunks requested by subscriber: n, refilled on n/2 of received items*/ + private static final int PREFETCH_WINDOW_SIZE = 4; + private static final Logger logger = LoggerFactory.getLogger(ResumeFileTransfer.class); + + public static void main(String[] args) { + + Resume resume = new Resume() + .sessionDuration(Duration.ofMinutes(5)) + .retry(Retry.fixedDelay(Long.MAX_VALUE, Duration.ofSeconds(1)) + .doBeforeRetry(s -> logger.debug("Disconnected. Trying to resume..."))); + + RequestCodec codec = new RequestCodec(); + + CloseableChannel server = RemotingServer.create(ChannelAcceptor.forRequestStream(payload -> { + Request request = codec.decode(payload); + payload.release(); + String fileName = request.getFileName(); + int chunkSize = request.getChunkSize(); + + Flux ticks = Flux.interval(Duration.ofMillis(500)).onBackpressureDrop(); + + return Files.fileSource(fileName, chunkSize) + .map(DefaultPayload::create) + .zipWith(ticks, (p, tick) -> p) + .log("server"); + })) + .resume(resume) + .bindNow(TcpServerTransport.create("localhost", 8000)); + + Channel client = + ChannelConnector.create() + .resume(resume) + .connect(TcpClientTransport.create("localhost", 8001)) + .block(); + + client.requestStream(codec.encode(new Request(16, "lorem.txt"))) + .log("client") + .doFinally(s -> server.dispose()) + .subscribe(Files.fileSink("today-remoting/build/lorem_output.txt", PREFETCH_WINDOW_SIZE)); + + server.onClose().block(); + } + + private static class RequestCodec { + + public Payload encode(Request request) { + String encoded = request.getChunkSize() + ":" + request.getFileName(); + return DefaultPayload.create(encoded); + } + + public Request decode(Payload payload) { + String encoded = payload.getDataUtf8(); + String[] chunkSizeAndFileName = encoded.split(":"); + int chunkSize = Integer.parseInt(chunkSizeAndFileName[0]); + String fileName = chunkSizeAndFileName[1]; + return new Request(chunkSize, fileName); + } + } + + private static class Request { + private final int chunkSize; + private final String fileName; + + public Request(int chunkSize, String fileName) { + this.chunkSize = chunkSize; + this.fileName = fileName; + } + + public int getChunkSize() { + return chunkSize; + } + + public String getFileName() { + return fileName; + } + } +} diff --git a/today-remoting/src/test/java/infra/remoting/examples/tcp/resume/readme.md b/today-remoting/src/test/java/infra/remoting/examples/tcp/resume/readme.md new file mode 100644 index 0000000..55e761f --- /dev/null +++ b/today-remoting/src/test/java/infra/remoting/examples/tcp/resume/readme.md @@ -0,0 +1,29 @@ +1. Start socat. It is used for emulation of transport disconnects + +`socat -d TCP-LISTEN:8001,fork,reuseaddr TCP:localhost:8000` + +2. start `ResumeFileTransfer.main` + +3. terminate/start socat periodically for session resumption + +`ResumeFileTransfer` output is as follows + +``` +Received file chunk: 7. Total size: 112 +Received file chunk: 8. Total size: 128 +Received file chunk: 9. Total size: 144 +Received file chunk: 10. Total size: 160 +Disconnected. Trying to resume connection... +Disconnected. Trying to resume connection... +Disconnected. Trying to resume connection... +Disconnected. Trying to resume connection... +Disconnected. Trying to resume connection... +Received file chunk: 11. Total size: 176 +Received file chunk: 12. Total size: 192 +Received file chunk: 13. Total size: 208 +Received file chunk: 14. Total size: 224 +Received file chunk: 15. Total size: 240 +Received file chunk: 16. Total size: 256 +``` + +It transfers file from `resources/lorem.txt` to `build/out/lorem_output.txt` in chunks of 16 bytes every 500 millis diff --git a/today-remoting/src/test/java/infra/remoting/examples/tcp/stream/ClientStreamingToServer.java b/today-remoting/src/test/java/infra/remoting/examples/tcp/stream/ClientStreamingToServer.java new file mode 100644 index 0000000..30f68b5 --- /dev/null +++ b/today-remoting/src/test/java/infra/remoting/examples/tcp/stream/ClientStreamingToServer.java @@ -0,0 +1,65 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.remoting.examples.tcp.stream; + +import java.time.Duration; + +import infra.logging.Logger; +import infra.logging.LoggerFactory; +import infra.remoting.Channel; +import infra.remoting.ChannelAcceptor; +import infra.remoting.Payload; +import infra.remoting.core.ChannelConnector; +import infra.remoting.core.RemotingServer; +import infra.remoting.transport.netty.client.TcpClientTransport; +import infra.remoting.transport.netty.server.TcpServerTransport; +import infra.remoting.util.DefaultPayload; +import reactor.core.publisher.Flux; + +public final class ClientStreamingToServer { + + private static final Logger logger = LoggerFactory.getLogger(ClientStreamingToServer.class); + + public static void main(String[] args) throws InterruptedException { + RemotingServer.create( + ChannelAcceptor.forRequestStream( + payload -> + Flux.interval(Duration.ofMillis(100)) + .map(aLong -> DefaultPayload.create("Interval: " + aLong)))) + .bindNow(TcpServerTransport.create("localhost", 7000)); + + Channel socket = + ChannelConnector.create() + .setupPayload(DefaultPayload.create("test", "test")) + .connect(TcpClientTransport.create("localhost", 7000)) + .block(); + + final Payload payload = DefaultPayload.create("Hello"); + socket + .requestStream(payload) + .map(Payload::getDataUtf8) + .doOnNext(logger::debug) + .take(10) + .then() + .doFinally(signalType -> socket.dispose()) + .then() + .block(); + + Thread.sleep(1000000); + } +} diff --git a/today-remoting/src/test/java/infra/remoting/examples/tcp/stream/ServerStreamingToClient.java b/today-remoting/src/test/java/infra/remoting/examples/tcp/stream/ServerStreamingToClient.java new file mode 100644 index 0000000..f5c421f --- /dev/null +++ b/today-remoting/src/test/java/infra/remoting/examples/tcp/stream/ServerStreamingToClient.java @@ -0,0 +1,59 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.remoting.examples.tcp.stream; + +import java.time.Duration; + +import infra.remoting.Channel; +import infra.remoting.Payload; +import infra.remoting.core.ChannelConnector; +import infra.remoting.core.RemotingServer; +import infra.remoting.transport.netty.client.TcpClientTransport; +import infra.remoting.transport.netty.server.TcpServerTransport; +import infra.remoting.util.DefaultPayload; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +import static infra.remoting.ChannelAcceptor.forRequestStream; + +public final class ServerStreamingToClient { + + public static void main(String[] args) { + + RemotingServer.create((setup, channel) -> { + channel + .requestStream(DefaultPayload.create("Hello-Bidi")) + .map(Payload::getDataUtf8) + .log() + .subscribe(); + + return Mono.just(new Channel() { }); + }) + .bindNow(TcpServerTransport.create("localhost", 7000)); + + Channel channel = + ChannelConnector.create() + .acceptor(forRequestStream(payload -> + Flux.interval(Duration.ofSeconds(1)) + .map(aLong -> DefaultPayload.create("Bi-di Response => " + aLong)))) + .connect(TcpClientTransport.create("localhost", 7000)) + .block(); + + channel.onClose().block(); + } +} diff --git a/today-remoting/src/test/java/infra/remoting/examples/ws/WebSocketAggregationSample.java b/today-remoting/src/test/java/infra/remoting/examples/ws/WebSocketAggregationSample.java new file mode 100644 index 0000000..8db1c37 --- /dev/null +++ b/today-remoting/src/test/java/infra/remoting/examples/ws/WebSocketAggregationSample.java @@ -0,0 +1,77 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.remoting.examples.ws; + +import java.time.Duration; + +import infra.logging.Logger; +import infra.logging.LoggerFactory; +import infra.remoting.Channel; +import infra.remoting.ChannelAcceptor; +import infra.remoting.core.ChannelConnector; +import infra.remoting.core.RemotingServer; +import infra.remoting.frame.decoder.PayloadDecoder; +import infra.remoting.transport.ConnectionAcceptor; +import infra.remoting.transport.netty.WebsocketDuplexConnection; +import infra.remoting.transport.netty.client.WebsocketClientTransport; +import infra.remoting.util.ByteBufPayload; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; +import reactor.netty.Connection; +import reactor.netty.DisposableServer; +import reactor.netty.http.server.HttpServer; + +public class WebSocketAggregationSample { + + private static final Logger logger = LoggerFactory.getLogger(WebSocketAggregationSample.class); + + public static void main(String[] args) { + + ConnectionAcceptor connectionAcceptor = + RemotingServer.create(ChannelAcceptor.forRequestResponse(Mono::just)) + .payloadDecoder(PayloadDecoder.ZERO_COPY) + .asConnectionAcceptor(); + + DisposableServer server = + HttpServer.create() + .host("localhost") + .port(0) + .handle((req, res) -> res.sendWebsocket((in, out) -> connectionAcceptor + .accept(new WebsocketDuplexConnection( + (Connection) in.aggregateFrames())) + .then(out.neverComplete()))) + .bindNow(); + + WebsocketClientTransport transport = + WebsocketClientTransport.create(server.host(), server.port()); + + Channel clientChannel = + ChannelConnector.create() + .keepAlive(Duration.ofMinutes(10), Duration.ofMinutes(10)) + .payloadDecoder(PayloadDecoder.ZERO_COPY) + .connect(transport) + .block(); + + Flux.range(1, 100) + .concatMap(i -> clientChannel.requestResponse(ByteBufPayload.create("Hello " + i))) + .doOnNext(payload -> logger.debug("Processed " + payload.getDataUtf8())) + .blockLast(); + clientChannel.dispose(); + server.dispose(); + } +} diff --git a/today-remoting/src/test/java/infra/remoting/examples/ws/WebSocketHeadersSample.java b/today-remoting/src/test/java/infra/remoting/examples/ws/WebSocketHeadersSample.java new file mode 100644 index 0000000..b191e44 --- /dev/null +++ b/today-remoting/src/test/java/infra/remoting/examples/ws/WebSocketHeadersSample.java @@ -0,0 +1,98 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.remoting.examples.ws; + +import java.time.Duration; + +import infra.logging.Logger; +import infra.logging.LoggerFactory; +import infra.remoting.Channel; +import infra.remoting.ChannelAcceptor; +import infra.remoting.core.ChannelConnector; +import infra.remoting.core.RemotingServer; +import infra.remoting.frame.decoder.PayloadDecoder; +import infra.remoting.transport.ConnectionAcceptor; +import infra.remoting.transport.netty.WebsocketDuplexConnection; +import infra.remoting.transport.netty.client.WebsocketClientTransport; +import infra.remoting.util.ByteBufPayload; +import io.netty.handler.codec.http.HttpResponseStatus; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; +import reactor.netty.Connection; +import reactor.netty.DisposableServer; +import reactor.netty.http.server.HttpServer; + +public class WebSocketHeadersSample { + + private static final Logger logger = LoggerFactory.getLogger(WebSocketHeadersSample.class); + + public static void main(String[] args) { + + ConnectionAcceptor connectionAcceptor = + RemotingServer.create(ChannelAcceptor.forRequestResponse(Mono::just)) + .payloadDecoder(PayloadDecoder.ZERO_COPY) + .asConnectionAcceptor(); + + DisposableServer server = + HttpServer.create() + .host("localhost") + .port(0) + .route(routes -> routes.get( + "/", + (req, res) -> { + if (req.requestHeaders().containsValue("Authorization", "test", true)) { + return res.sendWebsocket((in, out) -> + connectionAcceptor + .accept(new WebsocketDuplexConnection((Connection) in)) + .then(out.neverComplete())); + } + res.status(HttpResponseStatus.UNAUTHORIZED); + return res.send(); + })) + .bindNow(); + + logger.debug( + "\n\nStart of Authorized WebSocket Connection\n----------------------------------\n"); + + WebsocketClientTransport transport = + WebsocketClientTransport.create(server.host(), server.port()) + .header("Authorization", "test"); + + Channel clientChannel = + ChannelConnector.create() + .keepAlive(Duration.ofMinutes(10), Duration.ofMinutes(10)) + .payloadDecoder(PayloadDecoder.ZERO_COPY) + .connect(transport) + .block(); + + Flux.range(1, 100) + .concatMap(i -> clientChannel.requestResponse(ByteBufPayload.create("Hello " + i))) + .doOnNext(payload -> logger.debug("Processed " + payload.getDataUtf8())) + .blockLast(); + clientChannel.dispose(); + + logger.debug( + "\n\nStart of Unauthorized WebSocket Upgrade\n----------------------------------\n"); + + ChannelConnector.create() + .keepAlive(Duration.ofMinutes(10), Duration.ofMinutes(10)) + .payloadDecoder(PayloadDecoder.ZERO_COPY) + .connect(WebsocketClientTransport.create(server.host(), server.port())) + .block(); + } +} diff --git a/today-remoting/src/test/java/infra/remoting/lb/LoadbalanceTests.java b/today-remoting/src/test/java/infra/remoting/lb/LoadbalanceTests.java index 16d87e7..2404c78 100644 --- a/today-remoting/src/test/java/infra/remoting/lb/LoadbalanceTests.java +++ b/today-remoting/src/test/java/infra/remoting/lb/LoadbalanceTests.java @@ -38,7 +38,7 @@ import infra.remoting.test.util.TestClientTransport; import infra.remoting.transport.ClientTransport; import infra.remoting.util.EmptyPayload; -import infra.remoting.util.ChannelDecorator; +import infra.remoting.util.ChannelWrapper; import reactor.core.CoreSubscriber; import reactor.core.publisher.Flux; import reactor.core.publisher.Hooks; @@ -405,7 +405,7 @@ public Mono fireAndForget(Payload payload) { Assertions.assertThat(counter.get()).isOne(); } - static class TestChannel extends ChannelDecorator { + static class TestChannel extends ChannelWrapper { final Sinks.Empty sink = Sinks.empty(); diff --git a/today-remoting/src/test/java/infra/remoting/resume/DisconnectableClientTransport.java b/today-remoting/src/test/java/infra/remoting/resume/DisconnectableClientTransport.java new file mode 100644 index 0000000..8b3d90e --- /dev/null +++ b/today-remoting/src/test/java/infra/remoting/resume/DisconnectableClientTransport.java @@ -0,0 +1,78 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.remoting.resume; + +import java.nio.channels.ClosedChannelException; +import java.time.Duration; +import java.util.concurrent.atomic.AtomicReference; + +import infra.remoting.DuplexConnection; +import infra.remoting.transport.ClientTransport; +import reactor.core.publisher.Mono; + +class DisconnectableClientTransport implements ClientTransport { + + private final ClientTransport clientTransport; + + private final AtomicReference curConnection = new AtomicReference<>(); + + private long nextConnectPermitMillis; + + public DisconnectableClientTransport(ClientTransport clientTransport) { + this.clientTransport = clientTransport; + } + + @Override + public Mono connect() { + return Mono.defer(() -> + now() < nextConnectPermitMillis + ? Mono.error(new ClosedChannelException()) + : clientTransport.connect().map(c -> { + if (curConnection.compareAndSet(null, c)) { + return c; + } + else { + throw new IllegalStateException( + "Transport supports at most 1 connection"); + } + })); + } + + public void disconnect() { + disconnectFor(Duration.ZERO); + } + + public void disconnectPermanently() { + disconnectFor(Duration.ofDays(42)); + } + + public void disconnectFor(Duration cooldown) { + DuplexConnection cur = curConnection.getAndSet(null); + if (cur != null) { + nextConnectPermitMillis = now() + cooldown.toMillis(); + cur.dispose(); + } + else { + throw new IllegalStateException("Trying to disconnect while not connected"); + } + } + + private static long now() { + return System.currentTimeMillis(); + } +} diff --git a/today-remoting/src/test/java/infra/remoting/resume/ResumeIntegrationTests.java b/today-remoting/src/test/java/infra/remoting/resume/ResumeIntegrationTests.java new file mode 100644 index 0000000..61e773e --- /dev/null +++ b/today-remoting/src/test/java/infra/remoting/resume/ResumeIntegrationTests.java @@ -0,0 +1,227 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.remoting.resume; + +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.Test; +import org.reactivestreams.Publisher; + +import java.net.InetSocketAddress; +import java.nio.channels.ClosedChannelException; +import java.time.Duration; +import java.util.concurrent.atomic.AtomicInteger; + +import infra.remoting.Channel; +import infra.remoting.ChannelAcceptor; +import infra.remoting.Payload; +import infra.remoting.core.ChannelConnector; +import infra.remoting.core.RemotingServer; +import infra.remoting.core.Resume; +import infra.remoting.exceptions.RejectedResumeException; +import infra.remoting.exceptions.UnsupportedSetupException; +import infra.remoting.test.SlowTest; +import infra.remoting.transport.ClientTransport; +import infra.remoting.transport.ServerTransport; +import infra.remoting.transport.netty.client.TcpClientTransport; +import infra.remoting.transport.netty.server.CloseableChannel; +import infra.remoting.transport.netty.server.TcpServerTransport; +import infra.remoting.util.DefaultPayload; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; +import reactor.core.scheduler.Schedulers; +import reactor.test.StepVerifier; +import reactor.util.retry.Retry; + +@SlowTest +public class ResumeIntegrationTests { + + private static final String SERVER_HOST = "localhost"; + + private static final int SERVER_PORT = 0; + + @Test + void timeoutOnPermanentDisconnect() { + CloseableChannel closeable = newServerChannel().block(); + + DisconnectableClientTransport clientTransport = + new DisconnectableClientTransport(clientTransport(closeable.address())); + + int sessionDurationSeconds = 5; + Channel channel = newClientChannel(clientTransport, sessionDurationSeconds).block(); + + Mono.delay(Duration.ofSeconds(1)).subscribe(v -> clientTransport.disconnectPermanently()); + + StepVerifier.create(channel.requestChannel(testRequest()).then().doFinally(s -> closeable.dispose())) + .expectError(ClosedChannelException.class) + .verify(Duration.ofSeconds(7)); + } + + @Test + public void reconnectOnDisconnect() { + CloseableChannel closeable = newServerChannel().block(); + + DisconnectableClientTransport clientTransport = + new DisconnectableClientTransport(clientTransport(closeable.address())); + + int sessionDurationSeconds = 15; + Channel channel = newClientChannel(clientTransport, sessionDurationSeconds).block(); + + Flux.just(3, 20, 40, 75) + .flatMap(v -> Mono.delay(Duration.ofSeconds(v))) + .subscribe(v -> clientTransport.disconnectFor(Duration.ofSeconds(7))); + + AtomicInteger counter = new AtomicInteger(-1); + StepVerifier.create( + channel + .requestChannel(testRequest()) + .take(Duration.ofSeconds(600)) + .map(Payload::getDataUtf8) + .timeout(Duration.ofSeconds(12)) + .doOnNext(x -> throwOnNonContinuous(counter, x)) + .then() + .doFinally(s -> closeable.dispose())) + .expectComplete() + .verify(); + } + + @Test + public void reconnectOnMissingSession() { + + int serverSessionDuration = 2; + + CloseableChannel closeable = newServerChannel(serverSessionDuration).block(); + + DisconnectableClientTransport clientTransport = + new DisconnectableClientTransport(clientTransport(closeable.address())); + int clientSessionDurationSeconds = 10; + + Channel channel = newClientChannel(clientTransport, clientSessionDurationSeconds).block(); + + Mono.delay(Duration.ofSeconds(1)) + .subscribe(v -> clientTransport.disconnectFor(Duration.ofSeconds(3))); + + StepVerifier.create( + channel.requestChannel(testRequest()).then().doFinally(s -> closeable.dispose())) + .expectError() + .verify(Duration.ofSeconds(5)); + + StepVerifier.create(channel.onClose()) + .expectErrorMatches( + err -> + err instanceof RejectedResumeException + && "unknown resume token".equals(err.getMessage())) + .verify(Duration.ofSeconds(5)); + } + + @Test + void serverMissingResume() { + CloseableChannel closeableChannel = + RemotingServer.create(ChannelAcceptor.with(new TestResponderChannel())) + .bind(serverTransport(SERVER_HOST, SERVER_PORT)) + .block(); + + Channel channel = ChannelConnector.create() + .resume(new Resume()) + .connect(clientTransport(closeableChannel.address())) + .block(); + + StepVerifier.create(channel.onClose().doFinally(s -> closeableChannel.dispose())) + .expectErrorMatches(err -> err instanceof UnsupportedSetupException + && "resume not supported".equals(err.getMessage())) + .verify(Duration.ofSeconds(5)); + + Assertions.assertThat(channel.isDisposed()).isTrue(); + } + + static ClientTransport clientTransport(InetSocketAddress address) { + return TcpClientTransport.create(address); + } + + static ServerTransport serverTransport(String host, int port) { + return TcpServerTransport.create(host, port); + } + + private static Flux testRequest() { + return Flux.interval(Duration.ofMillis(500)) + .map(v -> DefaultPayload.create("client_request")) + .onBackpressureDrop(); + } + + private void throwOnNonContinuous(AtomicInteger counter, String x) { + int curValue = Integer.parseInt(x); + int prevValue = counter.get(); + if (prevValue >= 0) { + int dif = curValue - prevValue; + if (dif != 1) { + throw new IllegalStateException(String.format( + "Payload values are expected to be continuous numbers: %d %d", prevValue, curValue)); + } + } + counter.set(curValue); + } + + private static Mono newClientChannel( + DisconnectableClientTransport clientTransport, int sessionDurationSeconds) { + return ChannelConnector.create() + .resume(new Resume() + .sessionDuration(Duration.ofSeconds(sessionDurationSeconds)) + .storeFactory(t -> new InMemoryResumableFramesStore("client", t, 500_000)) + .cleanupStoreOnKeepAlive() + .retry(Retry.fixedDelay(Long.MAX_VALUE, Duration.ofSeconds(1)))) + .keepAlive(Duration.ofSeconds(5), Duration.ofMinutes(5)) + .connect(clientTransport); + } + + private static Mono newServerChannel() { + return newServerChannel(15); + } + + private static Mono newServerChannel(int sessionDurationSeconds) { + return RemotingServer.create(ChannelAcceptor.with(new TestResponderChannel())) + .resume( + new Resume() + .sessionDuration(Duration.ofSeconds(sessionDurationSeconds)) + .cleanupStoreOnKeepAlive() + .storeFactory(t -> new InMemoryResumableFramesStore("server", t, 500_000))) + .bind(serverTransport(SERVER_HOST, SERVER_PORT)); + } + + private static class TestResponderChannel implements Channel { + + AtomicInteger counter = new AtomicInteger(); + + @Override + public Flux requestChannel(Publisher payloads) { + return duplicate( + Flux.interval(Duration.ofMillis(1)) + .onBackpressureLatest() + .publishOn(Schedulers.boundedElastic()), + 20) + .map(v -> DefaultPayload.create(String.valueOf(counter.getAndIncrement()))) + .takeUntilOther(Flux.from(payloads).then()); + } + + private Flux duplicate(Flux f, int n) { + Flux r = Flux.empty(); + for (int i = 0; i < n; i++) { + r = r.mergeWith(f); + } + return r; + } + } +} diff --git a/today-remoting/src/test/resources/logback-test.xml b/today-remoting/src/test/resources/logback-test.xml index aa99ace..a380c54 100644 --- a/today-remoting/src/test/resources/logback-test.xml +++ b/today-remoting/src/test/resources/logback-test.xml @@ -25,6 +25,9 @@ + + + diff --git a/today-remoting/src/test/resources/lorem.txt b/today-remoting/src/test/resources/lorem.txt new file mode 100644 index 0000000..e035ea8 --- /dev/null +++ b/today-remoting/src/test/resources/lorem.txt @@ -0,0 +1,32 @@ +Alteration literature to or an sympathize mr imprudence. Of is ferrars subject as enjoyed or tedious cottage. +Procuring as in resembled by in agreeable. Next long no gave mr eyes. Admiration advantages no he celebrated so pianoforte unreserved. +Not its herself forming charmed amiable. Him why feebly expect future now. + +Situation admitting promotion at or to perceived be. Mr acuteness we as estimable enjoyment up. +An held late as felt know. Learn do allow solid to grave. Middleton suspicion age her attention. +Chiefly several bed its wishing. Is so moments on chamber pressed to. Doubtful yet way properly answered humanity its desirous. + Minuter believe service arrived civilly add all. Acuteness allowance an at eagerness favourite in extensive exquisite ye. + + Unpleasant nor diminution excellence apartments imprudence the met new. Draw part them he an to he roof only. + Music leave say doors him. Tore bred form if sigh case as do. Staying he no looking if do opinion. + Sentiments way understood end partiality and his. + + Ladyship it daughter securing procured or am moreover mr. Put sir she exercise vicinity cheerful wondered. + Continual say suspicion provision you neglected sir curiosity unwilling. Simplicity end themselves increasing led day sympathize yet. + General windows effects not are drawing man garrets. Common indeed garden you his ladies out yet. Preference imprudence contrasted to remarkably in on. + Taken now you him trees tears any. Her object giving end sister except oppose. + + No comfort do written conduct at prevent manners on. Celebrated contrasted discretion him sympathize her collecting occasional. + Do answered bachelor occasion in of offended no concerns. Supply worthy warmth branch of no ye. Voice tried known to as my to. + Though wished merits or be. Alone visit use these smart rooms ham. No waiting in on enjoyed placing it inquiry. + + So insisted received is occasion advanced honoured. Among ready to which up. Attacks smiling and may out assured moments man nothing outward. + Thrown any behind afford either the set depend one temper. Instrument melancholy in acceptance collecting frequently be if. + Zealously now pronounce existence add you instantly say offending. Merry their far had widen was. Concerns no in expenses raillery formerly. + + As am hastily invited settled at limited civilly fortune me. Really spring in extent an by. Judge but built gay party world. + Of so am he remember although required. Bachelor unpacked be advanced at. Confined in declared marianne is vicinity. + + In alteration insipidity impression by travelling reasonable up motionless. Of regard warmth by unable sudden garden ladies. + No kept hung am size spot no. Likewise led and dissuade rejoiced welcomed husbands boy. Do listening on he suspected resembled. + Water would still if to. Position boy required law moderate was may. \ No newline at end of file diff --git a/today-remoting/src/testFixtures/java/infra/remoting/test/PingHandler.java b/today-remoting/src/testFixtures/java/infra/remoting/test/PingHandler.java index c9d4581..a662c72 100644 --- a/today-remoting/src/testFixtures/java/infra/remoting/test/PingHandler.java +++ b/today-remoting/src/testFixtures/java/infra/remoting/test/PingHandler.java @@ -42,7 +42,7 @@ public PingHandler(byte[] data) { } @Override - public Mono accept(ConnectionSetupPayload setup, Channel sendingSocket) { + public Mono accept(ConnectionSetupPayload setup, Channel channel) { return Mono.just( new Channel() { @Override diff --git a/today-remoting/src/testFixtures/java/infra/remoting/test/TransportPair.java b/today-remoting/src/testFixtures/java/infra/remoting/test/TransportPair.java index e272744..2d391ff 100644 --- a/today-remoting/src/testFixtures/java/infra/remoting/test/TransportPair.java +++ b/today-remoting/src/testFixtures/java/infra/remoting/test/TransportPair.java @@ -38,7 +38,7 @@ import infra.remoting.core.RemotingServer; import infra.remoting.core.Resume; import infra.remoting.frame.decoder.PayloadDecoder; -import infra.remoting.plugins.ConnectionInterceptor; +import infra.remoting.plugins.ConnectionDecorator; import infra.remoting.resume.InMemoryResumableFramesStore; import infra.remoting.transport.ClientTransport; import infra.remoting.transport.ServerTransport; @@ -121,7 +121,7 @@ public TransportPair(Supplier addressSupplier, allocatorToSupply2 = ByteBufAllocator.DEFAULT; } responder = new TestChannel(TransportPair.data, metadata); - final RemotingServer remotingServer = RemotingServer.create((setup, sendingSocket) -> Mono.just(responder)) + final RemotingServer remotingServer = RemotingServer.create((setup, channel) -> Mono.just(responder)) .payloadDecoder(PayloadDecoder.ZERO_COPY) .interceptors(registry -> { if (runServerWithAsyncInterceptors && !withResumability) { @@ -133,7 +133,7 @@ public TransportPair(Supplier addressSupplier, if (withResumability) { registry.forConnection((type, duplexConnection) -> - type == ConnectionInterceptor.Type.SOURCE + type == ConnectionDecorator.Type.SOURCE ? new DisconnectingDuplexConnection( "Server", duplexConnection, @@ -170,7 +170,7 @@ public TransportPair(Supplier addressSupplier, if (withResumability) { registry.forConnection((type, duplexConnection) -> - type == ConnectionInterceptor.Type.SOURCE + type == ConnectionDecorator.Type.SOURCE ? new DisconnectingDuplexConnection( "Client", duplexConnection, From 56045e9c10bb608c1cd31bceda35df27a6d8a873 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Mon, 4 Aug 2025 21:30:56 +0800 Subject: [PATCH 019/104] :art: --- .../FireAndForgetResponderSubscriber.java | 26 +++++-------------- 1 file changed, 6 insertions(+), 20 deletions(-) diff --git a/today-remoting/src/main/java/infra/remoting/core/FireAndForgetResponderSubscriber.java b/today-remoting/src/main/java/infra/remoting/core/FireAndForgetResponderSubscriber.java index a13dc2a..5543ebc 100644 --- a/today-remoting/src/main/java/infra/remoting/core/FireAndForgetResponderSubscriber.java +++ b/today-remoting/src/main/java/infra/remoting/core/FireAndForgetResponderSubscriber.java @@ -25,10 +25,8 @@ import infra.remoting.Channel; import infra.remoting.Payload; import infra.remoting.frame.FrameType; -import infra.remoting.frame.decoder.PayloadDecoder; import infra.remoting.plugins.RequestInterceptor; import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufAllocator; import io.netty.buffer.CompositeByteBuf; import io.netty.util.ReferenceCountUtil; import reactor.core.CoreSubscriber; @@ -41,13 +39,10 @@ final class FireAndForgetResponderSubscriber implements CoreSubscriber, Re static final FireAndForgetResponderSubscriber INSTANCE = new FireAndForgetResponderSubscriber(); final int streamId; - final ByteBufAllocator allocator; - final PayloadDecoder payloadDecoder; final ChannelSupport channel; final Channel handler; - final int maxInboundPayloadSize; @Nullable final RequestInterceptor requestInterceptor; @@ -56,9 +51,6 @@ final class FireAndForgetResponderSubscriber implements CoreSubscriber, Re private FireAndForgetResponderSubscriber() { this.streamId = 0; - this.allocator = null; - this.payloadDecoder = null; - this.maxInboundPayloadSize = 0; this.channel = null; this.handler = null; this.requestInterceptor = null; @@ -67,9 +59,6 @@ private FireAndForgetResponderSubscriber() { FireAndForgetResponderSubscriber(int streamId, ChannelSupport channel) { this.streamId = streamId; - this.allocator = null; - this.payloadDecoder = null; - this.maxInboundPayloadSize = 0; this.channel = null; this.handler = null; this.requestInterceptor = channel.getRequestInterceptor(); @@ -78,15 +67,12 @@ private FireAndForgetResponderSubscriber() { FireAndForgetResponderSubscriber(int streamId, ByteBuf firstFrame, ChannelSupport channel, Channel handler) { this.streamId = streamId; - this.allocator = channel.getAllocator(); - this.payloadDecoder = channel.getPayloadDecoder(); - this.maxInboundPayloadSize = channel.getMaxInboundPayloadSize(); this.channel = channel; this.handler = handler; this.requestInterceptor = channel.getRequestInterceptor(); this.frames = ReassemblyUtils.addFollowingFrame( - allocator.compositeBuffer(), firstFrame, true, maxInboundPayloadSize); + channel.allocator.compositeBuffer(), firstFrame, true, channel.maxInboundPayloadSize); } @Override @@ -118,14 +104,14 @@ public void onComplete() { @Override public void handleNext(ByteBuf followingFrame, boolean hasFollows, boolean isLastPayload) { final CompositeByteBuf frames = this.frames; - + final ChannelSupport channel = this.channel; try { ReassemblyUtils.addFollowingFrame( - frames, followingFrame, hasFollows, this.maxInboundPayloadSize); + frames, followingFrame, hasFollows, channel.maxInboundPayloadSize); } catch (IllegalStateException t) { final int streamId = this.streamId; - this.channel.remove(streamId, this); + channel.remove(streamId, this); this.frames = null; frames.release(); @@ -140,12 +126,12 @@ public void handleNext(ByteBuf followingFrame, boolean hasFollows, boolean isLas } if (!hasFollows) { - this.channel.remove(this.streamId, this); + channel.remove(this.streamId, this); this.frames = null; Payload payload; try { - payload = this.payloadDecoder.decode(frames); + payload = channel.payloadDecoder.decode(frames); frames.release(); } catch (Throwable t) { From c8c710323e0cce7173a0e583da6d3a91c31d0b49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Mon, 4 Aug 2025 21:43:09 +0800 Subject: [PATCH 020/104] :art: --- .../remoting/core/DefaultRemotingClient.java | 8 +--- .../infra/remoting/core/RemotingClient.java | 34 +++++++++++++++ .../remoting/core/ResolvingOperator.java | 6 +-- .../lb/LoadBalanceRemotingClient.java | 29 ++----------- .../infra/remoting/lb/LoadBalanceTarget.java | 4 +- .../RoundRobinLoadbalancerExample.java | 43 ++++++------------- .../lb/LoadbalanceChannelClientTests.java | 23 +++++----- 7 files changed, 69 insertions(+), 78 deletions(-) diff --git a/today-remoting/src/main/java/infra/remoting/core/DefaultRemotingClient.java b/today-remoting/src/main/java/infra/remoting/core/DefaultRemotingClient.java index 9e85a36..9121623 100644 --- a/today-remoting/src/main/java/infra/remoting/core/DefaultRemotingClient.java +++ b/today-remoting/src/main/java/infra/remoting/core/DefaultRemotingClient.java @@ -61,12 +61,8 @@ class DefaultRemotingClient extends ResolvingOperator } }; - static final Object ON_DISCARD_KEY; - - static { - Context discardAwareContext = Operators.enableOnDiscard(null, DISCARD_ELEMENTS_CONSUMER); - ON_DISCARD_KEY = discardAwareContext.stream().findFirst().get().getKey(); - } + static final Object ON_DISCARD_KEY = Operators.enableOnDiscard(null, DISCARD_ELEMENTS_CONSUMER) + .stream().findFirst().get().getKey(); final Mono source; diff --git a/today-remoting/src/main/java/infra/remoting/core/RemotingClient.java b/today-remoting/src/main/java/infra/remoting/core/RemotingClient.java index f43a2c7..4fae6b7 100644 --- a/today-remoting/src/main/java/infra/remoting/core/RemotingClient.java +++ b/today-remoting/src/main/java/infra/remoting/core/RemotingClient.java @@ -14,14 +14,18 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see [http://www.gnu.org/licenses/] */ + package infra.remoting.core; import org.reactivestreams.Publisher; +import java.util.List; + import infra.remoting.Channel; import infra.remoting.Closeable; import infra.remoting.Payload; import infra.remoting.lb.LoadBalanceRemotingClient; +import infra.remoting.lb.LoadBalanceTarget; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; @@ -68,6 +72,7 @@ * RemotingClient client = RemotingClient.from(source); * }

    * + * @author 海子 Yang * @see LoadBalanceRemotingClient */ public interface RemotingClient extends Closeable { @@ -147,4 +152,33 @@ static RemotingClient from(Mono source) { static RemotingClient from(Channel channel) { return new RemotingClientAdapter(channel); } + + /** + * Shortcut to create an {@link LoadBalanceRemotingClient} with round-robin load balancing. + * Effectively a shortcut for: + * + *
    {@code
    +   * LoadBalanceRemotingClient.builder(targetPublisher)
    +   *    .connector(ChannelConnector.create())
    +   *    .build();
    +   * }
    + * + * @param connector a "template" for connecting to load balance targets + * @param targetPublisher refreshes the list of load balance targets periodically + * @return the created client instance + */ + static LoadBalanceRemotingClient forLoadBalance(ChannelConnector connector, Publisher> targetPublisher) { + return forLoadBalance(targetPublisher).connector(connector).build(); + } + + /** + * Return a builder for a {@link LoadBalanceRemotingClient}. + * + * @param targetPublisher refreshes the list of load balance targets periodically + * @return the created builder + */ + static LoadBalanceRemotingClient.Builder forLoadBalance(Publisher> targetPublisher) { + return LoadBalanceRemotingClient.builder(targetPublisher); + } + } diff --git a/today-remoting/src/main/java/infra/remoting/core/ResolvingOperator.java b/today-remoting/src/main/java/infra/remoting/core/ResolvingOperator.java index 837486c..fba2b49 100644 --- a/today-remoting/src/main/java/infra/remoting/core/ResolvingOperator.java +++ b/today-remoting/src/main/java/infra/remoting/core/ResolvingOperator.java @@ -92,10 +92,7 @@ public final boolean isPending() { @Nullable public final T valueIfResolved() { if (this.subscribers == READY) { - T value = this.value; - if (value != null) { - return value; - } + return this.value; } return null; @@ -647,6 +644,7 @@ public void onError(Throwable t) { } } + @Nullable @Override public Object scanUnsafe(Attr key) { if (key == Attr.PARENT) diff --git a/today-remoting/src/main/java/infra/remoting/lb/LoadBalanceRemotingClient.java b/today-remoting/src/main/java/infra/remoting/lb/LoadBalanceRemotingClient.java index 2a5a5a5..285be1c 100644 --- a/today-remoting/src/main/java/infra/remoting/lb/LoadBalanceRemotingClient.java +++ b/today-remoting/src/main/java/infra/remoting/lb/LoadBalanceRemotingClient.java @@ -90,24 +90,6 @@ public void dispose() { channelPool.dispose(); } - /** - * Shortcut to create an {@link LoadBalanceRemotingClient} with round-robin load balancing. - * Effectively a shortcut for: - * - *
    -   * LoadBalanceRemotingClient.builder(targetPublisher)
    -   *    .connector(ChannelConnector.create())
    -   *    .build();
    -   * 
    - * - * @param connector a "template" for connecting to load balance targets - * @param targetPublisher refreshes the list of load balance targets periodically - * @return the created client instance - */ - public static LoadBalanceRemotingClient create(ChannelConnector connector, Publisher> targetPublisher) { - return builder(targetPublisher).connector(connector).build(); - } - /** * Return a builder for a {@link LoadBalanceRemotingClient}. * @@ -181,13 +163,10 @@ public Builder loadBalanceStrategy(LoadBalanceStrategy strategy) { /** Build the {@link LoadBalanceRemotingClient} instance. */ public LoadBalanceRemotingClient build() { - final ChannelConnector connector = - (this.connector != null ? this.connector : ChannelConnector.create()); - - final LoadBalanceStrategy strategy = - (this.loadbalanceStrategy != null - ? this.loadbalanceStrategy - : new RoundRobinLoadBalanceStrategy()); + final ChannelConnector connector = this.connector != null ? this.connector : ChannelConnector.create(); + final LoadBalanceStrategy strategy = loadbalanceStrategy != null + ? loadbalanceStrategy + : new RoundRobinLoadBalanceStrategy(); if (strategy instanceof ClientLoadBalanceStrategy) { ((ClientLoadBalanceStrategy) strategy).initialize(connector); diff --git a/today-remoting/src/main/java/infra/remoting/lb/LoadBalanceTarget.java b/today-remoting/src/main/java/infra/remoting/lb/LoadBalanceTarget.java index 852ef6a..3e6fc5f 100644 --- a/today-remoting/src/main/java/infra/remoting/lb/LoadBalanceTarget.java +++ b/today-remoting/src/main/java/infra/remoting/lb/LoadBalanceTarget.java @@ -19,6 +19,7 @@ import org.reactivestreams.Publisher; import infra.remoting.core.ChannelConnector; +import infra.remoting.core.RemotingClient; import infra.remoting.transport.ClientTransport; /** @@ -27,7 +28,8 @@ * #getKey()} is used to identify a target uniquely while the {@link #getTransport() transport} is * used to connect to the target server. * - * @see LoadBalanceRemotingClient#create(ChannelConnector, Publisher) + * @author 海子 Yang + * @see RemotingClient#forLoadBalance(ChannelConnector, Publisher) */ public class LoadBalanceTarget { diff --git a/today-remoting/src/test/java/infra/remoting/examples/tcp/loadbalancer/RoundRobinLoadbalancerExample.java b/today-remoting/src/test/java/infra/remoting/examples/tcp/loadbalancer/RoundRobinLoadbalancerExample.java index 0d6ba34..bf43c2d 100644 --- a/today-remoting/src/test/java/infra/remoting/examples/tcp/loadbalancer/RoundRobinLoadbalancerExample.java +++ b/today-remoting/src/test/java/infra/remoting/examples/tcp/loadbalancer/RoundRobinLoadbalancerExample.java @@ -24,7 +24,6 @@ import infra.remoting.ChannelAcceptor; import infra.remoting.core.RemotingClient; import infra.remoting.core.RemotingServer; -import infra.remoting.lb.LoadBalanceRemotingClient; import infra.remoting.lb.LoadBalanceTarget; import infra.remoting.transport.netty.client.TcpClientTransport; import infra.remoting.transport.netty.server.CloseableChannel; @@ -71,35 +70,21 @@ public static void main(String[] args) { LoadBalanceTarget target8082 = LoadBalanceTarget.of("8082", TcpClientTransport.create(8082)); Flux> producer = - Flux.interval(Duration.ofSeconds(5)) - .log() - .map( - i -> { - int val = i.intValue(); - switch (val) { - case 0: - return Collections.emptyList(); - case 1: - return Collections.singletonList(target8080); - case 2: - return Arrays.asList(target8080, target8081); - case 3: - return Arrays.asList(target8080, target8082); - case 4: - return Arrays.asList(target8081, target8082); - case 5: - return Arrays.asList(target8080, target8081, target8082); - case 6: - return Collections.emptyList(); - case 7: - return Collections.emptyList(); - default: - return Arrays.asList(target8080, target8081, target8082); - } - }); + Flux.interval(Duration.ofSeconds(5)).log().map(i -> { + int val = i.intValue(); + return switch (val) { + case 0, 6, 7 -> Collections.emptyList(); + case 1 -> Collections.singletonList(target8080); + case 2 -> Arrays.asList(target8080, target8081); + case 3 -> Arrays.asList(target8080, target8082); + case 4 -> Arrays.asList(target8081, target8082); + default -> Arrays.asList(target8080, target8081, target8082); + }; + }); - RemotingClient client = - LoadBalanceRemotingClient.builder(producer).roundRobinLoadBalanceStrategy().build(); + RemotingClient client = RemotingClient.forLoadBalance(producer) + .roundRobinLoadBalanceStrategy() + .build(); for (int i = 0; i < 10000; i++) { try { diff --git a/today-remoting/src/test/java/infra/remoting/lb/LoadbalanceChannelClientTests.java b/today-remoting/src/test/java/infra/remoting/lb/LoadbalanceChannelClientTests.java index 9bba704..4b9b80c 100644 --- a/today-remoting/src/test/java/infra/remoting/lb/LoadbalanceChannelClientTests.java +++ b/today-remoting/src/test/java/infra/remoting/lb/LoadbalanceChannelClientTests.java @@ -26,10 +26,10 @@ import java.time.Duration; import java.util.concurrent.atomic.AtomicInteger; -import infra.remoting.Payload; import infra.remoting.Channel; -import infra.remoting.core.RemotingClient; +import infra.remoting.Payload; import infra.remoting.core.ChannelConnector; +import infra.remoting.core.RemotingClient; import infra.remoting.transport.ClientTransport; import infra.remoting.util.DefaultPayload; import reactor.core.publisher.Flux; @@ -78,17 +78,14 @@ public Flux requestChannel(Publisher payloads) { void testChannelReconnection() { when(channelConnector.connect(clientTransport)).thenReturn(PROGRESSING_HANDLER); - RemotingClient client = - LoadBalanceRemotingClient.create( - channelConnector, - Mono.just(singletonList(LoadBalanceTarget.of("key", clientTransport)))); - - Publisher result = - client - .requestChannel(SOURCE) - .repeatWhen(longFlux -> longFlux.delayElements(LONG_DURATION).take(5)) - .map(Payload::getDataUtf8) - .log(); + RemotingClient client = RemotingClient.forLoadBalance(channelConnector, + Mono.just(singletonList(LoadBalanceTarget.of("key", clientTransport)))); + + Publisher result = client + .requestChannel(SOURCE) + .repeatWhen(longFlux -> longFlux.delayElements(LONG_DURATION).take(5)) + .map(Payload::getDataUtf8) + .log(); StepVerifier.create(result) .expectSubscription() From 2bfbba9552427becd408f640f19a7d761aad2418 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Mon, 4 Aug 2025 21:44:34 +0800 Subject: [PATCH 021/104] =?UTF-8?q?:fire:=20=E5=88=A0=E9=99=A4=20ETCD=20?= =?UTF-8?q?=E6=A8=A1=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- settings.gradle | 2 - today-cloud-config-server-etcd/build.gradle | 13 --- .../infra/config/etcd/ByteSequenceUtils.java | 34 -------- .../ConfigApplicationStartupListener.java | 57 ------------- .../infra/config/etcd/EtcdProperties.java | 85 ------------------- .../infra/config/etcd/EtcdPropertySource.java | 78 ----------------- ...ditional-infra-configuration-metadata.json | 60 ------------- .../main/resources/META-INF/today.strategies | 18 ---- .../config/etcd/EtcdPropertySourceTests.java | 76 ----------------- .../java/infra/config/etcd/EtcdTests.java | 57 ------------- .../demo-tests/demo-registry/build.gradle | 1 - today-service-registry-etcd/build.gradle | 15 ---- .../cloud/registry/EtcdDiscoveryClient.java | 41 --------- 13 files changed, 537 deletions(-) delete mode 100644 today-cloud-config-server-etcd/build.gradle delete mode 100644 today-cloud-config-server-etcd/src/main/java/infra/config/etcd/ByteSequenceUtils.java delete mode 100644 today-cloud-config-server-etcd/src/main/java/infra/config/etcd/ConfigApplicationStartupListener.java delete mode 100644 today-cloud-config-server-etcd/src/main/java/infra/config/etcd/EtcdProperties.java delete mode 100644 today-cloud-config-server-etcd/src/main/java/infra/config/etcd/EtcdPropertySource.java delete mode 100644 today-cloud-config-server-etcd/src/main/resources/META-INF/additional-infra-configuration-metadata.json delete mode 100644 today-cloud-config-server-etcd/src/main/resources/META-INF/today.strategies delete mode 100644 today-cloud-config-server-etcd/src/test/java/infra/config/etcd/EtcdPropertySourceTests.java delete mode 100644 today-cloud-config-server-etcd/src/test/java/infra/config/etcd/EtcdTests.java delete mode 100644 today-service-registry-etcd/build.gradle delete mode 100644 today-service-registry-etcd/src/main/java/infra/cloud/registry/EtcdDiscoveryClient.java diff --git a/settings.gradle b/settings.gradle index 50fcc8b..4446dd6 100644 --- a/settings.gradle +++ b/settings.gradle @@ -30,7 +30,6 @@ include 'today-cloud-dependencies' include 'today-cloud-core' include 'today-cloud-gateway' include 'today-cloud-config-server' -include 'today-cloud-config-server-etcd' include 'today-service-client' include 'today-service-provider' @@ -48,5 +47,4 @@ include 'today-cloud-samples:demo-tests:demo-user-api' include 'today-cloud-samples:demo-tests:demo-user-rest' include 'today-cloud-samples:demo-tests:demo-user-service' include 'today-cloud-samples:today-petclinic' -include 'today-service-registry-etcd' diff --git a/today-cloud-config-server-etcd/build.gradle b/today-cloud-config-server-etcd/build.gradle deleted file mode 100644 index 2857ca4..0000000 --- a/today-cloud-config-server-etcd/build.gradle +++ /dev/null @@ -1,13 +0,0 @@ -description = "TODAY Cloud Etcd Config Server" - -dependencies { - - implementation project(":today-cloud-config-server") - implementation 'cn.taketoday:today-framework' - implementation "io.etcd:jetcd-core:0.6.1" - - annotationProcessor 'cn.taketoday:infra-configuration-processor' - - testImplementation "cn.taketoday:today-test" - -} diff --git a/today-cloud-config-server-etcd/src/main/java/infra/config/etcd/ByteSequenceUtils.java b/today-cloud-config-server-etcd/src/main/java/infra/config/etcd/ByteSequenceUtils.java deleted file mode 100644 index 452e834..0000000 --- a/today-cloud-config-server-etcd/src/main/java/infra/config/etcd/ByteSequenceUtils.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2021 - 2024 the original author or authors. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] - */ - -package infra.config.etcd; - -import java.nio.charset.StandardCharsets; - -import io.etcd.jetcd.ByteSequence; - -/** - * @author Harry Yang - * @since 1.0 2023/11/7 22:13 - */ -public class ByteSequenceUtils { - - public static ByteSequence forString(String source) { - return ByteSequence.from(source, StandardCharsets.UTF_8); - } - -} diff --git a/today-cloud-config-server-etcd/src/main/java/infra/config/etcd/ConfigApplicationStartupListener.java b/today-cloud-config-server-etcd/src/main/java/infra/config/etcd/ConfigApplicationStartupListener.java deleted file mode 100644 index 592f863..0000000 --- a/today-cloud-config-server-etcd/src/main/java/infra/config/etcd/ConfigApplicationStartupListener.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2021 - 2024 the original author or authors. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] - */ - -package infra.config.etcd; - -import infra.app.Application; -import infra.app.env.EnvironmentPostProcessor; -import infra.context.properties.bind.BindResult; -import infra.context.properties.bind.Binder; -import infra.core.Ordered; -import infra.core.env.ConfigurableEnvironment; -import io.etcd.jetcd.Client; -import io.etcd.jetcd.KV; - -/** - * @author Harry Yang - * @since 1.0 2023/11/7 21:34 - */ -public class ConfigApplicationStartupListener implements EnvironmentPostProcessor, Ordered { - - @Override - public void postProcessEnvironment(ConfigurableEnvironment environment, Application application) { - BindResult result = Binder.get(environment).bind("config.server.etcd", EtcdProperties.class); - if (result.isBound()) { - EtcdProperties properties = result.get(); - Client client = Client.builder() - .endpoints(properties.getEndpoints()) - .user(ByteSequenceUtils.forString(properties.getUsername())) - .password(ByteSequenceUtils.forString(properties.getPassword())) - .build(); - - KV kvClient = client.getKVClient(); - environment.getPropertySources() - .addLast(new EtcdPropertySource(kvClient, properties.getNamespace())); - } - } - - @Override - public int getOrder() { - return Ordered.LOWEST_PRECEDENCE; - } - -} diff --git a/today-cloud-config-server-etcd/src/main/java/infra/config/etcd/EtcdProperties.java b/today-cloud-config-server-etcd/src/main/java/infra/config/etcd/EtcdProperties.java deleted file mode 100644 index e22cfe3..0000000 --- a/today-cloud-config-server-etcd/src/main/java/infra/config/etcd/EtcdProperties.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright 2021 - 2024 the original author or authors. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] - */ - -package infra.config.etcd; - -import infra.beans.factory.annotation.Value; -import infra.context.properties.ConfigurationProperties; -import infra.lang.Nullable; - -/** - * @author Harry Yang - * @since 1.0 2023/11/7 21:51 - */ -@ConfigurationProperties("config.server.etcd") -public class EtcdProperties { - - /** - * Etcd server endpoints. - */ - private String[] endpoints; - - /** - * Etcd server key namespace. - */ - @Nullable - @Value("${app.name:application}") - private String namespace; - - /** - * Etcd server user name. - */ - private String username; - - /** - * Etcd server user password. - */ - private String password; - - public void setNamespace(@Nullable String namespace) { - this.namespace = namespace; - } - - public void setPassword(String password) { - this.password = password; - } - - public void setUsername(String username) { - this.username = username; - } - - public void setEndpoints(String[] endpoints) { - this.endpoints = endpoints; - } - - public String[] getEndpoints() { - return endpoints; - } - - @Nullable - public String getNamespace() { - return namespace; - } - - public String getPassword() { - return password; - } - - public String getUsername() { - return username; - } -} diff --git a/today-cloud-config-server-etcd/src/main/java/infra/config/etcd/EtcdPropertySource.java b/today-cloud-config-server-etcd/src/main/java/infra/config/etcd/EtcdPropertySource.java deleted file mode 100644 index fcdc5f4..0000000 --- a/today-cloud-config-server-etcd/src/main/java/infra/config/etcd/EtcdPropertySource.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright 2021 - 2024 the original author or authors. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] - */ - -package infra.config.etcd; - -import java.nio.charset.StandardCharsets; -import java.util.List; - -import infra.core.env.PropertySource; -import infra.lang.Nullable; -import infra.logging.Logger; -import infra.logging.LoggerFactory; -import infra.util.CollectionUtils; -import infra.util.ExceptionUtils; -import io.etcd.jetcd.ByteSequence; -import io.etcd.jetcd.KV; -import io.etcd.jetcd.KeyValue; - -/** - * @author Harry Yang - * @since 1.0 2023/10/6 21:41 - */ -public class EtcdPropertySource extends PropertySource { - - private final Logger logger = LoggerFactory.getLogger(getClass()); - - @Nullable - private final String namespace; - - public EtcdPropertySource(KV kvClient) { - this(kvClient, null); - } - - public EtcdPropertySource(KV kvClient, @Nullable String namespace) { - super("etcd", kvClient); - this.namespace = namespace; - } - - @Nullable - @Override - public Object getProperty(String name) { - ByteSequence key = getKey(name); - try { - List kvs = source.get(key).get().getKvs(); - KeyValue keyValue = CollectionUtils.firstElement(kvs); - if (keyValue != null) { - logger.info("found property: {}: key: {} value: {}", name, key, keyValue.getValue()); - return keyValue.getValue().toString(); - } - return null; - } - catch (Exception e) { - throw ExceptionUtils.sneakyThrow(e); - } - } - - private ByteSequence getKey(String name) { - if (namespace != null) { - return ByteSequence.from(namespace + name, StandardCharsets.UTF_8); - } - return ByteSequence.from(name, StandardCharsets.UTF_8); - } - -} diff --git a/today-cloud-config-server-etcd/src/main/resources/META-INF/additional-infra-configuration-metadata.json b/today-cloud-config-server-etcd/src/main/resources/META-INF/additional-infra-configuration-metadata.json deleted file mode 100644 index 879bec0..0000000 --- a/today-cloud-config-server-etcd/src/main/resources/META-INF/additional-infra-configuration-metadata.json +++ /dev/null @@ -1,60 +0,0 @@ -{ - "groups": [ - { - "name": "logging", - "type": "infra.app.context.logging.LoggingApplicationListener" - } - ], - "properties": [ - { - "name": "config.server.etcd.endpoints", - "type": "java.lang.String[]", - "description": "Etcd server endpoints.", - "sourceType": "infra.config.etcd.EtcdProperties", - "defaultValue": [] - }, - { - "name": "config.server.etcd.username", - "type": "java.lang.String", - "description": "Etcd server user name.", - "sourceType": "infra.config.etcd.EtcdProperties", - "defaultValue": "root" - }, - { - "name": "config.server.etcd.password", - "type": "java.lang.String", - "description": "Etcd server user password.", - "sourceType": "infra.config.etcd.EtcdProperties" - }, - { - "name": "config.server.etcd.namespace", - "type": "java.lang.String", - "description": "Etcd server key namespace.", - "sourceType": "infra.config.etcd.EtcdProperties" - } - ], - "hints": [ - { - "name": "app.config.import", - "values": [ - { - "value": "file:" - }, - { - "value": "classpath:" - }, - { - "value": "configtree:" - }, - { - "value": "config-server:" - } - ], - "providers": [ - { - "name": "any" - } - ] - } - ] -} diff --git a/today-cloud-config-server-etcd/src/main/resources/META-INF/today.strategies b/today-cloud-config-server-etcd/src/main/resources/META-INF/today.strategies deleted file mode 100644 index f009692..0000000 --- a/today-cloud-config-server-etcd/src/main/resources/META-INF/today.strategies +++ /dev/null @@ -1,18 +0,0 @@ -# -# Copyright 2021 - 2024 the original author or authors. -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see [http://www.gnu.org/licenses/] -# -infra.app.env.EnvironmentPostProcessor=\ -infra.config.etcd.ConfigApplicationStartupListener diff --git a/today-cloud-config-server-etcd/src/test/java/infra/config/etcd/EtcdPropertySourceTests.java b/today-cloud-config-server-etcd/src/test/java/infra/config/etcd/EtcdPropertySourceTests.java deleted file mode 100644 index 31e7234..0000000 --- a/today-cloud-config-server-etcd/src/test/java/infra/config/etcd/EtcdPropertySourceTests.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright 2021 - 2024 the original author or authors. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] - */ - -package infra.config.etcd; - -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; - -import java.nio.charset.StandardCharsets; - -import io.etcd.jetcd.ByteSequence; -import io.etcd.jetcd.Client; -import io.etcd.jetcd.KV; -import io.etcd.jetcd.Watch; -import io.etcd.jetcd.options.WatchOption; -import io.etcd.jetcd.watch.WatchResponse; - -/** - * @author Harry Yang - * @since 1.0 2023/10/6 22:20 - */ -@Disabled -class EtcdPropertySourceTests { - - @Test - void test() throws InterruptedException { - Client client = Client.builder() - .endpoints("http://localhost:2379") - .user(ByteSequence.from("root", StandardCharsets.UTF_8)) - .password(ByteSequence.from("88888888", StandardCharsets.UTF_8)) - .build(); - - KV kvClient = client.getKVClient(); - EtcdPropertySource source = new EtcdPropertySource(kvClient); - - Object property = source.getProperty("key"); - System.out.println(property); - - Watch watchClient = client.getWatchClient(); - watchClient.watch(ByteSequence.from("cn.taketoday.blog.BlogApplication", StandardCharsets.UTF_8), - WatchOption.newBuilder().isPrefix(true).build(), new Watch.Listener() { - - @Override - public void onNext(WatchResponse response) { - System.out.println(response); - } - - @Override - public void onError(Throwable throwable) { - throwable.printStackTrace(); - } - - @Override - public void onCompleted() { - System.out.println("onCompleted"); - } - }); - - Thread.currentThread().join(); - } - -} \ No newline at end of file diff --git a/today-cloud-config-server-etcd/src/test/java/infra/config/etcd/EtcdTests.java b/today-cloud-config-server-etcd/src/test/java/infra/config/etcd/EtcdTests.java deleted file mode 100644 index 70174e0..0000000 --- a/today-cloud-config-server-etcd/src/test/java/infra/config/etcd/EtcdTests.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2021 - 2024 the original author or authors. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] - */ - -package infra.config.etcd; - -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; - -import java.nio.charset.StandardCharsets; - -import infra.util.CollectionUtils; -import io.etcd.jetcd.ByteSequence; -import io.etcd.jetcd.Client; -import io.etcd.jetcd.KV; -import io.etcd.jetcd.kv.GetResponse; - -/** - * @author Harry Yang - * @since 1.0 2023/10/6 20:40 - */ -@Disabled -class EtcdTests { - - @Test - void test() throws Exception { - Client client = Client.builder() - .endpoints("http://localhost:2379") - .user(ByteSequence.from("root", StandardCharsets.UTF_8)) - .password(ByteSequence.from("88888888", StandardCharsets.UTF_8)) - .build(); - - KV kvClient = client.getKVClient(); - - ByteSequence key = ByteSequence.from("key", StandardCharsets.UTF_8); - kvClient.put(key, ByteSequence.from("value", StandardCharsets.UTF_8)); - - GetResponse response = kvClient.get(key).get(); - - System.out.println(CollectionUtils.firstElement(response.getKvs()).getValue()); - - } - -} diff --git a/today-cloud-samples/demo-tests/demo-registry/build.gradle b/today-cloud-samples/demo-tests/demo-registry/build.gradle index 7508661..437d1d6 100644 --- a/today-cloud-samples/demo-tests/demo-registry/build.gradle +++ b/today-cloud-samples/demo-tests/demo-registry/build.gradle @@ -24,7 +24,6 @@ infraJar { dependencies { implementation project(":today-service-registry") - implementation project(":today-cloud-config-server-etcd") implementation 'cn.taketoday:today-starter-web' implementation 'cn.taketoday:today-starter-netty' implementation 'ch.qos.logback:logback-classic' diff --git a/today-service-registry-etcd/build.gradle b/today-service-registry-etcd/build.gradle deleted file mode 100644 index 0802435..0000000 --- a/today-service-registry-etcd/build.gradle +++ /dev/null @@ -1,15 +0,0 @@ -description = "TODAY Cloud Etcd Service Registry" - -dependencies { - - implementation project(":today-cloud-core") - implementation project(":today-service-registry") - // implementation project(":today-cloud-config-server") - implementation 'cn.taketoday:today-framework' - implementation "io.etcd:jetcd-core:0.6.1" - - annotationProcessor 'cn.taketoday:infra-configuration-processor' - - testImplementation "cn.taketoday:today-test" - -} diff --git a/today-service-registry-etcd/src/main/java/infra/cloud/registry/EtcdDiscoveryClient.java b/today-service-registry-etcd/src/main/java/infra/cloud/registry/EtcdDiscoveryClient.java deleted file mode 100644 index 89c78e3..0000000 --- a/today-service-registry-etcd/src/main/java/infra/cloud/registry/EtcdDiscoveryClient.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2021 - 2024 the original author or authors. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] - */ - -package infra.cloud.registry; - -import java.util.List; - -import infra.cloud.DiscoveryClient; -import infra.cloud.ServiceInstance; - -/** - * @author Harry Yang - * @since 1.0 2023/11/19 21:19 - */ -public class EtcdDiscoveryClient implements DiscoveryClient { - - @Override - public List getInstances(String serviceId) { - return null; - } - - @Override - public List getServices() { - return null; - } - -} From 58ecf052b0882e5ba1fbaf8d98404b331687eabd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Mon, 4 Aug 2025 21:53:19 +0800 Subject: [PATCH 022/104] :art: --- .../infra/remoting/core/RemotingServer.java | 48 ++++++------ .../RoundRobinLoadbalancerExample.java | 74 +++++++++---------- 2 files changed, 61 insertions(+), 61 deletions(-) diff --git a/today-remoting/src/main/java/infra/remoting/core/RemotingServer.java b/today-remoting/src/main/java/infra/remoting/core/RemotingServer.java index 683e588..4fc45ab 100644 --- a/today-remoting/src/main/java/infra/remoting/core/RemotingServer.java +++ b/today-remoting/src/main/java/infra/remoting/core/RemotingServer.java @@ -87,27 +87,6 @@ public final class RemotingServer { private RemotingServer() { } - /** Static factory method to create an {@code RemotingServer}. */ - public static RemotingServer create() { - return new RemotingServer(); - } - - /** - * Static factory method to create an {@code RemotingServer} instance with the given {@code - * ChannelAcceptor}. Effectively a shortcut for: - * - *
    -   * RemotingServer.create().acceptor(...);
    -   * 
    - * - * @param acceptor the acceptor to handle connections with - * @return the same instance for method chaining - * @see #acceptor(ChannelAcceptor) - */ - public static RemotingServer create(ChannelAcceptor acceptor) { - return RemotingServer.create().acceptor(acceptor); - } - /** * Set the acceptor to handle incoming connections and handle requests. * @@ -458,4 +437,31 @@ private ProtocolErrorException rejectedSetupError(Throwable err) { return new RejectedSetupException(msg == null ? "rejected by server acceptor" : msg); } + //--------------------------------------------------------------------- + // Static Factory Methods + //--------------------------------------------------------------------- + + /** + * Static factory method to create an {@code RemotingServer}. + */ + public static RemotingServer create() { + return new RemotingServer(); + } + + /** + * Static factory method to create an {@code RemotingServer} instance with the given {@code + * ChannelAcceptor}. Effectively a shortcut for: + * + *
    {@code
    +   * RemotingServer.create().acceptor(...);
    +   * }
    + * + * @param acceptor the acceptor to handle connections with + * @return the same instance for method chaining + * @see #acceptor(ChannelAcceptor) + */ + public static RemotingServer create(ChannelAcceptor acceptor) { + return RemotingServer.create().acceptor(acceptor); + } + } diff --git a/today-remoting/src/test/java/infra/remoting/examples/tcp/loadbalancer/RoundRobinLoadbalancerExample.java b/today-remoting/src/test/java/infra/remoting/examples/tcp/loadbalancer/RoundRobinLoadbalancerExample.java index bf43c2d..d676762 100644 --- a/today-remoting/src/test/java/infra/remoting/examples/tcp/loadbalancer/RoundRobinLoadbalancerExample.java +++ b/today-remoting/src/test/java/infra/remoting/examples/tcp/loadbalancer/RoundRobinLoadbalancerExample.java @@ -22,6 +22,7 @@ import java.util.List; import infra.remoting.ChannelAcceptor; +import infra.remoting.Payload; import infra.remoting.core.RemotingClient; import infra.remoting.core.RemotingServer; import infra.remoting.lb.LoadBalanceTarget; @@ -35,52 +36,40 @@ public class RoundRobinLoadbalancerExample { public static void main(String[] args) { - CloseableChannel server1 = - RemotingServer.create( - ChannelAcceptor.forRequestResponse( - p -> { - System.out.println("Server 1 got fnf " + p.getDataUtf8()); - return Mono.just(DefaultPayload.create("Server 1 response")) - .delayElement(Duration.ofMillis(100)); - })) - .bindNow(TcpServerTransport.create(8080)); + CloseableChannel server1 = RemotingServer.create(ChannelAcceptor.forRequestResponse(p -> { + System.out.println("Server 1 got fnf " + p.getDataUtf8()); + return Mono.just(DefaultPayload.create("Server 1 response")) + .delayElement(Duration.ofMillis(1)); + })) + .bindNow(TcpServerTransport.create(8080)); - CloseableChannel server2 = - RemotingServer.create( - ChannelAcceptor.forRequestResponse( - p -> { - System.out.println("Server 2 got fnf " + p.getDataUtf8()); - return Mono.just(DefaultPayload.create("Server 2 response")) - .delayElement(Duration.ofMillis(100)); - })) - .bindNow(TcpServerTransport.create(8081)); + CloseableChannel server2 = RemotingServer.create(ChannelAcceptor.forRequestResponse(p -> { + System.out.println("Server 2 got fnf " + p.getDataUtf8()); + return Mono.just(DefaultPayload.create("Server 2 response")); + })) + .bindNow(TcpServerTransport.create(8081)); - CloseableChannel server3 = - RemotingServer.create( - ChannelAcceptor.forRequestResponse( - p -> { - System.out.println("Server 3 got fnf " + p.getDataUtf8()); - return Mono.just(DefaultPayload.create("Server 3 response")) - .delayElement(Duration.ofMillis(100)); - })) - .bindNow(TcpServerTransport.create(8082)); + CloseableChannel server3 = RemotingServer.create(ChannelAcceptor.forRequestResponse(p -> { + System.out.println("Server 3 got fnf " + p.getDataUtf8()); + return Mono.just(DefaultPayload.create("Server 3 response")); + })) + .bindNow(TcpServerTransport.create(8082)); LoadBalanceTarget target8080 = LoadBalanceTarget.of("8080", TcpClientTransport.create(8080)); LoadBalanceTarget target8081 = LoadBalanceTarget.of("8081", TcpClientTransport.create(8081)); LoadBalanceTarget target8082 = LoadBalanceTarget.of("8082", TcpClientTransport.create(8082)); - Flux> producer = - Flux.interval(Duration.ofSeconds(5)).log().map(i -> { - int val = i.intValue(); - return switch (val) { - case 0, 6, 7 -> Collections.emptyList(); - case 1 -> Collections.singletonList(target8080); - case 2 -> Arrays.asList(target8080, target8081); - case 3 -> Arrays.asList(target8080, target8082); - case 4 -> Arrays.asList(target8081, target8082); - default -> Arrays.asList(target8080, target8081, target8082); - }; - }); + Flux> producer = Flux.interval(Duration.ofSeconds(5)).log().map(i -> { + int val = i.intValue(); + return switch (val) { + case 0, 6, 7 -> Collections.emptyList(); + case 1 -> Collections.singletonList(target8080); + case 2 -> Arrays.asList(target8080, target8081); + case 3 -> Arrays.asList(target8080, target8082); + case 4 -> Arrays.asList(target8081, target8082); + default -> Arrays.asList(target8080, target8081, target8082); + }; + }); RemotingClient client = RemotingClient.forLoadBalance(producer) .roundRobinLoadBalanceStrategy() @@ -88,11 +77,16 @@ public static void main(String[] args) { for (int i = 0; i < 10000; i++) { try { - client.requestResponse(Mono.just(DefaultPayload.create("test" + i))).block(); + Payload block = client.requestResponse(Mono.just(DefaultPayload.create("test-" + i))).block(); + System.out.println(block.getDataUtf8()); } catch (Throwable t) { // no ops } } + + server1.dispose(); + server2.dispose(); + server3.dispose(); } } From 5bb36339351ab4ccecf218f71db3c179db5a0e2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Mon, 4 Aug 2025 22:02:25 +0800 Subject: [PATCH 023/104] :art: --- build.gradle | 3 +- buildSrc/README.md | 58 ------------------------------------- today-remoting/build.gradle | 2 ++ 3 files changed, 4 insertions(+), 59 deletions(-) delete mode 100644 buildSrc/README.md diff --git a/build.gradle b/build.gradle index b7836e4..591407c 100644 --- a/build.gradle +++ b/build.gradle @@ -16,8 +16,9 @@ configure(allprojects) { repositories { mavenLocal() mavenCentral() - maven { url "https://repo.spring.io/milestone" } if (version.endsWith('-SNAPSHOT')) { + maven { url = "https://central.sonatype.com/repository/maven-snapshots/" } + maven { url "https://repo.spring.io/milestone" } maven { url "https://repo.spring.io/snapshot" } } } diff --git a/buildSrc/README.md b/buildSrc/README.md deleted file mode 100644 index 48a0f75..0000000 --- a/buildSrc/README.md +++ /dev/null @@ -1,58 +0,0 @@ -# Infra Cloud Build - -This folder contains the custom plugins and conventions for the Infra build. -They are declared in the `build.gradle` file in this folder. - -## Build Conventions - -The `infra.cloud.conventions` plugin applies all conventions to the Framework build: - -* Configuring the Java compiler, see `JavaConventions` -* Configuring testing in the build with `TestConventions` - - -## Build Plugins - -### Optional dependencies - -The `infra.cloud.optional-dependencies` plugin creates a new `optional` -Gradle configuration - it adds the dependencies to the project's compile and runtime classpath -but doesn't affect the classpath of dependent projects. -This plugin does not provide a `provided` configuration, as the native `compileOnly` and `testCompileOnly` -configurations are preferred. - -### RuntimeHints Java Agent - -The `today-core-test` project module contributes the `RuntimeHintsAgent` Java agent. - -The `RuntimeHintsAgentPlugin` Gradle plugin creates a dedicated `"runtimeHintsTest"` test task for each project. -This task will detect and execute [tests tagged](https://junit.org/junit5/docs/current/user-guide/#running-tests-build-gradle) -with the `"RuntimeHintsTests"` [JUnit tag](https://junit.org/junit5/docs/current/user-guide/#running-tests-tags). -In the Infra test suite, those are usually annotated with the `@EnabledIfRuntimeHintsAgent` annotation. - -By default, the agent will instrument all classes located in the `"cn.taketoday"` package, as they are loaded. -The `RuntimeHintsAgentExtension` allows to customize this using a DSL: - -```groovy -// this applies the `RuntimeHintsAgentPlugin` to the project -plugins { - id 'infra.cloud.runtimehints-agent' -} - -// You can configure the agent to include and exclude packages from the instrumentation process. -runtimeHintsAgent { - includedPackages = ["cn.taketoday", "io.spring"] - excludedPackages = ["org.example"] -} - -dependencies { - // to use the test infrastructure, the project should also depend on the "today-core-test" module - testImplementation(project(":today-core-test")) -} -``` - -With this configuration, `./gradlew runtimeHintsTest` will run all tests instrumented by this java agent. -The global `./gradlew check` task depends on `runtimeHintsTest`. - -NOTE: the "today-core-test" module doesn't shade "today-core" by design, so the agent should never instrument -code that doesn't have "today-core" on its classpath. \ No newline at end of file diff --git a/today-remoting/build.gradle b/today-remoting/build.gradle index 343edf2..f311d9e 100644 --- a/today-remoting/build.gradle +++ b/today-remoting/build.gradle @@ -16,6 +16,8 @@ dependencies { testImplementation 'org.awaitility:awaitility' testImplementation 'com.netflix.concurrency-limits:concurrency-limits-core:0.3.6' + testRuntimeOnly 'ch.qos.logback:logback-classic' + testFixturesApi "cn.taketoday:today-core" testFixturesApi 'org.assertj:assertj-core' testFixturesApi 'org.junit.jupiter:junit-jupiter-api' From 694036227dc86a51eed01d736480bb9e2eef3534 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Tue, 5 Aug 2025 14:12:06 +0800 Subject: [PATCH 024/104] :construction: --- .github/actions/building/action.yml | 2 +- settings.gradle | 26 +++++++++++++------------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/.github/actions/building/action.yml b/.github/actions/building/action.yml index b79723a..d9550c5 100644 --- a/.github/actions/building/action.yml +++ b/.github/actions/building/action.yml @@ -85,7 +85,7 @@ runs: id: build if: ${{ inputs.publish == 'false' }} shell: bash - run: ./gradlew -DCI=true --no-daemon --no-parallel check #--scan + run: ./gradlew -DCI=true --no-daemon --no-parallel check --scan - name: Publish id: publish diff --git a/settings.gradle b/settings.gradle index 4446dd6..c94e938 100644 --- a/settings.gradle +++ b/settings.gradle @@ -6,19 +6,19 @@ pluginManagement { } } -//plugins { -// id("com.gradle.enterprise") version("3.14.1") -//} -// -//gradleEnterprise { -// if (System.getenv("CI") != null || Boolean.getBoolean("CI")) { -// buildScan { -// publishAlways() -// termsOfServiceUrl = "https://gradle.com/terms-of-service" -// termsOfServiceAgree = "yes" -// } -// } -//} +plugins { + id("com.gradle.enterprise") version("3.14.1") +} + +gradleEnterprise { + if (System.getenv("CI") != null || Boolean.getBoolean("CI")) { + buildScan { + publishAlways() + termsOfServiceUrl = "https://gradle.com/terms-of-service" + termsOfServiceAgree = "yes" + } + } +} // A Java library for studying to create a microservices framework like Spring Cloud. From 7daf691bcb13ecb72bbfc67d55dc2170d34d72ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Tue, 5 Aug 2025 14:23:58 +0800 Subject: [PATCH 025/104] :art: --- .../ObservationRequesterChannel.java | 2 +- .../ObservationResponderChannel.java | 2 +- .../integration/IntegrationTests.java | 2 +- .../integration/StreamingTests.java | 2 +- .../integration/TcpIntegrationTests.java | 2 +- .../remoting/integration/FragmentTests.java | 2 +- .../transport/netty/SetupRejectionTests.java | 2 +- .../java/infra/remoting/ChannelAcceptor.java | 2 +- .../remoting/{util => }/ChannelWrapper.java | 4 +- .../src/main/java/infra/remoting/Payload.java | 5 +- .../infra/remoting/core/RemotingServer.java | 4 +- .../RequestChannelResponderSubscriber.java | 2 +- .../RequestResponseResponderSubscriber.java | 2 +- .../RequestStreamResponderSubscriber.java | 2 +- .../infra/remoting/core/RequesterChannel.java | 4 +- .../infra/remoting/core/ResponderChannel.java | 4 +- .../java/infra/remoting/core/SendUtils.java | 2 +- .../java/infra/remoting/core/ServerSetup.java | 4 +- .../ApplicationErrorException.java | 2 +- .../CanceledException.java | 2 +- .../ConnectionCloseException.java | 2 +- .../ConnectionErrorException.java | 2 +- .../CustomProtocolException.java | 2 +- .../{exceptions => error}/Exceptions.java | 2 +- .../InvalidException.java | 2 +- .../InvalidSetupException.java | 2 +- .../RejectedException.java | 2 +- .../RejectedResumeException.java | 2 +- .../RejectedSetupException.java | 2 +- .../{exceptions => error}/Retryable.java | 2 +- .../{exceptions => error}/SetupException.java | 2 +- .../UnsupportedSetupException.java | 2 +- .../{exceptions => error}/package-info.java | 2 +- .../remoting/lb/WeightedStatsChannel.java | 2 +- .../remoting/lease/MissingLeaseException.java | 2 +- .../remoting/plugins/RateLimitDecorator.java | 2 +- .../remoting/resume/ClientChannelSession.java | 6 +- .../resume/ResumableDuplexConnection.java | 2 +- .../remoting/resume/ServerChannelSession.java | 4 +- .../infra/remoting/util/ByteBufPayload.java | 27 ++-- .../remoting/core/ChannelLeaseTests.java | 4 +- .../infra/remoting/core/ChannelTests.java | 4 +- .../core/DefaultChannelClientTests.java | 2 +- ...a => FireAndForgetRequesterMonoTests.java} | 147 ++++++++---------- ...KeepAliveTest.java => KeepAliveTests.java} | 4 +- ....java => PayloadValidationUtilsTests.java} | 2 +- ... => RemotingServerFragmentationTests.java} | 2 +- ...rverTest.java => RemotingServerTests.java} | 4 +- ... => RequestRequesterChannelFluxTests.java} | 4 +- ...questResponderChannelSubscriberTests.java} | 4 +- ...=> RequestResponseRequesterMonoTests.java} | 4 +- ...a => RequestStreamRequesterFluxTests.java} | 4 +- .../remoting/core/RequesterChannelTests.java | 6 +- ...ava => RequesterOperatorsRacingTests.java} | 2 +- ...ava => ResponderOperatorsCommonTests.java} | 2 +- ...SendUtilsTest.java => SendUtilsTests.java} | 2 +- ...tionTest.java => SetupRejectionTests.java} | 6 +- .../remoting/core/ShouldNotHaveFlag.java | 29 ++-- .../ApplicationErrorExceptionTests.java | 2 +- .../CanceledExceptionTests.java | 2 +- .../ChannelExceptionTests.java | 2 +- .../ConnectionCloseExceptionTests.java | 2 +- .../ConnectionErrorExceptionTests.java | 2 +- .../ExceptionsTests.java | 2 +- .../InvalidExceptionTests.java | 2 +- .../InvalidSetupExceptionTests.java | 2 +- .../RejectedExceptionTests.java | 2 +- .../RejectedResumeExceptionTests.java | 2 +- .../RejectedSetupExceptionTests.java | 2 +- .../TestProtocolException.java | 2 +- .../UnsupportedSetupExceptionTests.java | 2 +- .../remoting/frame/ErrorFrameCodecTests.java | 2 +- .../infra/remoting/lb/LoadbalanceTests.java | 2 +- .../plugins/TestRequestInterceptor.java | 7 +- .../resume/ClientChannelSessionTests.java | 4 +- .../resume/ResumeIntegrationTests.java | 4 +- 76 files changed, 187 insertions(+), 214 deletions(-) rename today-remoting/src/main/java/infra/remoting/{util => }/ChannelWrapper.java (95%) rename today-remoting/src/main/java/infra/remoting/{exceptions => error}/ApplicationErrorException.java (97%) rename today-remoting/src/main/java/infra/remoting/{exceptions => error}/CanceledException.java (98%) rename today-remoting/src/main/java/infra/remoting/{exceptions => error}/ConnectionCloseException.java (98%) rename today-remoting/src/main/java/infra/remoting/{exceptions => error}/ConnectionErrorException.java (98%) rename today-remoting/src/main/java/infra/remoting/{exceptions => error}/CustomProtocolException.java (98%) rename today-remoting/src/main/java/infra/remoting/{exceptions => error}/Exceptions.java (99%) rename today-remoting/src/main/java/infra/remoting/{exceptions => error}/InvalidException.java (97%) rename today-remoting/src/main/java/infra/remoting/{exceptions => error}/InvalidSetupException.java (97%) rename today-remoting/src/main/java/infra/remoting/{exceptions => error}/RejectedException.java (98%) rename today-remoting/src/main/java/infra/remoting/{exceptions => error}/RejectedResumeException.java (97%) rename today-remoting/src/main/java/infra/remoting/{exceptions => error}/RejectedSetupException.java (97%) rename today-remoting/src/main/java/infra/remoting/{exceptions => error}/Retryable.java (96%) rename today-remoting/src/main/java/infra/remoting/{exceptions => error}/SetupException.java (97%) rename today-remoting/src/main/java/infra/remoting/{exceptions => error}/UnsupportedSetupException.java (97%) rename today-remoting/src/main/java/infra/remoting/{exceptions => error}/package-info.java (96%) rename today-remoting/src/test/java/infra/remoting/core/{FireAndForgetRequesterMonoTest.java => FireAndForgetRequesterMonoTests.java} (76%) rename today-remoting/src/test/java/infra/remoting/core/{KeepAliveTest.java => KeepAliveTests.java} (99%) rename today-remoting/src/test/java/infra/remoting/core/{PayloadValidationUtilsTest.java => PayloadValidationUtilsTests.java} (99%) rename today-remoting/src/test/java/infra/remoting/core/{RemotingServerFragmentationTest.java => RemotingServerFragmentationTests.java} (98%) rename today-remoting/src/test/java/infra/remoting/core/{RemotingServerTest.java => RemotingServerTests.java} (98%) rename today-remoting/src/test/java/infra/remoting/core/{RequestRequesterChannelFluxTest.java => RequestRequesterChannelFluxTests.java} (99%) rename today-remoting/src/test/java/infra/remoting/core/{RequestResponderChannelSubscriberTest.java => RequestResponderChannelSubscriberTests.java} (99%) rename today-remoting/src/test/java/infra/remoting/core/{RequestResponseRequesterMonoTest.java => RequestResponseRequesterMonoTests.java} (99%) rename today-remoting/src/test/java/infra/remoting/core/{RequestStreamRequesterFluxTest.java => RequestStreamRequesterFluxTests.java} (99%) rename today-remoting/src/test/java/infra/remoting/core/{RequesterOperatorsRacingTest.java => RequesterOperatorsRacingTests.java} (99%) rename today-remoting/src/test/java/infra/remoting/core/{ResponderOperatorsCommonTest.java => ResponderOperatorsCommonTests.java} (99%) rename today-remoting/src/test/java/infra/remoting/core/{SendUtilsTest.java => SendUtilsTests.java} (98%) rename today-remoting/src/test/java/infra/remoting/core/{SetupRejectionTest.java => SetupRejectionTests.java} (98%) rename today-remoting/src/test/java/infra/remoting/{exceptions => error}/ApplicationErrorExceptionTests.java (97%) rename today-remoting/src/test/java/infra/remoting/{exceptions => error}/CanceledExceptionTests.java (97%) rename today-remoting/src/test/java/infra/remoting/{exceptions => error}/ChannelExceptionTests.java (97%) rename today-remoting/src/test/java/infra/remoting/{exceptions => error}/ConnectionCloseExceptionTests.java (97%) rename today-remoting/src/test/java/infra/remoting/{exceptions => error}/ConnectionErrorExceptionTests.java (97%) rename today-remoting/src/test/java/infra/remoting/{exceptions => error}/ExceptionsTests.java (99%) rename today-remoting/src/test/java/infra/remoting/{exceptions => error}/InvalidExceptionTests.java (97%) rename today-remoting/src/test/java/infra/remoting/{exceptions => error}/InvalidSetupExceptionTests.java (97%) rename today-remoting/src/test/java/infra/remoting/{exceptions => error}/RejectedExceptionTests.java (97%) rename today-remoting/src/test/java/infra/remoting/{exceptions => error}/RejectedResumeExceptionTests.java (97%) rename today-remoting/src/test/java/infra/remoting/{exceptions => error}/RejectedSetupExceptionTests.java (97%) rename today-remoting/src/test/java/infra/remoting/{exceptions => error}/TestProtocolException.java (98%) rename today-remoting/src/test/java/infra/remoting/{exceptions => error}/UnsupportedSetupExceptionTests.java (97%) diff --git a/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/ObservationRequesterChannel.java b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/ObservationRequesterChannel.java index f0bf43a..fe2ed44 100644 --- a/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/ObservationRequesterChannel.java +++ b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/ObservationRequesterChannel.java @@ -25,7 +25,7 @@ import infra.remoting.Channel; import infra.remoting.Payload; import infra.remoting.frame.FrameType; -import infra.remoting.util.ChannelWrapper; +import infra.remoting.ChannelWrapper; import io.micrometer.common.util.StringUtils; import io.micrometer.observation.Observation; import io.micrometer.observation.ObservationRegistry; diff --git a/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/ObservationResponderChannel.java b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/ObservationResponderChannel.java index 4464cfe..2bf889e 100644 --- a/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/ObservationResponderChannel.java +++ b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/ObservationResponderChannel.java @@ -23,7 +23,7 @@ import infra.remoting.Channel; import infra.remoting.Payload; import infra.remoting.frame.FrameType; -import infra.remoting.util.ChannelWrapper; +import infra.remoting.ChannelWrapper; import io.micrometer.common.util.StringUtils; import io.micrometer.observation.Observation; import io.micrometer.observation.ObservationRegistry; diff --git a/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/IntegrationTests.java b/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/IntegrationTests.java index 55b8bb5..0c7eee7 100644 --- a/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/IntegrationTests.java +++ b/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/IntegrationTests.java @@ -38,7 +38,7 @@ import infra.remoting.transport.netty.client.TcpClientTransport; import infra.remoting.transport.netty.server.CloseableChannel; import infra.remoting.transport.netty.server.TcpServerTransport; -import infra.remoting.util.ChannelWrapper; +import infra.remoting.ChannelWrapper; import infra.remoting.util.DefaultPayload; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; diff --git a/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/StreamingTests.java b/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/StreamingTests.java index 14d746d..f372712 100644 --- a/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/StreamingTests.java +++ b/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/StreamingTests.java @@ -29,7 +29,7 @@ import infra.remoting.Payload; import infra.remoting.core.ChannelConnector; import infra.remoting.core.RemotingServer; -import infra.remoting.exceptions.ApplicationErrorException; +import infra.remoting.error.ApplicationErrorException; import infra.remoting.transport.local.LocalClientTransport; import infra.remoting.transport.local.LocalServerTransport; import infra.remoting.util.DefaultPayload; diff --git a/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/TcpIntegrationTests.java b/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/TcpIntegrationTests.java index 106fee5..62b3d4a 100644 --- a/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/TcpIntegrationTests.java +++ b/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/TcpIntegrationTests.java @@ -32,7 +32,7 @@ import infra.remoting.transport.netty.client.TcpClientTransport; import infra.remoting.transport.netty.server.CloseableChannel; import infra.remoting.transport.netty.server.TcpServerTransport; -import infra.remoting.util.ChannelWrapper; +import infra.remoting.ChannelWrapper; import infra.remoting.util.DefaultPayload; import infra.remoting.util.EmptyPayload; import reactor.core.publisher.Flux; diff --git a/today-remoting-transport-tcp/src/test/java/infra/remoting/integration/FragmentTests.java b/today-remoting-transport-tcp/src/test/java/infra/remoting/integration/FragmentTests.java index 93930a9..0821415 100644 --- a/today-remoting-transport-tcp/src/test/java/infra/remoting/integration/FragmentTests.java +++ b/today-remoting-transport-tcp/src/test/java/infra/remoting/integration/FragmentTests.java @@ -33,7 +33,7 @@ import infra.remoting.transport.netty.server.CloseableChannel; import infra.remoting.transport.netty.server.TcpServerTransport; import infra.remoting.util.DefaultPayload; -import infra.remoting.util.ChannelWrapper; +import infra.remoting.ChannelWrapper; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; diff --git a/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/SetupRejectionTests.java b/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/SetupRejectionTests.java index 3912086..d433ef4 100644 --- a/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/SetupRejectionTests.java +++ b/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/SetupRejectionTests.java @@ -29,7 +29,7 @@ import infra.remoting.ChannelAcceptor; import infra.remoting.core.ChannelConnector; import infra.remoting.core.RemotingServer; -import infra.remoting.exceptions.RejectedSetupException; +import infra.remoting.error.RejectedSetupException; import infra.remoting.transport.ClientTransport; import infra.remoting.transport.ServerTransport; import infra.remoting.transport.netty.client.TcpClientTransport; diff --git a/today-remoting/src/main/java/infra/remoting/ChannelAcceptor.java b/today-remoting/src/main/java/infra/remoting/ChannelAcceptor.java index e40daa8..1e84806 100644 --- a/today-remoting/src/main/java/infra/remoting/ChannelAcceptor.java +++ b/today-remoting/src/main/java/infra/remoting/ChannelAcceptor.java @@ -21,7 +21,7 @@ import java.util.function.Function; -import infra.remoting.exceptions.SetupException; +import infra.remoting.error.SetupException; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; diff --git a/today-remoting/src/main/java/infra/remoting/util/ChannelWrapper.java b/today-remoting/src/main/java/infra/remoting/ChannelWrapper.java similarity index 95% rename from today-remoting/src/main/java/infra/remoting/util/ChannelWrapper.java rename to today-remoting/src/main/java/infra/remoting/ChannelWrapper.java index 64fe93f..9b1ea38 100644 --- a/today-remoting/src/main/java/infra/remoting/util/ChannelWrapper.java +++ b/today-remoting/src/main/java/infra/remoting/ChannelWrapper.java @@ -15,12 +15,10 @@ * along with this program. If not, see [http://www.gnu.org/licenses/] */ -package infra.remoting.util; +package infra.remoting; import org.reactivestreams.Publisher; -import infra.remoting.Channel; -import infra.remoting.Payload; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; diff --git a/today-remoting/src/main/java/infra/remoting/Payload.java b/today-remoting/src/main/java/infra/remoting/Payload.java index 3105ef3..d55035f 100644 --- a/today-remoting/src/main/java/infra/remoting/Payload.java +++ b/today-remoting/src/main/java/infra/remoting/Payload.java @@ -24,8 +24,11 @@ import io.netty.util.ReferenceCounted; import io.netty.util.ResourceLeakDetector; -/** Payload of a Frame . */ +/** + * Payload of a Frame. + */ public interface Payload extends ReferenceCounted { + /** * Returns whether the payload has metadata, useful for tell if metadata is empty or not present. * diff --git a/today-remoting/src/main/java/infra/remoting/core/RemotingServer.java b/today-remoting/src/main/java/infra/remoting/core/RemotingServer.java index 4fc45ab..9e7df30 100644 --- a/today-remoting/src/main/java/infra/remoting/core/RemotingServer.java +++ b/today-remoting/src/main/java/infra/remoting/core/RemotingServer.java @@ -29,8 +29,8 @@ import infra.remoting.DuplexConnection; import infra.remoting.Payload; import infra.remoting.ProtocolErrorException; -import infra.remoting.exceptions.InvalidSetupException; -import infra.remoting.exceptions.RejectedSetupException; +import infra.remoting.error.InvalidSetupException; +import infra.remoting.error.RejectedSetupException; import infra.remoting.frame.FrameHeaderCodec; import infra.remoting.frame.SetupFrameCodec; import infra.remoting.frame.decoder.PayloadDecoder; diff --git a/today-remoting/src/main/java/infra/remoting/core/RequestChannelResponderSubscriber.java b/today-remoting/src/main/java/infra/remoting/core/RequestChannelResponderSubscriber.java index a52f706..04ec8c4 100644 --- a/today-remoting/src/main/java/infra/remoting/core/RequestChannelResponderSubscriber.java +++ b/today-remoting/src/main/java/infra/remoting/core/RequestChannelResponderSubscriber.java @@ -26,7 +26,7 @@ import infra.remoting.Channel; import infra.remoting.DuplexConnection; import infra.remoting.Payload; -import infra.remoting.exceptions.CanceledException; +import infra.remoting.error.CanceledException; import infra.remoting.frame.CancelFrameCodec; import infra.remoting.frame.ErrorFrameCodec; import infra.remoting.frame.FrameType; diff --git a/today-remoting/src/main/java/infra/remoting/core/RequestResponseResponderSubscriber.java b/today-remoting/src/main/java/infra/remoting/core/RequestResponseResponderSubscriber.java index 894f223..ce4bd71 100644 --- a/today-remoting/src/main/java/infra/remoting/core/RequestResponseResponderSubscriber.java +++ b/today-remoting/src/main/java/infra/remoting/core/RequestResponseResponderSubscriber.java @@ -27,7 +27,7 @@ import infra.remoting.Channel; import infra.remoting.DuplexConnection; import infra.remoting.Payload; -import infra.remoting.exceptions.CanceledException; +import infra.remoting.error.CanceledException; import infra.remoting.frame.ErrorFrameCodec; import infra.remoting.frame.FrameType; import infra.remoting.frame.PayloadFrameCodec; diff --git a/today-remoting/src/main/java/infra/remoting/core/RequestStreamResponderSubscriber.java b/today-remoting/src/main/java/infra/remoting/core/RequestStreamResponderSubscriber.java index 136f69c..513cafd 100644 --- a/today-remoting/src/main/java/infra/remoting/core/RequestStreamResponderSubscriber.java +++ b/today-remoting/src/main/java/infra/remoting/core/RequestStreamResponderSubscriber.java @@ -26,7 +26,7 @@ import infra.remoting.Channel; import infra.remoting.DuplexConnection; import infra.remoting.Payload; -import infra.remoting.exceptions.CanceledException; +import infra.remoting.error.CanceledException; import infra.remoting.frame.ErrorFrameCodec; import infra.remoting.frame.FrameType; import infra.remoting.frame.PayloadFrameCodec; diff --git a/today-remoting/src/main/java/infra/remoting/core/RequesterChannel.java b/today-remoting/src/main/java/infra/remoting/core/RequesterChannel.java index 50b1539..4fb5557 100644 --- a/today-remoting/src/main/java/infra/remoting/core/RequesterChannel.java +++ b/today-remoting/src/main/java/infra/remoting/core/RequesterChannel.java @@ -31,8 +31,8 @@ import infra.remoting.Channel; import infra.remoting.DuplexConnection; import infra.remoting.Payload; -import infra.remoting.exceptions.ConnectionErrorException; -import infra.remoting.exceptions.Exceptions; +import infra.remoting.error.ConnectionErrorException; +import infra.remoting.error.Exceptions; import infra.remoting.frame.ErrorFrameCodec; import infra.remoting.frame.FrameHeaderCodec; import infra.remoting.frame.FrameType; diff --git a/today-remoting/src/main/java/infra/remoting/core/ResponderChannel.java b/today-remoting/src/main/java/infra/remoting/core/ResponderChannel.java index 3a9185b..1f011d9 100644 --- a/today-remoting/src/main/java/infra/remoting/core/ResponderChannel.java +++ b/today-remoting/src/main/java/infra/remoting/core/ResponderChannel.java @@ -32,8 +32,8 @@ import infra.remoting.Channel; import infra.remoting.DuplexConnection; import infra.remoting.Payload; -import infra.remoting.exceptions.ConnectionErrorException; -import infra.remoting.exceptions.Exceptions; +import infra.remoting.error.ConnectionErrorException; +import infra.remoting.error.Exceptions; import infra.remoting.frame.ErrorFrameCodec; import infra.remoting.frame.FrameHeaderCodec; import infra.remoting.frame.FrameType; diff --git a/today-remoting/src/main/java/infra/remoting/core/SendUtils.java b/today-remoting/src/main/java/infra/remoting/core/SendUtils.java index b7b4491..7742b55 100644 --- a/today-remoting/src/main/java/infra/remoting/core/SendUtils.java +++ b/today-remoting/src/main/java/infra/remoting/core/SendUtils.java @@ -20,7 +20,7 @@ import infra.remoting.DuplexConnection; import infra.remoting.Payload; -import infra.remoting.exceptions.CanceledException; +import infra.remoting.error.CanceledException; import infra.remoting.frame.CancelFrameCodec; import infra.remoting.frame.ErrorFrameCodec; import infra.remoting.frame.FrameType; diff --git a/today-remoting/src/main/java/infra/remoting/core/ServerSetup.java b/today-remoting/src/main/java/infra/remoting/core/ServerSetup.java index 57b855c..c3de3ed 100644 --- a/today-remoting/src/main/java/infra/remoting/core/ServerSetup.java +++ b/today-remoting/src/main/java/infra/remoting/core/ServerSetup.java @@ -24,8 +24,8 @@ import infra.remoting.DuplexConnection; import infra.remoting.ProtocolErrorException; -import infra.remoting.exceptions.RejectedResumeException; -import infra.remoting.exceptions.UnsupportedSetupException; +import infra.remoting.error.RejectedResumeException; +import infra.remoting.error.UnsupportedSetupException; import infra.remoting.frame.ResumeFrameCodec; import infra.remoting.frame.SetupFrameCodec; import infra.remoting.keepalive.KeepAliveHandler; diff --git a/today-remoting/src/main/java/infra/remoting/exceptions/ApplicationErrorException.java b/today-remoting/src/main/java/infra/remoting/error/ApplicationErrorException.java similarity index 97% rename from today-remoting/src/main/java/infra/remoting/exceptions/ApplicationErrorException.java rename to today-remoting/src/main/java/infra/remoting/error/ApplicationErrorException.java index 32532bd..f8acfd3 100644 --- a/today-remoting/src/main/java/infra/remoting/exceptions/ApplicationErrorException.java +++ b/today-remoting/src/main/java/infra/remoting/error/ApplicationErrorException.java @@ -15,7 +15,7 @@ * along with this program. If not, see [http://www.gnu.org/licenses/] */ -package infra.remoting.exceptions; +package infra.remoting.error; import infra.lang.Nullable; import infra.remoting.ProtocolErrorException; diff --git a/today-remoting/src/main/java/infra/remoting/exceptions/CanceledException.java b/today-remoting/src/main/java/infra/remoting/error/CanceledException.java similarity index 98% rename from today-remoting/src/main/java/infra/remoting/exceptions/CanceledException.java rename to today-remoting/src/main/java/infra/remoting/error/CanceledException.java index 1ccf54a..c387eb3 100644 --- a/today-remoting/src/main/java/infra/remoting/exceptions/CanceledException.java +++ b/today-remoting/src/main/java/infra/remoting/error/CanceledException.java @@ -15,7 +15,7 @@ * along with this program. If not, see [http://www.gnu.org/licenses/] */ -package infra.remoting.exceptions; +package infra.remoting.error; import infra.lang.Nullable; import infra.remoting.ProtocolErrorException; diff --git a/today-remoting/src/main/java/infra/remoting/exceptions/ConnectionCloseException.java b/today-remoting/src/main/java/infra/remoting/error/ConnectionCloseException.java similarity index 98% rename from today-remoting/src/main/java/infra/remoting/exceptions/ConnectionCloseException.java rename to today-remoting/src/main/java/infra/remoting/error/ConnectionCloseException.java index e1c3576..55a80ff 100644 --- a/today-remoting/src/main/java/infra/remoting/exceptions/ConnectionCloseException.java +++ b/today-remoting/src/main/java/infra/remoting/error/ConnectionCloseException.java @@ -15,7 +15,7 @@ * along with this program. If not, see [http://www.gnu.org/licenses/] */ -package infra.remoting.exceptions; +package infra.remoting.error; import infra.lang.Nullable; import infra.remoting.ProtocolErrorException; diff --git a/today-remoting/src/main/java/infra/remoting/exceptions/ConnectionErrorException.java b/today-remoting/src/main/java/infra/remoting/error/ConnectionErrorException.java similarity index 98% rename from today-remoting/src/main/java/infra/remoting/exceptions/ConnectionErrorException.java rename to today-remoting/src/main/java/infra/remoting/error/ConnectionErrorException.java index 27f297d..ca3bd4d 100644 --- a/today-remoting/src/main/java/infra/remoting/exceptions/ConnectionErrorException.java +++ b/today-remoting/src/main/java/infra/remoting/error/ConnectionErrorException.java @@ -15,7 +15,7 @@ * along with this program. If not, see [http://www.gnu.org/licenses/] */ -package infra.remoting.exceptions; +package infra.remoting.error; import infra.lang.Nullable; import infra.remoting.ProtocolErrorException; diff --git a/today-remoting/src/main/java/infra/remoting/exceptions/CustomProtocolException.java b/today-remoting/src/main/java/infra/remoting/error/CustomProtocolException.java similarity index 98% rename from today-remoting/src/main/java/infra/remoting/exceptions/CustomProtocolException.java rename to today-remoting/src/main/java/infra/remoting/error/CustomProtocolException.java index 1d66836..4497930 100644 --- a/today-remoting/src/main/java/infra/remoting/exceptions/CustomProtocolException.java +++ b/today-remoting/src/main/java/infra/remoting/error/CustomProtocolException.java @@ -15,7 +15,7 @@ * along with this program. If not, see [http://www.gnu.org/licenses/] */ -package infra.remoting.exceptions; +package infra.remoting.error; import infra.lang.Nullable; import infra.remoting.ProtocolErrorException; diff --git a/today-remoting/src/main/java/infra/remoting/exceptions/Exceptions.java b/today-remoting/src/main/java/infra/remoting/error/Exceptions.java similarity index 99% rename from today-remoting/src/main/java/infra/remoting/exceptions/Exceptions.java rename to today-remoting/src/main/java/infra/remoting/error/Exceptions.java index 04d83df..8c45af3 100644 --- a/today-remoting/src/main/java/infra/remoting/exceptions/Exceptions.java +++ b/today-remoting/src/main/java/infra/remoting/error/Exceptions.java @@ -15,7 +15,7 @@ * along with this program. If not, see [http://www.gnu.org/licenses/] */ -package infra.remoting.exceptions; +package infra.remoting.error; import java.util.Objects; diff --git a/today-remoting/src/main/java/infra/remoting/exceptions/InvalidException.java b/today-remoting/src/main/java/infra/remoting/error/InvalidException.java similarity index 97% rename from today-remoting/src/main/java/infra/remoting/exceptions/InvalidException.java rename to today-remoting/src/main/java/infra/remoting/error/InvalidException.java index fe338e0..8772b88 100644 --- a/today-remoting/src/main/java/infra/remoting/exceptions/InvalidException.java +++ b/today-remoting/src/main/java/infra/remoting/error/InvalidException.java @@ -15,7 +15,7 @@ * along with this program. If not, see [http://www.gnu.org/licenses/] */ -package infra.remoting.exceptions; +package infra.remoting.error; import infra.lang.Nullable; import infra.remoting.ProtocolErrorException; diff --git a/today-remoting/src/main/java/infra/remoting/exceptions/InvalidSetupException.java b/today-remoting/src/main/java/infra/remoting/error/InvalidSetupException.java similarity index 97% rename from today-remoting/src/main/java/infra/remoting/exceptions/InvalidSetupException.java rename to today-remoting/src/main/java/infra/remoting/error/InvalidSetupException.java index 1830a0d..913ec54 100644 --- a/today-remoting/src/main/java/infra/remoting/exceptions/InvalidSetupException.java +++ b/today-remoting/src/main/java/infra/remoting/error/InvalidSetupException.java @@ -15,7 +15,7 @@ * along with this program. If not, see [http://www.gnu.org/licenses/] */ -package infra.remoting.exceptions; +package infra.remoting.error; import infra.lang.Nullable; import infra.remoting.frame.ErrorFrameCodec; diff --git a/today-remoting/src/main/java/infra/remoting/exceptions/RejectedException.java b/today-remoting/src/main/java/infra/remoting/error/RejectedException.java similarity index 98% rename from today-remoting/src/main/java/infra/remoting/exceptions/RejectedException.java rename to today-remoting/src/main/java/infra/remoting/error/RejectedException.java index 79ffc0f..1e55467 100644 --- a/today-remoting/src/main/java/infra/remoting/exceptions/RejectedException.java +++ b/today-remoting/src/main/java/infra/remoting/error/RejectedException.java @@ -15,7 +15,7 @@ * along with this program. If not, see [http://www.gnu.org/licenses/] */ -package infra.remoting.exceptions; +package infra.remoting.error; import infra.lang.Nullable; import infra.remoting.ProtocolErrorException; diff --git a/today-remoting/src/main/java/infra/remoting/exceptions/RejectedResumeException.java b/today-remoting/src/main/java/infra/remoting/error/RejectedResumeException.java similarity index 97% rename from today-remoting/src/main/java/infra/remoting/exceptions/RejectedResumeException.java rename to today-remoting/src/main/java/infra/remoting/error/RejectedResumeException.java index 1229166..a38c512 100644 --- a/today-remoting/src/main/java/infra/remoting/exceptions/RejectedResumeException.java +++ b/today-remoting/src/main/java/infra/remoting/error/RejectedResumeException.java @@ -15,7 +15,7 @@ * along with this program. If not, see [http://www.gnu.org/licenses/] */ -package infra.remoting.exceptions; +package infra.remoting.error; import infra.lang.Nullable; import infra.remoting.ProtocolErrorException; diff --git a/today-remoting/src/main/java/infra/remoting/exceptions/RejectedSetupException.java b/today-remoting/src/main/java/infra/remoting/error/RejectedSetupException.java similarity index 97% rename from today-remoting/src/main/java/infra/remoting/exceptions/RejectedSetupException.java rename to today-remoting/src/main/java/infra/remoting/error/RejectedSetupException.java index 1dd9b03..a0a862c 100644 --- a/today-remoting/src/main/java/infra/remoting/exceptions/RejectedSetupException.java +++ b/today-remoting/src/main/java/infra/remoting/error/RejectedSetupException.java @@ -15,7 +15,7 @@ * along with this program. If not, see [http://www.gnu.org/licenses/] */ -package infra.remoting.exceptions; +package infra.remoting.error; import infra.lang.Nullable; import infra.remoting.frame.ErrorFrameCodec; diff --git a/today-remoting/src/main/java/infra/remoting/exceptions/Retryable.java b/today-remoting/src/main/java/infra/remoting/error/Retryable.java similarity index 96% rename from today-remoting/src/main/java/infra/remoting/exceptions/Retryable.java rename to today-remoting/src/main/java/infra/remoting/error/Retryable.java index 8d6f3c9..ecd4018 100644 --- a/today-remoting/src/main/java/infra/remoting/exceptions/Retryable.java +++ b/today-remoting/src/main/java/infra/remoting/error/Retryable.java @@ -15,7 +15,7 @@ * along with this program. If not, see [http://www.gnu.org/licenses/] */ -package infra.remoting.exceptions; +package infra.remoting.error; /** * Indicates that an exception is retryable. This interface is a marker and the strategy for diff --git a/today-remoting/src/main/java/infra/remoting/exceptions/SetupException.java b/today-remoting/src/main/java/infra/remoting/error/SetupException.java similarity index 97% rename from today-remoting/src/main/java/infra/remoting/exceptions/SetupException.java rename to today-remoting/src/main/java/infra/remoting/error/SetupException.java index 9d931ad..ab25ef6 100644 --- a/today-remoting/src/main/java/infra/remoting/exceptions/SetupException.java +++ b/today-remoting/src/main/java/infra/remoting/error/SetupException.java @@ -15,7 +15,7 @@ * along with this program. If not, see [http://www.gnu.org/licenses/] */ -package infra.remoting.exceptions; +package infra.remoting.error; import infra.lang.Nullable; import infra.remoting.ProtocolErrorException; diff --git a/today-remoting/src/main/java/infra/remoting/exceptions/UnsupportedSetupException.java b/today-remoting/src/main/java/infra/remoting/error/UnsupportedSetupException.java similarity index 97% rename from today-remoting/src/main/java/infra/remoting/exceptions/UnsupportedSetupException.java rename to today-remoting/src/main/java/infra/remoting/error/UnsupportedSetupException.java index 8159614..774914f 100644 --- a/today-remoting/src/main/java/infra/remoting/exceptions/UnsupportedSetupException.java +++ b/today-remoting/src/main/java/infra/remoting/error/UnsupportedSetupException.java @@ -15,7 +15,7 @@ * along with this program. If not, see [http://www.gnu.org/licenses/] */ -package infra.remoting.exceptions; +package infra.remoting.error; import infra.lang.Nullable; import infra.remoting.frame.ErrorFrameCodec; diff --git a/today-remoting/src/main/java/infra/remoting/exceptions/package-info.java b/today-remoting/src/main/java/infra/remoting/error/package-info.java similarity index 96% rename from today-remoting/src/main/java/infra/remoting/exceptions/package-info.java rename to today-remoting/src/main/java/infra/remoting/error/package-info.java index b0ab702..919f543 100644 --- a/today-remoting/src/main/java/infra/remoting/exceptions/package-info.java +++ b/today-remoting/src/main/java/infra/remoting/error/package-info.java @@ -22,6 +22,6 @@ * Codes */ @NonNullApi -package infra.remoting.exceptions; +package infra.remoting.error; import infra.lang.NonNullApi; diff --git a/today-remoting/src/main/java/infra/remoting/lb/WeightedStatsChannel.java b/today-remoting/src/main/java/infra/remoting/lb/WeightedStatsChannel.java index 1cd8c23..d8aa384 100644 --- a/today-remoting/src/main/java/infra/remoting/lb/WeightedStatsChannel.java +++ b/today-remoting/src/main/java/infra/remoting/lb/WeightedStatsChannel.java @@ -18,7 +18,7 @@ package infra.remoting.lb; import infra.remoting.Channel; -import infra.remoting.util.ChannelWrapper; +import infra.remoting.ChannelWrapper; /** * Package private {@code ChannelWrapper} used from {@link WeightedStats#wrap(Channel)} to attach a diff --git a/today-remoting/src/main/java/infra/remoting/lease/MissingLeaseException.java b/today-remoting/src/main/java/infra/remoting/lease/MissingLeaseException.java index 73a845c..3709aa7 100644 --- a/today-remoting/src/main/java/infra/remoting/lease/MissingLeaseException.java +++ b/today-remoting/src/main/java/infra/remoting/lease/MissingLeaseException.java @@ -16,7 +16,7 @@ */ package infra.remoting.lease; -import infra.remoting.exceptions.RejectedException; +import infra.remoting.error.RejectedException; public class MissingLeaseException extends RejectedException { private static final long serialVersionUID = -6169748673403858959L; diff --git a/today-remoting/src/main/java/infra/remoting/plugins/RateLimitDecorator.java b/today-remoting/src/main/java/infra/remoting/plugins/RateLimitDecorator.java index c8a612f..c8cf2a0 100644 --- a/today-remoting/src/main/java/infra/remoting/plugins/RateLimitDecorator.java +++ b/today-remoting/src/main/java/infra/remoting/plugins/RateLimitDecorator.java @@ -21,7 +21,7 @@ import infra.remoting.Channel; import infra.remoting.Payload; -import infra.remoting.util.ChannelWrapper; +import infra.remoting.ChannelWrapper; import reactor.core.publisher.Flux; /** diff --git a/today-remoting/src/main/java/infra/remoting/resume/ClientChannelSession.java b/today-remoting/src/main/java/infra/remoting/resume/ClientChannelSession.java index 02d9dbd..ef92fb8 100644 --- a/today-remoting/src/main/java/infra/remoting/resume/ClientChannelSession.java +++ b/today-remoting/src/main/java/infra/remoting/resume/ClientChannelSession.java @@ -26,9 +26,9 @@ import infra.logging.Logger; import infra.logging.LoggerFactory; import infra.remoting.DuplexConnection; -import infra.remoting.exceptions.ConnectionErrorException; -import infra.remoting.exceptions.Exceptions; -import infra.remoting.exceptions.RejectedResumeException; +import infra.remoting.error.ConnectionErrorException; +import infra.remoting.error.Exceptions; +import infra.remoting.error.RejectedResumeException; import infra.remoting.frame.FrameHeaderCodec; import infra.remoting.frame.FrameType; import infra.remoting.frame.ResumeFrameCodec; diff --git a/today-remoting/src/main/java/infra/remoting/resume/ResumableDuplexConnection.java b/today-remoting/src/main/java/infra/remoting/resume/ResumableDuplexConnection.java index 69cc589..fc691fa 100644 --- a/today-remoting/src/main/java/infra/remoting/resume/ResumableDuplexConnection.java +++ b/today-remoting/src/main/java/infra/remoting/resume/ResumableDuplexConnection.java @@ -28,7 +28,7 @@ import infra.logging.LoggerFactory; import infra.remoting.DuplexConnection; import infra.remoting.ProtocolErrorException; -import infra.remoting.exceptions.ConnectionErrorException; +import infra.remoting.error.ConnectionErrorException; import infra.remoting.frame.ErrorFrameCodec; import infra.remoting.frame.FrameHeaderCodec; import infra.remoting.internal.UnboundedProcessor; diff --git a/today-remoting/src/main/java/infra/remoting/resume/ServerChannelSession.java b/today-remoting/src/main/java/infra/remoting/resume/ServerChannelSession.java index d7b7507..4973353 100644 --- a/today-remoting/src/main/java/infra/remoting/resume/ServerChannelSession.java +++ b/today-remoting/src/main/java/infra/remoting/resume/ServerChannelSession.java @@ -27,8 +27,8 @@ import infra.logging.Logger; import infra.logging.LoggerFactory; import infra.remoting.DuplexConnection; -import infra.remoting.exceptions.ConnectionErrorException; -import infra.remoting.exceptions.RejectedResumeException; +import infra.remoting.error.ConnectionErrorException; +import infra.remoting.error.RejectedResumeException; import infra.remoting.frame.ResumeFrameCodec; import infra.remoting.frame.ResumeOkFrameCodec; import infra.remoting.keepalive.KeepAliveSupport; diff --git a/today-remoting/src/main/java/infra/remoting/util/ByteBufPayload.java b/today-remoting/src/main/java/infra/remoting/util/ByteBufPayload.java index d9c14af..d4363bb 100644 --- a/today-remoting/src/main/java/infra/remoting/util/ByteBufPayload.java +++ b/today-remoting/src/main/java/infra/remoting/util/ByteBufPayload.java @@ -33,15 +33,17 @@ import io.netty.util.Recycler.Handle; public final class ByteBufPayload extends AbstractReferenceCounted implements Payload { - private static final Recycler RECYCLER = - new Recycler() { - protected ByteBufPayload newObject(Handle handle) { - return new ByteBufPayload(handle); - } - }; + + private static final Recycler RECYCLER = new Recycler<>() { + protected ByteBufPayload newObject(Handle handle) { + return new ByteBufPayload(handle); + } + }; private final Handle handle; + private ByteBuf data; + private ByteBuf metadata; private ByteBufPayload(final Handle handle) { @@ -78,13 +80,9 @@ public static Payload create(CharSequence data, Charset dataCharset) { null); } - public static Payload create( - CharSequence data, - Charset dataCharset, - @Nullable CharSequence metadata, - Charset metadataCharset) { - return create( - ByteBufUtil.encodeString(ByteBufAllocator.DEFAULT, CharBuffer.wrap(data), dataCharset), + public static Payload create(CharSequence data, Charset dataCharset, + @Nullable CharSequence metadata, Charset metadataCharset) { + return create(ByteBufUtil.encodeString(ByteBufAllocator.DEFAULT, CharBuffer.wrap(data), dataCharset), metadata == null ? null : ByteBufUtil.encodeString( @@ -123,8 +121,7 @@ public static Payload create(ByteBuf data, @Nullable ByteBuf metadata) { } public static Payload create(Payload payload) { - return create( - payload.sliceData().retain(), + return create(payload.sliceData().retain(), payload.hasMetadata() ? payload.sliceMetadata().retain() : null); } diff --git a/today-remoting/src/test/java/infra/remoting/core/ChannelLeaseTests.java b/today-remoting/src/test/java/infra/remoting/core/ChannelLeaseTests.java index 6dc0d58..2b3b71d 100644 --- a/today-remoting/src/test/java/infra/remoting/core/ChannelLeaseTests.java +++ b/today-remoting/src/test/java/infra/remoting/core/ChannelLeaseTests.java @@ -43,8 +43,8 @@ import infra.remoting.Payload; import infra.remoting.Channel; import infra.remoting.buffer.LeaksTrackingByteBufAllocator; -import infra.remoting.exceptions.Exceptions; -import infra.remoting.exceptions.RejectedException; +import infra.remoting.error.Exceptions; +import infra.remoting.error.RejectedException; import infra.remoting.frame.FrameHeaderCodec; import infra.remoting.frame.FrameType; import infra.remoting.frame.LeaseFrameCodec; diff --git a/today-remoting/src/test/java/infra/remoting/core/ChannelTests.java b/today-remoting/src/test/java/infra/remoting/core/ChannelTests.java index 18c8439..2e9c966 100644 --- a/today-remoting/src/test/java/infra/remoting/core/ChannelTests.java +++ b/today-remoting/src/test/java/infra/remoting/core/ChannelTests.java @@ -34,8 +34,8 @@ import infra.remoting.Payload; import infra.remoting.Channel; import infra.remoting.buffer.LeaksTrackingByteBufAllocator; -import infra.remoting.exceptions.ApplicationErrorException; -import infra.remoting.exceptions.CustomProtocolException; +import infra.remoting.error.ApplicationErrorException; +import infra.remoting.error.CustomProtocolException; import infra.remoting.frame.decoder.PayloadDecoder; import infra.remoting.internal.subscriber.AssertSubscriber; import infra.remoting.test.util.LocalDuplexConnection; diff --git a/today-remoting/src/test/java/infra/remoting/core/DefaultChannelClientTests.java b/today-remoting/src/test/java/infra/remoting/core/DefaultChannelClientTests.java index 4759012..7c32762 100644 --- a/today-remoting/src/test/java/infra/remoting/core/DefaultChannelClientTests.java +++ b/today-remoting/src/test/java/infra/remoting/core/DefaultChannelClientTests.java @@ -55,7 +55,7 @@ import infra.remoting.internal.subscriber.AssertSubscriber; import infra.remoting.test.util.TestDuplexConnection; import infra.remoting.util.ByteBufPayload; -import infra.remoting.util.ChannelWrapper; +import infra.remoting.ChannelWrapper; import reactor.core.Disposable; import reactor.core.publisher.Flux; import reactor.core.publisher.Hooks; diff --git a/today-remoting/src/test/java/infra/remoting/core/FireAndForgetRequesterMonoTest.java b/today-remoting/src/test/java/infra/remoting/core/FireAndForgetRequesterMonoTests.java similarity index 76% rename from today-remoting/src/test/java/infra/remoting/core/FireAndForgetRequesterMonoTest.java rename to today-remoting/src/test/java/infra/remoting/core/FireAndForgetRequesterMonoTests.java index 5170b25..97b4446 100644 --- a/today-remoting/src/test/java/infra/remoting/core/FireAndForgetRequesterMonoTest.java +++ b/today-remoting/src/test/java/infra/remoting/core/FireAndForgetRequesterMonoTests.java @@ -17,7 +17,6 @@ package infra.remoting.core; -import org.assertj.core.api.Assertions; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; @@ -30,10 +29,6 @@ import java.util.function.Consumer; import java.util.stream.Stream; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; -import io.netty.util.CharsetUtil; -import io.netty.util.IllegalReferenceCountException; import infra.remoting.FrameAssert; import infra.remoting.Payload; import infra.remoting.buffer.LeaksTrackingByteBufAllocator; @@ -41,6 +36,10 @@ import infra.remoting.plugins.TestRequestInterceptor; import infra.remoting.test.util.TestDuplexConnection; import infra.remoting.util.ByteBufPayload; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.util.CharsetUtil; +import io.netty.util.IllegalReferenceCountException; import reactor.core.Exceptions; import reactor.core.Scannable; import reactor.test.StepVerifier; @@ -51,8 +50,10 @@ import static infra.remoting.core.PayloadValidationUtils.INVALID_PAYLOAD_ERROR_MESSAGE; import static infra.remoting.core.TestChannelSupport.genericPayload; import static infra.remoting.frame.FrameLengthCodec.FRAME_LENGTH_MASK; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; -public class FireAndForgetRequesterMonoTest { +class FireAndForgetRequesterMonoTests { @BeforeAll public static void setUp() { @@ -80,7 +81,7 @@ public void frameShouldBeSentOnSubscription(Consumer monoConsumer.accept(fireAndForgetRequesterMono); - Assertions.assertThat(payload.refCnt()).isZero(); + assertThat(payload.refCnt()).isZero(); // should not add anything to map stateAssert.isTerminated(); activeStreams.assertNoActiveStreams(); @@ -98,7 +99,7 @@ public void frameShouldBeSentOnSubscription(Consumer .hasStreamId(1) .hasNoLeaks(); - Assertions.assertThat(activeStreams.getDuplexConnection().isEmpty()).isTrue(); + assertThat(activeStreams.getDuplexConnection().isEmpty()).isTrue(); activeStreams.getAllocator().assertHasNoLeaks(); testRequestInterceptor .expectOnStart(1, FrameType.REQUEST_FNF) @@ -141,7 +142,7 @@ public void frameFragmentsShouldBeSentOnSubscription( streamManager.assertNoActiveStreams(); stateAssert.isTerminated(); - Assertions.assertThat(payload.refCnt()).isZero(); + assertThat(payload.refCnt()).isZero(); final ByteBuf frameFragment1 = sender.awaitFrame(); FrameAssert.assertThat(frameFragment1) @@ -196,7 +197,7 @@ public void frameFragmentsShouldBeSentOnSubscription( .hasStreamId(1) .hasNoLeaks(); - Assertions.assertThat(sender.isEmpty()).isTrue(); + assertThat(sender.isEmpty()).isTrue(); allocator.assertHasNoLeaks(); } @@ -235,7 +236,7 @@ public void shouldErrorOnIncorrectRefCntInGivenPayload( stateAssert.isTerminated(); streamManager.assertNoActiveStreams(); - Assertions.assertThat(sender.isEmpty()).isTrue(); + assertThat(sender.isEmpty()).isTrue(); allocator.assertHasNoLeaks(); testRequestInterceptor .expectOnReject(FrameType.REQUEST_FNF, new IllegalReferenceCountException("refCnt: 0")) @@ -251,7 +252,7 @@ public void shouldErrorOnIncorrectRefCntInGivenPayload( .expectError(IllegalReferenceCountException.class) .verify(), fireAndForgetRequesterMono -> - Assertions.assertThatThrownBy(fireAndForgetRequesterMono::block) + assertThatThrownBy(fireAndForgetRequesterMono::block) .isInstanceOf(IllegalReferenceCountException.class)); } @@ -286,11 +287,11 @@ public void shouldErrorIfFragmentExitsAllowanceIfFragmentationDisabled( monoConsumer.accept(fireAndForgetRequesterMono); - Assertions.assertThat(payload.refCnt()).isZero(); + assertThat(payload.refCnt()).isZero(); stateAssert.isTerminated(); streamManager.assertNoActiveStreams(); - Assertions.assertThat(sender.isEmpty()).isTrue(); + assertThat(sender.isEmpty()).isTrue(); allocator.assertHasNoLeaks(); testRequestInterceptor .expectOnReject( @@ -302,19 +303,15 @@ public void shouldErrorIfFragmentExitsAllowanceIfFragmentationDisabled( static Stream> shouldErrorIfFragmentExitsAllowanceIfFragmentationDisabledSource() { - return Stream.of( - (s) -> - StepVerifier.create(s) - .expectSubscription() - .consumeErrorWith( - t -> - Assertions.assertThat(t) - .hasMessage( - String.format(INVALID_PAYLOAD_ERROR_MESSAGE, FRAME_LENGTH_MASK)) - .isInstanceOf(IllegalArgumentException.class)) - .verify(), + return Stream.of((s) -> StepVerifier.create(s) + .expectSubscription() + .consumeErrorWith(t -> + assertThat(t) + .hasMessage(String.format(INVALID_PAYLOAD_ERROR_MESSAGE, FRAME_LENGTH_MASK)) + .isInstanceOf(IllegalArgumentException.class)) + .verify(), fireAndForgetRequesterMono -> - Assertions.assertThatThrownBy(fireAndForgetRequesterMono::block) + assertThatThrownBy(fireAndForgetRequesterMono::block) .hasMessage(String.format(INVALID_PAYLOAD_ERROR_MESSAGE, FRAME_LENGTH_MASK)) .isInstanceOf(IllegalArgumentException.class)); } @@ -345,28 +342,25 @@ public void shouldErrorIfNoAvailability(Consumer mon monoConsumer.accept(fireAndForgetRequesterMono); - Assertions.assertThat(payload.refCnt()).isZero(); + assertThat(payload.refCnt()).isZero(); stateAssert.isTerminated(); streamManager.assertNoActiveStreams(); - Assertions.assertThat(sender.isEmpty()).isTrue(); + assertThat(sender.isEmpty()).isTrue(); allocator.assertHasNoLeaks(); testRequestInterceptor.expectOnReject(FrameType.REQUEST_FNF, exception).expectNothing(); } static Stream> shouldErrorIfNoAvailabilitySource() { - return Stream.of( - (s) -> - StepVerifier.create(s) - .expectSubscription() - .consumeErrorWith( - t -> - Assertions.assertThat(t) - .hasMessage("test") - .isInstanceOf(RuntimeException.class)) - .verify(), + return Stream.of((s) -> StepVerifier.create(s) + .expectSubscription() + .consumeErrorWith(t -> + assertThat(t) + .hasMessage("test") + .isInstanceOf(RuntimeException.class)) + .verify(), fireAndForgetRequesterMono -> - Assertions.assertThatThrownBy(fireAndForgetRequesterMono::block) + assertThatThrownBy(fireAndForgetRequesterMono::block) .hasMessage("test") .isInstanceOf(RuntimeException.class)); } @@ -375,44 +369,36 @@ static Stream> shouldErrorIfNoAvailabilityS @Test public void shouldSubscribeExactlyOnce1() { final TestRequestInterceptor testRequestInterceptor = new TestRequestInterceptor(); - final TestChannelSupport streamManager = - TestChannelSupport.client(testRequestInterceptor); + final TestChannelSupport streamManager = TestChannelSupport.client(testRequestInterceptor); final LeaksTrackingByteBufAllocator allocator = streamManager.getAllocator(); final TestDuplexConnection sender = streamManager.getDuplexConnection(); for (int i = 1; i < 50000; i += 2) { final Payload payload = ByteBufPayload.create("testData", "testMetadata"); - final FireAndForgetRequesterMono fireAndForgetRequesterMono = - new FireAndForgetRequesterMono(payload, streamManager); + final var fireAndForgetRequesterMono = new FireAndForgetRequesterMono(payload, streamManager); final StateAssert stateAssert = StateAssert.assertThat(FireAndForgetRequesterMono.STATE, fireAndForgetRequesterMono); - Assertions.assertThatThrownBy( - () -> - RaceTestUtils.race( - () -> { - AtomicReference atomicReference = new AtomicReference<>(); - fireAndForgetRequesterMono.subscribe(null, atomicReference::set); - Throwable throwable = atomicReference.get(); - if (throwable != null) { - throw Exceptions.propagate(throwable); - } - }, - fireAndForgetRequesterMono::block)) - .matches( - t -> { - Assertions.assertThat(t) - .hasMessageContaining("FireAndForgetMono allows only a single Subscriber"); - return true; - }); + assertThatThrownBy(() -> RaceTestUtils.race(() -> { + AtomicReference atomicReference = new AtomicReference<>(); + fireAndForgetRequesterMono.subscribe(null, atomicReference::set); + Throwable throwable = atomicReference.get(); + if (throwable != null) { + throw Exceptions.propagate(throwable); + } + }, fireAndForgetRequesterMono::block)) + + .matches(t -> { + assertThat(t).hasMessageContaining("FireAndForgetMono allows only a single Subscriber"); + return true; + }); final ByteBuf frame = sender.awaitFrame(); FrameAssert.assertThat(frame) .isNotNull() - .hasPayloadSize( - "testData".getBytes(CharsetUtil.UTF_8).length - + "testMetadata".getBytes(CharsetUtil.UTF_8).length) + .hasPayloadSize("testData".getBytes(CharsetUtil.UTF_8).length + + "testMetadata".getBytes(CharsetUtil.UTF_8).length) .hasMetadata("testMetadata") .hasData("testData") .hasNoFragmentsFollow() @@ -424,29 +410,20 @@ public void shouldSubscribeExactlyOnce1() { stateAssert.isTerminated(); streamManager.assertNoActiveStreams(); testRequestInterceptor - .assertNext( - event -> - Assertions.assertThat(event.eventType) - .isIn( - TestRequestInterceptor.EventType.ON_START, - TestRequestInterceptor.EventType.ON_REJECT)) - .assertNext( - event -> - Assertions.assertThat(event.eventType) - .isIn( - TestRequestInterceptor.EventType.ON_START, - TestRequestInterceptor.EventType.ON_COMPLETE, - TestRequestInterceptor.EventType.ON_REJECT)) - .assertNext( - event -> - Assertions.assertThat(event.eventType) - .isIn( - TestRequestInterceptor.EventType.ON_COMPLETE, - TestRequestInterceptor.EventType.ON_REJECT)) + .assertNext(event -> assertThat(event.eventType) + .isIn(TestRequestInterceptor.EventType.ON_START, + TestRequestInterceptor.EventType.ON_REJECT)) + .assertNext(event -> assertThat(event.eventType) + .isIn(TestRequestInterceptor.EventType.ON_START, + TestRequestInterceptor.EventType.ON_COMPLETE, + TestRequestInterceptor.EventType.ON_REJECT)) + .assertNext(event -> assertThat(event.eventType) + .isIn(TestRequestInterceptor.EventType.ON_COMPLETE, + TestRequestInterceptor.EventType.ON_REJECT)) .expectNothing(); } - Assertions.assertThat(sender.isEmpty()).isTrue(); + assertThat(sender.isEmpty()).isTrue(); allocator.assertHasNoLeaks(); } @@ -460,7 +437,7 @@ public void checkName() { final FireAndForgetRequesterMono fireAndForgetRequesterMono = new FireAndForgetRequesterMono(payload, testRequesterResponderSupport); - Assertions.assertThat(Scannable.from(fireAndForgetRequesterMono).name()) + assertThat(Scannable.from(fireAndForgetRequesterMono).name()) .isEqualTo("source(FireAndForgetMono)"); allocator.assertHasNoLeaks(); } diff --git a/today-remoting/src/test/java/infra/remoting/core/KeepAliveTest.java b/today-remoting/src/test/java/infra/remoting/core/KeepAliveTests.java similarity index 99% rename from today-remoting/src/test/java/infra/remoting/core/KeepAliveTest.java rename to today-remoting/src/test/java/infra/remoting/core/KeepAliveTests.java index 9d0a927..8a72a8e 100644 --- a/today-remoting/src/test/java/infra/remoting/core/KeepAliveTest.java +++ b/today-remoting/src/test/java/infra/remoting/core/KeepAliveTests.java @@ -28,7 +28,7 @@ import infra.remoting.Channel; import infra.remoting.FrameAssert; import infra.remoting.buffer.LeaksTrackingByteBufAllocator; -import infra.remoting.exceptions.ConnectionErrorException; +import infra.remoting.error.ConnectionErrorException; import infra.remoting.frame.FrameHeaderCodec; import infra.remoting.frame.FrameType; import infra.remoting.frame.KeepAliveFrameCodec; @@ -52,7 +52,7 @@ import static infra.remoting.keepalive.KeepAliveHandler.DefaultKeepAliveHandler; import static infra.remoting.keepalive.KeepAliveHandler.ResumableKeepAliveHandler; -public class KeepAliveTest { +public class KeepAliveTests { private static final int KEEP_ALIVE_INTERVAL = 100; private static final int KEEP_ALIVE_TIMEOUT = 1000; private static final int RESUMABLE_KEEP_ALIVE_TIMEOUT = 200; diff --git a/today-remoting/src/test/java/infra/remoting/core/PayloadValidationUtilsTest.java b/today-remoting/src/test/java/infra/remoting/core/PayloadValidationUtilsTests.java similarity index 99% rename from today-remoting/src/test/java/infra/remoting/core/PayloadValidationUtilsTest.java rename to today-remoting/src/test/java/infra/remoting/core/PayloadValidationUtilsTests.java index 9199810..853c3ad 100644 --- a/today-remoting/src/test/java/infra/remoting/core/PayloadValidationUtilsTest.java +++ b/today-remoting/src/test/java/infra/remoting/core/PayloadValidationUtilsTests.java @@ -29,7 +29,7 @@ import static infra.remoting.frame.FrameLengthCodec.FRAME_LENGTH_SIZE; -class PayloadValidationUtilsTest { +class PayloadValidationUtilsTests { @Test void shouldBeValidFrameWithNoFragmentation() { diff --git a/today-remoting/src/test/java/infra/remoting/core/RemotingServerFragmentationTest.java b/today-remoting/src/test/java/infra/remoting/core/RemotingServerFragmentationTests.java similarity index 98% rename from today-remoting/src/test/java/infra/remoting/core/RemotingServerFragmentationTest.java rename to today-remoting/src/test/java/infra/remoting/core/RemotingServerFragmentationTests.java index a8eae95..5e474b7 100644 --- a/today-remoting/src/test/java/infra/remoting/core/RemotingServerFragmentationTest.java +++ b/today-remoting/src/test/java/infra/remoting/core/RemotingServerFragmentationTests.java @@ -26,7 +26,7 @@ import infra.remoting.test.util.TestClientTransport; import infra.remoting.test.util.TestServerTransport; -public class RemotingServerFragmentationTest { +public class RemotingServerFragmentationTests { @Test public void serverErrorsWithEnabledFragmentationOnInsufficientMtu() { diff --git a/today-remoting/src/test/java/infra/remoting/core/RemotingServerTest.java b/today-remoting/src/test/java/infra/remoting/core/RemotingServerTests.java similarity index 98% rename from today-remoting/src/test/java/infra/remoting/core/RemotingServerTest.java rename to today-remoting/src/test/java/infra/remoting/core/RemotingServerTests.java index 42e8db4..89b542c 100644 --- a/today-remoting/src/test/java/infra/remoting/core/RemotingServerTest.java +++ b/today-remoting/src/test/java/infra/remoting/core/RemotingServerTests.java @@ -27,7 +27,7 @@ import infra.remoting.Closeable; import infra.remoting.FrameAssert; import infra.remoting.Channel; -import infra.remoting.exceptions.RejectedSetupException; +import infra.remoting.error.RejectedSetupException; import infra.remoting.frame.FrameType; import infra.remoting.frame.KeepAliveFrameCodec; import infra.remoting.frame.RequestResponseFrameCodec; @@ -44,7 +44,7 @@ import static infra.remoting.frame.FrameLengthCodec.FRAME_LENGTH_MASK; import static org.assertj.core.api.Assertions.assertThat; -public class RemotingServerTest { +public class RemotingServerTests { @Test public void unexpectedFramesBeforeSetupFrame() { diff --git a/today-remoting/src/test/java/infra/remoting/core/RequestRequesterChannelFluxTest.java b/today-remoting/src/test/java/infra/remoting/core/RequestRequesterChannelFluxTests.java similarity index 99% rename from today-remoting/src/test/java/infra/remoting/core/RequestRequesterChannelFluxTest.java rename to today-remoting/src/test/java/infra/remoting/core/RequestRequesterChannelFluxTests.java index a4c7aef..9717d0c 100644 --- a/today-remoting/src/test/java/infra/remoting/core/RequestRequesterChannelFluxTest.java +++ b/today-remoting/src/test/java/infra/remoting/core/RequestRequesterChannelFluxTests.java @@ -40,7 +40,7 @@ import infra.remoting.PayloadAssert; import infra.remoting.RaceTestConstants; import infra.remoting.buffer.LeaksTrackingByteBufAllocator; -import infra.remoting.exceptions.ApplicationErrorException; +import infra.remoting.error.ApplicationErrorException; import infra.remoting.frame.FrameType; import infra.remoting.internal.subscriber.AssertSubscriber; import infra.remoting.test.util.TestDuplexConnection; @@ -55,7 +55,7 @@ import static infra.remoting.frame.FrameLengthCodec.FRAME_LENGTH_MASK; import static infra.remoting.frame.FrameType.CANCEL; -public class RequestRequesterChannelFluxTest { +public class RequestRequesterChannelFluxTests { @BeforeAll public static void setUp() { diff --git a/today-remoting/src/test/java/infra/remoting/core/RequestResponderChannelSubscriberTest.java b/today-remoting/src/test/java/infra/remoting/core/RequestResponderChannelSubscriberTests.java similarity index 99% rename from today-remoting/src/test/java/infra/remoting/core/RequestResponderChannelSubscriberTest.java rename to today-remoting/src/test/java/infra/remoting/core/RequestResponderChannelSubscriberTests.java index 8e4304d..de952a3 100644 --- a/today-remoting/src/test/java/infra/remoting/core/RequestResponderChannelSubscriberTest.java +++ b/today-remoting/src/test/java/infra/remoting/core/RequestResponderChannelSubscriberTests.java @@ -41,7 +41,7 @@ import infra.remoting.PayloadAssert; import infra.remoting.RaceTestConstants; import infra.remoting.buffer.LeaksTrackingByteBufAllocator; -import infra.remoting.exceptions.ApplicationErrorException; +import infra.remoting.error.ApplicationErrorException; import infra.remoting.frame.FrameType; import infra.remoting.internal.subscriber.AssertSubscriber; import infra.remoting.test.util.TestDuplexConnection; @@ -64,7 +64,7 @@ import static reactor.test.publisher.TestPublisher.Violation.CLEANUP_ON_TERMINATE; import static reactor.test.publisher.TestPublisher.Violation.DEFER_CANCELLATION; -public class RequestResponderChannelSubscriberTest { +public class RequestResponderChannelSubscriberTests { @BeforeAll public static void setUp() { diff --git a/today-remoting/src/test/java/infra/remoting/core/RequestResponseRequesterMonoTest.java b/today-remoting/src/test/java/infra/remoting/core/RequestResponseRequesterMonoTests.java similarity index 99% rename from today-remoting/src/test/java/infra/remoting/core/RequestResponseRequesterMonoTest.java rename to today-remoting/src/test/java/infra/remoting/core/RequestResponseRequesterMonoTests.java index 4d9fe22..07737c7 100644 --- a/today-remoting/src/test/java/infra/remoting/core/RequestResponseRequesterMonoTest.java +++ b/today-remoting/src/test/java/infra/remoting/core/RequestResponseRequesterMonoTests.java @@ -33,7 +33,7 @@ import infra.remoting.Payload; import infra.remoting.PayloadAssert; import infra.remoting.buffer.LeaksTrackingByteBufAllocator; -import infra.remoting.exceptions.ApplicationErrorException; +import infra.remoting.error.ApplicationErrorException; import infra.remoting.frame.FrameType; import infra.remoting.test.util.TestDuplexConnection; import infra.remoting.util.ByteBufPayload; @@ -51,7 +51,7 @@ import static infra.remoting.core.TestChannelSupport.genericPayload; import static infra.remoting.frame.FrameLengthCodec.FRAME_LENGTH_MASK; -public class RequestResponseRequesterMonoTest { +public class RequestResponseRequesterMonoTests { @BeforeAll public static void setUp() { diff --git a/today-remoting/src/test/java/infra/remoting/core/RequestStreamRequesterFluxTest.java b/today-remoting/src/test/java/infra/remoting/core/RequestStreamRequesterFluxTests.java similarity index 99% rename from today-remoting/src/test/java/infra/remoting/core/RequestStreamRequesterFluxTest.java rename to today-remoting/src/test/java/infra/remoting/core/RequestStreamRequesterFluxTests.java index 03bd6fb..0a6a123 100644 --- a/today-remoting/src/test/java/infra/remoting/core/RequestStreamRequesterFluxTest.java +++ b/today-remoting/src/test/java/infra/remoting/core/RequestStreamRequesterFluxTests.java @@ -34,7 +34,7 @@ import infra.remoting.Payload; import infra.remoting.PayloadAssert; import infra.remoting.buffer.LeaksTrackingByteBufAllocator; -import infra.remoting.exceptions.ApplicationErrorException; +import infra.remoting.error.ApplicationErrorException; import infra.remoting.frame.FrameType; import infra.remoting.internal.subscriber.AssertSubscriber; import infra.remoting.test.util.TestDuplexConnection; @@ -53,7 +53,7 @@ import static infra.remoting.core.PayloadValidationUtils.INVALID_PAYLOAD_ERROR_MESSAGE; import static infra.remoting.frame.FrameLengthCodec.FRAME_LENGTH_MASK; -public class RequestStreamRequesterFluxTest { +public class RequestStreamRequesterFluxTests { @BeforeAll public static void setUp() { diff --git a/today-remoting/src/test/java/infra/remoting/core/RequesterChannelTests.java b/today-remoting/src/test/java/infra/remoting/core/RequesterChannelTests.java index 2673c9e..7ca12d8 100644 --- a/today-remoting/src/test/java/infra/remoting/core/RequesterChannelTests.java +++ b/today-remoting/src/test/java/infra/remoting/core/RequesterChannelTests.java @@ -58,9 +58,9 @@ import infra.remoting.Channel; import infra.remoting.RaceTestConstants; import infra.remoting.buffer.LeaksTrackingByteBufAllocator; -import infra.remoting.exceptions.ApplicationErrorException; -import infra.remoting.exceptions.CustomProtocolException; -import infra.remoting.exceptions.RejectedSetupException; +import infra.remoting.error.ApplicationErrorException; +import infra.remoting.error.CustomProtocolException; +import infra.remoting.error.RejectedSetupException; import infra.remoting.frame.CancelFrameCodec; import infra.remoting.frame.ErrorFrameCodec; import infra.remoting.frame.FrameHeaderCodec; diff --git a/today-remoting/src/test/java/infra/remoting/core/RequesterOperatorsRacingTest.java b/today-remoting/src/test/java/infra/remoting/core/RequesterOperatorsRacingTests.java similarity index 99% rename from today-remoting/src/test/java/infra/remoting/core/RequesterOperatorsRacingTest.java rename to today-remoting/src/test/java/infra/remoting/core/RequesterOperatorsRacingTests.java index e1a6dce..a4f6e9e 100644 --- a/today-remoting/src/test/java/infra/remoting/core/RequesterOperatorsRacingTest.java +++ b/today-remoting/src/test/java/infra/remoting/core/RequesterOperatorsRacingTests.java @@ -55,7 +55,7 @@ import static infra.remoting.frame.FrameType.REQUEST_STREAM; @SuppressWarnings("ALL") -public class RequesterOperatorsRacingTest { +public class RequesterOperatorsRacingTests { interface Scenario { FrameType requestType(); diff --git a/today-remoting/src/test/java/infra/remoting/core/ResponderOperatorsCommonTest.java b/today-remoting/src/test/java/infra/remoting/core/ResponderOperatorsCommonTests.java similarity index 99% rename from today-remoting/src/test/java/infra/remoting/core/ResponderOperatorsCommonTest.java rename to today-remoting/src/test/java/infra/remoting/core/ResponderOperatorsCommonTests.java index 1bf1c72..bc42c3b 100755 --- a/today-remoting/src/test/java/infra/remoting/core/ResponderOperatorsCommonTest.java +++ b/today-remoting/src/test/java/infra/remoting/core/ResponderOperatorsCommonTests.java @@ -48,7 +48,7 @@ import static infra.remoting.frame.FrameType.REQUEST_RESPONSE; import static infra.remoting.frame.FrameType.REQUEST_STREAM; -public class ResponderOperatorsCommonTest { +public class ResponderOperatorsCommonTests { interface Scenario { FrameType requestType(); diff --git a/today-remoting/src/test/java/infra/remoting/core/SendUtilsTest.java b/today-remoting/src/test/java/infra/remoting/core/SendUtilsTests.java similarity index 98% rename from today-remoting/src/test/java/infra/remoting/core/SendUtilsTest.java rename to today-remoting/src/test/java/infra/remoting/core/SendUtilsTests.java index bb6d981..7b8e2d6 100644 --- a/today-remoting/src/test/java/infra/remoting/core/SendUtilsTest.java +++ b/today-remoting/src/test/java/infra/remoting/core/SendUtilsTests.java @@ -27,7 +27,7 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -public class SendUtilsTest { +public class SendUtilsTests { @Test void droppedElementsConsumerShouldAcceptOtherTypesThanReferenceCounted() { diff --git a/today-remoting/src/test/java/infra/remoting/core/SetupRejectionTest.java b/today-remoting/src/test/java/infra/remoting/core/SetupRejectionTests.java similarity index 98% rename from today-remoting/src/test/java/infra/remoting/core/SetupRejectionTest.java rename to today-remoting/src/test/java/infra/remoting/core/SetupRejectionTests.java index c573f07..2b44909 100644 --- a/today-remoting/src/test/java/infra/remoting/core/SetupRejectionTest.java +++ b/today-remoting/src/test/java/infra/remoting/core/SetupRejectionTests.java @@ -29,8 +29,8 @@ import infra.remoting.Channel; import infra.remoting.ChannelAcceptor; import infra.remoting.buffer.LeaksTrackingByteBufAllocator; -import infra.remoting.exceptions.Exceptions; -import infra.remoting.exceptions.RejectedSetupException; +import infra.remoting.error.Exceptions; +import infra.remoting.error.RejectedSetupException; import infra.remoting.frame.ErrorFrameCodec; import infra.remoting.frame.FrameHeaderCodec; import infra.remoting.frame.FrameType; @@ -46,7 +46,7 @@ import static infra.remoting.frame.FrameLengthCodec.FRAME_LENGTH_MASK; import static org.assertj.core.api.Assertions.assertThat; -public class SetupRejectionTest { +public class SetupRejectionTests { @Test void responderRejectSetup() { diff --git a/today-remoting/src/test/java/infra/remoting/core/ShouldNotHaveFlag.java b/today-remoting/src/test/java/infra/remoting/core/ShouldNotHaveFlag.java index 2dafae9..aba2c84 100644 --- a/today-remoting/src/test/java/infra/remoting/core/ShouldNotHaveFlag.java +++ b/today-remoting/src/test/java/infra/remoting/core/ShouldNotHaveFlag.java @@ -29,19 +29,18 @@ class ShouldNotHaveFlag extends BasicErrorMessageFactory { - static final Map FLAGS_NAMES = - new HashMap() { - { - put(StateUtils.UNSUBSCRIBED_STATE, "UNSUBSCRIBED"); - put(StateUtils.TERMINATED_STATE, "TERMINATED"); - put(SUBSCRIBED_FLAG, "SUBSCRIBED"); - put(StateUtils.REQUEST_MASK, "REQUESTED(%n)"); - put(StateUtils.FIRST_FRAME_SENT_FLAG, "FIRST_FRAME_SENT"); - put(StateUtils.REASSEMBLING_FLAG, "REASSEMBLING"); - put(StateUtils.INBOUND_TERMINATED_FLAG, "INBOUND_TERMINATED"); - put(StateUtils.OUTBOUND_TERMINATED_FLAG, "OUTBOUND_TERMINATED"); - } - }; + static final Map FLAGS_NAMES = new HashMap<>() { + { + put(StateUtils.UNSUBSCRIBED_STATE, "UNSUBSCRIBED"); + put(StateUtils.TERMINATED_STATE, "TERMINATED"); + put(SUBSCRIBED_FLAG, "SUBSCRIBED"); + put(StateUtils.REQUEST_MASK, "REQUESTED(%n)"); + put(StateUtils.FIRST_FRAME_SENT_FLAG, "FIRST_FRAME_SENT"); + put(StateUtils.REASSEMBLING_FLAG, "REASSEMBLING"); + put(StateUtils.INBOUND_TERMINATED_FLAG, "INBOUND_TERMINATED"); + put(StateUtils.OUTBOUND_TERMINATED_FLAG, "OUTBOUND_TERMINATED"); + } + }; static final String SHOULD_NOT_HAVE_FLAG = "Expected state\n\t%s\nto not have\n\t%s\nbut had\n\t[%s]"; @@ -59,7 +58,7 @@ static ErrorMessageFactory shouldNotHaveFlag(long currentState, long expectedFla long flag = 1L << 31; for (int i = 0; i < 33; i++, flag <<= 1) { if ((currentState & flag) == flag) { - if (stringBuilder.length() > 0) { + if (!stringBuilder.isEmpty()) { stringBuilder.append(", "); } stringBuilder.append(FLAGS_NAMES.get(flag)); @@ -67,7 +66,7 @@ static ErrorMessageFactory shouldNotHaveFlag(long currentState, long expectedFla } long requestN = extractRequestN(currentState); if (requestN > 0) { - if (stringBuilder.length() > 0) { + if (!stringBuilder.isEmpty()) { stringBuilder.append(", "); } stringBuilder.append(String.format(FLAGS_NAMES.get(REQUEST_MASK), requestN)); diff --git a/today-remoting/src/test/java/infra/remoting/exceptions/ApplicationErrorExceptionTests.java b/today-remoting/src/test/java/infra/remoting/error/ApplicationErrorExceptionTests.java similarity index 97% rename from today-remoting/src/test/java/infra/remoting/exceptions/ApplicationErrorExceptionTests.java rename to today-remoting/src/test/java/infra/remoting/error/ApplicationErrorExceptionTests.java index 15370c2..50a94bf 100644 --- a/today-remoting/src/test/java/infra/remoting/exceptions/ApplicationErrorExceptionTests.java +++ b/today-remoting/src/test/java/infra/remoting/error/ApplicationErrorExceptionTests.java @@ -15,7 +15,7 @@ * along with this program. If not, see [http://www.gnu.org/licenses/] */ -package infra.remoting.exceptions; +package infra.remoting.error; final class ApplicationErrorExceptionTests implements ChannelExceptionTests { diff --git a/today-remoting/src/test/java/infra/remoting/exceptions/CanceledExceptionTests.java b/today-remoting/src/test/java/infra/remoting/error/CanceledExceptionTests.java similarity index 97% rename from today-remoting/src/test/java/infra/remoting/exceptions/CanceledExceptionTests.java rename to today-remoting/src/test/java/infra/remoting/error/CanceledExceptionTests.java index f376062..e8a2c18 100644 --- a/today-remoting/src/test/java/infra/remoting/exceptions/CanceledExceptionTests.java +++ b/today-remoting/src/test/java/infra/remoting/error/CanceledExceptionTests.java @@ -15,7 +15,7 @@ * along with this program. If not, see [http://www.gnu.org/licenses/] */ -package infra.remoting.exceptions; +package infra.remoting.error; final class CanceledExceptionTests implements ChannelExceptionTests { diff --git a/today-remoting/src/test/java/infra/remoting/exceptions/ChannelExceptionTests.java b/today-remoting/src/test/java/infra/remoting/error/ChannelExceptionTests.java similarity index 97% rename from today-remoting/src/test/java/infra/remoting/exceptions/ChannelExceptionTests.java rename to today-remoting/src/test/java/infra/remoting/error/ChannelExceptionTests.java index 1beb7cb..eff3082 100644 --- a/today-remoting/src/test/java/infra/remoting/exceptions/ChannelExceptionTests.java +++ b/today-remoting/src/test/java/infra/remoting/error/ChannelExceptionTests.java @@ -15,7 +15,7 @@ * along with this program. If not, see [http://www.gnu.org/licenses/] */ -package infra.remoting.exceptions; +package infra.remoting.error; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; diff --git a/today-remoting/src/test/java/infra/remoting/exceptions/ConnectionCloseExceptionTests.java b/today-remoting/src/test/java/infra/remoting/error/ConnectionCloseExceptionTests.java similarity index 97% rename from today-remoting/src/test/java/infra/remoting/exceptions/ConnectionCloseExceptionTests.java rename to today-remoting/src/test/java/infra/remoting/error/ConnectionCloseExceptionTests.java index bfc8a3c..e4aecb8 100644 --- a/today-remoting/src/test/java/infra/remoting/exceptions/ConnectionCloseExceptionTests.java +++ b/today-remoting/src/test/java/infra/remoting/error/ConnectionCloseExceptionTests.java @@ -15,7 +15,7 @@ * along with this program. If not, see [http://www.gnu.org/licenses/] */ -package infra.remoting.exceptions; +package infra.remoting.error; final class ConnectionCloseExceptionTests implements ChannelExceptionTests { diff --git a/today-remoting/src/test/java/infra/remoting/exceptions/ConnectionErrorExceptionTests.java b/today-remoting/src/test/java/infra/remoting/error/ConnectionErrorExceptionTests.java similarity index 97% rename from today-remoting/src/test/java/infra/remoting/exceptions/ConnectionErrorExceptionTests.java rename to today-remoting/src/test/java/infra/remoting/error/ConnectionErrorExceptionTests.java index db08cba..20ae2dc 100644 --- a/today-remoting/src/test/java/infra/remoting/exceptions/ConnectionErrorExceptionTests.java +++ b/today-remoting/src/test/java/infra/remoting/error/ConnectionErrorExceptionTests.java @@ -15,7 +15,7 @@ * along with this program. If not, see [http://www.gnu.org/licenses/] */ -package infra.remoting.exceptions; +package infra.remoting.error; final class ConnectionErrorExceptionTests implements ChannelExceptionTests { diff --git a/today-remoting/src/test/java/infra/remoting/exceptions/ExceptionsTests.java b/today-remoting/src/test/java/infra/remoting/error/ExceptionsTests.java similarity index 99% rename from today-remoting/src/test/java/infra/remoting/exceptions/ExceptionsTests.java rename to today-remoting/src/test/java/infra/remoting/error/ExceptionsTests.java index bafcc3f..3880ba4 100644 --- a/today-remoting/src/test/java/infra/remoting/exceptions/ExceptionsTests.java +++ b/today-remoting/src/test/java/infra/remoting/error/ExceptionsTests.java @@ -15,7 +15,7 @@ * along with this program. If not, see [http://www.gnu.org/licenses/] */ -package infra.remoting.exceptions; +package infra.remoting.error; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; diff --git a/today-remoting/src/test/java/infra/remoting/exceptions/InvalidExceptionTests.java b/today-remoting/src/test/java/infra/remoting/error/InvalidExceptionTests.java similarity index 97% rename from today-remoting/src/test/java/infra/remoting/exceptions/InvalidExceptionTests.java rename to today-remoting/src/test/java/infra/remoting/error/InvalidExceptionTests.java index bc3487e..0b107c0 100644 --- a/today-remoting/src/test/java/infra/remoting/exceptions/InvalidExceptionTests.java +++ b/today-remoting/src/test/java/infra/remoting/error/InvalidExceptionTests.java @@ -15,7 +15,7 @@ * along with this program. If not, see [http://www.gnu.org/licenses/] */ -package infra.remoting.exceptions; +package infra.remoting.error; final class InvalidExceptionTests implements ChannelExceptionTests { diff --git a/today-remoting/src/test/java/infra/remoting/exceptions/InvalidSetupExceptionTests.java b/today-remoting/src/test/java/infra/remoting/error/InvalidSetupExceptionTests.java similarity index 97% rename from today-remoting/src/test/java/infra/remoting/exceptions/InvalidSetupExceptionTests.java rename to today-remoting/src/test/java/infra/remoting/error/InvalidSetupExceptionTests.java index a2ae4f9..5e9497b 100644 --- a/today-remoting/src/test/java/infra/remoting/exceptions/InvalidSetupExceptionTests.java +++ b/today-remoting/src/test/java/infra/remoting/error/InvalidSetupExceptionTests.java @@ -15,7 +15,7 @@ * along with this program. If not, see [http://www.gnu.org/licenses/] */ -package infra.remoting.exceptions; +package infra.remoting.error; final class InvalidSetupExceptionTests implements ChannelExceptionTests { diff --git a/today-remoting/src/test/java/infra/remoting/exceptions/RejectedExceptionTests.java b/today-remoting/src/test/java/infra/remoting/error/RejectedExceptionTests.java similarity index 97% rename from today-remoting/src/test/java/infra/remoting/exceptions/RejectedExceptionTests.java rename to today-remoting/src/test/java/infra/remoting/error/RejectedExceptionTests.java index 781d2a2..d768dd9 100644 --- a/today-remoting/src/test/java/infra/remoting/exceptions/RejectedExceptionTests.java +++ b/today-remoting/src/test/java/infra/remoting/error/RejectedExceptionTests.java @@ -15,7 +15,7 @@ * along with this program. If not, see [http://www.gnu.org/licenses/] */ -package infra.remoting.exceptions; +package infra.remoting.error; final class RejectedExceptionTests implements ChannelExceptionTests { diff --git a/today-remoting/src/test/java/infra/remoting/exceptions/RejectedResumeExceptionTests.java b/today-remoting/src/test/java/infra/remoting/error/RejectedResumeExceptionTests.java similarity index 97% rename from today-remoting/src/test/java/infra/remoting/exceptions/RejectedResumeExceptionTests.java rename to today-remoting/src/test/java/infra/remoting/error/RejectedResumeExceptionTests.java index f503d8d..f88af45 100644 --- a/today-remoting/src/test/java/infra/remoting/exceptions/RejectedResumeExceptionTests.java +++ b/today-remoting/src/test/java/infra/remoting/error/RejectedResumeExceptionTests.java @@ -15,7 +15,7 @@ * along with this program. If not, see [http://www.gnu.org/licenses/] */ -package infra.remoting.exceptions; +package infra.remoting.error; final class RejectedResumeExceptionTests implements ChannelExceptionTests { diff --git a/today-remoting/src/test/java/infra/remoting/exceptions/RejectedSetupExceptionTests.java b/today-remoting/src/test/java/infra/remoting/error/RejectedSetupExceptionTests.java similarity index 97% rename from today-remoting/src/test/java/infra/remoting/exceptions/RejectedSetupExceptionTests.java rename to today-remoting/src/test/java/infra/remoting/error/RejectedSetupExceptionTests.java index 4c0c25b..3dd674e 100644 --- a/today-remoting/src/test/java/infra/remoting/exceptions/RejectedSetupExceptionTests.java +++ b/today-remoting/src/test/java/infra/remoting/error/RejectedSetupExceptionTests.java @@ -15,7 +15,7 @@ * along with this program. If not, see [http://www.gnu.org/licenses/] */ -package infra.remoting.exceptions; +package infra.remoting.error; final class RejectedSetupExceptionTests implements ChannelExceptionTests { diff --git a/today-remoting/src/test/java/infra/remoting/exceptions/TestProtocolException.java b/today-remoting/src/test/java/infra/remoting/error/TestProtocolException.java similarity index 98% rename from today-remoting/src/test/java/infra/remoting/exceptions/TestProtocolException.java rename to today-remoting/src/test/java/infra/remoting/error/TestProtocolException.java index 6cf0c10..badf646 100644 --- a/today-remoting/src/test/java/infra/remoting/exceptions/TestProtocolException.java +++ b/today-remoting/src/test/java/infra/remoting/error/TestProtocolException.java @@ -15,7 +15,7 @@ * along with this program. If not, see [http://www.gnu.org/licenses/] */ -package infra.remoting.exceptions; +package infra.remoting.error; import infra.remoting.ProtocolErrorException; import infra.remoting.frame.ErrorFrameCodec; diff --git a/today-remoting/src/test/java/infra/remoting/exceptions/UnsupportedSetupExceptionTests.java b/today-remoting/src/test/java/infra/remoting/error/UnsupportedSetupExceptionTests.java similarity index 97% rename from today-remoting/src/test/java/infra/remoting/exceptions/UnsupportedSetupExceptionTests.java rename to today-remoting/src/test/java/infra/remoting/error/UnsupportedSetupExceptionTests.java index f530802..45ef572 100644 --- a/today-remoting/src/test/java/infra/remoting/exceptions/UnsupportedSetupExceptionTests.java +++ b/today-remoting/src/test/java/infra/remoting/error/UnsupportedSetupExceptionTests.java @@ -15,7 +15,7 @@ * along with this program. If not, see [http://www.gnu.org/licenses/] */ -package infra.remoting.exceptions; +package infra.remoting.error; final class UnsupportedSetupExceptionTests implements ChannelExceptionTests { diff --git a/today-remoting/src/test/java/infra/remoting/frame/ErrorFrameCodecTests.java b/today-remoting/src/test/java/infra/remoting/frame/ErrorFrameCodecTests.java index 8f53590..0f57e63 100644 --- a/today-remoting/src/test/java/infra/remoting/frame/ErrorFrameCodecTests.java +++ b/today-remoting/src/test/java/infra/remoting/frame/ErrorFrameCodecTests.java @@ -22,7 +22,7 @@ import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufAllocator; import io.netty.buffer.ByteBufUtil; -import infra.remoting.exceptions.ApplicationErrorException; +import infra.remoting.error.ApplicationErrorException; import static org.junit.jupiter.api.Assertions.assertEquals; diff --git a/today-remoting/src/test/java/infra/remoting/lb/LoadbalanceTests.java b/today-remoting/src/test/java/infra/remoting/lb/LoadbalanceTests.java index 2404c78..27b0efc 100644 --- a/today-remoting/src/test/java/infra/remoting/lb/LoadbalanceTests.java +++ b/today-remoting/src/test/java/infra/remoting/lb/LoadbalanceTests.java @@ -38,7 +38,7 @@ import infra.remoting.test.util.TestClientTransport; import infra.remoting.transport.ClientTransport; import infra.remoting.util.EmptyPayload; -import infra.remoting.util.ChannelWrapper; +import infra.remoting.ChannelWrapper; import reactor.core.CoreSubscriber; import reactor.core.publisher.Flux; import reactor.core.publisher.Hooks; diff --git a/today-remoting/src/test/java/infra/remoting/plugins/TestRequestInterceptor.java b/today-remoting/src/test/java/infra/remoting/plugins/TestRequestInterceptor.java index 64ad6c5..b397ca4 100644 --- a/today-remoting/src/test/java/infra/remoting/plugins/TestRequestInterceptor.java +++ b/today-remoting/src/test/java/infra/remoting/plugins/TestRequestInterceptor.java @@ -24,9 +24,9 @@ import java.util.function.Consumer; import infra.lang.Nullable; -import io.netty.buffer.ByteBuf; import infra.remoting.frame.FrameType; import infra.remoting.internal.jctools.queues.MpscUnboundedArrayQueue; +import io.netty.buffer.ByteBuf; public class TestRequestInterceptor implements RequestInterceptor { @@ -42,9 +42,8 @@ public void onStart(int streamId, FrameType requestType, @Nullable ByteBuf metad @Override public void onTerminate(int streamId, FrameType requestType, @Nullable Throwable t) { - events.add( - new Event( - t == null ? EventType.ON_COMPLETE : EventType.ON_ERROR, streamId, requestType, t)); + events.add(new Event( + t == null ? EventType.ON_COMPLETE : EventType.ON_ERROR, streamId, requestType, t)); } @Override diff --git a/today-remoting/src/test/java/infra/remoting/resume/ClientChannelSessionTests.java b/today-remoting/src/test/java/infra/remoting/resume/ClientChannelSessionTests.java index ebfbc12..08587bc 100644 --- a/today-remoting/src/test/java/infra/remoting/resume/ClientChannelSessionTests.java +++ b/today-remoting/src/test/java/infra/remoting/resume/ClientChannelSessionTests.java @@ -26,8 +26,8 @@ import io.netty.buffer.Unpooled; import io.netty.util.ReferenceCounted; import infra.remoting.FrameAssert; -import infra.remoting.exceptions.ConnectionCloseException; -import infra.remoting.exceptions.RejectedResumeException; +import infra.remoting.error.ConnectionCloseException; +import infra.remoting.error.RejectedResumeException; import infra.remoting.frame.ErrorFrameCodec; import infra.remoting.frame.FrameType; import infra.remoting.frame.KeepAliveFrameCodec; diff --git a/today-remoting/src/test/java/infra/remoting/resume/ResumeIntegrationTests.java b/today-remoting/src/test/java/infra/remoting/resume/ResumeIntegrationTests.java index 61e773e..fb88c51 100644 --- a/today-remoting/src/test/java/infra/remoting/resume/ResumeIntegrationTests.java +++ b/today-remoting/src/test/java/infra/remoting/resume/ResumeIntegrationTests.java @@ -32,8 +32,8 @@ import infra.remoting.core.ChannelConnector; import infra.remoting.core.RemotingServer; import infra.remoting.core.Resume; -import infra.remoting.exceptions.RejectedResumeException; -import infra.remoting.exceptions.UnsupportedSetupException; +import infra.remoting.error.RejectedResumeException; +import infra.remoting.error.UnsupportedSetupException; import infra.remoting.test.SlowTest; import infra.remoting.transport.ClientTransport; import infra.remoting.transport.ServerTransport; From 0bd9fb7ac473f40d00951b92cd2777dc1a657357 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Tue, 5 Aug 2025 14:24:20 +0800 Subject: [PATCH 026/104] :art: --- .../src/main/java/infra/remoting/error/Retryable.java | 2 +- .../main/java/infra/remoting/plugins/RateLimitDecorator.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/today-remoting/src/main/java/infra/remoting/error/Retryable.java b/today-remoting/src/main/java/infra/remoting/error/Retryable.java index ecd4018..9e8c960 100644 --- a/today-remoting/src/main/java/infra/remoting/error/Retryable.java +++ b/today-remoting/src/main/java/infra/remoting/error/Retryable.java @@ -22,5 +22,5 @@ * retrying and operation that causes a {@link Retryable} to be thrown is not specified. */ public interface Retryable { - + } diff --git a/today-remoting/src/main/java/infra/remoting/plugins/RateLimitDecorator.java b/today-remoting/src/main/java/infra/remoting/plugins/RateLimitDecorator.java index c8cf2a0..cd28cee 100644 --- a/today-remoting/src/main/java/infra/remoting/plugins/RateLimitDecorator.java +++ b/today-remoting/src/main/java/infra/remoting/plugins/RateLimitDecorator.java @@ -20,8 +20,8 @@ import org.reactivestreams.Publisher; import infra.remoting.Channel; -import infra.remoting.Payload; import infra.remoting.ChannelWrapper; +import infra.remoting.Payload; import reactor.core.publisher.Flux; /** From d4d3d7f1650b46f246ed79be07a088e8e7d97014 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Tue, 5 Aug 2025 15:00:57 +0800 Subject: [PATCH 027/104] :recycle: --- settings.gradle | 1 + ...nection.java => MicrometerConnection.java} | 14 ++-- ...ava => MicrometerConnectionDecorator.java} | 10 +-- ...> MicrometerConnectionDecoratorTests.java} | 18 ++-- ...ts.java => MicrometerConnectionTests.java} | 46 +++++----- today-remoting-transport-local/build.gradle | 7 -- .../transport/local/LocalClientTransport.java | 10 +-- ...exConnection.java => LocalConnection.java} | 14 ++-- .../transport/local/LocalServerTransport.java | 18 ++-- .../src/test/resources/logback-test.xml | 2 +- today-remoting-transport-tcp/build.gradle | 7 -- ...plexConnection.java => TcpConnection.java} | 22 ++--- .../netty/client/TcpClientTransport.java | 8 +- .../netty/server/CloseableChannel.java | 2 +- .../netty/server/TcpServerTransport.java | 4 +- .../transport/tcp/TCPServerTransport.java | 4 +- .../netty/TcpFragmentationTransportTests.java | 2 +- .../src/test/resources/logback-test.xml | 4 +- .../build.gradle | 24 ++++++ .../BaseWebsocketServerTransport.java | 6 +- .../transport/websocket/CloseableChannel.java | 84 +++++++++++++++++++ .../websocket}/WebsocketClientTransport.java | 14 ++-- .../websocket/WebsocketConnection.java | 23 +++-- .../websocket}/WebsocketRouteTransport.java | 30 +++---- .../websocket}/WebsocketServerTransport.java | 9 +- .../transport/websocket}/WebSocketClient.java | 2 +- .../websocket}/WebSocketClientHandler.java | 2 +- .../WebSocketTransportIntegrationTests.java | 4 +- .../WebsocketClientTransportTests.java | 3 +- .../transport/websocket}/WebsocketPing.java | 3 +- .../WebsocketPingPongIntegrationTests.java | 19 ++--- .../websocket}/WebsocketPongServer.java | 3 +- .../WebsocketResumableTransportTests.java | 6 +- ...umableWithFragmentationTransportTests.java | 43 +++++----- .../WebsocketRouteTransportTests.java | 2 +- .../WebsocketSecureTransportTests.java | 8 +- .../WebsocketServerTransportTests.java | 2 +- .../websocket}/WebsocketTransportTests.java | 40 +++++---- today-remoting/build.gradle | 1 + ...{DuplexConnection.java => Connection.java} | 2 +- ...ionWrapper.java => ConnectionWrapper.java} | 6 +- .../infra/remoting/core/ChannelConnector.java | 22 ++--- .../infra/remoting/core/ChannelSupport.java | 8 +- .../core/ClientServerInputMultiplexer.java | 42 +++++----- .../java/infra/remoting/core/ClientSetup.java | 10 +-- ...Connection.java => LoggingConnection.java} | 14 ++-- .../infra/remoting/core/RemotingServer.java | 28 +++---- .../core/RequestChannelRequesterFlux.java | 4 +- .../RequestChannelResponderSubscriber.java | 10 +-- .../core/RequestResponseRequesterMono.java | 4 +- .../RequestResponseResponderSubscriber.java | 4 +- .../core/RequestStreamRequesterFlux.java | 4 +- .../RequestStreamResponderSubscriber.java | 4 +- .../infra/remoting/core/RequesterChannel.java | 4 +- .../infra/remoting/core/ResponderChannel.java | 4 +- .../remoting/core/ResponderLeaseTracker.java | 6 +- .../java/infra/remoting/core/SendUtils.java | 8 +- .../java/infra/remoting/core/ServerSetup.java | 66 +++++++-------- ...tion.java => SetupHandlingConnection.java} | 16 ++-- .../remoting/frame/FrameLengthCodec.java | 2 +- .../java/infra/remoting/frame/FrameUtil.java | 3 +- ...lexConnection.java => BaseConnection.java} | 6 +- .../remoting/keepalive/KeepAliveHandler.java | 10 +-- .../remoting/plugins/ConnectionDecorator.java | 6 +- .../InitializingInterceptorRegistry.java | 4 +- .../remoting/resume/ClientChannelSession.java | 74 ++++++++-------- .../resume/InMemoryResumableFramesStore.java | 2 +- ...nnection.java => ResumableConnection.java} | 48 +++++------ .../remoting/resume/ServerChannelSession.java | 44 +++++----- .../remoting/transport/ClientTransport.java | 4 +- .../transport/ConnectionAcceptor.java | 10 +-- .../infra/remoting/transport/Transport.java | 4 +- .../infra/remoting/util}/PromiseAdapter.java | 2 +- .../remoting/core/AbstractChannelRule.java | 6 +- .../remoting/core/ChannelConnectorTests.java | 6 +- .../remoting/core/ChannelLeaseTests.java | 8 +- .../remoting/core/ChannelReconnectTests.java | 6 +- .../infra/remoting/core/ChannelTests.java | 10 +-- .../ClientServerInputMultiplexerTest.java | 6 +- .../core/DefaultChannelClientTests.java | 4 +- .../core/FireAndForgetRequesterMonoTests.java | 16 ++-- .../infra/remoting/core/KeepAliveTests.java | 58 ++++++------- .../remoting/core/RemotingServerTests.java | 10 +-- .../RequestRequesterChannelFluxTests.java | 18 ++-- ...equestResponderChannelSubscriberTests.java | 16 ++-- .../RequestResponseRequesterMonoTests.java | 16 ++-- .../core/RequestStreamRequesterFluxTests.java | 20 ++--- .../RequesterChannelSubscribersTests.java | 6 +- .../core/RequesterOperatorsRacingTests.java | 48 +++++------ .../remoting/core/ResponderChannelTests.java | 6 +- .../core/ResponderOperatorsCommonTests.java | 6 +- .../remoting/core/SetupRejectionTests.java | 14 ++-- .../remoting/core/TestChannelSupport.java | 22 ++--- .../ws/WebSocketAggregationSample.java | 6 +- .../examples/ws/WebSocketHeadersSample.java | 6 +- .../resume/ClientChannelSessionTests.java | 50 +++++------ .../resume/DisconnectableClientTransport.java | 8 +- .../resume/InMemoryResumeStoreTests.java | 2 +- .../resume/ServerChannelSessionTests.java | 20 ++--- ...exConnection.java => LocalConnection.java} | 6 +- .../test/util/TestClientTransport.java | 15 ++-- ...lexConnection.java => TestConnection.java} | 62 +++++++------- .../test/util/TestServerTransport.java | 10 +-- ...lexConnection.java => TestConnection.java} | 6 +- .../infra/remoting/test/TransportPair.java | 44 +++++----- 105 files changed, 805 insertions(+), 738 deletions(-) rename today-remoting-micrometer/src/main/java/infra/remoting/micrometer/{MicrometerDuplexConnection.java => MicrometerConnection.java} (95%) rename today-remoting-micrometer/src/main/java/infra/remoting/micrometer/{MicrometerDuplexConnectionDecorator.java => MicrometerConnectionDecorator.java} (85%) rename today-remoting-micrometer/src/test/java/infra/remoting/micrometer/{MicrometerDuplexConnectionDecoratorTests.java => MicrometerConnectionDecoratorTests.java} (74%) rename today-remoting-micrometer/src/test/java/infra/remoting/micrometer/{MicrometerDuplexConnectionTests.java => MicrometerConnectionTests.java} (84%) rename today-remoting-transport-local/src/main/java/infra/remoting/transport/local/{LocalDuplexConnection.java => LocalConnection.java} (91%) rename today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/{TcpDuplexConnection.java => TcpConnection.java} (78%) create mode 100644 today-remoting-transport-websocket/build.gradle rename {today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/server => today-remoting-transport-websocket/src/main/java/infra/remoting/transport/websocket}/BaseWebsocketServerTransport.java (93%) create mode 100644 today-remoting-transport-websocket/src/main/java/infra/remoting/transport/websocket/CloseableChannel.java rename {today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/client => today-remoting-transport-websocket/src/main/java/infra/remoting/transport/websocket}/WebsocketClientTransport.java (92%) rename today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/WebsocketDuplexConnection.java => today-remoting-transport-websocket/src/main/java/infra/remoting/transport/websocket/WebsocketConnection.java (79%) rename {today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/server => today-remoting-transport-websocket/src/main/java/infra/remoting/transport/websocket}/WebsocketRouteTransport.java (71%) rename {today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/server => today-remoting-transport-websocket/src/main/java/infra/remoting/transport/websocket}/WebsocketServerTransport.java (91%) rename {today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty => today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket}/WebSocketClient.java (99%) rename {today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty => today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket}/WebSocketClientHandler.java (98%) rename {today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty => today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket}/WebSocketTransportIntegrationTests.java (92%) rename {today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/client => today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket}/WebsocketClientTransportTests.java (97%) rename {today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty => today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket}/WebsocketPing.java (93%) rename {today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty => today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket}/WebsocketPingPongIntegrationTests.java (95%) rename {today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty => today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket}/WebsocketPongServer.java (91%) rename {today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty => today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket}/WebsocketResumableTransportTests.java (92%) rename {today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty => today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket}/WebsocketResumableWithFragmentationTransportTests.java (53%) rename {today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/server => today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket}/WebsocketRouteTransportTests.java (98%) rename {today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty => today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket}/WebsocketSecureTransportTests.java (95%) rename {today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/server => today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket}/WebsocketServerTransportTests.java (99%) rename {today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty => today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket}/WebsocketTransportTests.java (53%) rename today-remoting/src/main/java/infra/remoting/{DuplexConnection.java => Connection.java} (97%) rename today-remoting/src/main/java/infra/remoting/{DuplexConnectionWrapper.java => ConnectionWrapper.java} (91%) rename today-remoting/src/main/java/infra/remoting/core/{LoggingDuplexConnection.java => LoggingConnection.java} (87%) rename today-remoting/src/main/java/infra/remoting/core/{SetupHandlingDuplexConnection.java => SetupHandlingConnection.java} (89%) rename today-remoting/src/main/java/infra/remoting/internal/{BaseDuplexConnection.java => BaseConnection.java} (91%) rename today-remoting/src/main/java/infra/remoting/resume/{ResumableDuplexConnection.java => ResumableConnection.java} (89%) rename {today-remoting-transport-tcp/src/main/java/infra/remoting/transport/tcp => today-remoting/src/main/java/infra/remoting/util}/PromiseAdapter.java (97%) rename today-remoting/src/test/java/infra/remoting/test/util/{LocalDuplexConnection.java => LocalConnection.java} (96%) rename today-remoting/src/test/java/infra/remoting/test/util/{TestDuplexConnection.java => TestConnection.java} (75%) rename today-remoting/src/testFixtures/java/infra/remoting/test/{TestDuplexConnection.java => TestConnection.java} (97%) diff --git a/settings.gradle b/settings.gradle index c94e938..ac39276 100644 --- a/settings.gradle +++ b/settings.gradle @@ -39,6 +39,7 @@ include 'today-remoting' include 'today-remoting-micrometer' include 'today-remoting-transport-tcp' include 'today-remoting-transport-local' +include 'today-remoting-transport-websocket' // Samples diff --git a/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/MicrometerDuplexConnection.java b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/MicrometerConnection.java similarity index 95% rename from today-remoting-micrometer/src/main/java/infra/remoting/micrometer/MicrometerDuplexConnection.java rename to today-remoting-micrometer/src/main/java/infra/remoting/micrometer/MicrometerConnection.java index f9a5846..287e7c5 100644 --- a/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/MicrometerDuplexConnection.java +++ b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/MicrometerConnection.java @@ -23,7 +23,7 @@ import infra.logging.Logger; import infra.logging.LoggerFactory; -import infra.remoting.DuplexConnection; +import infra.remoting.Connection; import infra.remoting.ProtocolErrorException; import infra.remoting.frame.FrameHeaderCodec; import infra.remoting.frame.FrameType; @@ -58,7 +58,7 @@ import static infra.remoting.frame.FrameType.SETUP; /** - * An implementation of {@link DuplexConnection} that intercepts frames and gathers Micrometer + * An implementation of {@link Connection} that intercepts frames and gathers Micrometer * metrics about them. * *

    The metric is called {@code infra.remoting.frame} and is tagged with {@code connection.type} ({@link @@ -69,27 +69,27 @@ * * @see Micrometer */ -final class MicrometerDuplexConnection implements DuplexConnection { +final class MicrometerConnection implements Connection { private final Counter close; - private final DuplexConnection delegate; + private final Connection delegate; private final Counter dispose; private final FrameCounters frameCounters; /** - * Creates a new {@link DuplexConnection}. + * Creates a new {@link Connection}. * * @param connectionType the type of connection being monitored - * @param delegate the {@link DuplexConnection} to delegate to + * @param delegate the {@link Connection} to delegate to * @param meterRegistry the {@link MeterRegistry} to use * @param tags additional tags to attach to {@link Meter}s * @throws NullPointerException if {@code connectionType}, {@code delegate}, or {@code * meterRegistry} is {@code null} */ - MicrometerDuplexConnection(Type connectionType, DuplexConnection delegate, MeterRegistry meterRegistry, Tag... tags) { + MicrometerConnection(Type connectionType, Connection delegate, MeterRegistry meterRegistry, Tag... tags) { Objects.requireNonNull(connectionType, "connectionType is required"); this.delegate = Objects.requireNonNull(delegate, "delegate is required"); Objects.requireNonNull(meterRegistry, "meterRegistry is required"); diff --git a/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/MicrometerDuplexConnectionDecorator.java b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/MicrometerConnectionDecorator.java similarity index 85% rename from today-remoting-micrometer/src/main/java/infra/remoting/micrometer/MicrometerDuplexConnectionDecorator.java rename to today-remoting-micrometer/src/main/java/infra/remoting/micrometer/MicrometerConnectionDecorator.java index c2c2231..55f0654 100644 --- a/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/MicrometerDuplexConnectionDecorator.java +++ b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/MicrometerConnectionDecorator.java @@ -19,7 +19,7 @@ import java.util.Objects; -import infra.remoting.DuplexConnection; +import infra.remoting.Connection; import infra.remoting.frame.FrameType; import infra.remoting.plugins.ConnectionDecorator; import io.micrometer.core.instrument.Meter; @@ -38,7 +38,7 @@ * * @see Micrometer */ -public final class MicrometerDuplexConnectionDecorator implements ConnectionDecorator { +public final class MicrometerConnectionDecorator implements ConnectionDecorator { private final MeterRegistry meterRegistry; @@ -51,16 +51,16 @@ public final class MicrometerDuplexConnectionDecorator implements ConnectionDeco * @param tags the additional tags to attach to each {@link Meter} * @throws NullPointerException if {@code meterRegistry} is {@code null} */ - public MicrometerDuplexConnectionDecorator(MeterRegistry meterRegistry, Tag... tags) { + public MicrometerConnectionDecorator(MeterRegistry meterRegistry, Tag... tags) { this.meterRegistry = Objects.requireNonNull(meterRegistry, "meterRegistry is required"); this.tags = tags; } @Override - public DuplexConnection decorate(Type connectionType, DuplexConnection delegate) { + public Connection decorate(Type connectionType, Connection delegate) { Objects.requireNonNull(delegate, "delegate is required"); Objects.requireNonNull(connectionType, "connectionType is required"); - return new MicrometerDuplexConnection(connectionType, delegate, meterRegistry, tags); + return new MicrometerConnection(connectionType, delegate, meterRegistry, tags); } } diff --git a/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/MicrometerDuplexConnectionDecoratorTests.java b/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/MicrometerConnectionDecoratorTests.java similarity index 74% rename from today-remoting-micrometer/src/test/java/infra/remoting/micrometer/MicrometerDuplexConnectionDecoratorTests.java rename to today-remoting-micrometer/src/test/java/infra/remoting/micrometer/MicrometerConnectionDecoratorTests.java index e5c23c8..4e164f9 100644 --- a/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/MicrometerDuplexConnectionDecoratorTests.java +++ b/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/MicrometerConnectionDecoratorTests.java @@ -20,7 +20,7 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import infra.remoting.DuplexConnection; +import infra.remoting.Connection; import io.micrometer.core.instrument.simple.SimpleMeterRegistry; import static infra.remoting.plugins.ConnectionDecorator.Type.CLIENT; @@ -29,17 +29,17 @@ import static org.mockito.Mockito.RETURNS_SMART_NULLS; import static org.mockito.Mockito.mock; -final class MicrometerDuplexConnectionDecoratorTests { +final class MicrometerConnectionDecoratorTests { - private final DuplexConnection delegate = mock(DuplexConnection.class, RETURNS_SMART_NULLS); + private final Connection delegate = mock(Connection.class, RETURNS_SMART_NULLS); private final SimpleMeterRegistry meterRegistry = new SimpleMeterRegistry(); - @DisplayName("creates MicrometerDuplexConnection") + @DisplayName("creates MicrometerConnection") @Test void apply() { - assertThat(new MicrometerDuplexConnectionDecorator(meterRegistry).decorate(CLIENT, delegate)) - .isInstanceOf(MicrometerDuplexConnection.class); + assertThat(new MicrometerConnectionDecorator(meterRegistry).decorate(CLIENT, delegate)) + .isInstanceOf(MicrometerConnection.class); } @DisplayName("apply throws NullPointerException with null connectionType") @@ -47,7 +47,7 @@ void apply() { void applyNullConnectionType() { assertThatNullPointerException() .isThrownBy( - () -> new MicrometerDuplexConnectionDecorator(meterRegistry).decorate(null, delegate)) + () -> new MicrometerConnectionDecorator(meterRegistry).decorate(null, delegate)) .withMessage("connectionType is required"); } @@ -56,7 +56,7 @@ void applyNullConnectionType() { void applyNullDelegate() { assertThatNullPointerException() .isThrownBy( - () -> new MicrometerDuplexConnectionDecorator(meterRegistry).decorate(CLIENT, null)) + () -> new MicrometerConnectionDecorator(meterRegistry).decorate(CLIENT, null)) .withMessage("delegate is required"); } @@ -64,7 +64,7 @@ void applyNullDelegate() { @Test void constructorNullMeterRegistry() { assertThatNullPointerException() - .isThrownBy(() -> new MicrometerDuplexConnectionDecorator(null)) + .isThrownBy(() -> new MicrometerConnectionDecorator(null)) .withMessage("meterRegistry is required"); } } diff --git a/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/MicrometerDuplexConnectionTests.java b/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/MicrometerConnectionTests.java similarity index 84% rename from today-remoting-micrometer/src/test/java/infra/remoting/micrometer/MicrometerDuplexConnectionTests.java rename to today-remoting-micrometer/src/test/java/infra/remoting/micrometer/MicrometerConnectionTests.java index 9661084..f27e327 100644 --- a/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/MicrometerDuplexConnectionTests.java +++ b/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/MicrometerConnectionTests.java @@ -22,7 +22,7 @@ import org.mockito.ArgumentCaptor; import org.mockito.Mockito; -import infra.remoting.DuplexConnection; +import infra.remoting.Connection; import infra.remoting.frame.FrameType; import infra.remoting.plugins.ConnectionDecorator.Type; import io.micrometer.core.instrument.Counter; @@ -67,9 +67,9 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; -final class MicrometerDuplexConnectionTests { +final class MicrometerConnectionTests { - private final DuplexConnection delegate = mock(DuplexConnection.class, RETURNS_SMART_NULLS); + private final Connection delegate = mock(Connection.class, RETURNS_SMART_NULLS); private final SimpleMeterRegistry meterRegistry = new SimpleMeterRegistry(); @@ -77,7 +77,7 @@ final class MicrometerDuplexConnectionTests { @Test void constructorNullConnectionType() { assertThatNullPointerException() - .isThrownBy(() -> new MicrometerDuplexConnection(null, delegate, meterRegistry)) + .isThrownBy(() -> new MicrometerConnection(null, delegate, meterRegistry)) .withMessage("connectionType is required"); } @@ -85,7 +85,7 @@ void constructorNullConnectionType() { @Test void constructorNullDelegate() { assertThatNullPointerException() - .isThrownBy(() -> new MicrometerDuplexConnection(CLIENT, null, meterRegistry)) + .isThrownBy(() -> new MicrometerConnection(CLIENT, null, meterRegistry)) .withMessage("delegate is required"); } @@ -94,14 +94,14 @@ void constructorNullDelegate() { void constructorNullMeterRegistry() { assertThatNullPointerException() - .isThrownBy(() -> new MicrometerDuplexConnection(CLIENT, delegate, null)) + .isThrownBy(() -> new MicrometerConnection(CLIENT, delegate, null)) .withMessage("meterRegistry is required"); } @DisplayName("dispose gathers metrics") @Test void dispose() { - new MicrometerDuplexConnection( + new MicrometerConnection( CLIENT, delegate, meterRegistry, Tag.of("test-key", "test-value")) .dispose(); @@ -120,7 +120,7 @@ void dispose() { void onClose() { when(delegate.onClose()).thenReturn(Mono.empty()); - new MicrometerDuplexConnection( + new MicrometerConnection( CLIENT, delegate, meterRegistry, Tag.of("test-key", "test-value")) .onClose() .subscribe(Operators.drainSubscriber()); @@ -155,7 +155,7 @@ void receive() { when(delegate.receive()).thenReturn(frames); - new MicrometerDuplexConnection( + new MicrometerConnection( CLIENT, delegate, meterRegistry, Tag.of("test-key", "test-value")) .receive() .as(StepVerifier::create) @@ -183,21 +183,21 @@ void send() { ArgumentCaptor captor = ArgumentCaptor.forClass(ByteBuf.class); doNothing().when(delegate).sendFrame(Mockito.anyInt(), captor.capture()); - final MicrometerDuplexConnection micrometerDuplexConnection = - new MicrometerDuplexConnection( + final MicrometerConnection micrometerConnection = + new MicrometerConnection( SERVER, delegate, meterRegistry, Tag.of("test-key", "test-value")); - micrometerDuplexConnection.sendFrame(1, createTestCancelFrame()); - micrometerDuplexConnection.sendFrame(1, createTestErrorFrame()); - micrometerDuplexConnection.sendFrame(1, createTestKeepaliveFrame()); - micrometerDuplexConnection.sendFrame(1, createTestLeaseFrame()); - micrometerDuplexConnection.sendFrame(1, createTestMetadataPushFrame()); - micrometerDuplexConnection.sendFrame(1, createTestPayloadFrame()); - micrometerDuplexConnection.sendFrame(1, createTestRequestChannelFrame()); - micrometerDuplexConnection.sendFrame(1, createTestRequestFireAndForgetFrame()); - micrometerDuplexConnection.sendFrame(1, createTestRequestNFrame()); - micrometerDuplexConnection.sendFrame(1, createTestRequestResponseFrame()); - micrometerDuplexConnection.sendFrame(1, createTestRequestStreamFrame()); - micrometerDuplexConnection.sendFrame(1, createTestSetupFrame()); + micrometerConnection.sendFrame(1, createTestCancelFrame()); + micrometerConnection.sendFrame(1, createTestErrorFrame()); + micrometerConnection.sendFrame(1, createTestKeepaliveFrame()); + micrometerConnection.sendFrame(1, createTestLeaseFrame()); + micrometerConnection.sendFrame(1, createTestMetadataPushFrame()); + micrometerConnection.sendFrame(1, createTestPayloadFrame()); + micrometerConnection.sendFrame(1, createTestRequestChannelFrame()); + micrometerConnection.sendFrame(1, createTestRequestFireAndForgetFrame()); + micrometerConnection.sendFrame(1, createTestRequestNFrame()); + micrometerConnection.sendFrame(1, createTestRequestResponseFrame()); + micrometerConnection.sendFrame(1, createTestRequestStreamFrame()); + micrometerConnection.sendFrame(1, createTestSetupFrame()); StepVerifier.create(Flux.fromIterable(captor.getAllValues())) .expectNextCount(12) diff --git a/today-remoting-transport-local/build.gradle b/today-remoting-transport-local/build.gradle index 9e11908..1f945d3 100644 --- a/today-remoting-transport-local/build.gradle +++ b/today-remoting-transport-local/build.gradle @@ -33,10 +33,3 @@ dependencies { testImplementation testFixtures(project(":today-remoting")) } - -jar { - manifest { - attributes("Automatic-Module-Name": "infra.remoting.transport.local") - } -} - diff --git a/today-remoting-transport-local/src/main/java/infra/remoting/transport/local/LocalClientTransport.java b/today-remoting-transport-local/src/main/java/infra/remoting/transport/local/LocalClientTransport.java index e1f2045..786a470 100644 --- a/today-remoting-transport-local/src/main/java/infra/remoting/transport/local/LocalClientTransport.java +++ b/today-remoting-transport-local/src/main/java/infra/remoting/transport/local/LocalClientTransport.java @@ -19,7 +19,7 @@ import java.util.Objects; -import infra.remoting.DuplexConnection; +import infra.remoting.Connection; import infra.remoting.internal.UnboundedProcessor; import infra.remoting.transport.ClientTransport; import infra.remoting.transport.ConnectionAcceptor; @@ -72,7 +72,7 @@ public static LocalClientTransport create(String name, ByteBufAllocator allocato } @Override - public Mono connect() { + public Mono connect() { return Mono.defer(() -> { ConnectionAcceptor server = LocalServerTransport.findServer(name); if (server == null) { @@ -86,10 +86,10 @@ public Mono connect() { Mono onClose = inSink.asMono().and(outSink.asMono()); - server.accept(new LocalDuplexConnection(name, allocator, out, in, onClose)).subscribe(); + server.accept(new LocalConnection(name, allocator, out, in, onClose)).subscribe(); - return Mono.just( - new LocalDuplexConnection(name, allocator, in, out, onClose)); + return Mono.just( + new LocalConnection(name, allocator, in, out, onClose)); }); } } diff --git a/today-remoting-transport-local/src/main/java/infra/remoting/transport/local/LocalDuplexConnection.java b/today-remoting-transport-local/src/main/java/infra/remoting/transport/local/LocalConnection.java similarity index 91% rename from today-remoting-transport-local/src/main/java/infra/remoting/transport/local/LocalDuplexConnection.java rename to today-remoting-transport-local/src/main/java/infra/remoting/transport/local/LocalConnection.java index 8132eda..aa21578 100644 --- a/today-remoting-transport-local/src/main/java/infra/remoting/transport/local/LocalDuplexConnection.java +++ b/today-remoting-transport-local/src/main/java/infra/remoting/transport/local/LocalConnection.java @@ -22,7 +22,7 @@ import java.net.SocketAddress; import java.util.Objects; -import infra.remoting.DuplexConnection; +import infra.remoting.Connection; import infra.remoting.ProtocolErrorException; import infra.remoting.frame.ErrorFrameCodec; import infra.remoting.internal.UnboundedProcessor; @@ -34,8 +34,8 @@ import reactor.core.publisher.Mono; import reactor.core.publisher.Operators; -/** An implementation of {@link DuplexConnection} that connects inside the same JVM. */ -final class LocalDuplexConnection implements DuplexConnection { +/** An implementation of {@link Connection} that connects inside the same JVM. */ +final class LocalConnection implements Connection { private final LocalSocketAddress address; private final ByteBufAllocator allocator; @@ -54,7 +54,7 @@ final class LocalDuplexConnection implements DuplexConnection { * @param onClose the closing notifier * @throws NullPointerException if {@code in}, {@code out}, or {@code onClose} are {@code null} */ - LocalDuplexConnection(String name, ByteBufAllocator allocator, + LocalConnection(String name, ByteBufAllocator allocator, UnboundedProcessor in, UnboundedProcessor out, Mono onClose) { this.address = new LocalSocketAddress(name); this.allocator = Objects.requireNonNull(allocator, "allocator is required"); @@ -112,19 +112,19 @@ public SocketAddress remoteAddress() { @Override public String toString() { - return "LocalDuplexConnection{" + "address=" + address + "hash=" + hashCode() + '}'; + return "LocalConnection{" + "address=" + address + "hash=" + hashCode() + '}'; } static class ByteBufReleaserOperator implements CoreSubscriber, Subscription, Fuseable.QueueSubscription { final CoreSubscriber actual; - final LocalDuplexConnection parent; + final LocalConnection parent; Subscription s; public ByteBufReleaserOperator( - CoreSubscriber actual, LocalDuplexConnection parent) { + CoreSubscriber actual, LocalConnection parent) { this.actual = actual; this.parent = parent; } diff --git a/today-remoting-transport-local/src/main/java/infra/remoting/transport/local/LocalServerTransport.java b/today-remoting-transport-local/src/main/java/infra/remoting/transport/local/LocalServerTransport.java index 3776cca..87ddc45 100644 --- a/today-remoting-transport-local/src/main/java/infra/remoting/transport/local/LocalServerTransport.java +++ b/today-remoting-transport-local/src/main/java/infra/remoting/transport/local/LocalServerTransport.java @@ -26,7 +26,7 @@ import infra.lang.Nullable; import infra.remoting.Closeable; -import infra.remoting.DuplexConnection; +import infra.remoting.Connection; import infra.remoting.transport.ClientTransport; import infra.remoting.transport.ConnectionAcceptor; import infra.remoting.transport.ServerTransport; @@ -131,7 +131,7 @@ static class ServerCloseableAcceptor implements ConnectionAcceptor, Closeable { private final ConnectionAcceptor acceptor; - private final Set activeConnections = ConcurrentHashMap.newKeySet(); + private final Set activeConnections = ConcurrentHashMap.newKeySet(); private final Sinks.Empty onClose = Sinks.unsafe().empty(); @@ -142,13 +142,13 @@ static class ServerCloseableAcceptor implements ConnectionAcceptor, Closeable { } @Override - public Mono accept(DuplexConnection duplexConnection) { - activeConnections.add(duplexConnection); - duplexConnection + public Mono accept(Connection connection) { + activeConnections.add(connection); + connection .onClose() - .doFinally(__ -> activeConnections.remove(duplexConnection)) + .doFinally(__ -> activeConnections.remove(connection)) .subscribe(); - return acceptor.accept(duplexConnection); + return acceptor.accept(connection); } @Override @@ -158,8 +158,8 @@ public void dispose() { return; } - Mono.whenDelayError(activeConnections.stream().peek(DuplexConnection::dispose) - .map(DuplexConnection::onClose).collect(Collectors.toList())) + Mono.whenDelayError(activeConnections.stream().peek(Connection::dispose) + .map(Connection::onClose).collect(Collectors.toList())) .subscribe(null, onClose::tryEmitError, onClose::tryEmitEmpty); } diff --git a/today-remoting-transport-local/src/test/resources/logback-test.xml b/today-remoting-transport-local/src/test/resources/logback-test.xml index 2ecf24f..04b396a 100644 --- a/today-remoting-transport-local/src/test/resources/logback-test.xml +++ b/today-remoting-transport-local/src/test/resources/logback-test.xml @@ -39,7 +39,7 @@ - + diff --git a/today-remoting-transport-tcp/build.gradle b/today-remoting-transport-tcp/build.gradle index 195a1b3..d8aa2e8 100644 --- a/today-remoting-transport-tcp/build.gradle +++ b/today-remoting-transport-tcp/build.gradle @@ -15,7 +15,6 @@ dependencies { api(project(":today-remoting")) api "io.projectreactor.netty:reactor-netty-core" - api "io.projectreactor.netty:reactor-netty-http" optional 'io.netty:netty-transport' optional 'io.netty:netty-codec' @@ -33,9 +32,3 @@ dependencies { testImplementation testFixtures(project(":today-remoting")) } - -jar { - manifest { - attributes("Automatic-Module-Name": "infra.remoting.transport.tcp") - } -} \ No newline at end of file diff --git a/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/TcpDuplexConnection.java b/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/TcpConnection.java similarity index 78% rename from today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/TcpDuplexConnection.java rename to today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/TcpConnection.java index 6851922..63d2bc0 100644 --- a/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/TcpDuplexConnection.java +++ b/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/TcpConnection.java @@ -20,37 +20,37 @@ import java.net.SocketAddress; import java.util.Objects; -import infra.remoting.DuplexConnection; +import infra.remoting.Connection; import infra.remoting.ProtocolErrorException; import infra.remoting.frame.ErrorFrameCodec; import infra.remoting.frame.FrameLengthCodec; -import infra.remoting.internal.BaseDuplexConnection; +import infra.remoting.internal.BaseConnection; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufAllocator; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; -import reactor.netty.Connection; -/** An implementation of {@link DuplexConnection} that connects via TCP. */ -public final class TcpDuplexConnection extends BaseDuplexConnection { +/** An implementation of {@link Connection} that connects via TCP. */ +public final class TcpConnection extends BaseConnection { + private final String side; - private final Connection connection; + private final reactor.netty.Connection connection; /** * Creates a new instance * - * @param connection the {@link Connection} for managing the server + * @param connection the {@link reactor.netty.Connection} for managing the server */ - public TcpDuplexConnection(Connection connection) { + public TcpConnection(reactor.netty.Connection connection) { this("unknown", connection); } /** * Creates a new instance * - * @param connection the {@link Connection} for managing the server + * @param connection the {@link reactor.netty.Connection} for managing the server */ - public TcpDuplexConnection(String side, Connection connection) { + public TcpConnection(String side, reactor.netty.Connection connection) { this.connection = Objects.requireNonNull(connection, "connection is required"); this.side = side; @@ -95,7 +95,7 @@ public void sendFrame(int streamId, ByteBuf frame) { @Override public String toString() { - return "TcpDuplexConnection{side='%s', connection=%s}".formatted(side, connection); + return "TcpConnection{side='%s', connection=%s}".formatted(side, connection); } } diff --git a/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/client/TcpClientTransport.java b/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/client/TcpClientTransport.java index 8366c91..694db0c 100644 --- a/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/client/TcpClientTransport.java +++ b/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/client/TcpClientTransport.java @@ -20,11 +20,11 @@ import java.net.InetSocketAddress; import java.util.Objects; -import infra.remoting.DuplexConnection; +import infra.remoting.Connection; import infra.remoting.transport.ClientTransport; import infra.remoting.transport.ServerTransport; import infra.remoting.transport.netty.ProtocolFrameLengthCodec; -import infra.remoting.transport.netty.TcpDuplexConnection; +import infra.remoting.transport.netty.TcpConnection; import reactor.core.publisher.Mono; import reactor.netty.tcp.TcpClient; @@ -114,10 +114,10 @@ public int getMaxFrameLength() { } @Override - public Mono connect() { + public Mono connect() { return client .doOnConnected(c -> c.addHandlerLast(new ProtocolFrameLengthCodec(maxFrameLength))) .connect() - .map(connection -> new TcpDuplexConnection("client", connection)); + .map(connection -> new TcpConnection("client", connection)); } } diff --git a/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/server/CloseableChannel.java b/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/server/CloseableChannel.java index 8aa8f53..a3a7311 100644 --- a/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/server/CloseableChannel.java +++ b/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/server/CloseableChannel.java @@ -26,7 +26,7 @@ import reactor.core.publisher.Mono; import reactor.netty.DisposableChannel; -import static infra.remoting.transport.tcp.PromiseAdapter.adapt; +import static infra.remoting.util.PromiseAdapter.adapt; /** * An implementation of {@link Closeable} that wraps a {@link DisposableChannel}, enabling diff --git a/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/server/TcpServerTransport.java b/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/server/TcpServerTransport.java index 2cf8812..bdba76b 100644 --- a/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/server/TcpServerTransport.java +++ b/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/server/TcpServerTransport.java @@ -24,7 +24,7 @@ import infra.remoting.transport.ConnectionAcceptor; import infra.remoting.transport.ServerTransport; import infra.remoting.transport.netty.ProtocolFrameLengthCodec; -import infra.remoting.transport.netty.TcpDuplexConnection; +import infra.remoting.transport.netty.TcpConnection; import reactor.core.publisher.Mono; import reactor.netty.tcp.TcpServer; @@ -115,7 +115,7 @@ public Mono start(ConnectionAcceptor acceptor) { Objects.requireNonNull(acceptor, "acceptor is required"); return server.doOnConnection(c -> { c.addHandlerLast(new ProtocolFrameLengthCodec(maxFrameLength)); - acceptor.accept(new TcpDuplexConnection("server", c)) + acceptor.accept(new TcpConnection("server", c)) .then(Mono.never()) .subscribe(c.disposeSubscriber()); }) diff --git a/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/tcp/TCPServerTransport.java b/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/tcp/TCPServerTransport.java index 9393d7c..3a398f8 100644 --- a/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/tcp/TCPServerTransport.java +++ b/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/tcp/TCPServerTransport.java @@ -53,7 +53,7 @@ import io.netty.util.concurrent.DefaultThreadFactory; import reactor.core.publisher.Mono; -import static infra.remoting.transport.tcp.PromiseAdapter.adapt; +import static infra.remoting.util.PromiseAdapter.adapt; /** * Netty TCP server transport @@ -359,7 +359,7 @@ protected void initChannel(Channel ch) throws Exception { 0, FRAME_LENGTH_SIZE, 0, FRAME_LENGTH_SIZE)) .addLast("channel-transport", transport); -// acceptor.accept(new TcpDuplexConnection(ch)); +// acceptor.accept(new TcpConnection(ch)); } } diff --git a/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/TcpFragmentationTransportTests.java b/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/TcpFragmentationTransportTests.java index 8346a7e..e050f0a 100644 --- a/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/TcpFragmentationTransportTests.java +++ b/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/TcpFragmentationTransportTests.java @@ -22,11 +22,11 @@ import java.net.InetSocketAddress; import java.time.Duration; -import io.netty.channel.ChannelOption; import infra.remoting.test.TransportPair; import infra.remoting.test.TransportTest; import infra.remoting.transport.netty.client.TcpClientTransport; import infra.remoting.transport.netty.server.TcpServerTransport; +import io.netty.channel.ChannelOption; import reactor.netty.tcp.TcpClient; import reactor.netty.tcp.TcpServer; diff --git a/today-remoting-transport-tcp/src/test/resources/logback-test.xml b/today-remoting-transport-tcp/src/test/resources/logback-test.xml index 2b44f51..8918d37 100644 --- a/today-remoting-transport-tcp/src/test/resources/logback-test.xml +++ b/today-remoting-transport-tcp/src/test/resources/logback-test.xml @@ -26,14 +26,14 @@ - + - + diff --git a/today-remoting-transport-websocket/build.gradle b/today-remoting-transport-websocket/build.gradle new file mode 100644 index 0000000..fbc3a29 --- /dev/null +++ b/today-remoting-transport-websocket/build.gradle @@ -0,0 +1,24 @@ +description = "TODAY Remoting Transport Websocket based on netty" + + +dependencies { + api(project(":today-remoting")) + + api "io.projectreactor.netty:reactor-netty-core" + api "io.projectreactor.netty:reactor-netty-http" + + optional 'io.netty:netty-transport' + optional 'io.netty:netty-codec' + optional 'io.netty:netty-handler' + optional 'io.netty:netty-transport-classes-epoll' + + testImplementation 'io.projectreactor:reactor-test' + + testRuntimeOnly 'org.bouncycastle:bcpkix-jdk15on:1.70' + testRuntimeOnly 'ch.qos.logback:logback-classic' +// testRuntimeOnly 'io.netty:netty-tcnative-boringssl-static' + os_suffix + + testImplementation testFixtures(project(":today-remoting")) + +} + diff --git a/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/server/BaseWebsocketServerTransport.java b/today-remoting-transport-websocket/src/main/java/infra/remoting/transport/websocket/BaseWebsocketServerTransport.java similarity index 93% rename from today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/server/BaseWebsocketServerTransport.java rename to today-remoting-transport-websocket/src/main/java/infra/remoting/transport/websocket/BaseWebsocketServerTransport.java index 89de061..d8a10fc 100644 --- a/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/server/BaseWebsocketServerTransport.java +++ b/today-remoting-transport-websocket/src/main/java/infra/remoting/transport/websocket/BaseWebsocketServerTransport.java @@ -15,7 +15,7 @@ * along with this program. If not, see [http://www.gnu.org/licenses/] */ -package infra.remoting.transport.netty.server; +package infra.remoting.transport.websocket; import java.util.function.Consumer; import java.util.function.Function; @@ -23,6 +23,7 @@ import infra.logging.Logger; import infra.logging.LoggerFactory; import infra.remoting.Closeable; +import infra.remoting.frame.FrameLengthCodec; import infra.remoting.transport.ServerTransport; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandlerContext; @@ -32,7 +33,6 @@ import reactor.netty.http.server.HttpServer; import reactor.netty.http.server.WebsocketServerSpec; -import static infra.remoting.frame.FrameLengthCodec.FRAME_LENGTH_MASK; import static io.netty.channel.ChannelHandler.Sharable; abstract class BaseWebsocketServerTransport, T extends Closeable> implements ServerTransport { @@ -45,7 +45,7 @@ abstract class BaseWebsocketServerTransport server.doOnConnection(connection -> connection.addHandlerLast(pongHandler)); final WebsocketServerSpec.Builder specBuilder = - WebsocketServerSpec.builder().maxFramePayloadLength(FRAME_LENGTH_MASK); + WebsocketServerSpec.builder().maxFramePayloadLength(FrameLengthCodec.FRAME_LENGTH_MASK); /** * Provide a consumer to customize properties of the {@link WebsocketServerSpec} to use for diff --git a/today-remoting-transport-websocket/src/main/java/infra/remoting/transport/websocket/CloseableChannel.java b/today-remoting-transport-websocket/src/main/java/infra/remoting/transport/websocket/CloseableChannel.java new file mode 100644 index 0000000..8c66b8a --- /dev/null +++ b/today-remoting-transport-websocket/src/main/java/infra/remoting/transport/websocket/CloseableChannel.java @@ -0,0 +1,84 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.remoting.transport.websocket; + +import java.net.InetSocketAddress; +import java.util.Objects; + +import infra.remoting.Closeable; +import infra.remoting.util.FutureMono; +import io.netty.channel.Channel; +import reactor.core.publisher.Mono; +import reactor.netty.DisposableChannel; + +import static infra.remoting.util.PromiseAdapter.adapt; + +/** + * An implementation of {@link Closeable} that wraps a {@link DisposableChannel}, enabling + * close-ability and exposing the {@link DisposableChannel}'s address. + */ +public final class CloseableChannel implements Closeable { + + private final Channel channel; + + /** + * Creates a new instance + * + * @param channel the {@link DisposableChannel} to wrap + * @throws NullPointerException if {@code context} is {@code null} + */ + CloseableChannel(DisposableChannel channel) { + this.channel = Objects.requireNonNull(channel, "channel is required").channel(); + } + + /** + * Creates a new instance + * + * @param channel the {@link DisposableChannel} to wrap + * @throws NullPointerException if {@code context} is {@code null} + */ + public CloseableChannel(Channel channel) { + this.channel = Objects.requireNonNull(channel, "channel is required"); + } + + /** + * Return local server selector channel address. + * + * @return local {@link InetSocketAddress} + * @see DisposableChannel#address() + */ + public InetSocketAddress address() { + return (InetSocketAddress) channel.localAddress(); + } + + @Override + public void dispose() { + channel.close(); + } + + @Override + public boolean isDisposed() { + return !channel.isActive(); + } + + @Override + public Mono onClose() { + return FutureMono.of(adapt(channel.closeFuture())); + } + +} diff --git a/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/client/WebsocketClientTransport.java b/today-remoting-transport-websocket/src/main/java/infra/remoting/transport/websocket/WebsocketClientTransport.java similarity index 92% rename from today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/client/WebsocketClientTransport.java rename to today-remoting-transport-websocket/src/main/java/infra/remoting/transport/websocket/WebsocketClientTransport.java index 955bc38..1bc9cb5 100644 --- a/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/client/WebsocketClientTransport.java +++ b/today-remoting-transport-websocket/src/main/java/infra/remoting/transport/websocket/WebsocketClientTransport.java @@ -15,7 +15,7 @@ * along with this program. If not, see [http://www.gnu.org/licenses/] */ -package infra.remoting.transport.netty.client; +package infra.remoting.transport.websocket; import java.net.InetSocketAddress; import java.net.URI; @@ -23,10 +23,10 @@ import java.util.Objects; import java.util.function.Consumer; -import infra.remoting.DuplexConnection; +import infra.remoting.Connection; +import infra.remoting.frame.FrameLengthCodec; import infra.remoting.transport.ClientTransport; import infra.remoting.transport.ServerTransport; -import infra.remoting.transport.netty.WebsocketDuplexConnection; import io.netty.handler.codec.http.DefaultHttpHeaders; import io.netty.handler.codec.http.HttpHeaders; import reactor.core.publisher.Mono; @@ -34,8 +34,6 @@ import reactor.netty.http.client.WebsocketClientSpec; import reactor.netty.tcp.TcpClient; -import static infra.remoting.frame.FrameLengthCodec.FRAME_LENGTH_MASK; - /** * An implementation of {@link ClientTransport} that connects to a {@link ServerTransport} over * WebSocket. @@ -51,7 +49,7 @@ public final class WebsocketClientTransport implements ClientTransport { private HttpHeaders headers = new DefaultHttpHeaders(); private final WebsocketClientSpec.Builder specBuilder = - WebsocketClientSpec.builder().maxFramePayloadLength(FRAME_LENGTH_MASK); + WebsocketClientSpec.builder().maxFramePayloadLength(FrameLengthCodec.FRAME_LENGTH_MASK); private WebsocketClientTransport(HttpClient client, String path) { Objects.requireNonNull(client, "HttpClient is required"); @@ -166,12 +164,12 @@ public int getMaxFrameLength() { } @Override - public Mono connect() { + public Mono connect() { return client .headers(headers -> headers.add(this.headers)) .websocket(specBuilder.build()) .uri(path) .connect() - .map(connection -> new WebsocketDuplexConnection("client", connection)); + .map(connection -> new WebsocketConnection("client", connection)); } } diff --git a/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/WebsocketDuplexConnection.java b/today-remoting-transport-websocket/src/main/java/infra/remoting/transport/websocket/WebsocketConnection.java similarity index 79% rename from today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/WebsocketDuplexConnection.java rename to today-remoting-transport-websocket/src/main/java/infra/remoting/transport/websocket/WebsocketConnection.java index b511743..b6ff46e 100644 --- a/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/WebsocketDuplexConnection.java +++ b/today-remoting-transport-websocket/src/main/java/infra/remoting/transport/websocket/WebsocketConnection.java @@ -15,48 +15,47 @@ * along with this program. If not, see [http://www.gnu.org/licenses/] */ -package infra.remoting.transport.netty; +package infra.remoting.transport.websocket; import java.net.SocketAddress; import java.util.Objects; -import infra.remoting.DuplexConnection; +import infra.remoting.Connection; import infra.remoting.ProtocolErrorException; import infra.remoting.frame.ErrorFrameCodec; -import infra.remoting.internal.BaseDuplexConnection; +import infra.remoting.internal.BaseConnection; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufAllocator; import io.netty.handler.codec.http.websocketx.BinaryWebSocketFrame; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; -import reactor.netty.Connection; /** - * An implementation of {@link DuplexConnection} that connects via a Websocket. + * An implementation of {@link Connection} that connects via a Websocket. * *

    strongly assumes that each ByteBuf is encoded with the length. This is not true * for message oriented transports so this must be specifically dropped from Frames sent and * stitched back on for frames received. */ -public final class WebsocketDuplexConnection extends BaseDuplexConnection { +public final class WebsocketConnection extends BaseConnection { private final String side; - private final Connection connection; + private final reactor.netty.Connection connection; /** * Creates a new instance * - * @param connection the {@link Connection} to for managing the server + * @param connection the {@link reactor.netty.Connection} to for managing the server */ - public WebsocketDuplexConnection(Connection connection) { + public WebsocketConnection(reactor.netty.Connection connection) { this("unknown", connection); } /** * Creates a new instance * - * @param connection the {@link Connection} to for managing the server + * @param connection the {@link reactor.netty.Connection} to for managing the server */ - public WebsocketDuplexConnection(String side, Connection connection) { + public WebsocketConnection(String side, reactor.netty.Connection connection) { this.connection = Objects.requireNonNull(connection, "connection is required"); this.side = side; @@ -101,7 +100,7 @@ public void sendErrorAndClose(ProtocolErrorException e) { @Override public String toString() { - return "WebsocketDuplexConnection{" + return "WebsocketConnection{" + "side='" + side + '\'' diff --git a/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/server/WebsocketRouteTransport.java b/today-remoting-transport-websocket/src/main/java/infra/remoting/transport/websocket/WebsocketRouteTransport.java similarity index 71% rename from today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/server/WebsocketRouteTransport.java rename to today-remoting-transport-websocket/src/main/java/infra/remoting/transport/websocket/WebsocketRouteTransport.java index de4a895..e506939 100644 --- a/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/server/WebsocketRouteTransport.java +++ b/today-remoting-transport-websocket/src/main/java/infra/remoting/transport/websocket/WebsocketRouteTransport.java @@ -15,7 +15,7 @@ * along with this program. If not, see [http://www.gnu.org/licenses/] */ -package infra.remoting.transport.netty.server; +package infra.remoting.transport.websocket; import org.reactivestreams.Publisher; @@ -26,7 +26,6 @@ import infra.remoting.Closeable; import infra.remoting.transport.ConnectionAcceptor; import infra.remoting.transport.ServerTransport; -import infra.remoting.transport.netty.WebsocketDuplexConnection; import reactor.core.publisher.Mono; import reactor.netty.Connection; import reactor.netty.http.server.HttpServer; @@ -38,8 +37,7 @@ * An implementation of {@link ServerTransport} that connects via Websocket and listens on specified * routes. */ -public final class WebsocketRouteTransport - extends BaseWebsocketServerTransport { +public final class WebsocketRouteTransport extends BaseWebsocketServerTransport { private final String path; @@ -54,9 +52,8 @@ public final class WebsocketRouteTransport * @param routesBuilder the builder for the routes that will be listened on * @param path the path foe each route */ - public WebsocketRouteTransport( - HttpServer server, Consumer routesBuilder, String path) { - this.server = serverConfigurer.apply(Objects.requireNonNull(server, "server is required")); + public WebsocketRouteTransport(HttpServer server, Consumer routesBuilder, String path) { + this.server = BaseWebsocketServerTransport.serverConfigurer.apply(Objects.requireNonNull(server, "server is required")); this.routesBuilder = Objects.requireNonNull(routesBuilder, "routesBuilder is required"); this.path = Objects.requireNonNull(path, "path is required"); } @@ -64,12 +61,10 @@ public WebsocketRouteTransport( @Override public Mono start(ConnectionAcceptor acceptor) { Objects.requireNonNull(acceptor, "acceptor is required"); - return server - .route( - routes -> { - routesBuilder.accept(routes); - routes.ws(path, newHandler(acceptor), specBuilder.build()); - }) + return server.route(routes -> { + routesBuilder.accept(routes); + routes.ws(path, newHandler(acceptor), specBuilder.build()); + }) .bind() .map(CloseableChannel::new); } @@ -81,11 +76,8 @@ public Mono start(ConnectionAcceptor acceptor) { * @return a new Websocket handler * @throws NullPointerException if {@code acceptor} is {@code null} */ - public static BiFunction> newHandler( - ConnectionAcceptor acceptor) { - return (in, out) -> - acceptor - .accept(new WebsocketDuplexConnection("server", (Connection) in)) - .then(out.neverComplete()); + public static BiFunction> newHandler(ConnectionAcceptor acceptor) { + return (in, out) -> acceptor.accept(new WebsocketConnection("server", (Connection) in)) + .then(out.neverComplete()); } } diff --git a/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/server/WebsocketServerTransport.java b/today-remoting-transport-websocket/src/main/java/infra/remoting/transport/websocket/WebsocketServerTransport.java similarity index 91% rename from today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/server/WebsocketServerTransport.java rename to today-remoting-transport-websocket/src/main/java/infra/remoting/transport/websocket/WebsocketServerTransport.java index 4fd2fc9..8c8cda2 100644 --- a/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/server/WebsocketServerTransport.java +++ b/today-remoting-transport-websocket/src/main/java/infra/remoting/transport/websocket/WebsocketServerTransport.java @@ -15,7 +15,7 @@ * along with this program. If not, see [http://www.gnu.org/licenses/] */ -package infra.remoting.transport.netty.server; +package infra.remoting.transport.websocket; import java.net.InetSocketAddress; import java.util.Arrays; @@ -24,7 +24,6 @@ import infra.remoting.transport.ClientTransport; import infra.remoting.transport.ConnectionAcceptor; import infra.remoting.transport.ServerTransport; -import infra.remoting.transport.netty.WebsocketDuplexConnection; import io.netty.handler.codec.http.DefaultHttpHeaders; import io.netty.handler.codec.http.HttpHeaders; import reactor.core.publisher.Mono; @@ -39,10 +38,10 @@ public final class WebsocketServerTransport extends BaseWebsocketServerTransport private final HttpServer server; - private HttpHeaders headers = new DefaultHttpHeaders(); + private final HttpHeaders headers = new DefaultHttpHeaders(); private WebsocketServerTransport(HttpServer server) { - this.server = serverConfigurer.apply(Objects.requireNonNull(server, "server is required")); + this.server = BaseWebsocketServerTransport.serverConfigurer.apply(Objects.requireNonNull(server, "server is required")); } /** @@ -116,7 +115,7 @@ public Mono start(ConnectionAcceptor acceptor) { return response.sendWebsocket( (in, out) -> acceptor - .accept(new WebsocketDuplexConnection("server", (Connection) in)) + .accept(new WebsocketConnection("server", (Connection) in)) .then(out.neverComplete()), specBuilder.build()); }) diff --git a/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/WebSocketClient.java b/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/WebSocketClient.java similarity index 99% rename from today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/WebSocketClient.java rename to today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/WebSocketClient.java index d4b5b7a..a0d27ea 100644 --- a/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/WebSocketClient.java +++ b/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/WebSocketClient.java @@ -15,7 +15,7 @@ * along with this program. If not, see [http://www.gnu.org/licenses/] */ -package infra.remoting.transport.netty; +package infra.remoting.transport.websocket; import java.io.BufferedReader; import java.io.InputStreamReader; diff --git a/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/WebSocketClientHandler.java b/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/WebSocketClientHandler.java similarity index 98% rename from today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/WebSocketClientHandler.java rename to today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/WebSocketClientHandler.java index eb90ae4..1bf23cc 100644 --- a/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/WebSocketClientHandler.java +++ b/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/WebSocketClientHandler.java @@ -15,7 +15,7 @@ * along with this program. If not, see [http://www.gnu.org/licenses/] */ -package infra.remoting.transport.netty; +package infra.remoting.transport.websocket; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; diff --git a/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/WebSocketTransportIntegrationTests.java b/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/WebSocketTransportIntegrationTests.java similarity index 92% rename from today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/WebSocketTransportIntegrationTests.java rename to today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/WebSocketTransportIntegrationTests.java index 5dcbfee..10b555e 100644 --- a/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/WebSocketTransportIntegrationTests.java +++ b/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/WebSocketTransportIntegrationTests.java @@ -15,15 +15,13 @@ * along with this program. If not, see [http://www.gnu.org/licenses/] */ -package infra.remoting.transport.netty; +package infra.remoting.transport.websocket; import org.junit.jupiter.api.Test; import java.net.URI; import java.time.Duration; -import infra.remoting.transport.netty.client.WebsocketClientTransport; -import infra.remoting.transport.netty.server.WebsocketRouteTransport; import infra.remoting.Channel; import infra.remoting.ChannelAcceptor; import infra.remoting.core.ChannelConnector; diff --git a/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/client/WebsocketClientTransportTests.java b/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/WebsocketClientTransportTests.java similarity index 97% rename from today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/client/WebsocketClientTransportTests.java rename to today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/WebsocketClientTransportTests.java index 3bf9840..ecc5efc 100644 --- a/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/client/WebsocketClientTransportTests.java +++ b/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/WebsocketClientTransportTests.java @@ -15,7 +15,7 @@ * along with this program. If not, see [http://www.gnu.org/licenses/] */ -package infra.remoting.transport.netty.client; +package infra.remoting.transport.websocket; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -25,7 +25,6 @@ import java.net.InetSocketAddress; import java.net.URI; -import infra.remoting.transport.netty.server.WebsocketServerTransport; import reactor.core.publisher.Mono; import reactor.netty.http.client.HttpClient; import reactor.test.StepVerifier; diff --git a/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/WebsocketPing.java b/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/WebsocketPing.java similarity index 93% rename from today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/WebsocketPing.java rename to today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/WebsocketPing.java index 6e14aae..dcb8e14 100644 --- a/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/WebsocketPing.java +++ b/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/WebsocketPing.java @@ -15,7 +15,7 @@ * along with this program. If not, see [http://www.gnu.org/licenses/] */ -package infra.remoting.transport.netty; +package infra.remoting.transport.websocket; import org.HdrHistogram.Recorder; @@ -25,7 +25,6 @@ import infra.remoting.core.ChannelConnector; import infra.remoting.frame.decoder.PayloadDecoder; import infra.remoting.test.PingClient; -import infra.remoting.transport.netty.client.WebsocketClientTransport; import reactor.core.publisher.Mono; public final class WebsocketPing { diff --git a/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/WebsocketPingPongIntegrationTests.java b/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/WebsocketPingPongIntegrationTests.java similarity index 95% rename from today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/WebsocketPingPongIntegrationTests.java rename to today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/WebsocketPingPongIntegrationTests.java index 46d304c..3b901b6 100644 --- a/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/WebsocketPingPongIntegrationTests.java +++ b/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/WebsocketPingPongIntegrationTests.java @@ -14,7 +14,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see [http://www.gnu.org/licenses/] */ -package infra.remoting.transport.netty; +package infra.remoting.transport.websocket; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.params.ParameterizedTest; @@ -25,6 +25,13 @@ import java.time.Duration; import java.util.stream.Stream; +import infra.remoting.Channel; +import infra.remoting.ChannelAcceptor; +import infra.remoting.Closeable; +import infra.remoting.core.ChannelConnector; +import infra.remoting.core.RemotingServer; +import infra.remoting.transport.ServerTransport; +import infra.remoting.util.DefaultPayload; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; @@ -32,16 +39,6 @@ import io.netty.handler.codec.http.websocketx.PongWebSocketFrame; import io.netty.handler.codec.http.websocketx.WebSocketFrame; import io.netty.util.ReferenceCountUtil; -import infra.remoting.Closeable; -import infra.remoting.Channel; -import infra.remoting.ChannelAcceptor; -import infra.remoting.core.ChannelConnector; -import infra.remoting.core.RemotingServer; -import infra.remoting.transport.ServerTransport; -import infra.remoting.transport.netty.client.WebsocketClientTransport; -import infra.remoting.transport.netty.server.WebsocketRouteTransport; -import infra.remoting.transport.netty.server.WebsocketServerTransport; -import infra.remoting.util.DefaultPayload; import reactor.core.Scannable; import reactor.core.publisher.Mono; import reactor.core.publisher.Sinks; diff --git a/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/WebsocketPongServer.java b/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/WebsocketPongServer.java similarity index 91% rename from today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/WebsocketPongServer.java rename to today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/WebsocketPongServer.java index f3abe8c..6d3efba 100644 --- a/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/WebsocketPongServer.java +++ b/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/WebsocketPongServer.java @@ -15,12 +15,11 @@ * along with this program. If not, see [http://www.gnu.org/licenses/] */ -package infra.remoting.transport.netty; +package infra.remoting.transport.websocket; import infra.remoting.core.RemotingServer; import infra.remoting.frame.decoder.PayloadDecoder; import infra.remoting.test.PingHandler; -import infra.remoting.transport.netty.server.WebsocketServerTransport; public final class WebsocketPongServer { diff --git a/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/WebsocketResumableTransportTests.java b/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/WebsocketResumableTransportTests.java similarity index 92% rename from today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/WebsocketResumableTransportTests.java rename to today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/WebsocketResumableTransportTests.java index dcc5415..fe1ccf1 100644 --- a/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/WebsocketResumableTransportTests.java +++ b/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/WebsocketResumableTransportTests.java @@ -15,18 +15,16 @@ * along with this program. If not, see [http://www.gnu.org/licenses/] */ -package infra.remoting.transport.netty; +package infra.remoting.transport.websocket; import org.junit.jupiter.api.BeforeEach; import java.net.InetSocketAddress; import java.time.Duration; -import io.netty.channel.ChannelOption; import infra.remoting.test.TransportPair; import infra.remoting.test.TransportTest; -import infra.remoting.transport.netty.client.WebsocketClientTransport; -import infra.remoting.transport.netty.server.WebsocketServerTransport; +import io.netty.channel.ChannelOption; import reactor.netty.http.client.HttpClient; import reactor.netty.http.server.HttpServer; diff --git a/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/WebsocketResumableWithFragmentationTransportTests.java b/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/WebsocketResumableWithFragmentationTransportTests.java similarity index 53% rename from today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/WebsocketResumableWithFragmentationTransportTests.java rename to today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/WebsocketResumableWithFragmentationTransportTests.java index 5772e3e..9eb1ef8 100644 --- a/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/WebsocketResumableWithFragmentationTransportTests.java +++ b/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/WebsocketResumableWithFragmentationTransportTests.java @@ -15,18 +15,16 @@ * along with this program. If not, see [http://www.gnu.org/licenses/] */ -package infra.remoting.transport.netty; +package infra.remoting.transport.websocket; import org.junit.jupiter.api.BeforeEach; import java.net.InetSocketAddress; import java.time.Duration; -import io.netty.channel.ChannelOption; import infra.remoting.test.TransportPair; import infra.remoting.test.TransportTest; -import infra.remoting.transport.netty.client.WebsocketClientTransport; -import infra.remoting.transport.netty.server.WebsocketServerTransport; +import io.netty.channel.ChannelOption; import reactor.netty.http.client.HttpClient; import reactor.netty.http.server.HttpServer; @@ -35,25 +33,24 @@ final class WebsocketResumableWithFragmentationTransportTests implements Transpo @BeforeEach void createTestPair() { - transportPair = - new TransportPair<>( - () -> InetSocketAddress.createUnresolved("localhost", 0), - (address, server, allocator) -> - WebsocketClientTransport.create( - HttpClient.create() - .host(server.address().getHostName()) - .port(server.address().getPort()) - .option(ChannelOption.ALLOCATOR, allocator), - ""), - (address, allocator) -> { - return WebsocketServerTransport.create( - HttpServer.create() - .host(address.getHostName()) - .port(address.getPort()) - .option(ChannelOption.ALLOCATOR, allocator)); - }, - true, - true); + transportPair = new TransportPair<>( + () -> InetSocketAddress.createUnresolved("localhost", 0), + (address, server, allocator) -> + WebsocketClientTransport.create( + HttpClient.create() + .host(server.address().getHostName()) + .port(server.address().getPort()) + .option(ChannelOption.ALLOCATOR, allocator), + ""), + (address, allocator) -> { + return WebsocketServerTransport.create( + HttpServer.create() + .host(address.getHostName()) + .port(address.getPort()) + .option(ChannelOption.ALLOCATOR, allocator)); + }, + true, + true); } @Override diff --git a/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/server/WebsocketRouteTransportTests.java b/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/WebsocketRouteTransportTests.java similarity index 98% rename from today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/server/WebsocketRouteTransportTests.java rename to today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/WebsocketRouteTransportTests.java index e705b7b..6873f44 100644 --- a/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/server/WebsocketRouteTransportTests.java +++ b/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/WebsocketRouteTransportTests.java @@ -15,7 +15,7 @@ * along with this program. If not, see [http://www.gnu.org/licenses/] */ -package infra.remoting.transport.netty.server; +package infra.remoting.transport.websocket; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; diff --git a/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/WebsocketSecureTransportTests.java b/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/WebsocketSecureTransportTests.java similarity index 95% rename from today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/WebsocketSecureTransportTests.java rename to today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/WebsocketSecureTransportTests.java index ee6ec2c..e5d4794 100644 --- a/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/WebsocketSecureTransportTests.java +++ b/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/WebsocketSecureTransportTests.java @@ -15,7 +15,7 @@ * along with this program. If not, see [http://www.gnu.org/licenses/] */ -package infra.remoting.transport.netty; +package infra.remoting.transport.websocket; import org.junit.jupiter.api.BeforeEach; @@ -25,14 +25,12 @@ import javax.net.ssl.SSLException; +import infra.remoting.test.TransportPair; +import infra.remoting.test.TransportTest; import io.netty.channel.ChannelOption; import io.netty.handler.ssl.SslContextBuilder; import io.netty.handler.ssl.util.InsecureTrustManagerFactory; import io.netty.handler.ssl.util.SelfSignedCertificate; -import infra.remoting.test.TransportPair; -import infra.remoting.test.TransportTest; -import infra.remoting.transport.netty.client.WebsocketClientTransport; -import infra.remoting.transport.netty.server.WebsocketServerTransport; import reactor.core.Exceptions; import reactor.netty.http.client.HttpClient; import reactor.netty.http.server.HttpServer; diff --git a/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/server/WebsocketServerTransportTests.java b/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/WebsocketServerTransportTests.java similarity index 99% rename from today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/server/WebsocketServerTransportTests.java rename to today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/WebsocketServerTransportTests.java index a1cc03b..f756913 100644 --- a/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/server/WebsocketServerTransportTests.java +++ b/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/WebsocketServerTransportTests.java @@ -15,7 +15,7 @@ * along with this program. If not, see [http://www.gnu.org/licenses/] */ -package infra.remoting.transport.netty.server; +package infra.remoting.transport.websocket; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; diff --git a/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/WebsocketTransportTests.java b/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/WebsocketTransportTests.java similarity index 53% rename from today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/WebsocketTransportTests.java rename to today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/WebsocketTransportTests.java index 20b115a..25f5923 100644 --- a/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/WebsocketTransportTests.java +++ b/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/WebsocketTransportTests.java @@ -15,43 +15,41 @@ * along with this program. If not, see [http://www.gnu.org/licenses/] */ -package infra.remoting.transport.netty; +package infra.remoting.transport.websocket; import org.junit.jupiter.api.BeforeEach; import java.net.InetSocketAddress; import java.time.Duration; -import io.netty.channel.ChannelOption; import infra.remoting.test.TransportPair; import infra.remoting.test.TransportTest; -import infra.remoting.transport.netty.client.WebsocketClientTransport; -import infra.remoting.transport.netty.server.WebsocketServerTransport; +import io.netty.channel.ChannelOption; import reactor.netty.http.client.HttpClient; import reactor.netty.http.server.HttpServer; final class WebsocketTransportTests implements TransportTest { + private TransportPair transportPair; @BeforeEach void createTestPair() { - transportPair = - new TransportPair<>( - () -> InetSocketAddress.createUnresolved("localhost", 0), - (address, server, allocator) -> - WebsocketClientTransport.create( - HttpClient.create() - .host(server.address().getHostName()) - .port(server.address().getPort()) - .option(ChannelOption.ALLOCATOR, allocator), - ""), - (address, allocator) -> { - return WebsocketServerTransport.create( - HttpServer.create() - .host(address.getHostName()) - .port(address.getPort()) - .option(ChannelOption.ALLOCATOR, allocator)); - }); + transportPair = new TransportPair<>( + () -> InetSocketAddress.createUnresolved("localhost", 0), + (address, server, allocator) -> + WebsocketClientTransport.create( + HttpClient.create() + .host(server.address().getHostName()) + .port(server.address().getPort()) + .option(ChannelOption.ALLOCATOR, allocator), + ""), + (address, allocator) -> { + return WebsocketServerTransport.create( + HttpServer.create() + .host(address.getHostName()) + .port(address.getPort()) + .option(ChannelOption.ALLOCATOR, allocator)); + }); } @Override diff --git a/today-remoting/build.gradle b/today-remoting/build.gradle index f311d9e..2bc4f5e 100644 --- a/today-remoting/build.gradle +++ b/today-remoting/build.gradle @@ -11,6 +11,7 @@ dependencies { testImplementation(project(":today-remoting-transport-local")) testImplementation(project(":today-remoting-transport-tcp")) + testImplementation(project(":today-remoting-transport-websocket")) testImplementation 'io.projectreactor:reactor-test' testImplementation 'org.awaitility:awaitility' diff --git a/today-remoting/src/main/java/infra/remoting/DuplexConnection.java b/today-remoting/src/main/java/infra/remoting/Connection.java similarity index 97% rename from today-remoting/src/main/java/infra/remoting/DuplexConnection.java rename to today-remoting/src/main/java/infra/remoting/Connection.java index 5837dd0..9f6c678 100644 --- a/today-remoting/src/main/java/infra/remoting/DuplexConnection.java +++ b/today-remoting/src/main/java/infra/remoting/Connection.java @@ -29,7 +29,7 @@ /** * Represents a connection with input/output that the protocol uses. */ -public interface DuplexConnection extends Availability, Closeable { +public interface Connection extends Availability, Closeable { /** * Delivers the given frame to the underlying transport connection. This method is non-blocking diff --git a/today-remoting/src/main/java/infra/remoting/DuplexConnectionWrapper.java b/today-remoting/src/main/java/infra/remoting/ConnectionWrapper.java similarity index 91% rename from today-remoting/src/main/java/infra/remoting/DuplexConnectionWrapper.java rename to today-remoting/src/main/java/infra/remoting/ConnectionWrapper.java index d2f0598..9bfe6c6 100644 --- a/today-remoting/src/main/java/infra/remoting/DuplexConnectionWrapper.java +++ b/today-remoting/src/main/java/infra/remoting/ConnectionWrapper.java @@ -28,11 +28,11 @@ * @author 海子 Yang * @since 1.0 2025/8/3 11:25 */ -public class DuplexConnectionWrapper implements DuplexConnection { +public class ConnectionWrapper implements Connection { - private final DuplexConnection delegate; + private final Connection delegate; - public DuplexConnectionWrapper(DuplexConnection delegate) { + public ConnectionWrapper(Connection delegate) { this.delegate = delegate; } diff --git a/today-remoting/src/main/java/infra/remoting/core/ChannelConnector.java b/today-remoting/src/main/java/infra/remoting/core/ChannelConnector.java index 67b3c8c..2f08f96 100644 --- a/today-remoting/src/main/java/infra/remoting/core/ChannelConnector.java +++ b/today-remoting/src/main/java/infra/remoting/core/ChannelConnector.java @@ -27,7 +27,7 @@ import infra.remoting.Channel; import infra.remoting.ChannelAcceptor; import infra.remoting.ConnectionSetupPayload; -import infra.remoting.DuplexConnection; +import infra.remoting.Connection; import infra.remoting.Payload; import infra.remoting.frame.SetupFrameCodec; import infra.remoting.frame.decoder.PayloadDecoder; @@ -38,7 +38,7 @@ import infra.remoting.plugins.InterceptorRegistry; import infra.remoting.plugins.RateLimitDecorator; import infra.remoting.resume.ClientChannelSession; -import infra.remoting.resume.ResumableDuplexConnection; +import infra.remoting.resume.ResumableConnection; import infra.remoting.resume.ResumableFramesStore; import infra.remoting.transport.ClientTransport; import infra.remoting.transport.Transport; @@ -510,13 +510,13 @@ public Mono connect(ClientTransport transport) { public Mono connect(Supplier transportSupplier) { return Mono.fromSupplier(transportSupplier).flatMap(ct -> { int maxFrameLength = ct.getMaxFrameLength(); - Mono connectionMono = Mono.fromCallable(() -> { + Mono connectionMono = Mono.fromCallable(() -> { assertValidateSetup(maxFrameLength, maxInboundPayloadSize, mtu); return ct; }) .flatMap(transport -> transport.connect()) .map(sourceConnection -> interceptors.initConnection(ConnectionDecorator.Type.SOURCE, sourceConnection)) - .map(con -> LoggingDuplexConnection.wrapIfEnabled(con)); + .map(con -> LoggingConnection.wrapIfEnabled(con)); return connectionMono .flatMap(connection -> setupPayloadMono @@ -525,7 +525,7 @@ public Mono connect(Supplier transportSupplier) { .doOnError(ex -> connection.dispose()) .doOnCancel(connection::dispose)) .flatMap(tuple2 -> { - DuplexConnection sourceConnection = tuple2.getT1(); + Connection sourceConnection = tuple2.getT1(); Payload setupPayload = tuple2.getT2(); boolean leaseEnabled = leaseConfigurer != null; boolean resumeEnabled = resume != null; @@ -552,20 +552,20 @@ public Mono connect(Supplier transportSupplier) { sourceConnection.sendFrame(0, setupFrame.retainedSlice()); return clientSetup.init(sourceConnection).flatMap(tuple -> { - final DuplexConnection clientServerConnection = tuple.getT2(); + final Connection clientServerConnection = tuple.getT2(); final KeepAliveHandler keepAliveHandler; - final DuplexConnection wrappedConnection; + final Connection wrappedConnection; final InitializingInterceptorRegistry interceptors = this.interceptors; if (resumeEnabled) { final ResumableClientSetup resumableClientSetup = new ResumableClientSetup(); final ResumableFramesStore resumableFramesStore = resume.getStoreFactory(CLIENT_TAG).apply(resumeToken); - final ResumableDuplexConnection resumableDuplexConnection = new ResumableDuplexConnection(CLIENT_TAG, resumeToken, clientServerConnection, resumableFramesStore); - final ClientChannelSession session = new ClientChannelSession(resumeToken, resumableDuplexConnection, connectionMono, resumableClientSetup::init, + final ResumableConnection resumableConnection = new ResumableConnection(CLIENT_TAG, resumeToken, clientServerConnection, resumableFramesStore); + final ClientChannelSession session = new ClientChannelSession(resumeToken, resumableConnection, connectionMono, resumableClientSetup::init, resumableFramesStore, resume.getSessionDuration(), resume.getRetry(), resume.isCleanupStoreOnKeepAlive()); - keepAliveHandler = new KeepAliveHandler.ResumableKeepAliveHandler(resumableDuplexConnection, session, session); - wrappedConnection = resumableDuplexConnection; + keepAliveHandler = new KeepAliveHandler.ResumableKeepAliveHandler(resumableConnection, session, session); + wrappedConnection = resumableConnection; } else { keepAliveHandler = new KeepAliveHandler.DefaultKeepAliveHandler(); diff --git a/today-remoting/src/main/java/infra/remoting/core/ChannelSupport.java b/today-remoting/src/main/java/infra/remoting/core/ChannelSupport.java index 79130fd..798e2e0 100644 --- a/today-remoting/src/main/java/infra/remoting/core/ChannelSupport.java +++ b/today-remoting/src/main/java/infra/remoting/core/ChannelSupport.java @@ -22,7 +22,7 @@ import infra.lang.Nullable; import infra.remoting.Channel; -import infra.remoting.DuplexConnection; +import infra.remoting.Connection; import infra.remoting.frame.decoder.PayloadDecoder; import infra.remoting.plugins.RequestInterceptor; import io.netty.buffer.ByteBufAllocator; @@ -41,7 +41,7 @@ class ChannelSupport { public final ByteBufAllocator allocator; - public final DuplexConnection connection; + public final Connection connection; @Nullable public final RequestInterceptor requestInterceptor; @@ -52,7 +52,7 @@ class ChannelSupport { protected final IntObjectMap activeStreams; public ChannelSupport(int mtu, int maxFrameLength, int maxInboundPayloadSize, - PayloadDecoder payloadDecoder, DuplexConnection connection, @Nullable StreamIdProvider streamIdProvider, + PayloadDecoder payloadDecoder, Connection connection, @Nullable StreamIdProvider streamIdProvider, Function requestInterceptorFunction) { this.activeStreams = new IntObjectHashMap<>(); @@ -86,7 +86,7 @@ public ByteBufAllocator getAllocator() { return allocator; } - public DuplexConnection getDuplexConnection() { + public Connection getConnection() { return connection; } diff --git a/today-remoting/src/main/java/infra/remoting/core/ClientServerInputMultiplexer.java b/today-remoting/src/main/java/infra/remoting/core/ClientServerInputMultiplexer.java index 5c8e0de..95d7ac0 100644 --- a/today-remoting/src/main/java/infra/remoting/core/ClientServerInputMultiplexer.java +++ b/today-remoting/src/main/java/infra/remoting/core/ClientServerInputMultiplexer.java @@ -23,7 +23,7 @@ import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; import infra.remoting.Closeable; -import infra.remoting.DuplexConnection; +import infra.remoting.Connection; import infra.remoting.ProtocolErrorException; import infra.remoting.frame.FrameHeaderCodec; import infra.remoting.plugins.ConnectionDecorator.Type; @@ -36,7 +36,7 @@ import reactor.core.publisher.Operators; /** - * {@link DuplexConnection#receive()} is a single stream on which the following type of frames + * {@link Connection#receive()} is a single stream on which the following type of frames * arrive: * *

      @@ -50,11 +50,11 @@ */ class ClientServerInputMultiplexer implements CoreSubscriber, Closeable { - private final InternalDuplexConnection serverReceiver; - private final InternalDuplexConnection clientReceiver; - private final DuplexConnection serverConnection; - private final DuplexConnection clientConnection; - private final DuplexConnection source; + private final InternalConnection serverReceiver; + private final InternalConnection clientReceiver; + private final Connection serverConnection; + private final Connection clientConnection; + private final Connection source; private final boolean isClient; private Subscription s; @@ -66,21 +66,21 @@ class ClientServerInputMultiplexer implements CoreSubscriber, Closeable AtomicIntegerFieldUpdater.newUpdater(ClientServerInputMultiplexer.class, "state"); public ClientServerInputMultiplexer( - DuplexConnection source, InitializingInterceptorRegistry registry, boolean isClient) { + Connection source, InitializingInterceptorRegistry registry, boolean isClient) { this.source = source; this.isClient = isClient; - this.serverReceiver = new InternalDuplexConnection(Type.SERVER, this, source); - this.clientReceiver = new InternalDuplexConnection(Type.CLIENT, this, source); + this.serverReceiver = new InternalConnection(Type.SERVER, this, source); + this.clientReceiver = new InternalConnection(Type.CLIENT, this, source); this.serverConnection = registry.initConnection(Type.SERVER, serverReceiver); this.clientConnection = registry.initConnection(Type.CLIENT, clientReceiver); } - DuplexConnection asServerConnection() { + Connection asServerConnection() { return serverConnection; } - DuplexConnection asClientConnection() { + Connection asClientConnection() { return clientConnection; } @@ -224,22 +224,22 @@ public String toString() { + '}'; } - private static class InternalDuplexConnection extends Flux - implements Subscription, DuplexConnection { + private static class InternalConnection extends Flux + implements Subscription, Connection { private final Type type; private final ClientServerInputMultiplexer clientServerInputMultiplexer; - private final DuplexConnection source; + private final Connection source; private volatile int state; - static final AtomicIntegerFieldUpdater STATE = - AtomicIntegerFieldUpdater.newUpdater(InternalDuplexConnection.class, "state"); + static final AtomicIntegerFieldUpdater STATE = + AtomicIntegerFieldUpdater.newUpdater(InternalConnection.class, "state"); CoreSubscriber actual; - public InternalDuplexConnection( + public InternalConnection( Type type, ClientServerInputMultiplexer clientServerInputMultiplexer, - DuplexConnection source) { + Connection source) { this.type = type; this.clientServerInputMultiplexer = clientServerInputMultiplexer; this.source = source; @@ -254,7 +254,7 @@ public void subscribe(CoreSubscriber actual) { else { Operators.error( actual, - new IllegalStateException("InternalDuplexConnection allows only single subscription")); + new IllegalStateException("InternalConnection allows only single subscription")); } } @@ -342,7 +342,7 @@ public double availability() { @Override public String toString() { - return "InternalDuplexConnection{" + return "InternalConnection{" + "type=" + type + ", source=" diff --git a/today-remoting/src/main/java/infra/remoting/core/ClientSetup.java b/today-remoting/src/main/java/infra/remoting/core/ClientSetup.java index a0336ee..2e79ad6 100644 --- a/today-remoting/src/main/java/infra/remoting/core/ClientSetup.java +++ b/today-remoting/src/main/java/infra/remoting/core/ClientSetup.java @@ -19,7 +19,7 @@ import java.nio.channels.ClosedChannelException; -import infra.remoting.DuplexConnection; +import infra.remoting.Connection; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import reactor.core.Disposable; @@ -29,13 +29,13 @@ abstract class ClientSetup { - abstract Mono> init(DuplexConnection connection); + abstract Mono> init(Connection connection); } class DefaultClientSetup extends ClientSetup { @Override - Mono> init(DuplexConnection connection) { + Mono> init(Connection connection) { return Mono.create(sink -> sink.onRequest(__ -> sink.success(Tuples.of(Unpooled.EMPTY_BUFFER, connection)))); } } @@ -43,9 +43,9 @@ Mono> init(DuplexConnection connection) { class ResumableClientSetup extends ClientSetup { @Override - Mono> init(DuplexConnection connection) { + Mono> init(Connection connection) { return Mono.create(sink -> { - sink.onRequest(__ -> new SetupHandlingDuplexConnection(connection, sink)); + sink.onRequest(__ -> new SetupHandlingConnection(connection, sink)); Disposable subscribe = connection.onClose() .doFinally(__ -> sink.error(new ClosedChannelException())) diff --git a/today-remoting/src/main/java/infra/remoting/core/LoggingDuplexConnection.java b/today-remoting/src/main/java/infra/remoting/core/LoggingConnection.java similarity index 87% rename from today-remoting/src/main/java/infra/remoting/core/LoggingDuplexConnection.java rename to today-remoting/src/main/java/infra/remoting/core/LoggingConnection.java index 8b9047d..790003d 100644 --- a/today-remoting/src/main/java/infra/remoting/core/LoggingDuplexConnection.java +++ b/today-remoting/src/main/java/infra/remoting/core/LoggingConnection.java @@ -21,7 +21,7 @@ import infra.logging.Logger; import infra.logging.LoggerFactory; -import infra.remoting.DuplexConnection; +import infra.remoting.Connection; import infra.remoting.ProtocolErrorException; import infra.remoting.frame.FrameUtil; import io.netty.buffer.ByteBuf; @@ -29,12 +29,13 @@ import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; -class LoggingDuplexConnection implements DuplexConnection { +final class LoggingConnection implements Connection { + private static final Logger LOGGER = LoggerFactory.getLogger("infra.remoting.FrameLogger"); - final DuplexConnection source; + private final Connection source; - LoggingDuplexConnection(DuplexConnection source) { + LoggingConnection(Connection source) { this.source = source; } @@ -77,11 +78,10 @@ public SocketAddress remoteAddress() { return source.remoteAddress(); } - static DuplexConnection wrapIfEnabled(DuplexConnection source) { + static Connection wrapIfEnabled(Connection source) { if (LOGGER.isDebugEnabled()) { - return new LoggingDuplexConnection(source); + return new LoggingConnection(source); } - return source; } } diff --git a/today-remoting/src/main/java/infra/remoting/core/RemotingServer.java b/today-remoting/src/main/java/infra/remoting/core/RemotingServer.java index 9e7df30..79bffa5 100644 --- a/today-remoting/src/main/java/infra/remoting/core/RemotingServer.java +++ b/today-remoting/src/main/java/infra/remoting/core/RemotingServer.java @@ -26,7 +26,7 @@ import infra.remoting.ChannelAcceptor; import infra.remoting.Closeable; import infra.remoting.ConnectionSetupPayload; -import infra.remoting.DuplexConnection; +import infra.remoting.Connection; import infra.remoting.Payload; import infra.remoting.ProtocolErrorException; import infra.remoting.error.InvalidSetupException; @@ -325,29 +325,29 @@ public ConnectionAcceptor asConnectionAcceptor(int maxFrameLength) { private final ServerSetup serverSetup = serverSetup(timeout); @Override - public Mono accept(DuplexConnection connection) { + public Mono accept(Connection connection) { return acceptor(serverSetup, connection, maxFrameLength); } }; } - private Mono acceptor(ServerSetup serverSetup, DuplexConnection sourceConnection, int maxFrameLength) { - final DuplexConnection interceptedConnection = interceptors.initConnection(ConnectionDecorator.Type.SOURCE, sourceConnection); + private Mono acceptor(ServerSetup serverSetup, Connection sourceConnection, int maxFrameLength) { + final Connection interceptedConnection = interceptors.initConnection(ConnectionDecorator.Type.SOURCE, sourceConnection); return serverSetup - .init(LoggingDuplexConnection.wrapIfEnabled(interceptedConnection)) + .init(LoggingConnection.wrapIfEnabled(interceptedConnection)) .flatMap(tuple2 -> { final ByteBuf startFrame = tuple2.getT1(); - final DuplexConnection clientServerConnection = tuple2.getT2(); + final Connection clientServerConnection = tuple2.getT2(); return accept(serverSetup, startFrame, clientServerConnection, maxFrameLength); }); } - private Mono acceptResume(ServerSetup serverSetup, ByteBuf resumeFrame, DuplexConnection clientServerConnection) { + private Mono acceptResume(ServerSetup serverSetup, ByteBuf resumeFrame, Connection clientServerConnection) { return serverSetup.acceptChannelResume(resumeFrame, clientServerConnection); } - private Mono accept(ServerSetup serverSetup, ByteBuf startFrame, DuplexConnection clientServerConnection, int maxFrameLength) { + private Mono accept(ServerSetup serverSetup, ByteBuf startFrame, Connection clientServerConnection, int maxFrameLength) { return switch (FrameHeaderCodec.frameType(startFrame)) { case SETUP -> acceptSetup(serverSetup, startFrame, clientServerConnection, maxFrameLength); case RESUME -> acceptResume(serverSetup, startFrame, clientServerConnection); @@ -358,7 +358,7 @@ private Mono accept(ServerSetup serverSetup, ByteBuf startFrame, DuplexCon }; } - private Mono acceptSetup(ServerSetup serverSetup, ByteBuf setupFrame, DuplexConnection clientServerConnection, int maxFrameLength) { + private Mono acceptSetup(ServerSetup serverSetup, ByteBuf setupFrame, Connection clientServerConnection, int maxFrameLength) { if (!SetupFrameCodec.isSupportedVersion(setupFrame)) { serverSetup.sendError(clientServerConnection, new InvalidSetupException( "Unsupported version: " + SetupFrameCodec.humanReadableVersion(setupFrame))); @@ -371,10 +371,10 @@ private Mono acceptSetup(ServerSetup serverSetup, ByteBuf setupFrame, Dupl return clientServerConnection.onClose(); } - return serverSetup.acceptChannelSetup(setupFrame, clientServerConnection, (keepAliveHandler, wrappedDuplexConnection) -> { + return serverSetup.acceptChannelSetup(setupFrame, clientServerConnection, (keepAliveHandler, wrappedConnection) -> { final InitializingInterceptorRegistry interceptors = this.interceptors; final ConnectionSetupPayload setupPayload = new DefaultConnectionSetupPayload(setupFrame.retain()); - final ClientServerInputMultiplexer multiplexer = new ClientServerInputMultiplexer(wrappedDuplexConnection, interceptors, false); + final ClientServerInputMultiplexer multiplexer = new ClientServerInputMultiplexer(wrappedConnection, interceptors, false); final LeaseSpec leases; final RequesterLeaseTracker requesterLeaseTracker; if (leaseEnabled) { @@ -401,12 +401,12 @@ private Mono acceptSetup(ServerSetup serverSetup, ByteBuf setupFrame, Dupl .decorateAcceptor(acceptor) .accept(setupPayload, wrappedChannelRequester) .onErrorResume(err -> Mono.fromRunnable(() -> serverSetup.sendError( - wrappedDuplexConnection, rejectedSetupError(err))) - .then(wrappedDuplexConnection.onClose()) + wrappedConnection, rejectedSetupError(err))) + .then(wrappedConnection.onClose()) .then(Mono.error(err))) .doOnNext(channelHandler -> { Channel wrappedChannelHandler = interceptors.decorateResponder(channelHandler); - DuplexConnection clientConnection = multiplexer.asClientConnection(); + Connection clientConnection = multiplexer.asClientConnection(); ResponderLeaseTracker responderLeaseTracker = leaseEnabled ? new ResponderLeaseTracker(SERVER_TAG, clientConnection, leases.sender) diff --git a/today-remoting/src/main/java/infra/remoting/core/RequestChannelRequesterFlux.java b/today-remoting/src/main/java/infra/remoting/core/RequestChannelRequesterFlux.java index ed6b912..a20cb96 100644 --- a/today-remoting/src/main/java/infra/remoting/core/RequestChannelRequesterFlux.java +++ b/today-remoting/src/main/java/infra/remoting/core/RequestChannelRequesterFlux.java @@ -26,7 +26,7 @@ import infra.lang.NonNull; import infra.lang.Nullable; -import infra.remoting.DuplexConnection; +import infra.remoting.Connection; import infra.remoting.Payload; import infra.remoting.frame.CancelFrameCodec; import infra.remoting.frame.ErrorFrameCodec; @@ -269,7 +269,7 @@ void sendFirstPayload(Payload firstPayload, long initialRequestN, boolean comple } final ChannelSupport channel = this.channel; - final DuplexConnection connection = channel.connection; + final Connection connection = channel.connection; final ByteBufAllocator allocator = channel.allocator; final int streamId; diff --git a/today-remoting/src/main/java/infra/remoting/core/RequestChannelResponderSubscriber.java b/today-remoting/src/main/java/infra/remoting/core/RequestChannelResponderSubscriber.java index 04ec8c4..37111b4 100644 --- a/today-remoting/src/main/java/infra/remoting/core/RequestChannelResponderSubscriber.java +++ b/today-remoting/src/main/java/infra/remoting/core/RequestChannelResponderSubscriber.java @@ -24,7 +24,7 @@ import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; import infra.remoting.Channel; -import infra.remoting.DuplexConnection; +import infra.remoting.Connection; import infra.remoting.Payload; import infra.remoting.error.CanceledException; import infra.remoting.frame.CancelFrameCodec; @@ -71,7 +71,7 @@ final class RequestChannelResponderSubscriber extends Flux implements R final ChannelSupport channel; - final DuplexConnection connection; + final Connection connection; final long firstRequest; @@ -103,7 +103,7 @@ public RequestChannelResponderSubscriber(int streamId, long firstRequestN, ByteBuf firstFrame, ChannelSupport channel, Channel handler) { this.streamId = streamId; this.channel = channel; - this.connection = channel.getDuplexConnection(); + this.connection = channel.getConnection(); this.handler = handler; this.firstRequest = firstRequestN; @@ -116,7 +116,7 @@ public RequestChannelResponderSubscriber(int streamId, long firstRequestN, Payload firstPayload, ChannelSupport channel) { this.streamId = streamId; this.channel = channel; - this.connection = channel.getDuplexConnection(); + this.connection = channel.getConnection(); this.firstRequest = firstRequestN; this.firstPayload = firstPayload; @@ -725,7 +725,7 @@ public void onNext(Payload p) { } final int streamId = this.streamId; - final DuplexConnection connection = channel.connection; + final Connection connection = channel.connection; final ByteBufAllocator allocator = channel.allocator; final int mtu = channel.mtu; diff --git a/today-remoting/src/main/java/infra/remoting/core/RequestResponseRequesterMono.java b/today-remoting/src/main/java/infra/remoting/core/RequestResponseRequesterMono.java index 9e8812a..1c2a6dd 100644 --- a/today-remoting/src/main/java/infra/remoting/core/RequestResponseRequesterMono.java +++ b/today-remoting/src/main/java/infra/remoting/core/RequestResponseRequesterMono.java @@ -22,7 +22,7 @@ import infra.lang.NonNull; import infra.lang.Nullable; -import infra.remoting.DuplexConnection; +import infra.remoting.Connection; import infra.remoting.Payload; import infra.remoting.frame.CancelFrameCodec; import infra.remoting.frame.FrameType; @@ -164,7 +164,7 @@ public boolean handlePermit() { void sendFirstPayload(Payload payload) { final ChannelSupport sm = this.channel; - final DuplexConnection connection = sm.connection; + final Connection connection = sm.connection; final ByteBufAllocator allocator = sm.allocator; final int streamId; diff --git a/today-remoting/src/main/java/infra/remoting/core/RequestResponseResponderSubscriber.java b/today-remoting/src/main/java/infra/remoting/core/RequestResponseResponderSubscriber.java index ce4bd71..35c13ee 100644 --- a/today-remoting/src/main/java/infra/remoting/core/RequestResponseResponderSubscriber.java +++ b/today-remoting/src/main/java/infra/remoting/core/RequestResponseResponderSubscriber.java @@ -25,7 +25,7 @@ import infra.logging.Logger; import infra.logging.LoggerFactory; import infra.remoting.Channel; -import infra.remoting.DuplexConnection; +import infra.remoting.Connection; import infra.remoting.Payload; import infra.remoting.error.CanceledException; import infra.remoting.frame.ErrorFrameCodec; @@ -111,7 +111,7 @@ public void onNext(@Nullable Payload p) { final int streamId = this.streamId; final ChannelSupport channel = this.channel; - final DuplexConnection connection = channel.connection; + final Connection connection = channel.connection; final ByteBufAllocator allocator = channel.allocator; channel.remove(streamId, this); diff --git a/today-remoting/src/main/java/infra/remoting/core/RequestStreamRequesterFlux.java b/today-remoting/src/main/java/infra/remoting/core/RequestStreamRequesterFlux.java index 958dd88..430f993 100644 --- a/today-remoting/src/main/java/infra/remoting/core/RequestStreamRequesterFlux.java +++ b/today-remoting/src/main/java/infra/remoting/core/RequestStreamRequesterFlux.java @@ -22,7 +22,7 @@ import infra.lang.NonNull; import infra.lang.Nullable; -import infra.remoting.DuplexConnection; +import infra.remoting.Connection; import infra.remoting.Payload; import infra.remoting.frame.CancelFrameCodec; import infra.remoting.frame.FrameType; @@ -180,7 +180,7 @@ public boolean handlePermit() { void sendFirstPayload(Payload payload, long initialRequestN) { final ChannelSupport channel = this.channel; - final DuplexConnection connection = channel.connection; + final Connection connection = channel.connection; final ByteBufAllocator allocator = channel.allocator; final int streamId; diff --git a/today-remoting/src/main/java/infra/remoting/core/RequestStreamResponderSubscriber.java b/today-remoting/src/main/java/infra/remoting/core/RequestStreamResponderSubscriber.java index 513cafd..f66ca84 100644 --- a/today-remoting/src/main/java/infra/remoting/core/RequestStreamResponderSubscriber.java +++ b/today-remoting/src/main/java/infra/remoting/core/RequestStreamResponderSubscriber.java @@ -24,7 +24,7 @@ import infra.logging.Logger; import infra.logging.LoggerFactory; import infra.remoting.Channel; -import infra.remoting.DuplexConnection; +import infra.remoting.Connection; import infra.remoting.Payload; import infra.remoting.error.CanceledException; import infra.remoting.frame.ErrorFrameCodec; @@ -99,7 +99,7 @@ public void onNext(Payload p) { } final int streamId = this.streamId; - final DuplexConnection sender = channel.connection; + final Connection sender = channel.connection; final ByteBufAllocator allocator = channel.allocator; final int mtu = channel.mtu; diff --git a/today-remoting/src/main/java/infra/remoting/core/RequesterChannel.java b/today-remoting/src/main/java/infra/remoting/core/RequesterChannel.java index 4fb5557..c0ee76c 100644 --- a/today-remoting/src/main/java/infra/remoting/core/RequesterChannel.java +++ b/today-remoting/src/main/java/infra/remoting/core/RequesterChannel.java @@ -29,7 +29,7 @@ import infra.logging.Logger; import infra.logging.LoggerFactory; import infra.remoting.Channel; -import infra.remoting.DuplexConnection; +import infra.remoting.Connection; import infra.remoting.Payload; import infra.remoting.error.ConnectionErrorException; import infra.remoting.error.Exceptions; @@ -76,7 +76,7 @@ class RequesterChannel extends ChannelSupport implements Channel { private final Mono onAllClosed; - RequesterChannel(DuplexConnection connection, PayloadDecoder payloadDecoder, StreamIdProvider streamIdProvider, + RequesterChannel(Connection connection, PayloadDecoder payloadDecoder, StreamIdProvider streamIdProvider, int mtu, int maxFrameLength, int maxInboundPayloadSize, int keepAliveTickPeriod, int keepAliveAckTimeout, @Nullable KeepAliveHandler keepAliveHandler, Function requestInterceptorFunction, @Nullable RequesterLeaseTracker requesterLeaseTracker, Sinks.Empty onThisSideClosedSink, Mono onAllClosed) { diff --git a/today-remoting/src/main/java/infra/remoting/core/ResponderChannel.java b/today-remoting/src/main/java/infra/remoting/core/ResponderChannel.java index 1f011d9..496bca8 100644 --- a/today-remoting/src/main/java/infra/remoting/core/ResponderChannel.java +++ b/today-remoting/src/main/java/infra/remoting/core/ResponderChannel.java @@ -30,7 +30,7 @@ import infra.logging.Logger; import infra.logging.LoggerFactory; import infra.remoting.Channel; -import infra.remoting.DuplexConnection; +import infra.remoting.Connection; import infra.remoting.Payload; import infra.remoting.error.ConnectionErrorException; import infra.remoting.error.Exceptions; @@ -70,7 +70,7 @@ class ResponderChannel extends ChannelSupport implements Channel { AtomicReferenceFieldUpdater.newUpdater( ResponderChannel.class, Throwable.class, "terminationError"); - ResponderChannel(DuplexConnection connection, Channel requestHandler, PayloadDecoder payloadDecoder, @Nullable ResponderLeaseTracker leaseHandler, + ResponderChannel(Connection connection, Channel requestHandler, PayloadDecoder payloadDecoder, @Nullable ResponderLeaseTracker leaseHandler, int mtu, int maxFrameLength, int maxInboundPayloadSize, Function requestInterceptorFunction, Sinks.Empty onThisSideClosedSink) { super(mtu, maxFrameLength, maxInboundPayloadSize, payloadDecoder, connection, null, requestInterceptorFunction); diff --git a/today-remoting/src/main/java/infra/remoting/core/ResponderLeaseTracker.java b/today-remoting/src/main/java/infra/remoting/core/ResponderLeaseTracker.java index 1bd72b5..4a4d47a 100644 --- a/today-remoting/src/main/java/infra/remoting/core/ResponderLeaseTracker.java +++ b/today-remoting/src/main/java/infra/remoting/core/ResponderLeaseTracker.java @@ -19,7 +19,7 @@ import infra.lang.Nullable; import infra.remoting.Availability; -import infra.remoting.DuplexConnection; +import infra.remoting.Connection; import infra.remoting.frame.LeaseFrameCodec; import infra.remoting.lease.Lease; import infra.remoting.lease.LeaseSender; @@ -32,12 +32,12 @@ final class ResponderLeaseTracker extends BaseSubscriber implements Dispo final String tag; final ByteBufAllocator allocator; - final DuplexConnection connection; + final Connection connection; @Nullable volatile MutableLease currentLease; - ResponderLeaseTracker(String tag, DuplexConnection connection, LeaseSender leaseSender) { + ResponderLeaseTracker(String tag, Connection connection, LeaseSender leaseSender) { this.tag = tag; this.connection = connection; this.allocator = connection.alloc(); diff --git a/today-remoting/src/main/java/infra/remoting/core/SendUtils.java b/today-remoting/src/main/java/infra/remoting/core/SendUtils.java index 7742b55..e7a9475 100644 --- a/today-remoting/src/main/java/infra/remoting/core/SendUtils.java +++ b/today-remoting/src/main/java/infra/remoting/core/SendUtils.java @@ -18,7 +18,7 @@ import java.util.function.Consumer; -import infra.remoting.DuplexConnection; +import infra.remoting.Connection; import infra.remoting.Payload; import infra.remoting.error.CanceledException; import infra.remoting.frame.CancelFrameCodec; @@ -55,7 +55,7 @@ final class SendUtils { static final Context DISCARD_CONTEXT = Operators.enableOnDiscard(null, DROPPED_ELEMENTS_CONSUMER); static void sendReleasingPayload(int streamId, FrameType frameType, int mtu, Payload payload, - DuplexConnection connection, ByteBufAllocator allocator, boolean requester) { + Connection connection, ByteBufAllocator allocator, boolean requester) { final boolean hasMetadata = payload.hasMetadata(); final ByteBuf metadata = hasMetadata ? payload.metadata() : null; @@ -148,7 +148,7 @@ static void sendReleasingPayload(int streamId, FrameType frameType, int mtu, Pay } static void sendReleasingPayload(int streamId, FrameType frameType, long initialRequestN, int mtu, - Payload payload, DuplexConnection connection, ByteBufAllocator allocator, boolean complete) { + Payload payload, Connection connection, ByteBufAllocator allocator, boolean complete) { final boolean hasMetadata = payload.hasMetadata(); final ByteBuf metadata = hasMetadata ? payload.metadata() : null; @@ -239,7 +239,7 @@ static void sendReleasingPayload(int streamId, FrameType frameType, long initial } } - static void sendTerminalFrame(int streamId, FrameType frameType, DuplexConnection connection, + static void sendTerminalFrame(int streamId, FrameType frameType, Connection connection, ByteBufAllocator allocator, boolean requester, boolean onFollowingFrame, Throwable t) { if (onFollowingFrame) { diff --git a/today-remoting/src/main/java/infra/remoting/core/ServerSetup.java b/today-remoting/src/main/java/infra/remoting/core/ServerSetup.java index c3de3ed..36a80e3 100644 --- a/today-remoting/src/main/java/infra/remoting/core/ServerSetup.java +++ b/today-remoting/src/main/java/infra/remoting/core/ServerSetup.java @@ -22,14 +22,14 @@ import java.util.function.BiFunction; import java.util.function.Function; -import infra.remoting.DuplexConnection; +import infra.remoting.Connection; import infra.remoting.ProtocolErrorException; import infra.remoting.error.RejectedResumeException; import infra.remoting.error.UnsupportedSetupException; import infra.remoting.frame.ResumeFrameCodec; import infra.remoting.frame.SetupFrameCodec; import infra.remoting.keepalive.KeepAliveHandler; -import infra.remoting.resume.ResumableDuplexConnection; +import infra.remoting.resume.ResumableConnection; import infra.remoting.resume.ResumableFramesStore; import infra.remoting.resume.ServerChannelSession; import infra.remoting.resume.SessionManager; @@ -48,23 +48,23 @@ protected ServerSetup(Duration timeout) { this.timeout = timeout; } - Mono> init(DuplexConnection connection) { - return Mono.>create(sink -> sink.onRequest(__ -> new SetupHandlingDuplexConnection(connection, sink))) + Mono> init(Connection connection) { + return Mono.>create(sink -> sink.onRequest(__ -> new SetupHandlingConnection(connection, sink))) .timeout(this.timeout) .or(connection.onClose().then(Mono.error(ClosedChannelException::new))); } abstract Mono acceptChannelSetup(ByteBuf frame, - DuplexConnection clientServerConnection, - BiFunction> then); + Connection clientServerConnection, + BiFunction> then); - abstract Mono acceptChannelResume(ByteBuf frame, DuplexConnection connection); + abstract Mono acceptChannelResume(ByteBuf frame, Connection connection); void dispose() { } - void sendError(DuplexConnection duplexConnection, ProtocolErrorException exception) { - duplexConnection.sendErrorAndClose(exception); - duplexConnection.receive().subscribe(); + void sendError(Connection connection, ProtocolErrorException exception) { + connection.sendErrorAndClose(exception); + connection.receive().subscribe(); } static class DefaultServerSetup extends ServerSetup { @@ -74,22 +74,22 @@ static class DefaultServerSetup extends ServerSetup { } @Override - public Mono acceptChannelSetup(ByteBuf frame, DuplexConnection duplexConnection, - BiFunction> then) { + public Mono acceptChannelSetup(ByteBuf frame, Connection connection, + BiFunction> then) { if (SetupFrameCodec.resumeEnabled(frame)) { - sendError(duplexConnection, new UnsupportedSetupException("resume not supported")); - return duplexConnection.onClose(); + sendError(connection, new UnsupportedSetupException("resume not supported")); + return connection.onClose(); } else { - return then.apply(new DefaultKeepAliveHandler(), duplexConnection); + return then.apply(new DefaultKeepAliveHandler(), connection); } } @Override - public Mono acceptChannelResume(ByteBuf frame, DuplexConnection duplexConnection) { - sendError(duplexConnection, new RejectedResumeException("resume not supported")); - return duplexConnection.onClose(); + public Mono acceptChannelResume(ByteBuf frame, Connection connection) { + sendError(connection, new RejectedResumeException("resume not supported")); + return connection.onClose(); } } @@ -112,21 +112,21 @@ static class ResumableServerSetup extends ServerSetup { } @Override - public Mono acceptChannelSetup(ByteBuf frame, DuplexConnection duplexConnection, - BiFunction> then) { + public Mono acceptChannelSetup(ByteBuf frame, Connection connection, + BiFunction> then) { if (SetupFrameCodec.resumeEnabled(frame)) { ByteBuf resumeToken = SetupFrameCodec.resumeToken(frame); final ResumableFramesStore resumableFramesStore = resumeStoreFactory.apply(resumeToken); - final ResumableDuplexConnection resumableDuplexConnection = - new ResumableDuplexConnection( - "server", resumeToken, duplexConnection, resumableFramesStore); + final ResumableConnection resumableConnection = + new ResumableConnection( + "server", resumeToken, connection, resumableFramesStore); final ServerChannelSession serverChannelSession = new ServerChannelSession( resumeToken, - resumableDuplexConnection, - duplexConnection, + resumableConnection, + connection, resumableFramesStore, resumeSessionDuration, cleanupStoreOnKeepAlive); @@ -134,24 +134,24 @@ public Mono acceptChannelSetup(ByteBuf frame, DuplexConnection duplexConne sessionManager.save(serverChannelSession, resumeToken); return then.apply(new ResumableKeepAliveHandler( - resumableDuplexConnection, serverChannelSession, serverChannelSession), - resumableDuplexConnection); + resumableConnection, serverChannelSession, serverChannelSession), + resumableConnection); } else { - return then.apply(new DefaultKeepAliveHandler(), duplexConnection); + return then.apply(new DefaultKeepAliveHandler(), connection); } } @Override - public Mono acceptChannelResume(ByteBuf frame, DuplexConnection duplexConnection) { + public Mono acceptChannelResume(ByteBuf frame, Connection connection) { ServerChannelSession session = sessionManager.get(ResumeFrameCodec.token(frame)); if (session != null) { - session.resumeWith(frame, duplexConnection); - return duplexConnection.onClose(); + session.resumeWith(frame, connection); + return connection.onClose(); } else { - sendError(duplexConnection, new RejectedResumeException("unknown resume token")); - return duplexConnection.onClose(); + sendError(connection, new RejectedResumeException("unknown resume token")); + return connection.onClose(); } } diff --git a/today-remoting/src/main/java/infra/remoting/core/SetupHandlingDuplexConnection.java b/today-remoting/src/main/java/infra/remoting/core/SetupHandlingConnection.java similarity index 89% rename from today-remoting/src/main/java/infra/remoting/core/SetupHandlingDuplexConnection.java rename to today-remoting/src/main/java/infra/remoting/core/SetupHandlingConnection.java index 09a2bd0..18e8789 100644 --- a/today-remoting/src/main/java/infra/remoting/core/SetupHandlingDuplexConnection.java +++ b/today-remoting/src/main/java/infra/remoting/core/SetupHandlingConnection.java @@ -22,7 +22,7 @@ import java.net.SocketAddress; import java.nio.channels.ClosedChannelException; -import infra.remoting.DuplexConnection; +import infra.remoting.Connection; import infra.remoting.ProtocolErrorException; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufAllocator; @@ -35,11 +35,11 @@ import reactor.util.function.Tuple2; import reactor.util.function.Tuples; -class SetupHandlingDuplexConnection extends Flux - implements DuplexConnection, CoreSubscriber, Subscription { +class SetupHandlingConnection extends Flux + implements Connection, CoreSubscriber, Subscription { - final DuplexConnection source; - final MonoSink> sink; + final Connection source; + final MonoSink> sink; Subscription s; boolean firstFrameReceived = false; @@ -49,8 +49,8 @@ class SetupHandlingDuplexConnection extends Flux boolean done; Throwable t; - SetupHandlingDuplexConnection( - DuplexConnection source, MonoSink> sink) { + SetupHandlingConnection( + Connection source, MonoSink> sink) { this.source = source; this.sink = sink; @@ -191,6 +191,6 @@ public ByteBufAllocator alloc() { @Override public String toString() { - return "SetupHandlingDuplexConnection{" + "source=" + source + ", done=" + done + '}'; + return "SetupHandlingConnection{" + "source=" + source + ", done=" + done + '}'; } } diff --git a/today-remoting/src/main/java/infra/remoting/frame/FrameLengthCodec.java b/today-remoting/src/main/java/infra/remoting/frame/FrameLengthCodec.java index 3d93d1d..519f5b6 100644 --- a/today-remoting/src/main/java/infra/remoting/frame/FrameLengthCodec.java +++ b/today-remoting/src/main/java/infra/remoting/frame/FrameLengthCodec.java @@ -21,7 +21,7 @@ import io.netty.buffer.ByteBufAllocator; /** - * Some transports like TCP aren't framed, and require a length. This is used by DuplexConnections + * Some transports like TCP aren't framed, and require a length. This is used by Connections * for transports that need to send length */ public class FrameLengthCodec { diff --git a/today-remoting/src/main/java/infra/remoting/frame/FrameUtil.java b/today-remoting/src/main/java/infra/remoting/frame/FrameUtil.java index f96f354..1355d4c 100644 --- a/today-remoting/src/main/java/infra/remoting/frame/FrameUtil.java +++ b/today-remoting/src/main/java/infra/remoting/frame/FrameUtil.java @@ -22,7 +22,8 @@ public class FrameUtil { - private FrameUtil() { } + private FrameUtil() { + } public static String toString(ByteBuf frame) { FrameType frameType = FrameHeaderCodec.frameType(frame); diff --git a/today-remoting/src/main/java/infra/remoting/internal/BaseDuplexConnection.java b/today-remoting/src/main/java/infra/remoting/internal/BaseConnection.java similarity index 91% rename from today-remoting/src/main/java/infra/remoting/internal/BaseDuplexConnection.java rename to today-remoting/src/main/java/infra/remoting/internal/BaseConnection.java index 28b57c7..d41871b 100644 --- a/today-remoting/src/main/java/infra/remoting/internal/BaseDuplexConnection.java +++ b/today-remoting/src/main/java/infra/remoting/internal/BaseConnection.java @@ -16,19 +16,19 @@ */ package infra.remoting.internal; -import infra.remoting.DuplexConnection; +import infra.remoting.Connection; import io.netty.buffer.ByteBuf; import reactor.core.Scannable; import reactor.core.publisher.Mono; import reactor.core.publisher.Sinks; -public abstract class BaseDuplexConnection implements DuplexConnection { +public abstract class BaseConnection implements Connection { protected final Sinks.Empty onClose = Sinks.empty(); protected final UnboundedProcessor sender = new UnboundedProcessor(onClose::tryEmitEmpty); - public BaseDuplexConnection() { + public BaseConnection() { } @Override diff --git a/today-remoting/src/main/java/infra/remoting/keepalive/KeepAliveHandler.java b/today-remoting/src/main/java/infra/remoting/keepalive/KeepAliveHandler.java index 534bfd2..9cd0658 100644 --- a/today-remoting/src/main/java/infra/remoting/keepalive/KeepAliveHandler.java +++ b/today-remoting/src/main/java/infra/remoting/keepalive/KeepAliveHandler.java @@ -21,7 +21,7 @@ import infra.remoting.keepalive.KeepAliveSupport.KeepAlive; import infra.remoting.resume.ChannelSession; -import infra.remoting.resume.ResumableDuplexConnection; +import infra.remoting.resume.ResumableConnection; import infra.remoting.resume.ResumeStateHolder; import io.netty.buffer.ByteBuf; @@ -44,15 +44,15 @@ public KeepAliveFramesAcceptor start(KeepAliveSupport keepAliveSupport, class ResumableKeepAliveHandler implements KeepAliveHandler { - private final ResumableDuplexConnection resumableDuplexConnection; + private final ResumableConnection resumableConnection; private final ChannelSession channelSession; private final ResumeStateHolder resumeStateHolder; - public ResumableKeepAliveHandler(ResumableDuplexConnection resumableDuplexConnection, + public ResumableKeepAliveHandler(ResumableConnection resumableConnection, ChannelSession channelSession, ResumeStateHolder resumeStateHolder) { - this.resumableDuplexConnection = resumableDuplexConnection; + this.resumableConnection = resumableConnection; this.channelSession = channelSession; this.resumeStateHolder = resumeStateHolder; } @@ -65,7 +65,7 @@ public KeepAliveFramesAcceptor start(KeepAliveSupport keepAliveSupport, return keepAliveSupport .resumeState(resumeStateHolder) .onSendKeepAliveFrame(onSendKeepAliveFrame) - .onTimeout(keepAlive -> resumableDuplexConnection.disconnect()) + .onTimeout(keepAlive -> resumableConnection.disconnect()) .start(); } } diff --git a/today-remoting/src/main/java/infra/remoting/plugins/ConnectionDecorator.java b/today-remoting/src/main/java/infra/remoting/plugins/ConnectionDecorator.java index a2857c6..83fb404 100644 --- a/today-remoting/src/main/java/infra/remoting/plugins/ConnectionDecorator.java +++ b/today-remoting/src/main/java/infra/remoting/plugins/ConnectionDecorator.java @@ -17,10 +17,10 @@ package infra.remoting.plugins; -import infra.remoting.DuplexConnection; +import infra.remoting.Connection; /** - * Contract to decorate a {@link DuplexConnection} and intercept the sending and receiving of + * Contract to decorate a {@link Connection} and intercept the sending and receiving of * protocol frames at the transport level. */ @FunctionalInterface @@ -32,6 +32,6 @@ enum Type { SOURCE } - DuplexConnection decorate(Type type, DuplexConnection connection); + Connection decorate(Type type, Connection connection); } diff --git a/today-remoting/src/main/java/infra/remoting/plugins/InitializingInterceptorRegistry.java b/today-remoting/src/main/java/infra/remoting/plugins/InitializingInterceptorRegistry.java index 15419fc..9120097 100644 --- a/today-remoting/src/main/java/infra/remoting/plugins/InitializingInterceptorRegistry.java +++ b/today-remoting/src/main/java/infra/remoting/plugins/InitializingInterceptorRegistry.java @@ -22,7 +22,7 @@ import infra.lang.Nullable; import infra.remoting.Channel; import infra.remoting.ChannelAcceptor; -import infra.remoting.DuplexConnection; +import infra.remoting.Connection; /** * Extends {@link InterceptorRegistry} with methods for building a chain of registered interceptors. @@ -47,7 +47,7 @@ public RequestInterceptor initResponderRequestInterceptor(Channel channelRespond .collect(Collectors.toList())); } - public DuplexConnection initConnection(ConnectionDecorator.Type type, DuplexConnection connection) { + public Connection initConnection(ConnectionDecorator.Type type, Connection connection) { for (ConnectionDecorator interceptor : connectionDecorators) { connection = interceptor.decorate(type, connection); } diff --git a/today-remoting/src/main/java/infra/remoting/resume/ClientChannelSession.java b/today-remoting/src/main/java/infra/remoting/resume/ClientChannelSession.java index ef92fb8..6850a37 100644 --- a/today-remoting/src/main/java/infra/remoting/resume/ClientChannelSession.java +++ b/today-remoting/src/main/java/infra/remoting/resume/ClientChannelSession.java @@ -25,7 +25,7 @@ import infra.logging.Logger; import infra.logging.LoggerFactory; -import infra.remoting.DuplexConnection; +import infra.remoting.Connection; import infra.remoting.error.ConnectionErrorException; import infra.remoting.error.Exceptions; import infra.remoting.error.RejectedResumeException; @@ -45,12 +45,12 @@ import reactor.util.retry.Retry; public class ClientChannelSession implements ChannelSession, ResumeStateHolder, - CoreSubscriber> { + CoreSubscriber> { private static final Logger logger = LoggerFactory.getLogger(ClientChannelSession.class); - final ResumableDuplexConnection resumableConnection; - final Mono> connectionFactory; + final ResumableConnection resumableConnection; + final Mono> connectionFactory; final ResumableFramesStore resumableFramesStore; final ByteBufAllocator allocator; @@ -69,9 +69,9 @@ public class ClientChannelSession implements ChannelSession, ResumeStateHolder, public ClientChannelSession( ByteBuf resumeToken, - ResumableDuplexConnection resumableDuplexConnection, - Mono connectionFactory, - Function>> connectionTransformer, + ResumableConnection resumableConnection, + Mono connectionFactory, + Function>> connectionTransformer, ResumableFramesStore resumableFramesStore, Duration resumeSessionDuration, Retry retry, @@ -81,7 +81,7 @@ public ClientChannelSession( this.connectionFactory = connectionFactory .doOnDiscard( - DuplexConnection.class, + Connection.class, c -> { final ConnectionErrorException connectionErrorException = new ConnectionErrorException("resumption_server=[Session Expired]"); @@ -115,16 +115,16 @@ public ClientChannelSession( }) .doOnDiscard(Tuple2.class, this::tryReestablishSession); this.resumableFramesStore = resumableFramesStore; - this.allocator = resumableDuplexConnection.alloc(); + this.allocator = resumableConnection.alloc(); this.resumeSessionDuration = resumeSessionDuration; this.retry = retry; this.cleanupStoreOnKeepAlive = cleanupStoreOnKeepAlive; - this.resumableConnection = resumableDuplexConnection; + this.resumableConnection = resumableConnection; - resumableDuplexConnection.onClose().doFinally(__ -> dispose()).subscribe(); + resumableConnection.onClose().doFinally(__ -> dispose()).subscribe(); this.reconnectDisposable = - resumableDuplexConnection.onActiveConnectionClosed().subscribe(this::reconnect); + resumableConnection.onActiveConnectionClosed().subscribe(this::reconnect); } void reconnect(int index) { @@ -196,12 +196,12 @@ public boolean isDisposed() { return resumableConnection.isDisposed(); } - void tryReestablishSession(Tuple2 tuple2) { + void tryReestablishSession(Tuple2 tuple2) { if (logger.isDebugEnabled()) { logger.debug("Active subscription is canceled {}", s == Operators.cancelledSubscription()); } ByteBuf shouldBeResumeOKFrame = tuple2.getT1(); - DuplexConnection nextDuplexConnection = tuple2.getT2(); + Connection nextConnection = tuple2.getT2(); final int streamId = FrameHeaderCodec.streamId(shouldBeResumeOKFrame); if (streamId != 0) { @@ -212,9 +212,9 @@ void tryReestablishSession(Tuple2 tuple2) { } final ConnectionErrorException connectionErrorException = new ConnectionErrorException("RESUME_OK frame must be received before any others"); - resumableConnection.dispose(nextDuplexConnection, connectionErrorException); - nextDuplexConnection.sendErrorAndClose(connectionErrorException); - nextDuplexConnection.receive().subscribe(); + resumableConnection.dispose(nextConnection, connectionErrorException); + nextConnection.sendErrorAndClose(connectionErrorException); + nextConnection.receive().subscribe(); throw connectionErrorException; // throw to retry connection again } @@ -251,10 +251,10 @@ void tryReestablishSession(Tuple2 tuple2) { } final ConnectionErrorException t = new ConnectionErrorException(e.getMessage(), e); - resumableConnection.dispose(nextDuplexConnection, t); + resumableConnection.dispose(nextConnection, t); - nextDuplexConnection.sendErrorAndClose(t); - nextDuplexConnection.receive().subscribe(); + nextConnection.sendErrorAndClose(t); + nextConnection.receive().subscribe(); return; } @@ -267,8 +267,8 @@ void tryReestablishSession(Tuple2 tuple2) { } final ConnectionErrorException connectionErrorException = new ConnectionErrorException("resumption_server=[Session Expired]"); - nextDuplexConnection.sendErrorAndClose(connectionErrorException); - nextDuplexConnection.receive().subscribe(); + nextConnection.sendErrorAndClose(connectionErrorException); + nextConnection.receive().subscribe(); return; } @@ -278,7 +278,7 @@ void tryReestablishSession(Tuple2 tuple2) { logger.debug("Side[client]|Session[{}]. Session has been resumed successfully", session); } - if (!resumableConnection.connect(nextDuplexConnection)) { + if (!resumableConnection.connect(nextConnection)) { if (logger.isDebugEnabled()) { logger.debug( "Side[client]|Session[{}]. Session has already been expired. Terminating received connection", @@ -286,8 +286,8 @@ void tryReestablishSession(Tuple2 tuple2) { } final ConnectionErrorException connectionErrorException = new ConnectionErrorException("resumption_server_pos=[Session Expired]"); - nextDuplexConnection.sendErrorAndClose(connectionErrorException); - nextDuplexConnection.receive().subscribe(); + nextConnection.sendErrorAndClose(connectionErrorException); + nextConnection.receive().subscribe(); // no need to do anything since connection resumable connection is liklly to // be disposed } @@ -303,10 +303,10 @@ void tryReestablishSession(Tuple2 tuple2) { final ConnectionErrorException connectionErrorException = new ConnectionErrorException("resumption_server_pos=[" + remoteImpliedPos + "]"); - resumableConnection.dispose(nextDuplexConnection, connectionErrorException); + resumableConnection.dispose(nextConnection, connectionErrorException); - nextDuplexConnection.sendErrorAndClose(connectionErrorException); - nextDuplexConnection.receive().subscribe(); + nextConnection.sendErrorAndClose(connectionErrorException); + nextConnection.receive().subscribe(); } } else if (frameType == FrameType.ERROR) { @@ -318,14 +318,14 @@ else if (frameType == FrameType.ERROR) { exception); } if (exception instanceof RejectedResumeException) { - resumableConnection.dispose(nextDuplexConnection, exception); - nextDuplexConnection.dispose(); - nextDuplexConnection.receive().subscribe(); + resumableConnection.dispose(nextConnection, exception); + nextConnection.dispose(); + nextConnection.receive().subscribe(); return; } - nextDuplexConnection.dispose(); - nextDuplexConnection.receive().subscribe(); + nextConnection.dispose(); + nextConnection.receive().subscribe(); throw exception; // assume retryable exception } else { @@ -337,10 +337,10 @@ else if (frameType == FrameType.ERROR) { final ConnectionErrorException connectionErrorException = new ConnectionErrorException("RESUME_OK frame must be received before any others"); - resumableConnection.dispose(nextDuplexConnection, connectionErrorException); + resumableConnection.dispose(nextConnection, connectionErrorException); - nextDuplexConnection.sendErrorAndClose(connectionErrorException); - nextDuplexConnection.receive().subscribe(); + nextConnection.sendErrorAndClose(connectionErrorException); + nextConnection.receive().subscribe(); // no need to do anything since remote server rejected our connection completely } @@ -369,7 +369,7 @@ public void onSubscribe(Subscription s) { } @Override - public void onNext(Tuple2 objects) { } + public void onNext(Tuple2 objects) { } @Override public void onError(Throwable t) { diff --git a/today-remoting/src/main/java/infra/remoting/resume/InMemoryResumableFramesStore.java b/today-remoting/src/main/java/infra/remoting/resume/InMemoryResumableFramesStore.java index 2cef98b..d9a3f0a 100644 --- a/today-remoting/src/main/java/infra/remoting/resume/InMemoryResumableFramesStore.java +++ b/today-remoting/src/main/java/infra/remoting/resume/InMemoryResumableFramesStore.java @@ -37,7 +37,7 @@ import reactor.core.publisher.Operators; import reactor.core.publisher.Sinks; -import static infra.remoting.resume.ResumableDuplexConnection.isResumableFrame; +import static infra.remoting.resume.ResumableConnection.isResumableFrame; /** * writes - n (where n is frequent, primary operation) reads - m (where m == KeepAliveFrequency) diff --git a/today-remoting/src/main/java/infra/remoting/resume/ResumableDuplexConnection.java b/today-remoting/src/main/java/infra/remoting/resume/ResumableConnection.java similarity index 89% rename from today-remoting/src/main/java/infra/remoting/resume/ResumableDuplexConnection.java rename to today-remoting/src/main/java/infra/remoting/resume/ResumableConnection.java index fc691fa..6000294 100644 --- a/today-remoting/src/main/java/infra/remoting/resume/ResumableDuplexConnection.java +++ b/today-remoting/src/main/java/infra/remoting/resume/ResumableConnection.java @@ -26,7 +26,7 @@ import infra.lang.Nullable; import infra.logging.Logger; import infra.logging.LoggerFactory; -import infra.remoting.DuplexConnection; +import infra.remoting.Connection; import infra.remoting.ProtocolErrorException; import infra.remoting.error.ConnectionErrorException; import infra.remoting.frame.ErrorFrameCodec; @@ -43,10 +43,10 @@ import reactor.core.publisher.Operators; import reactor.core.publisher.Sinks; -public class ResumableDuplexConnection extends Flux - implements DuplexConnection, Subscription { +public class ResumableConnection extends Flux + implements Connection, Subscription { - static final Logger logger = LoggerFactory.getLogger(ResumableDuplexConnection.class); + static final Logger logger = LoggerFactory.getLogger(ResumableConnection.class); final String side; final String session; @@ -62,21 +62,21 @@ public class ResumableDuplexConnection extends Flux FrameReceivingSubscriber activeReceivingSubscriber; volatile int state; - static final AtomicIntegerFieldUpdater STATE = - AtomicIntegerFieldUpdater.newUpdater(ResumableDuplexConnection.class, "state"); + static final AtomicIntegerFieldUpdater STATE = + AtomicIntegerFieldUpdater.newUpdater(ResumableConnection.class, "state"); - volatile DuplexConnection activeConnection; - static final AtomicReferenceFieldUpdater + volatile Connection activeConnection; + static final AtomicReferenceFieldUpdater ACTIVE_CONNECTION = AtomicReferenceFieldUpdater.newUpdater( - ResumableDuplexConnection.class, DuplexConnection.class, "activeConnection"); + ResumableConnection.class, Connection.class, "activeConnection"); int connectionIndex = 0; - public ResumableDuplexConnection( + public ResumableConnection( String side, ByteBuf session, - DuplexConnection initialConnection, + Connection initialConnection, ResumableFramesStore resumableFramesStore) { this.side = side; this.session = session.toString(CharsetUtil.UTF_8); @@ -92,8 +92,8 @@ public ResumableDuplexConnection( ACTIVE_CONNECTION.lazySet(this, initialConnection); } - public boolean connect(DuplexConnection nextConnection) { - final DuplexConnection activeConnection = this.activeConnection; + public boolean connect(Connection nextConnection) { + final Connection activeConnection = this.activeConnection; if (activeConnection != DisposedConnection.INSTANCE && ACTIVE_CONNECTION.compareAndSet(this, activeConnection, nextConnection)) { @@ -111,7 +111,7 @@ public boolean connect(DuplexConnection nextConnection) { } } - void initConnection(DuplexConnection nextConnection) { + void initConnection(Connection nextConnection) { final int nextConnectionIndex = this.connectionIndex + 1; final FrameReceivingSubscriber frameReceivingSubscriber = new FrameReceivingSubscriber(side, resumableFramesStore, receiveSubscriber); @@ -121,7 +121,7 @@ void initConnection(DuplexConnection nextConnection) { if (logger.isDebugEnabled()) { logger.debug( - "Side[{}]|Session[{}]|DuplexConnection[{}]. Connecting", side, session, connectionIndex); + "Side[{}]|Session[{}]|Connection[{}]. Connecting", side, session, connectionIndex); } final Disposable resumeStreamSubscription = @@ -148,7 +148,7 @@ void initConnection(DuplexConnection nextConnection) { resumeStreamSubscription.dispose(); if (logger.isDebugEnabled()) { logger.debug( - "Side[{}]|Session[{}]|DuplexConnection[{}]. Disconnected", + "Side[{}]|Session[{}]|Connection[{}]. Disconnected", side, session, connectionIndex); @@ -156,7 +156,7 @@ void initConnection(DuplexConnection nextConnection) { Sinks.EmitResult result = onConnectionClosedSink.tryEmitNext(nextConnectionIndex); if (!result.equals(Sinks.EmitResult.OK)) { logger.error( - "Side[{}]|Session[{}]|DuplexConnection[{}]. Failed to notify session of closed connection: {}", + "Side[{}]|Session[{}]|Connection[{}]. Failed to notify session of closed connection: {}", side, session, connectionIndex, @@ -167,7 +167,7 @@ void initConnection(DuplexConnection nextConnection) { } public void disconnect() { - final DuplexConnection activeConnection = this.activeConnection; + final Connection activeConnection = this.activeConnection; if (activeConnection != DisposedConnection.INSTANCE && !activeConnection.isDisposed()) { activeConnection.dispose(); } @@ -194,7 +194,7 @@ Flux onActiveConnectionClosed() { @Override public void sendErrorAndClose(ProtocolErrorException exception) { - final DuplexConnection activeConnection = + final Connection activeConnection = ACTIVE_CONNECTION.getAndSet(this, DisposedConnection.INSTANCE); if (activeConnection == DisposedConnection.INSTANCE) { return; @@ -242,7 +242,7 @@ public Mono onClose() { @Override public void dispose() { - final DuplexConnection activeConnection = + final Connection activeConnection = ACTIVE_CONNECTION.getAndSet(this, DisposedConnection.INSTANCE); if (activeConnection == DisposedConnection.INSTANCE) { return; @@ -262,8 +262,8 @@ public void dispose() { }); } - void dispose(DuplexConnection nextConnection, @Nullable Throwable e) { - final DuplexConnection activeConnection = + void dispose(Connection nextConnection, @Nullable Throwable e) { + final Connection activeConnection = ACTIVE_CONNECTION.getAndSet(this, DisposedConnection.INSTANCE); if (activeConnection == DisposedConnection.INSTANCE) { return; @@ -332,7 +332,7 @@ static boolean isResumableFrame(ByteBuf frame) { @Override public String toString() { - return "ResumableDuplexConnection{" + return "ResumableConnection{" + "side='" + side + '\'' @@ -350,7 +350,7 @@ public String toString() { + '}'; } - private static final class DisposedConnection implements DuplexConnection { + private static final class DisposedConnection implements Connection { static final DisposedConnection INSTANCE = new DisposedConnection(); diff --git a/today-remoting/src/main/java/infra/remoting/resume/ServerChannelSession.java b/today-remoting/src/main/java/infra/remoting/resume/ServerChannelSession.java index 4973353..a3c2d25 100644 --- a/today-remoting/src/main/java/infra/remoting/resume/ServerChannelSession.java +++ b/today-remoting/src/main/java/infra/remoting/resume/ServerChannelSession.java @@ -26,7 +26,7 @@ import infra.logging.Logger; import infra.logging.LoggerFactory; -import infra.remoting.DuplexConnection; +import infra.remoting.Connection; import infra.remoting.error.ConnectionErrorException; import infra.remoting.error.RejectedResumeException; import infra.remoting.frame.ResumeFrameCodec; @@ -44,7 +44,7 @@ public class ServerChannelSession implements ChannelSession, ResumeStateHolder, private static final Logger logger = LoggerFactory.getLogger(ServerChannelSession.class); - final ResumableDuplexConnection resumableConnection; + final ResumableConnection resumableConnection; final Duration resumeSessionDuration; final ResumableFramesStore resumableFramesStore; final String session; @@ -69,23 +69,23 @@ public class ServerChannelSession implements ChannelSession, ResumeStateHolder, KeepAliveSupport keepAliveSupport; public ServerChannelSession(ByteBuf session, - ResumableDuplexConnection resumableDuplexConnection, - DuplexConnection initialDuplexConnection, + ResumableConnection resumableConnection, + Connection initialConnection, ResumableFramesStore resumableFramesStore, Duration resumeSessionDuration, boolean cleanupStoreOnKeepAlive) { this.session = session.toString(CharsetUtil.UTF_8); - this.allocator = initialDuplexConnection.alloc(); + this.allocator = initialConnection.alloc(); this.resumeSessionDuration = resumeSessionDuration; this.resumableFramesStore = resumableFramesStore; this.cleanupStoreOnKeepAlive = cleanupStoreOnKeepAlive; - this.resumableConnection = resumableDuplexConnection; + this.resumableConnection = resumableConnection; this.connectionsQueue = Queues.unboundedMultiproducer().get(); WIP.lazySet(this, 1); - resumableDuplexConnection.onClose().doFinally(__ -> dispose()).subscribe(); - resumableDuplexConnection.onActiveConnectionClosed().subscribe(__ -> tryTimeoutSession()); + resumableConnection.onClose().doFinally(__ -> dispose()).subscribe(); + resumableConnection.onActiveConnectionClosed().subscribe(__ -> tryTimeoutSession()); } void tryTimeoutSession() { @@ -109,16 +109,16 @@ void tryTimeoutSession() { } } - public void resumeWith(ByteBuf resumeFrame, DuplexConnection nextDuplexConnection) { + public void resumeWith(ByteBuf resumeFrame, Connection nextConnection) { if (logger.isDebugEnabled()) { - logger.debug("Side[server]|Session[{}]. New DuplexConnection received.", session); + logger.debug("Side[server]|Session[{}]. New Connection received.", session); } long remotePos = ResumeFrameCodec.firstAvailableClientPos(resumeFrame); long remoteImpliedPos = ResumeFrameCodec.lastReceivedServerPos(resumeFrame); - connectionsQueue.offer(() -> doResume(remotePos, remoteImpliedPos, nextDuplexConnection)); + connectionsQueue.offer(() -> doResume(remotePos, remoteImpliedPos, nextConnection)); if (WIP.getAndIncrement(this) != 0) { return; @@ -130,7 +130,7 @@ public void resumeWith(ByteBuf resumeFrame, DuplexConnection nextDuplexConnectio } } - void doResume(long remotePos, long remoteImpliedPos, DuplexConnection nextDuplexConnection) { + void doResume(long remotePos, long remoteImpliedPos, Connection nextConnection) { if (!tryCancelSessionTimeout()) { if (logger.isDebugEnabled()) { logger.debug( @@ -139,8 +139,8 @@ void doResume(long remotePos, long remoteImpliedPos, DuplexConnection nextDuplex } final RejectedResumeException rejectedResumeException = new RejectedResumeException("resume_internal_error: Session Expired"); - nextDuplexConnection.sendErrorAndClose(rejectedResumeException); - nextDuplexConnection.receive().subscribe(); + nextConnection.sendErrorAndClose(rejectedResumeException); + nextConnection.receive().subscribe(); return; } @@ -162,7 +162,7 @@ void doResume(long remotePos, long remoteImpliedPos, DuplexConnection nextDuplex if (position != remoteImpliedPos) { resumableFramesStore.releaseFrames(remoteImpliedPos); } - nextDuplexConnection.sendFrame(0, ResumeOkFrameCodec.encode(allocator, impliedPosition)); + nextConnection.sendFrame(0, ResumeOkFrameCodec.encode(allocator, impliedPosition)); if (logger.isDebugEnabled()) { logger.debug( "Side[server]|Session[{}]. ResumeOKFrame[impliedPosition[{}]] has been sent", @@ -182,8 +182,8 @@ void doResume(long remotePos, long remoteImpliedPos, DuplexConnection nextDuplex final RejectedResumeException rejectedResumeException = new RejectedResumeException(t.getMessage(), t); - nextDuplexConnection.sendErrorAndClose(rejectedResumeException); - nextDuplexConnection.receive().subscribe(); + nextConnection.sendErrorAndClose(rejectedResumeException); + nextConnection.receive().subscribe(); return; } @@ -194,7 +194,7 @@ void doResume(long remotePos, long remoteImpliedPos, DuplexConnection nextDuplex logger.debug("Side[server]|Session[{}]. Session has been resumed successfully", session); } - if (!resumableConnection.connect(nextDuplexConnection)) { + if (!resumableConnection.connect(nextConnection)) { if (logger.isDebugEnabled()) { logger.debug( "Side[server]|Session[{}]. Session has already been expired. Terminating received connection", @@ -202,8 +202,8 @@ void doResume(long remotePos, long remoteImpliedPos, DuplexConnection nextDuplex } final RejectedResumeException rejectedResumeException = new RejectedResumeException("resume_internal_error: Session Expired"); - nextDuplexConnection.sendErrorAndClose(rejectedResumeException); - nextDuplexConnection.receive().subscribe(); + nextConnection.sendErrorAndClose(rejectedResumeException); + nextConnection.receive().subscribe(); // resumableConnection is likely to be disposed at this stage. Thus we have // nothing to do @@ -227,8 +227,8 @@ void doResume(long remotePos, long remoteImpliedPos, DuplexConnection nextDuplex String.format( "resumption_pos=[ remote: { pos: %d, impliedPos: %d }, local: { pos: %d, impliedPos: %d }]", remotePos, remoteImpliedPos, position, impliedPosition)); - nextDuplexConnection.sendErrorAndClose(rejectedResumeException); - nextDuplexConnection.receive().subscribe(); + nextConnection.sendErrorAndClose(rejectedResumeException); + nextConnection.receive().subscribe(); } } diff --git a/today-remoting/src/main/java/infra/remoting/transport/ClientTransport.java b/today-remoting/src/main/java/infra/remoting/transport/ClientTransport.java index b792612..2514397 100644 --- a/today-remoting/src/main/java/infra/remoting/transport/ClientTransport.java +++ b/today-remoting/src/main/java/infra/remoting/transport/ClientTransport.java @@ -17,7 +17,7 @@ package infra.remoting.transport; -import infra.remoting.DuplexConnection; +import infra.remoting.Connection; import reactor.core.publisher.Mono; /** A client contract for writing transports of protocol. */ @@ -26,6 +26,6 @@ public interface ClientTransport extends Transport { /** * Return a {@code Mono} that connects for each subscriber. */ - Mono connect(); + Mono connect(); } diff --git a/today-remoting/src/main/java/infra/remoting/transport/ConnectionAcceptor.java b/today-remoting/src/main/java/infra/remoting/transport/ConnectionAcceptor.java index dec92a8..52af3ef 100644 --- a/today-remoting/src/main/java/infra/remoting/transport/ConnectionAcceptor.java +++ b/today-remoting/src/main/java/infra/remoting/transport/ConnectionAcceptor.java @@ -17,11 +17,11 @@ package infra.remoting.transport; -import infra.remoting.DuplexConnection; +import infra.remoting.Connection; import reactor.core.publisher.Mono; /** - * A contract to accept a new {@code DuplexConnection}. + * A contract to accept a new {@code Connection}. * * @author 海子 Yang * @since 1.0 2025/8/2 22:06 @@ -29,12 +29,12 @@ public interface ConnectionAcceptor { /** - * Accept a new {@code DuplexConnection} and returns {@code Publisher} signifying the end of + * Accept a new {@code Connection} and returns {@code Publisher} signifying the end of * processing of the connection. * - * @param connection New {@code DuplexConnection} to be processed. + * @param connection New {@code Connection} to be processed. * @return A {@code Publisher} which terminates when the processing of the connection finishes. */ - Mono accept(DuplexConnection connection); + Mono accept(Connection connection); } diff --git a/today-remoting/src/main/java/infra/remoting/transport/Transport.java b/today-remoting/src/main/java/infra/remoting/transport/Transport.java index 2dcc0b2..f79bf60 100644 --- a/today-remoting/src/main/java/infra/remoting/transport/Transport.java +++ b/today-remoting/src/main/java/infra/remoting/transport/Transport.java @@ -17,14 +17,14 @@ package infra.remoting.transport; -import infra.remoting.DuplexConnection; +import infra.remoting.Connection; import static infra.remoting.frame.FrameLengthCodec.FRAME_LENGTH_MASK; public interface Transport { /** - * Configurations that exposes the maximum frame size that a {@link DuplexConnection} can bring up. + * Configurations that exposes the maximum frame size that a {@link Connection} can bring up. * *

      This number should not exist the 16,777,215 (maximum frame size specified by protocol spec) * diff --git a/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/tcp/PromiseAdapter.java b/today-remoting/src/main/java/infra/remoting/util/PromiseAdapter.java similarity index 97% rename from today-remoting-transport-tcp/src/main/java/infra/remoting/transport/tcp/PromiseAdapter.java rename to today-remoting/src/main/java/infra/remoting/util/PromiseAdapter.java index 5aa5a93..b9d83c2 100644 --- a/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/tcp/PromiseAdapter.java +++ b/today-remoting/src/main/java/infra/remoting/util/PromiseAdapter.java @@ -15,7 +15,7 @@ * along with this program. If not, see [http://www.gnu.org/licenses/] */ -package infra.remoting.transport.tcp; +package infra.remoting.util; import infra.util.concurrent.Future; import infra.util.concurrent.Promise; diff --git a/today-remoting/src/test/java/infra/remoting/core/AbstractChannelRule.java b/today-remoting/src/test/java/infra/remoting/core/AbstractChannelRule.java index 5b9c3ca..fae89cd 100644 --- a/today-remoting/src/test/java/infra/remoting/core/AbstractChannelRule.java +++ b/today-remoting/src/test/java/infra/remoting/core/AbstractChannelRule.java @@ -24,14 +24,14 @@ import io.netty.buffer.ByteBufAllocator; import infra.remoting.Channel; import infra.remoting.buffer.LeaksTrackingByteBufAllocator; -import infra.remoting.test.util.TestDuplexConnection; +import infra.remoting.test.util.TestConnection; import infra.remoting.test.util.TestSubscriber; import static infra.remoting.frame.FrameLengthCodec.FRAME_LENGTH_MASK; public abstract class AbstractChannelRule { - protected TestDuplexConnection connection; + protected TestConnection connection; protected Subscriber connectSub; protected T channel; protected LeaksTrackingByteBufAllocator allocator; @@ -53,7 +53,7 @@ protected void doInit() { if (channel != null) { channel.dispose(); } - connection = new TestDuplexConnection(allocator); + connection = new TestConnection(allocator); channel = newChannel(); } diff --git a/today-remoting/src/test/java/infra/remoting/core/ChannelConnectorTests.java b/today-remoting/src/test/java/infra/remoting/core/ChannelConnectorTests.java index 3005e34..60577e9 100644 --- a/today-remoting/src/test/java/infra/remoting/core/ChannelConnectorTests.java +++ b/today-remoting/src/test/java/infra/remoting/core/ChannelConnectorTests.java @@ -38,7 +38,7 @@ import infra.remoting.frame.KeepAliveFrameCodec; import infra.remoting.frame.RequestResponseFrameCodec; import infra.remoting.test.util.TestClientTransport; -import infra.remoting.test.util.TestDuplexConnection; +import infra.remoting.test.util.TestConnection; import infra.remoting.util.ByteBufPayload; import reactor.core.publisher.Mono; import reactor.test.StepVerifier; @@ -58,7 +58,7 @@ public void unexpectedFramesBeforeResumeOKFrame(String frameType) { .connect(transport) .block(); - final TestDuplexConnection duplexConnection = transport.testConnection(); + final TestConnection duplexConnection = transport.testConnection(); duplexConnection.addToReceivedBuffer( KeepAliveFrameCodec.encode(duplexConnection.alloc(), false, 1, Unpooled.EMPTY_BUFFER)); @@ -71,7 +71,7 @@ public void unexpectedFramesBeforeResumeOKFrame(String frameType) { duplexConnection.dispose(); - final TestDuplexConnection duplexConnection2 = transport.testConnection(); + final TestConnection duplexConnection2 = transport.testConnection(); final ByteBuf frame; switch (frameType) { diff --git a/today-remoting/src/test/java/infra/remoting/core/ChannelLeaseTests.java b/today-remoting/src/test/java/infra/remoting/core/ChannelLeaseTests.java index 2b3b71d..b7e0304 100644 --- a/today-remoting/src/test/java/infra/remoting/core/ChannelLeaseTests.java +++ b/today-remoting/src/test/java/infra/remoting/core/ChannelLeaseTests.java @@ -60,7 +60,7 @@ import infra.remoting.lease.MissingLeaseException; import infra.remoting.plugins.InitializingInterceptorRegistry; import infra.remoting.test.util.TestClientTransport; -import infra.remoting.test.util.TestDuplexConnection; +import infra.remoting.test.util.TestConnection; import infra.remoting.test.util.TestServerTransport; import infra.remoting.util.ByteBufPayload; import infra.remoting.util.DefaultPayload; @@ -89,7 +89,7 @@ class ChannelLeaseTests { private Channel channelRequester; private ResponderLeaseTracker responderLeaseTracker; private LeaksTrackingByteBufAllocator byteBufAllocator; - private TestDuplexConnection connection; + private TestConnection connection; private ResponderChannel responderChannel; private Channel mockChannelHandler; @@ -103,7 +103,7 @@ void setUp() { PayloadDecoder payloadDecoder = PayloadDecoder.DEFAULT; byteBufAllocator = LeaksTrackingByteBufAllocator.instrument(ByteBufAllocator.DEFAULT); - connection = new TestDuplexConnection(byteBufAllocator); + connection = new TestConnection(byteBufAllocator); requesterLeaseTracker = new RequesterLeaseTracker(TAG, 0); responderLeaseTracker = new ResponderLeaseTracker(TAG, connection, () -> leaseSender.asFlux()); this.thisClosedSink = Sinks.empty(); @@ -217,7 +217,7 @@ public void serverChannelFactoryRejectsUnsupportedLease() { TestServerTransport transport = new TestServerTransport(); RemotingServer.create().bind(transport).block(); - TestDuplexConnection connection = transport.connect(); + TestConnection connection = transport.connect(); connection.addToReceivedBuffer(setupFrame); Collection sent = connection.getSent(); diff --git a/today-remoting/src/test/java/infra/remoting/core/ChannelReconnectTests.java b/today-remoting/src/test/java/infra/remoting/core/ChannelReconnectTests.java index 4bfa859..d66187a 100644 --- a/today-remoting/src/test/java/infra/remoting/core/ChannelReconnectTests.java +++ b/today-remoting/src/test/java/infra/remoting/core/ChannelReconnectTests.java @@ -31,7 +31,7 @@ import infra.remoting.Channel; import infra.remoting.frame.FrameType; import infra.remoting.test.util.TestClientTransport; -import infra.remoting.test.util.TestDuplexConnection; +import infra.remoting.test.util.TestConnection; import infra.remoting.transport.ClientTransport; import reactor.core.Exceptions; import reactor.core.publisher.Mono; @@ -164,7 +164,7 @@ public void shouldBeNotBeASharedReconnectableInstanceOfChannelMono() { Mono channelMono = ChannelConnector.connectWith(transport); Channel channel1 = channelMono.block(); - TestDuplexConnection connection1 = transport.testConnection(); + TestConnection connection1 = transport.testConnection(); FrameAssert.assertThat(connection1.awaitFrame()) .typeOf(FrameType.SETUP) @@ -172,7 +172,7 @@ public void shouldBeNotBeASharedReconnectableInstanceOfChannelMono() { .hasNoLeaks(); Channel channel2 = channelMono.block(); - TestDuplexConnection connection2 = transport.testConnection(); + TestConnection connection2 = transport.testConnection(); assertThat(channel1).isNotEqualTo(channel2); diff --git a/today-remoting/src/test/java/infra/remoting/core/ChannelTests.java b/today-remoting/src/test/java/infra/remoting/core/ChannelTests.java index 2e9c966..c5a8b9e 100644 --- a/today-remoting/src/test/java/infra/remoting/core/ChannelTests.java +++ b/today-remoting/src/test/java/infra/remoting/core/ChannelTests.java @@ -38,7 +38,7 @@ import infra.remoting.error.CustomProtocolException; import infra.remoting.frame.decoder.PayloadDecoder; import infra.remoting.internal.subscriber.AssertSubscriber; -import infra.remoting.test.util.LocalDuplexConnection; +import infra.remoting.test.util.LocalConnection; import infra.remoting.util.DefaultPayload; import infra.remoting.util.EmptyPayload; import reactor.core.Disposable; @@ -533,10 +533,10 @@ public void init() { this.thisClosedSink = Sinks.empty(); this.otherClosedSink = Sinks.empty(); - LocalDuplexConnection serverConnection = - new LocalDuplexConnection("server", allocator, clientProcessor, serverProcessor); - LocalDuplexConnection clientConnection = - new LocalDuplexConnection("client", allocator, serverProcessor, clientProcessor); + LocalConnection serverConnection = + new LocalConnection("server", allocator, clientProcessor, serverProcessor); + LocalConnection clientConnection = + new LocalConnection("client", allocator, serverProcessor, clientProcessor); clientConnection.onClose().doFinally(__ -> serverConnection.dispose()).subscribe(); serverConnection.onClose().doFinally(__ -> clientConnection.dispose()).subscribe(); diff --git a/today-remoting/src/test/java/infra/remoting/core/ClientServerInputMultiplexerTest.java b/today-remoting/src/test/java/infra/remoting/core/ClientServerInputMultiplexerTest.java index e46b68e..f0e2634 100644 --- a/today-remoting/src/test/java/infra/remoting/core/ClientServerInputMultiplexerTest.java +++ b/today-remoting/src/test/java/infra/remoting/core/ClientServerInputMultiplexerTest.java @@ -31,12 +31,12 @@ import infra.remoting.frame.LeaseFrameCodec; import infra.remoting.frame.MetadataPushFrameCodec; import infra.remoting.plugins.InitializingInterceptorRegistry; -import infra.remoting.test.util.TestDuplexConnection; +import infra.remoting.test.util.TestConnection; import static org.assertj.core.api.Assertions.assertThat; public class ClientServerInputMultiplexerTest { - private TestDuplexConnection source; + private TestConnection source; private ClientServerInputMultiplexer clientMultiplexer; private LeaksTrackingByteBufAllocator allocator = LeaksTrackingByteBufAllocator.instrument(ByteBufAllocator.DEFAULT); @@ -44,7 +44,7 @@ public class ClientServerInputMultiplexerTest { @BeforeEach public void setup() { - source = new TestDuplexConnection(allocator); + source = new TestConnection(allocator); clientMultiplexer = new ClientServerInputMultiplexer(source, new InitializingInterceptorRegistry(), true); serverMultiplexer = diff --git a/today-remoting/src/test/java/infra/remoting/core/DefaultChannelClientTests.java b/today-remoting/src/test/java/infra/remoting/core/DefaultChannelClientTests.java index 7c32762..7b29a77 100644 --- a/today-remoting/src/test/java/infra/remoting/core/DefaultChannelClientTests.java +++ b/today-remoting/src/test/java/infra/remoting/core/DefaultChannelClientTests.java @@ -53,7 +53,7 @@ import infra.remoting.frame.PayloadFrameCodec; import infra.remoting.frame.decoder.PayloadDecoder; import infra.remoting.internal.subscriber.AssertSubscriber; -import infra.remoting.test.util.TestDuplexConnection; +import infra.remoting.test.util.TestConnection; import infra.remoting.util.ByteBufPayload; import infra.remoting.ChannelWrapper; import reactor.core.Disposable; @@ -629,7 +629,7 @@ public void shouldBeRestartedIfSourceWasClosed() { terminateSubscriber.assertNotTerminated(); Assertions.assertThat(rule.client.isDisposed()).isFalse(); - rule.connection = new TestDuplexConnection(rule.allocator); + rule.connection = new TestConnection(rule.allocator); rule.channel = rule.newChannel(); rule.producer = Sinks.one(); diff --git a/today-remoting/src/test/java/infra/remoting/core/FireAndForgetRequesterMonoTests.java b/today-remoting/src/test/java/infra/remoting/core/FireAndForgetRequesterMonoTests.java index 97b4446..6dbdf02 100644 --- a/today-remoting/src/test/java/infra/remoting/core/FireAndForgetRequesterMonoTests.java +++ b/today-remoting/src/test/java/infra/remoting/core/FireAndForgetRequesterMonoTests.java @@ -34,7 +34,7 @@ import infra.remoting.buffer.LeaksTrackingByteBufAllocator; import infra.remoting.frame.FrameType; import infra.remoting.plugins.TestRequestInterceptor; -import infra.remoting.test.util.TestDuplexConnection; +import infra.remoting.test.util.TestConnection; import infra.remoting.util.ByteBufPayload; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; @@ -85,7 +85,7 @@ public void frameShouldBeSentOnSubscription(Consumer // should not add anything to map stateAssert.isTerminated(); activeStreams.assertNoActiveStreams(); - final ByteBuf frame = activeStreams.getDuplexConnection().awaitFrame(); + final ByteBuf frame = activeStreams.getConnection().awaitFrame(); FrameAssert.assertThat(frame) .isNotNull() .hasPayloadSize( @@ -99,7 +99,7 @@ public void frameShouldBeSentOnSubscription(Consumer .hasStreamId(1) .hasNoLeaks(); - assertThat(activeStreams.getDuplexConnection().isEmpty()).isTrue(); + assertThat(activeStreams.getConnection().isEmpty()).isTrue(); activeStreams.getAllocator().assertHasNoLeaks(); testRequestInterceptor .expectOnStart(1, FrameType.REQUEST_FNF) @@ -119,7 +119,7 @@ public void frameFragmentsShouldBeSentOnSubscription( final int mtu = 64; final TestChannelSupport streamManager = TestChannelSupport.client(mtu); final LeaksTrackingByteBufAllocator allocator = streamManager.getAllocator(); - final TestDuplexConnection sender = streamManager.getDuplexConnection(); + final TestConnection sender = streamManager.getConnection(); final byte[] metadata = new byte[65]; final byte[] data = new byte[129]; @@ -219,7 +219,7 @@ public void shouldErrorOnIncorrectRefCntInGivenPayload( final TestChannelSupport streamManager = TestChannelSupport.client(testRequestInterceptor); final LeaksTrackingByteBufAllocator allocator = streamManager.getAllocator(); - final TestDuplexConnection sender = streamManager.getDuplexConnection(); + final TestConnection sender = streamManager.getConnection(); final Payload payload = ByteBufPayload.create(""); payload.release(); @@ -268,7 +268,7 @@ public void shouldErrorIfFragmentExitsAllowanceIfFragmentationDisabled( final TestChannelSupport streamManager = TestChannelSupport.client(testRequestInterceptor); final LeaksTrackingByteBufAllocator allocator = streamManager.getAllocator(); - final TestDuplexConnection sender = streamManager.getDuplexConnection(); + final TestConnection sender = streamManager.getConnection(); final byte[] metadata = new byte[FRAME_LENGTH_MASK]; final byte[] data = new byte[FRAME_LENGTH_MASK]; @@ -329,7 +329,7 @@ public void shouldErrorIfNoAvailability(Consumer mon final TestChannelSupport streamManager = TestChannelSupport.client(exception, testRequestInterceptor); final LeaksTrackingByteBufAllocator allocator = streamManager.getAllocator(); - final TestDuplexConnection sender = streamManager.getDuplexConnection(); + final TestConnection sender = streamManager.getConnection(); final Payload payload = genericPayload(allocator); final FireAndForgetRequesterMono fireAndForgetRequesterMono = @@ -371,7 +371,7 @@ public void shouldSubscribeExactlyOnce1() { final TestRequestInterceptor testRequestInterceptor = new TestRequestInterceptor(); final TestChannelSupport streamManager = TestChannelSupport.client(testRequestInterceptor); final LeaksTrackingByteBufAllocator allocator = streamManager.getAllocator(); - final TestDuplexConnection sender = streamManager.getDuplexConnection(); + final TestConnection sender = streamManager.getConnection(); for (int i = 1; i < 50000; i += 2) { final Payload payload = ByteBufPayload.create("testData", "testMetadata"); diff --git a/today-remoting/src/test/java/infra/remoting/core/KeepAliveTests.java b/today-remoting/src/test/java/infra/remoting/core/KeepAliveTests.java index 8a72a8e..048b1f9 100644 --- a/today-remoting/src/test/java/infra/remoting/core/KeepAliveTests.java +++ b/today-remoting/src/test/java/infra/remoting/core/KeepAliveTests.java @@ -35,9 +35,9 @@ import infra.remoting.frame.decoder.PayloadDecoder; import infra.remoting.resume.ChannelSession; import infra.remoting.resume.InMemoryResumableFramesStore; -import infra.remoting.resume.ResumableDuplexConnection; +import infra.remoting.resume.ResumableConnection; import infra.remoting.resume.ResumeStateHolder; -import infra.remoting.test.util.TestDuplexConnection; +import infra.remoting.test.util.TestConnection; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufAllocator; import io.netty.buffer.Unpooled; @@ -72,7 +72,7 @@ public void tearDown() { static ChannelState requester(int tickPeriod, int timeout) { LeaksTrackingByteBufAllocator allocator = LeaksTrackingByteBufAllocator.instrument(ByteBufAllocator.DEFAULT); - TestDuplexConnection connection = new TestDuplexConnection(allocator); + TestConnection connection = new TestConnection(allocator); Sinks.Empty empty = Sinks.empty(); RequesterChannel channel = new RequesterChannel( @@ -95,9 +95,9 @@ static ChannelState requester(int tickPeriod, int timeout) { static ResumableChannelState resumableRequester(int tickPeriod, int timeout) { LeaksTrackingByteBufAllocator allocator = LeaksTrackingByteBufAllocator.instrument(ByteBufAllocator.DEFAULT); - TestDuplexConnection connection = new TestDuplexConnection(allocator); - ResumableDuplexConnection resumableConnection = - new ResumableDuplexConnection( + TestConnection connection = new TestConnection(allocator); + ResumableConnection resumableConnection = + new ResumableConnection( "test", Unpooled.EMPTY_BUFFER, connection, @@ -129,7 +129,7 @@ static ResumableChannelState resumableRequester(int tickPeriod, int timeout) { void channelNotDisposedOnPresentKeepAlives() { ChannelState requesterState = requester(KEEP_ALIVE_INTERVAL, KEEP_ALIVE_TIMEOUT); - TestDuplexConnection connection = requesterState.connection(); + TestConnection connection = requesterState.connection(); Disposable disposable = Flux.interval(Duration.ofMillis(KEEP_ALIVE_INTERVAL)) @@ -196,7 +196,7 @@ void channelDisposedOnMissingKeepAlives() { @Test void clientRequesterSendsKeepAlives() { ChannelState channelState = requester(KEEP_ALIVE_INTERVAL, KEEP_ALIVE_TIMEOUT); - TestDuplexConnection connection = channelState.connection(); + TestConnection connection = channelState.connection(); virtualTimeScheduler.advanceTimeBy(Duration.ofMillis(KEEP_ALIVE_INTERVAL)); this.keepAliveFrameWithRespondFlag(connection.pollFrame()); @@ -218,7 +218,7 @@ void clientRequesterSendsKeepAlives() { @Test void requesterRespondsToKeepAlives() { ChannelState channelState = requester(100_000, 100_000); - TestDuplexConnection connection = channelState.connection(); + TestConnection connection = channelState.connection(); Duration duration = Duration.ofMillis(100); Mono.delay(duration) .subscribe( @@ -247,10 +247,10 @@ void requesterRespondsToKeepAlives() { void resumableRequesterNoKeepAlivesAfterDisconnect() { ResumableChannelState channelState = resumableRequester(KEEP_ALIVE_INTERVAL, KEEP_ALIVE_TIMEOUT); - TestDuplexConnection testConnection = channelState.connection(); - ResumableDuplexConnection resumableDuplexConnection = channelState.resumableDuplexConnection(); + TestConnection testConnection = channelState.connection(); + ResumableConnection resumableConnection = channelState.resumableConnection(); - resumableDuplexConnection.disconnect(); + resumableConnection.disconnect(); Duration duration = Duration.ofMillis(KEEP_ALIVE_INTERVAL * 5); virtualTimeScheduler.advanceTimeBy(duration); @@ -266,11 +266,11 @@ void resumableRequesterNoKeepAlivesAfterDisconnect() { void resumableRequesterKeepAlivesAfterReconnect() { ResumableChannelState channelState = resumableRequester(KEEP_ALIVE_INTERVAL, KEEP_ALIVE_TIMEOUT); - ResumableDuplexConnection resumableDuplexConnection = channelState.resumableDuplexConnection(); - resumableDuplexConnection.disconnect(); - TestDuplexConnection newTestConnection = new TestDuplexConnection(channelState.alloc()); - resumableDuplexConnection.connect(newTestConnection); - // resumableDuplexConnection.(0, 0, ignored -> Mono.empty()); + ResumableConnection resumableConnection = channelState.resumableConnection(); + resumableConnection.disconnect(); + TestConnection newTestConnection = new TestConnection(channelState.alloc()); + resumableConnection.connect(newTestConnection); + // resumableConnection.(0, 0, ignored -> Mono.empty()); virtualTimeScheduler.advanceTimeBy(Duration.ofMillis(KEEP_ALIVE_INTERVAL)); @@ -327,7 +327,7 @@ void resumableChannelsNotDisposedOnMissingKeepAlives() throws InterruptedExcepti ResumableChannelState resumableRequesterState = resumableRequester(KEEP_ALIVE_INTERVAL, RESUMABLE_KEEP_ALIVE_TIMEOUT); Channel channel = resumableRequesterState.channel(); - TestDuplexConnection connection = resumableRequesterState.connection(); + TestConnection connection = resumableRequesterState.connection(); virtualTimeScheduler.advanceTimeBy(Duration.ofMillis(500)); @@ -356,13 +356,13 @@ private boolean keepAliveFrameWithoutRespondFlag(ByteBuf frame) { static class ChannelState { private final Channel channel; - private final TestDuplexConnection connection; + private final TestConnection connection; private final LeaksTrackingByteBufAllocator allocator; private final Sinks.Empty onClose; public ChannelState(Channel channel, LeaksTrackingByteBufAllocator allocator, - TestDuplexConnection connection, + TestConnection connection, Sinks.Empty onClose) { this.channel = channel; this.connection = connection; @@ -370,7 +370,7 @@ public ChannelState(Channel channel, this.onClose = onClose; } - public TestDuplexConnection connection() { + public TestConnection connection() { return connection; } @@ -385,30 +385,30 @@ public LeaksTrackingByteBufAllocator alloc() { static class ResumableChannelState { private final Channel channel; - private final TestDuplexConnection connection; - private final ResumableDuplexConnection resumableDuplexConnection; + private final TestConnection connection; + private final ResumableConnection resumableConnection; private final LeaksTrackingByteBufAllocator allocator; private final Sinks.Empty onClose; public ResumableChannelState( Channel channel, - TestDuplexConnection connection, - ResumableDuplexConnection resumableDuplexConnection, + TestConnection connection, + ResumableConnection resumableConnection, Sinks.Empty onClose, LeaksTrackingByteBufAllocator allocator) { this.channel = channel; this.connection = connection; - this.resumableDuplexConnection = resumableDuplexConnection; + this.resumableConnection = resumableConnection; this.onClose = onClose; this.allocator = allocator; } - public TestDuplexConnection connection() { + public TestConnection connection() { return connection; } - public ResumableDuplexConnection resumableDuplexConnection() { - return resumableDuplexConnection; + public ResumableConnection resumableConnection() { + return resumableConnection; } public Channel channel() { diff --git a/today-remoting/src/test/java/infra/remoting/core/RemotingServerTests.java b/today-remoting/src/test/java/infra/remoting/core/RemotingServerTests.java index 89b542c..33df2d3 100644 --- a/today-remoting/src/test/java/infra/remoting/core/RemotingServerTests.java +++ b/today-remoting/src/test/java/infra/remoting/core/RemotingServerTests.java @@ -32,7 +32,7 @@ import infra.remoting.frame.KeepAliveFrameCodec; import infra.remoting.frame.RequestResponseFrameCodec; import infra.remoting.frame.SetupFrameCodec; -import infra.remoting.test.util.TestDuplexConnection; +import infra.remoting.test.util.TestConnection; import infra.remoting.test.util.TestServerTransport; import infra.remoting.util.EmptyPayload; import reactor.core.Scannable; @@ -51,7 +51,7 @@ public void unexpectedFramesBeforeSetupFrame() { TestServerTransport transport = new TestServerTransport(); RemotingServer.create().bind(transport).block(); - final TestDuplexConnection duplexConnection = transport.connect(); + final TestConnection duplexConnection = transport.connect(); duplexConnection.addToReceivedBuffer( KeepAliveFrameCodec.encode(duplexConnection.alloc(), false, 1, Unpooled.EMPTY_BUFFER)); @@ -77,7 +77,7 @@ public void timeoutOnNoFirstFrame() { try { RemotingServer.create().maxTimeToFirstFrame(Duration.ofMinutes(2)).bind(transport).block(); - final TestDuplexConnection duplexConnection = transport.connect(); + final TestConnection duplexConnection = transport.connect(); scheduler.advanceTimeBy(Duration.ofMinutes(1)); @@ -151,7 +151,7 @@ public void unexpectedFramesBeforeSetup() { byte[] bytes = new byte[16_000_000]; new Random().nextBytes(bytes); - TestDuplexConnection connection = transport.connect(); + TestConnection connection = transport.connect(); connection.addToReceivedBuffer( RequestResponseFrameCodec.encode( ByteBufAllocator.DEFAULT, @@ -180,7 +180,7 @@ public void ensuresErrorFrameDeliveredPriorConnectionDisposal() { .bind(transport) .block(); - TestDuplexConnection connection = transport.connect(); + TestConnection connection = transport.connect(); connection.addToReceivedBuffer( SetupFrameCodec.encode( ByteBufAllocator.DEFAULT, diff --git a/today-remoting/src/test/java/infra/remoting/core/RequestRequesterChannelFluxTests.java b/today-remoting/src/test/java/infra/remoting/core/RequestRequesterChannelFluxTests.java index 9717d0c..ddcc1f0 100644 --- a/today-remoting/src/test/java/infra/remoting/core/RequestRequesterChannelFluxTests.java +++ b/today-remoting/src/test/java/infra/remoting/core/RequestRequesterChannelFluxTests.java @@ -43,7 +43,7 @@ import infra.remoting.error.ApplicationErrorException; import infra.remoting.frame.FrameType; import infra.remoting.internal.subscriber.AssertSubscriber; -import infra.remoting.test.util.TestDuplexConnection; +import infra.remoting.test.util.TestConnection; import infra.remoting.util.ByteBufPayload; import infra.remoting.util.DefaultPayload; import reactor.core.publisher.Hooks; @@ -72,7 +72,7 @@ public static void setUp() { public void requestNFrameShouldBeSentOnSubscriptionAndThenSeparately(String completionCase) { final TestChannelSupport activeStreams = TestChannelSupport.client(); final LeaksTrackingByteBufAllocator allocator = activeStreams.getAllocator(); - final TestDuplexConnection sender = activeStreams.getDuplexConnection(); + final TestConnection sender = activeStreams.getConnection(); final Payload payload = TestChannelSupport.genericPayload(allocator); final TestPublisher publisher = TestPublisher.create(); @@ -254,7 +254,7 @@ else if (completionCase.equals("outbound")) { public void streamShouldErrorWithoutInitializingRemoteStreamIfSourceIsEmpty(boolean doRequest) { final TestChannelSupport activeStreams = TestChannelSupport.client(); final LeaksTrackingByteBufAllocator allocator = activeStreams.getAllocator(); - final TestDuplexConnection sender = activeStreams.getDuplexConnection(); + final TestConnection sender = activeStreams.getConnection(); final TestPublisher publisher = TestPublisher.create(); final RequestChannelRequesterFlux requestChannelRequesterFlux = @@ -299,7 +299,7 @@ public void streamShouldPropagateErrorWithoutInitializingRemoteStreamIfTheFirstS boolean doRequest) { final TestChannelSupport activeStreams = TestChannelSupport.client(); final LeaksTrackingByteBufAllocator allocator = activeStreams.getAllocator(); - final TestDuplexConnection sender = activeStreams.getDuplexConnection(); + final TestConnection sender = activeStreams.getConnection(); final TestPublisher publisher = TestPublisher.create(); final RequestChannelRequesterFlux requestChannelRequesterFlux = @@ -343,7 +343,7 @@ public void streamShouldPropagateErrorWithoutInitializingRemoteStreamIfTheFirstS public void streamShouldBeInHalfClosedStateOnTheInboundCancellation(String terminationMode) { final TestChannelSupport activeStreams = TestChannelSupport.client(); final LeaksTrackingByteBufAllocator allocator = activeStreams.getAllocator(); - final TestDuplexConnection sender = activeStreams.getDuplexConnection(); + final TestConnection sender = activeStreams.getConnection(); final TestPublisher publisher = TestPublisher.create(); final RequestChannelRequesterFlux requestChannelRequesterFlux = @@ -442,7 +442,7 @@ else if (terminationMode.equals("inbound")) { public void errorShouldTerminateExecution(String terminationMode) { final TestChannelSupport activeStreams = TestChannelSupport.client(); final LeaksTrackingByteBufAllocator allocator = activeStreams.getAllocator(); - final TestDuplexConnection sender = activeStreams.getDuplexConnection(); + final TestConnection sender = activeStreams.getConnection(); final TestPublisher publisher = TestPublisher.create(); final RequestChannelRequesterFlux requestChannelRequesterFlux = @@ -525,7 +525,7 @@ else if (terminationMode.equals("inbound")) { public void failOnOverflow() { final TestChannelSupport activeStreams = TestChannelSupport.client(); final LeaksTrackingByteBufAllocator allocator = activeStreams.getAllocator(); - final TestDuplexConnection sender = activeStreams.getDuplexConnection(); + final TestConnection sender = activeStreams.getConnection(); final TestPublisher publisher = TestPublisher.create(); final RequestChannelRequesterFlux requestChannelRequesterFlux = @@ -628,7 +628,7 @@ public void shouldHaveEventsDeliveredSeriallyWhenOutboundErrorRacingWithInboundS for (int i = 0; i < RaceTestConstants.REPEATS; i++) { final TestChannelSupport activeStreams = TestChannelSupport.client(); final LeaksTrackingByteBufAllocator allocator = activeStreams.getAllocator(); - final TestDuplexConnection sender = activeStreams.getDuplexConnection(); + final TestConnection sender = activeStreams.getConnection(); final TestPublisher publisher = TestPublisher.createNoncompliant(TestPublisher.Violation.DEFER_CANCELLATION); @@ -800,7 +800,7 @@ public void shouldRemoveItselfFromActiveStreamsWhenInboundAndOutboundAreTerminat for (int i = 0; i < RaceTestConstants.REPEATS; i++) { final TestChannelSupport activeStreams = TestChannelSupport.client(); final LeaksTrackingByteBufAllocator allocator = activeStreams.getAllocator(); - final TestDuplexConnection sender = activeStreams.getDuplexConnection(); + final TestConnection sender = activeStreams.getConnection(); final TestPublisher publisher = TestPublisher.createNoncompliant(TestPublisher.Violation.DEFER_CANCELLATION); diff --git a/today-remoting/src/test/java/infra/remoting/core/RequestResponderChannelSubscriberTests.java b/today-remoting/src/test/java/infra/remoting/core/RequestResponderChannelSubscriberTests.java index de952a3..0ee04ac 100644 --- a/today-remoting/src/test/java/infra/remoting/core/RequestResponderChannelSubscriberTests.java +++ b/today-remoting/src/test/java/infra/remoting/core/RequestResponderChannelSubscriberTests.java @@ -44,7 +44,7 @@ import infra.remoting.error.ApplicationErrorException; import infra.remoting.frame.FrameType; import infra.remoting.internal.subscriber.AssertSubscriber; -import infra.remoting.test.util.TestDuplexConnection; +import infra.remoting.test.util.TestConnection; import infra.remoting.util.ByteBufPayload; import infra.remoting.util.DefaultPayload; import reactor.core.Exceptions; @@ -81,7 +81,7 @@ public static void setUp() { public void requestNFrameShouldBeSentOnSubscriptionAndThenSeparately(String completionCase) { final TestChannelSupport activeStreams = TestChannelSupport.client(); final LeaksTrackingByteBufAllocator allocator = activeStreams.getAllocator(); - final TestDuplexConnection sender = activeStreams.getDuplexConnection(); + final TestConnection sender = activeStreams.getConnection(); final Payload firstPayload = TestChannelSupport.genericPayload(allocator); final TestPublisher publisher = TestPublisher.create(); @@ -276,7 +276,7 @@ else if (completionCase.equals("outbound")) { public void failOnOverflow() { final TestChannelSupport activeStreams = TestChannelSupport.client(); final LeaksTrackingByteBufAllocator allocator = activeStreams.getAllocator(); - final TestDuplexConnection sender = activeStreams.getDuplexConnection(); + final TestConnection sender = activeStreams.getConnection(); final Payload firstPayload = TestChannelSupport.genericPayload(allocator); final TestPublisher publisher = TestPublisher.create(); @@ -356,7 +356,7 @@ public void failOnOverflow() { public void failOnOverflowBeforeFirstPayloadIsSent() { final TestChannelSupport activeStreams = TestChannelSupport.client(); final LeaksTrackingByteBufAllocator allocator = activeStreams.getAllocator(); - final TestDuplexConnection sender = activeStreams.getDuplexConnection(); + final TestConnection sender = activeStreams.getConnection(); final Payload firstPayload = TestChannelSupport.genericPayload(allocator); final TestPublisher publisher = TestPublisher.create(); @@ -420,7 +420,7 @@ public void streamShouldWorkCorrectlyWhenRacingHandleCompleteWithSubscription() for (int i = 0; i < RaceTestConstants.REPEATS; i++) { final TestChannelSupport activeStreams = TestChannelSupport.client(); final LeaksTrackingByteBufAllocator allocator = activeStreams.getAllocator(); - final TestDuplexConnection sender = activeStreams.getDuplexConnection(); + final TestConnection sender = activeStreams.getConnection(); ; final Payload firstPayload = TestChannelSupport.randomPayload(allocator); final TestPublisher publisher = TestPublisher.create(); @@ -550,7 +550,7 @@ public void streamShouldWorkCorrectlyWhenRacingOutboundErrorWithSubscription() { stateAssert.isTerminated(); - FrameAssert.assertThat(activeStreams.getDuplexConnection().awaitFrame()) + FrameAssert.assertThat(activeStreams.getConnection().awaitFrame()) .typeOf(ERROR) .hasData("test") .hasStreamId(1) @@ -643,7 +643,7 @@ public void shouldHaveEventsDeliveredSeriallyWhenOutboundErrorRacingWithInboundS for (int i = 0; i < RaceTestConstants.REPEATS; i++) { final TestChannelSupport activeStreams = TestChannelSupport.client(); final LeaksTrackingByteBufAllocator allocator = activeStreams.getAllocator(); - final TestDuplexConnection sender = activeStreams.getDuplexConnection(); + final TestConnection sender = activeStreams.getConnection(); final TestPublisher publisher = TestPublisher.createNoncompliant(DEFER_CANCELLATION, CLEANUP_ON_TERMINATE); @@ -819,7 +819,7 @@ public void shouldHaveNoLeaksOnReassemblyAndCancelRacing(String terminationMode) for (int i = 0; i < RaceTestConstants.REPEATS; i++) { final TestChannelSupport activeStreams = TestChannelSupport.client(); final LeaksTrackingByteBufAllocator allocator = activeStreams.getAllocator(); - final TestDuplexConnection sender = activeStreams.getDuplexConnection(); + final TestConnection sender = activeStreams.getConnection(); ; final TestPublisher publisher = TestPublisher.createNoncompliant(DEFER_CANCELLATION, CLEANUP_ON_TERMINATE); diff --git a/today-remoting/src/test/java/infra/remoting/core/RequestResponseRequesterMonoTests.java b/today-remoting/src/test/java/infra/remoting/core/RequestResponseRequesterMonoTests.java index 07737c7..cd9c5c6 100644 --- a/today-remoting/src/test/java/infra/remoting/core/RequestResponseRequesterMonoTests.java +++ b/today-remoting/src/test/java/infra/remoting/core/RequestResponseRequesterMonoTests.java @@ -35,7 +35,7 @@ import infra.remoting.buffer.LeaksTrackingByteBufAllocator; import infra.remoting.error.ApplicationErrorException; import infra.remoting.frame.FrameType; -import infra.remoting.test.util.TestDuplexConnection; +import infra.remoting.test.util.TestConnection; import infra.remoting.util.ByteBufPayload; import infra.remoting.util.EmptyPayload; import io.netty.buffer.ByteBuf; @@ -78,7 +78,7 @@ public void frameShouldBeSentOnSubscription( transformer) { final TestChannelSupport activeStreams = TestChannelSupport.client(); final LeaksTrackingByteBufAllocator allocator = activeStreams.getAllocator(); - final TestDuplexConnection sender = activeStreams.getDuplexConnection(); + final TestConnection sender = activeStreams.getConnection(); final Payload payload = genericPayload(allocator); final RequestResponseRequesterMono requestResponseRequesterMono = @@ -323,7 +323,7 @@ public void frameFragmentsShouldBeSentOnSubscription( final int mtu = 64; final TestChannelSupport activeStreams = TestChannelSupport.client(mtu); final LeaksTrackingByteBufAllocator allocator = activeStreams.getAllocator(); - final TestDuplexConnection sender = activeStreams.getDuplexConnection(); + final TestConnection sender = activeStreams.getConnection(); final byte[] metadata = new byte[65]; final byte[] data = new byte[129]; @@ -433,7 +433,7 @@ public void frameFragmentsShouldBeSentOnSubscription( public void shouldBeNoOpsOnCancel() { final TestChannelSupport activeStreams = TestChannelSupport.client(); final LeaksTrackingByteBufAllocator allocator = activeStreams.getAllocator(); - final TestDuplexConnection sender = activeStreams.getDuplexConnection(); + final TestConnection sender = activeStreams.getConnection(); final Payload payload = ByteBufPayload.create("testData", "testMetadata"); final RequestResponseRequesterMono requestResponseRequesterMono = @@ -469,7 +469,7 @@ public void shouldErrorOnIncorrectRefCntInGivenPayload( Consumer monoConsumer) { final TestChannelSupport activeStreams = TestChannelSupport.client(); final LeaksTrackingByteBufAllocator allocator = activeStreams.getAllocator(); - final TestDuplexConnection sender = activeStreams.getDuplexConnection(); + final TestConnection sender = activeStreams.getConnection(); ; final Payload payload = ByteBufPayload.create(""); payload.release(); @@ -513,7 +513,7 @@ public void shouldErrorOnIncorrectRefCntInGivenPayload( public void shouldErrorOnIncorrectRefCntInGivenPayloadLatePhase() { final TestChannelSupport activeStreams = TestChannelSupport.client(); final LeaksTrackingByteBufAllocator allocator = activeStreams.getAllocator(); - final TestDuplexConnection sender = activeStreams.getDuplexConnection(); + final TestConnection sender = activeStreams.getConnection(); ; final Payload payload = ByteBufPayload.create(""); @@ -548,7 +548,7 @@ public void shouldErrorOnIncorrectRefCntInGivenPayloadLatePhaseWithFragmentation final int mtu = 64; final TestChannelSupport activeStreams = TestChannelSupport.client(mtu); final LeaksTrackingByteBufAllocator allocator = activeStreams.getAllocator(); - final TestDuplexConnection sender = activeStreams.getDuplexConnection(); + final TestConnection sender = activeStreams.getConnection(); ; final byte[] metadata = new byte[65]; final byte[] data = new byte[129]; @@ -588,7 +588,7 @@ public void shouldErrorIfFragmentExitsAllowanceIfFragmentationDisabled( Consumer monoConsumer) { final TestChannelSupport activeStreams = TestChannelSupport.client(); final LeaksTrackingByteBufAllocator allocator = activeStreams.getAllocator(); - final TestDuplexConnection sender = activeStreams.getDuplexConnection(); + final TestConnection sender = activeStreams.getConnection(); ; final byte[] metadata = new byte[FRAME_LENGTH_MASK]; diff --git a/today-remoting/src/test/java/infra/remoting/core/RequestStreamRequesterFluxTests.java b/today-remoting/src/test/java/infra/remoting/core/RequestStreamRequesterFluxTests.java index 0a6a123..307aaeb 100644 --- a/today-remoting/src/test/java/infra/remoting/core/RequestStreamRequesterFluxTests.java +++ b/today-remoting/src/test/java/infra/remoting/core/RequestStreamRequesterFluxTests.java @@ -37,7 +37,7 @@ import infra.remoting.error.ApplicationErrorException; import infra.remoting.frame.FrameType; import infra.remoting.internal.subscriber.AssertSubscriber; -import infra.remoting.test.util.TestDuplexConnection; +import infra.remoting.test.util.TestConnection; import infra.remoting.util.ByteBufPayload; import infra.remoting.util.EmptyPayload; import io.netty.buffer.ByteBuf; @@ -83,7 +83,7 @@ public static void setUp() { public void requestNFrameShouldBeSentOnSubscriptionAndThenSeparately() { final TestChannelSupport activeStreams = TestChannelSupport.client(); final LeaksTrackingByteBufAllocator allocator = activeStreams.getAllocator(); - final TestDuplexConnection sender = activeStreams.getDuplexConnection(); + final TestConnection sender = activeStreams.getConnection(); final Payload payload = TestChannelSupport.genericPayload(allocator); final RequestStreamRequesterFlux requestStreamRequesterFlux = @@ -230,7 +230,7 @@ public void requestNFrameShouldBeSentOnSubscriptionAndThenSeparately() { public void requestNFrameShouldBeSentExactlyOnceIfItIsMaxAllowed() { final TestChannelSupport activeStreams = TestChannelSupport.client(); final LeaksTrackingByteBufAllocator allocator = activeStreams.getAllocator(); - final TestDuplexConnection sender = activeStreams.getDuplexConnection(); + final TestConnection sender = activeStreams.getConnection(); final Payload payload = TestChannelSupport.genericPayload(allocator); final RequestStreamRequesterFlux requestStreamRequesterFlux = @@ -335,7 +335,7 @@ public void frameShouldBeSentOnFirstRequest( transformer) { final TestChannelSupport activeStreams = TestChannelSupport.client(); final LeaksTrackingByteBufAllocator allocator = activeStreams.getAllocator(); - final TestDuplexConnection sender = activeStreams.getDuplexConnection(); + final TestConnection sender = activeStreams.getConnection(); final Payload payload = TestChannelSupport.genericPayload(allocator); final RequestStreamRequesterFlux requestStreamRequesterFlux = @@ -767,7 +767,7 @@ public void frameFragmentsShouldBeSentOnFirstRequest( final int mtu = 64; final TestChannelSupport activeStreams = TestChannelSupport.client(mtu); final LeaksTrackingByteBufAllocator allocator = activeStreams.getAllocator(); - final TestDuplexConnection sender = activeStreams.getDuplexConnection(); + final TestConnection sender = activeStreams.getConnection(); final byte[] metadata = new byte[65]; final byte[] data = new byte[129]; @@ -885,7 +885,7 @@ public void shouldErrorOnIncorrectRefCntInGivenPayload( Consumer monoConsumer) { final TestChannelSupport activeStreams = TestChannelSupport.client(); final LeaksTrackingByteBufAllocator allocator = activeStreams.getAllocator(); - final TestDuplexConnection sender = activeStreams.getDuplexConnection(); + final TestConnection sender = activeStreams.getConnection(); final Payload payload = ByteBufPayload.create(""); payload.release(); @@ -928,7 +928,7 @@ public void shouldErrorOnIncorrectRefCntInGivenPayload( public void shouldErrorOnIncorrectRefCntInGivenPayloadLatePhase() { final TestChannelSupport activeStreams = TestChannelSupport.client(); final LeaksTrackingByteBufAllocator allocator = activeStreams.getAllocator(); - final TestDuplexConnection sender = activeStreams.getDuplexConnection(); + final TestConnection sender = activeStreams.getConnection(); final Payload payload = ByteBufPayload.create(""); @@ -973,7 +973,7 @@ public void shouldErrorOnIncorrectRefCntInGivenPayloadLatePhaseWithFragmentation final int mtu = 64; final TestChannelSupport activeStreams = TestChannelSupport.client(mtu); final LeaksTrackingByteBufAllocator allocator = activeStreams.getAllocator(); - final TestDuplexConnection sender = activeStreams.getDuplexConnection(); + final TestConnection sender = activeStreams.getConnection(); final byte[] metadata = new byte[65]; final byte[] data = new byte[129]; @@ -1023,7 +1023,7 @@ public void shouldErrorIfFragmentExitsAllowanceIfFragmentationDisabled( Consumer monoConsumer) { final TestChannelSupport activeStreams = TestChannelSupport.client(); final LeaksTrackingByteBufAllocator allocator = activeStreams.getAllocator(); - final TestDuplexConnection sender = activeStreams.getDuplexConnection(); + final TestConnection sender = activeStreams.getConnection(); final byte[] metadata = new byte[FRAME_LENGTH_MASK]; final byte[] data = new byte[FRAME_LENGTH_MASK]; @@ -1136,7 +1136,7 @@ static Stream> shouldErrorIfNoAvailabilityS public void failOnOverflow() { final TestChannelSupport activeStreams = TestChannelSupport.client(); final LeaksTrackingByteBufAllocator allocator = activeStreams.getAllocator(); - final TestDuplexConnection sender = activeStreams.getDuplexConnection(); + final TestConnection sender = activeStreams.getConnection(); final Payload payload = TestChannelSupport.genericPayload(allocator); final RequestStreamRequesterFlux requestStreamRequesterFlux = diff --git a/today-remoting/src/test/java/infra/remoting/core/RequesterChannelSubscribersTests.java b/today-remoting/src/test/java/infra/remoting/core/RequesterChannelSubscribersTests.java index 0607794..0891009 100644 --- a/today-remoting/src/test/java/infra/remoting/core/RequesterChannelSubscribersTests.java +++ b/today-remoting/src/test/java/infra/remoting/core/RequesterChannelSubscribersTests.java @@ -43,7 +43,7 @@ import infra.remoting.frame.PayloadFrameCodec; import infra.remoting.frame.decoder.PayloadDecoder; import infra.remoting.internal.subscriber.AssertSubscriber; -import infra.remoting.test.util.TestDuplexConnection; +import infra.remoting.test.util.TestConnection; import infra.remoting.util.DefaultPayload; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; @@ -65,7 +65,7 @@ class RequesterChannelSubscribersTests { private LeaksTrackingByteBufAllocator allocator; private Channel channelRequester; - private TestDuplexConnection connection; + private TestConnection connection; protected Sinks.Empty thisClosedSink; protected Sinks.Empty otherClosedSink; @@ -77,7 +77,7 @@ void tearDownAndCheckNoLeaks() { @BeforeEach void setUp() { allocator = LeaksTrackingByteBufAllocator.instrument(ByteBufAllocator.DEFAULT); - connection = new TestDuplexConnection(allocator); + connection = new TestConnection(allocator); this.thisClosedSink = Sinks.empty(); this.otherClosedSink = Sinks.empty(); channelRequester = diff --git a/today-remoting/src/test/java/infra/remoting/core/RequesterOperatorsRacingTests.java b/today-remoting/src/test/java/infra/remoting/core/RequesterOperatorsRacingTests.java index a4f6e9e..5e83f58 100644 --- a/today-remoting/src/test/java/infra/remoting/core/RequesterOperatorsRacingTests.java +++ b/today-remoting/src/test/java/infra/remoting/core/RequesterOperatorsRacingTests.java @@ -185,7 +185,7 @@ public void shouldSubscribeExactlyOnce(Scenario scenario) { scenario.requestOperator(payloadSupplier, requesterResponderSupport); StepVerifier stepVerifier = - StepVerifier.create(requesterResponderSupport.getDuplexConnection().getSentAsPublisher()) + StepVerifier.create(requesterResponderSupport.getConnection().getSentAsPublisher()) .assertNext( frame -> { FrameAssert frameAssert = @@ -299,11 +299,11 @@ public void shouldSentRequestFrameOnceInCaseOfRequestRacing(Scenario scenario) { RaceTestUtils.race(() -> assertSubscriber.request(1), () -> assertSubscriber.request(1)); - final ByteBuf sentFrame = activeStreams.getDuplexConnection().awaitFrame(); + final ByteBuf sentFrame = activeStreams.getConnection().awaitFrame(); if (scenario.requestType().hasInitialRequestN()) { if (RequestStreamFrameCodec.initialRequestN(sentFrame) == 1) { - FrameAssert.assertThat(activeStreams.getDuplexConnection().awaitFrame()) + FrameAssert.assertThat(activeStreams.getConnection().awaitFrame()) .isNotNull() .hasStreamId(1) .hasRequestN(1) @@ -334,7 +334,7 @@ public void shouldSentRequestFrameOnceInCaseOfRequestRacing(Scenario scenario) { if (scenario.requestType() == REQUEST_CHANNEL) { ((CoreSubscriber) requestOperator).onComplete(); - FrameAssert.assertThat(activeStreams.getDuplexConnection().awaitFrame()) + FrameAssert.assertThat(activeStreams.getConnection().awaitFrame()) .typeOf(COMPLETE) .hasStreamId(1) .hasNoLeaks(); @@ -349,7 +349,7 @@ public void shouldSentRequestFrameOnceInCaseOfRequestRacing(Scenario scenario) { }); activeStreams.assertNoActiveStreams(); - Assertions.assertThat(activeStreams.getDuplexConnection().isEmpty()).isTrue(); + Assertions.assertThat(activeStreams.getConnection().isEmpty()).isTrue(); activeStreams.getAllocator().assertHasNoLeaks(); if (scenario.requestType() != METADATA_PUSH) { testRequestInterceptor @@ -384,7 +384,7 @@ public void shouldHaveNoLeaksOnReassemblyAndCancelRacing(Scenario scenario) { requestOperator.subscribe(assertSubscriber); - final ByteBuf sentFrame = activeStreams.getDuplexConnection().awaitFrame(); + final ByteBuf sentFrame = activeStreams.getConnection().awaitFrame(); FrameAssert.assertThat(sentFrame) .isNotNull() .hasPayloadSize( @@ -435,12 +435,12 @@ public void shouldHaveNoLeaksOnReassemblyAndCancelRacing(Scenario scenario) { }); } - if (!activeStreams.getDuplexConnection().isEmpty()) { + if (!activeStreams.getConnection().isEmpty()) { if (scenario.requestType() != REQUEST_CHANNEL) { assertSubscriber.assertNotTerminated(); } - final ByteBuf cancellationFrame = activeStreams.getDuplexConnection().awaitFrame(); + final ByteBuf cancellationFrame = activeStreams.getConnection().awaitFrame(); FrameAssert.assertThat(cancellationFrame) .isNotNull() .typeOf(FrameType.CANCEL) @@ -464,7 +464,7 @@ public void shouldHaveNoLeaksOnReassemblyAndCancelRacing(Scenario scenario) { Assertions.assertThat(responsePayload.refCnt()).isZero(); activeStreams.assertNoActiveStreams(); - Assertions.assertThat(activeStreams.getDuplexConnection().isEmpty()).isTrue(); + Assertions.assertThat(activeStreams.getConnection().isEmpty()).isTrue(); activeStreams.getAllocator().assertHasNoLeaks(); } } @@ -492,7 +492,7 @@ public void shouldHaveNoLeaksOnNextAndCancelRacing(Scenario scenario) { AssertSubscriber assertSubscriber = AssertSubscriber.create(); requestOperator.subscribe((AssertSubscriber) assertSubscriber); - final ByteBuf sentFrame = activeStreams.getDuplexConnection().awaitFrame(); + final ByteBuf sentFrame = activeStreams.getConnection().awaitFrame(); FrameAssert.assertThat(sentFrame) .isNotNull() .hasPayloadSize( @@ -515,9 +515,9 @@ public void shouldHaveNoLeaksOnNextAndCancelRacing(Scenario scenario) { Assertions.assertThat(response.refCnt()).isZero(); activeStreams.assertNoActiveStreams(); - final boolean isEmpty = activeStreams.getDuplexConnection().isEmpty(); + final boolean isEmpty = activeStreams.getConnection().isEmpty(); if (!isEmpty) { - final ByteBuf cancellationFrame = activeStreams.getDuplexConnection().awaitFrame(); + final ByteBuf cancellationFrame = activeStreams.getConnection().awaitFrame(); FrameAssert.assertThat(cancellationFrame) .isNotNull() .typeOf(FrameType.CANCEL) @@ -537,7 +537,7 @@ public void shouldHaveNoLeaksOnNextAndCancelRacing(Scenario scenario) { .expectOnComplete(1) .expectNothing(); } - Assertions.assertThat(activeStreams.getDuplexConnection().isEmpty()).isTrue(); + Assertions.assertThat(activeStreams.getConnection().isEmpty()).isTrue(); activeStreams.getAllocator().assertHasNoLeaks(); } } @@ -590,7 +590,7 @@ else if (requestOperator instanceof RequestStreamRequesterFlux) { stateAssert.hasSubscribedFlag().hasRequestN(1).hasFirstFrameSentFlag(); - final ByteBuf sentFrame = activeStreams.getDuplexConnection().awaitFrame(); + final ByteBuf sentFrame = activeStreams.getConnection().awaitFrame(); FrameAssert.assertThat(sentFrame) .isNotNull() .hasPayloadSize( @@ -621,9 +621,9 @@ else if (requestOperator instanceof RequestStreamRequesterFlux) { activeStreams.assertNoActiveStreams(); stateAssert.isTerminated(); - final boolean isEmpty = activeStreams.getDuplexConnection().isEmpty(); + final boolean isEmpty = activeStreams.getConnection().isEmpty(); if (!isEmpty) { - final ByteBuf cancellationFrame = activeStreams.getDuplexConnection().awaitFrame(); + final ByteBuf cancellationFrame = activeStreams.getConnection().awaitFrame(); FrameAssert.assertThat(cancellationFrame) .isNotNull() .typeOf(FrameType.CANCEL) @@ -645,7 +645,7 @@ else if (requestOperator instanceof RequestStreamRequesterFlux) { assertSubscriber.assertTerminated().assertErrorMessage("test"); } - Assertions.assertThat(activeStreams.getDuplexConnection().isEmpty()).isTrue(); + Assertions.assertThat(activeStreams.getConnection().isEmpty()).isTrue(); stateAssert.isTerminated(); droppedErrors.clear(); @@ -697,8 +697,8 @@ public void shouldBeConsistentInCaseOfRacingOfCancellationAndRequest(Scenario sc RaceTestUtils.race(() -> assertSubscriber.cancel(), () -> assertSubscriber.request(1)); - if (!activeStreams.getDuplexConnection().isEmpty()) { - final ByteBuf sentFrame = activeStreams.getDuplexConnection().awaitFrame(); + if (!activeStreams.getConnection().isEmpty()) { + final ByteBuf sentFrame = activeStreams.getConnection().awaitFrame(); FrameAssert.assertThat(sentFrame) .isNotNull() .typeOf(scenario.requestType()) @@ -709,7 +709,7 @@ public void shouldBeConsistentInCaseOfRacingOfCancellationAndRequest(Scenario sc .hasStreamId(1) .hasNoLeaks(); - final ByteBuf cancelFrame = activeStreams.getDuplexConnection().awaitFrame(); + final ByteBuf cancelFrame = activeStreams.getConnection().awaitFrame(); FrameAssert.assertThat(cancelFrame) .isNotNull() .typeOf(FrameType.CANCEL) @@ -728,7 +728,7 @@ public void shouldBeConsistentInCaseOfRacingOfCancellationAndRequest(Scenario sc Assertions.assertThat(response.refCnt()).isZero(); activeStreams.assertNoActiveStreams(); - Assertions.assertThat(activeStreams.getDuplexConnection().isEmpty()).isTrue(); + Assertions.assertThat(activeStreams.getConnection().isEmpty()).isTrue(); activeStreams.getAllocator().assertHasNoLeaks(); } } @@ -757,7 +757,7 @@ public void shouldSentCancelFrameExactlyOnce(Scenario scenario) { assertSubscriber.request(1); - final ByteBuf sentFrame = activeStreams.getDuplexConnection().awaitFrame(); + final ByteBuf sentFrame = activeStreams.getConnection().awaitFrame(); FrameAssert.assertThat(sentFrame) .isNotNull() .hasNoFragmentsFollow() @@ -771,7 +771,7 @@ public void shouldSentCancelFrameExactlyOnce(Scenario scenario) { RaceTestUtils.race( ((Subscription) requesterOperator)::cancel, ((Subscription) requesterOperator)::cancel); - final ByteBuf cancelFrame = activeStreams.getDuplexConnection().awaitFrame(); + final ByteBuf cancelFrame = activeStreams.getConnection().awaitFrame(); FrameAssert.assertThat(cancelFrame) .isNotNull() .typeOf(FrameType.CANCEL) @@ -794,7 +794,7 @@ public void shouldSentCancelFrameExactlyOnce(Scenario scenario) { assertSubscriber.assertNotTerminated(); activeStreams.assertNoActiveStreams(); - Assertions.assertThat(activeStreams.getDuplexConnection().isEmpty()).isTrue(); + Assertions.assertThat(activeStreams.getConnection().isEmpty()).isTrue(); activeStreams.getAllocator().assertHasNoLeaks(); } } diff --git a/today-remoting/src/test/java/infra/remoting/core/ResponderChannelTests.java b/today-remoting/src/test/java/infra/remoting/core/ResponderChannelTests.java index 6194ae9..5e8645e 100644 --- a/today-remoting/src/test/java/infra/remoting/core/ResponderChannelTests.java +++ b/today-remoting/src/test/java/infra/remoting/core/ResponderChannelTests.java @@ -64,7 +64,7 @@ import infra.remoting.internal.subscriber.AssertSubscriber; import infra.remoting.plugins.RequestInterceptor; import infra.remoting.plugins.TestRequestInterceptor; -import infra.remoting.test.util.TestDuplexConnection; +import infra.remoting.test.util.TestConnection; import infra.remoting.test.util.TestSubscriber; import infra.remoting.util.ByteBufPayload; import infra.remoting.util.DefaultPayload; @@ -1203,7 +1203,7 @@ public Mono requestResponse(Payload payload) { public void setAcceptingSocket(Channel acceptingSocket) { this.acceptingSocket = acceptingSocket; - connection = new TestDuplexConnection(alloc()); + connection = new TestConnection(alloc()); connectSub = TestSubscriber.create(); this.prefetch = Integer.MAX_VALUE; super.doInit(); @@ -1216,7 +1216,7 @@ public void setRequestInterceptor(RequestInterceptor requestInterceptor) { public void setAcceptingSocket(Channel acceptingSocket, int prefetch) { this.acceptingSocket = acceptingSocket; - connection = new TestDuplexConnection(alloc()); + connection = new TestConnection(alloc()); connectSub = TestSubscriber.create(); this.prefetch = prefetch; super.doInit(); diff --git a/today-remoting/src/test/java/infra/remoting/core/ResponderOperatorsCommonTests.java b/today-remoting/src/test/java/infra/remoting/core/ResponderOperatorsCommonTests.java index bc42c3b..19b11f5 100755 --- a/today-remoting/src/test/java/infra/remoting/core/ResponderOperatorsCommonTests.java +++ b/today-remoting/src/test/java/infra/remoting/core/ResponderOperatorsCommonTests.java @@ -35,7 +35,7 @@ import infra.remoting.internal.subscriber.AssertSubscriber; import infra.remoting.plugins.RequestInterceptor; import infra.remoting.plugins.TestRequestInterceptor; -import infra.remoting.test.util.TestDuplexConnection; +import infra.remoting.test.util.TestConnection; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import reactor.core.publisher.Operators; @@ -288,7 +288,7 @@ void shouldHandleRequest(Scenario scenario) { TestChannelSupport testRequesterResponderSupport = TestChannelSupport.client(testRequestInterceptor); final LeaksTrackingByteBufAllocator allocator = testRequesterResponderSupport.getAllocator(); - final TestDuplexConnection sender = testRequesterResponderSupport.getDuplexConnection(); + final TestConnection sender = testRequesterResponderSupport.getConnection(); TestPublisher testPublisher = TestPublisher.create(); TestHandler testHandler = new TestHandler(testPublisher, new AssertSubscriber<>(0)); @@ -356,7 +356,7 @@ void shouldHandleFragmentedRequest(Scenario scenario) { TestChannelSupport testRequesterResponderSupport = TestChannelSupport.client(testRequestInterceptor); final LeaksTrackingByteBufAllocator allocator = testRequesterResponderSupport.getAllocator(); - final TestDuplexConnection sender = testRequesterResponderSupport.getDuplexConnection(); + final TestConnection sender = testRequesterResponderSupport.getConnection(); TestPublisher testPublisher = TestPublisher.create(); TestHandler testHandler = new TestHandler(testPublisher, new AssertSubscriber<>(0)); diff --git a/today-remoting/src/test/java/infra/remoting/core/SetupRejectionTests.java b/today-remoting/src/test/java/infra/remoting/core/SetupRejectionTests.java index 2b44909..8c92e4c 100644 --- a/today-remoting/src/test/java/infra/remoting/core/SetupRejectionTests.java +++ b/today-remoting/src/test/java/infra/remoting/core/SetupRejectionTests.java @@ -24,7 +24,7 @@ import io.netty.buffer.ByteBufAllocator; import infra.remoting.Closeable; import infra.remoting.ConnectionSetupPayload; -import infra.remoting.DuplexConnection; +import infra.remoting.Connection; import infra.remoting.Payload; import infra.remoting.Channel; import infra.remoting.ChannelAcceptor; @@ -35,7 +35,7 @@ import infra.remoting.frame.FrameHeaderCodec; import infra.remoting.frame.FrameType; import infra.remoting.frame.SetupFrameCodec; -import infra.remoting.test.util.TestDuplexConnection; +import infra.remoting.test.util.TestConnection; import infra.remoting.transport.ConnectionAcceptor; import infra.remoting.transport.ServerTransport; import infra.remoting.util.DefaultPayload; @@ -73,7 +73,7 @@ void responderRejectSetup() { void requesterStreamsTerminatedOnZeroErrorFrame() { LeaksTrackingByteBufAllocator allocator = LeaksTrackingByteBufAllocator.instrument(ByteBufAllocator.DEFAULT); - TestDuplexConnection conn = new TestDuplexConnection(allocator); + TestConnection conn = new TestConnection(allocator); Sinks.Empty onThisSideClosedSink = Sinks.empty(); RequesterChannel channel = @@ -116,7 +116,7 @@ void requesterStreamsTerminatedOnZeroErrorFrame() { void requesterNewStreamsTerminatedAfterZeroErrorFrame() { LeaksTrackingByteBufAllocator allocator = LeaksTrackingByteBufAllocator.instrument(ByteBufAllocator.DEFAULT); - TestDuplexConnection conn = new TestDuplexConnection(allocator); + TestConnection conn = new TestConnection(allocator); Sinks.Empty onThisSideClosedSink = Sinks.empty(); RequesterChannel channel = new RequesterChannel( @@ -171,7 +171,7 @@ private static class SingleConnectionTransport implements ServerTransport start(ConnectionAcceptor acceptor) { @@ -192,9 +192,9 @@ public void connect() { private static class TestCloseable implements Closeable { - private final DuplexConnection conn; + private final Connection conn; - TestCloseable(ConnectionAcceptor acceptor, DuplexConnection conn) { + TestCloseable(ConnectionAcceptor acceptor, Connection conn) { this.conn = conn; Mono.from(acceptor.accept(conn)).subscribe(notUsed -> { }, err -> conn.dispose()); } diff --git a/today-remoting/src/test/java/infra/remoting/core/TestChannelSupport.java b/today-remoting/src/test/java/infra/remoting/core/TestChannelSupport.java index 5501e49..d83f371 100644 --- a/today-remoting/src/test/java/infra/remoting/core/TestChannelSupport.java +++ b/today-remoting/src/test/java/infra/remoting/core/TestChannelSupport.java @@ -26,14 +26,14 @@ import io.netty.buffer.ByteBufAllocator; import io.netty.buffer.Unpooled; import io.netty.util.CharsetUtil; -import infra.remoting.DuplexConnection; +import infra.remoting.Connection; import infra.remoting.Payload; import infra.remoting.Channel; import infra.remoting.buffer.LeaksTrackingByteBufAllocator; import infra.remoting.frame.FrameType; import infra.remoting.frame.decoder.PayloadDecoder; import infra.remoting.plugins.RequestInterceptor; -import infra.remoting.test.util.TestDuplexConnection; +import infra.remoting.test.util.TestConnection; import infra.remoting.util.ByteBufPayload; import reactor.core.Exceptions; @@ -46,15 +46,15 @@ final class TestChannelSupport extends ChannelSupport implements Channel { final Throwable error; - TestChannelSupport(@Nullable Throwable error, StreamIdProvider streamIdProvider, DuplexConnection connection, + TestChannelSupport(@Nullable Throwable error, StreamIdProvider streamIdProvider, Connection connection, int mtu, int maxFrameLength, int maxInboundPayloadSize, @Nullable RequestInterceptor requestInterceptor) { super(mtu, maxFrameLength, maxInboundPayloadSize, PayloadDecoder.ZERO_COPY, connection, streamIdProvider, (__) -> requestInterceptor); this.error = error; } @Override - public TestDuplexConnection getDuplexConnection() { - return (TestDuplexConnection) super.getDuplexConnection(); + public TestConnection getConnection() { + return (TestConnection) super.getConnection(); } static Payload genericPayload(LeaksTrackingByteBufAllocator allocator) { @@ -169,7 +169,7 @@ public synchronized int addAndGetNextStreamId(FrameHandler frameHandler) { public static TestChannelSupport client( @Nullable Throwable e, @Nullable RequestInterceptor requestInterceptor) { return client( - new TestDuplexConnection( + new TestConnection( LeaksTrackingByteBufAllocator.instrument(ByteBufAllocator.DEFAULT)), 0, FRAME_LENGTH_MASK, @@ -185,7 +185,7 @@ public static TestChannelSupport client(@Nullable Throwable e) { public static TestChannelSupport client( int mtu, int maxFrameLength, int maxInboundPayloadSize, @Nullable Throwable e) { return client( - new TestDuplexConnection( + new TestConnection( LeaksTrackingByteBufAllocator.instrument(ByteBufAllocator.DEFAULT)), mtu, maxFrameLength, @@ -195,7 +195,7 @@ public static TestChannelSupport client( } public static TestChannelSupport client( - TestDuplexConnection duplexConnection, + TestConnection duplexConnection, int mtu, int maxFrameLength, int maxInboundPayloadSize) { @@ -203,7 +203,7 @@ public static TestChannelSupport client( } public static TestChannelSupport client( - TestDuplexConnection duplexConnection, + TestConnection duplexConnection, int mtu, int maxFrameLength, int maxInboundPayloadSize, @@ -213,7 +213,7 @@ public static TestChannelSupport client( } public static TestChannelSupport client( - TestDuplexConnection duplexConnection, + TestConnection duplexConnection, int mtu, int maxFrameLength, int maxInboundPayloadSize, @@ -248,7 +248,7 @@ public static TestChannelSupport client() { public static TestChannelSupport client(RequestInterceptor requestInterceptor) { return client( - new TestDuplexConnection( + new TestConnection( LeaksTrackingByteBufAllocator.instrument(ByteBufAllocator.DEFAULT)), 0, FRAME_LENGTH_MASK, diff --git a/today-remoting/src/test/java/infra/remoting/examples/ws/WebSocketAggregationSample.java b/today-remoting/src/test/java/infra/remoting/examples/ws/WebSocketAggregationSample.java index 8db1c37..b214abb 100644 --- a/today-remoting/src/test/java/infra/remoting/examples/ws/WebSocketAggregationSample.java +++ b/today-remoting/src/test/java/infra/remoting/examples/ws/WebSocketAggregationSample.java @@ -27,8 +27,8 @@ import infra.remoting.core.RemotingServer; import infra.remoting.frame.decoder.PayloadDecoder; import infra.remoting.transport.ConnectionAcceptor; -import infra.remoting.transport.netty.WebsocketDuplexConnection; -import infra.remoting.transport.netty.client.WebsocketClientTransport; +import infra.remoting.transport.websocket.WebsocketClientTransport; +import infra.remoting.transport.websocket.WebsocketConnection; import infra.remoting.util.ByteBufPayload; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; @@ -52,7 +52,7 @@ public static void main(String[] args) { .host("localhost") .port(0) .handle((req, res) -> res.sendWebsocket((in, out) -> connectionAcceptor - .accept(new WebsocketDuplexConnection( + .accept(new WebsocketConnection( (Connection) in.aggregateFrames())) .then(out.neverComplete()))) .bindNow(); diff --git a/today-remoting/src/test/java/infra/remoting/examples/ws/WebSocketHeadersSample.java b/today-remoting/src/test/java/infra/remoting/examples/ws/WebSocketHeadersSample.java index b191e44..65f5a82 100644 --- a/today-remoting/src/test/java/infra/remoting/examples/ws/WebSocketHeadersSample.java +++ b/today-remoting/src/test/java/infra/remoting/examples/ws/WebSocketHeadersSample.java @@ -27,8 +27,8 @@ import infra.remoting.core.RemotingServer; import infra.remoting.frame.decoder.PayloadDecoder; import infra.remoting.transport.ConnectionAcceptor; -import infra.remoting.transport.netty.WebsocketDuplexConnection; -import infra.remoting.transport.netty.client.WebsocketClientTransport; +import infra.remoting.transport.websocket.WebsocketClientTransport; +import infra.remoting.transport.websocket.WebsocketConnection; import infra.remoting.util.ByteBufPayload; import io.netty.handler.codec.http.HttpResponseStatus; import reactor.core.publisher.Flux; @@ -58,7 +58,7 @@ public static void main(String[] args) { if (req.requestHeaders().containsValue("Authorization", "test", true)) { return res.sendWebsocket((in, out) -> connectionAcceptor - .accept(new WebsocketDuplexConnection((Connection) in)) + .accept(new WebsocketConnection((Connection) in)) .then(out.neverComplete())); } res.status(HttpResponseStatus.UNAUTHORIZED); diff --git a/today-remoting/src/test/java/infra/remoting/resume/ClientChannelSessionTests.java b/today-remoting/src/test/java/infra/remoting/resume/ClientChannelSessionTests.java index 08587bc..6867d75 100644 --- a/today-remoting/src/test/java/infra/remoting/resume/ClientChannelSessionTests.java +++ b/today-remoting/src/test/java/infra/remoting/resume/ClientChannelSessionTests.java @@ -34,7 +34,7 @@ import infra.remoting.frame.ResumeOkFrameCodec; import infra.remoting.keepalive.KeepAliveSupport; import infra.remoting.test.util.TestClientTransport; -import infra.remoting.test.util.TestDuplexConnection; +import infra.remoting.test.util.TestConnection; import reactor.core.publisher.Operators; import reactor.test.StepVerifier; import reactor.test.scheduler.VirtualTimeScheduler; @@ -55,20 +55,20 @@ void sessionTimeoutSmokeTest() { transport.connect().subscribe(); - final ResumableDuplexConnection resumableDuplexConnection = - new ResumableDuplexConnection( + final ResumableConnection resumableConnection = + new ResumableConnection( "test", Unpooled.EMPTY_BUFFER, transport.testConnection(), framesStore); - resumableDuplexConnection.receive().subscribe(); + resumableConnection.receive().subscribe(); final ClientChannelSession session = new ClientChannelSession( Unpooled.EMPTY_BUFFER, - resumableDuplexConnection, + resumableConnection, transport.connect().delaySubscription(Duration.ofMillis(1)), c -> { AtomicBoolean firstHandled = new AtomicBoolean(); - return ((TestDuplexConnection) c) + return ((TestConnection) c) .receive() .next() .doOnNext(__ -> firstHandled.set(true)) @@ -177,7 +177,7 @@ void sessionTimeoutSmokeTest() { assertThat(session.isDisposed()).isTrue(); - resumableDuplexConnection.onClose().as(StepVerifier::create).expectComplete().verify(); + resumableConnection.onClose().as(StepVerifier::create).expectComplete().verify(); keepAliveSupport.dispose(); transport.alloc().assertHasNoLeaks(); } @@ -197,20 +197,20 @@ void sessionTerminationOnWrongFrameTest() { transport.connect().subscribe(); - final ResumableDuplexConnection resumableDuplexConnection = - new ResumableDuplexConnection( + final ResumableConnection resumableConnection = + new ResumableConnection( "test", Unpooled.EMPTY_BUFFER, transport.testConnection(), framesStore); - resumableDuplexConnection.receive().subscribe(); + resumableConnection.receive().subscribe(); final ClientChannelSession session = new ClientChannelSession( Unpooled.EMPTY_BUFFER, - resumableDuplexConnection, + resumableConnection, transport.connect().delaySubscription(Duration.ofMillis(1)), c -> { AtomicBoolean firstHandled = new AtomicBoolean(); - return ((TestDuplexConnection) c) + return ((TestConnection) c) .receive() .next() .doOnNext(__ -> firstHandled.set(true)) @@ -307,7 +307,7 @@ void sessionTerminationOnWrongFrameTest() { .typeOf(FrameType.ERROR) .matches(ReferenceCounted::release); - resumableDuplexConnection + resumableConnection .onClose() .as(StepVerifier::create) .expectErrorMessage("RESUME_OK frame must be received before any others") @@ -330,20 +330,20 @@ void shouldErrorWithNoRetriesOnErrorFrameTest() { transport.connect().subscribe(); - final ResumableDuplexConnection resumableDuplexConnection = - new ResumableDuplexConnection( + final ResumableConnection resumableConnection = + new ResumableConnection( "test", Unpooled.EMPTY_BUFFER, transport.testConnection(), framesStore); - resumableDuplexConnection.receive().subscribe(); + resumableConnection.receive().subscribe(); final ClientChannelSession session = new ClientChannelSession( Unpooled.EMPTY_BUFFER, - resumableDuplexConnection, + resumableConnection, transport.connect().delaySubscription(Duration.ofMillis(1)), c -> { AtomicBoolean firstHandled = new AtomicBoolean(); - return ((TestDuplexConnection) c) + return ((TestConnection) c) .receive() .next() .doOnNext(__ -> firstHandled.set(true)) @@ -404,7 +404,7 @@ void shouldErrorWithNoRetriesOnErrorFrameTest() { assertThat(session.s).isNotNull(); assertThat(session.isDisposed()).isTrue(); - resumableDuplexConnection + resumableConnection .onClose() .as(StepVerifier::create) .expectError(RejectedResumeException.class) @@ -427,20 +427,20 @@ void shouldTerminateConnectionOnIllegalStateInKeepAliveFrame() { transport.connect().subscribe(); - final ResumableDuplexConnection resumableDuplexConnection = - new ResumableDuplexConnection( + final ResumableConnection resumableConnection = + new ResumableConnection( "test", Unpooled.EMPTY_BUFFER, transport.testConnection(), framesStore); - resumableDuplexConnection.receive().subscribe(); + resumableConnection.receive().subscribe(); final ClientChannelSession session = new ClientChannelSession( Unpooled.EMPTY_BUFFER, - resumableDuplexConnection, + resumableConnection, transport.connect().delaySubscription(Duration.ofMillis(1)), c -> { AtomicBoolean firstHandled = new AtomicBoolean(); - return ((TestDuplexConnection) c) + return ((TestConnection) c) .receive() .next() .doOnNext(__ -> firstHandled.set(true)) @@ -482,7 +482,7 @@ void shouldTerminateConnectionOnIllegalStateInKeepAliveFrame() { .typeOf(FrameType.ERROR) .matches(ReferenceCounted::release); - resumableDuplexConnection.onClose().as(StepVerifier::create).expectError().verify(); + resumableConnection.onClose().as(StepVerifier::create).expectError().verify(); keepAliveSupport.dispose(); transport.alloc().assertHasNoLeaks(); } diff --git a/today-remoting/src/test/java/infra/remoting/resume/DisconnectableClientTransport.java b/today-remoting/src/test/java/infra/remoting/resume/DisconnectableClientTransport.java index 8b3d90e..e104d3f 100644 --- a/today-remoting/src/test/java/infra/remoting/resume/DisconnectableClientTransport.java +++ b/today-remoting/src/test/java/infra/remoting/resume/DisconnectableClientTransport.java @@ -21,7 +21,7 @@ import java.time.Duration; import java.util.concurrent.atomic.AtomicReference; -import infra.remoting.DuplexConnection; +import infra.remoting.Connection; import infra.remoting.transport.ClientTransport; import reactor.core.publisher.Mono; @@ -29,7 +29,7 @@ class DisconnectableClientTransport implements ClientTransport { private final ClientTransport clientTransport; - private final AtomicReference curConnection = new AtomicReference<>(); + private final AtomicReference curConnection = new AtomicReference<>(); private long nextConnectPermitMillis; @@ -38,7 +38,7 @@ public DisconnectableClientTransport(ClientTransport clientTransport) { } @Override - public Mono connect() { + public Mono connect() { return Mono.defer(() -> now() < nextConnectPermitMillis ? Mono.error(new ClosedChannelException()) @@ -62,7 +62,7 @@ public void disconnectPermanently() { } public void disconnectFor(Duration cooldown) { - DuplexConnection cur = curConnection.getAndSet(null); + Connection cur = curConnection.getAndSet(null); if (cur != null) { nextConnectPermitMillis = now() + cooldown.toMillis(); cur.dispose(); diff --git a/today-remoting/src/test/java/infra/remoting/resume/InMemoryResumeStoreTests.java b/today-remoting/src/test/java/infra/remoting/resume/InMemoryResumeStoreTests.java index 549a13a..427808d 100644 --- a/today-remoting/src/test/java/infra/remoting/resume/InMemoryResumeStoreTests.java +++ b/today-remoting/src/test/java/infra/remoting/resume/InMemoryResumeStoreTests.java @@ -294,7 +294,7 @@ void sendingVsReconnectRaceTest(boolean withLateSubscriber) { final Consumer consumer = f -> { - if (ResumableDuplexConnection.isResumableFrame(f)) { + if (ResumableConnection.isResumableFrame(f)) { receivedPosition.addAndGet(f.readableBytes()); receivedFrames.offer(f); return; diff --git a/today-remoting/src/test/java/infra/remoting/resume/ServerChannelSessionTests.java b/today-remoting/src/test/java/infra/remoting/resume/ServerChannelSessionTests.java index 1bd2004..02057a2 100644 --- a/today-remoting/src/test/java/infra/remoting/resume/ServerChannelSessionTests.java +++ b/today-remoting/src/test/java/infra/remoting/resume/ServerChannelSessionTests.java @@ -48,16 +48,16 @@ void sessionTimeoutSmokeTest() { transport.connect().subscribe(); - final ResumableDuplexConnection resumableDuplexConnection = - new ResumableDuplexConnection( + final ResumableConnection resumableConnection = + new ResumableConnection( "test", Unpooled.EMPTY_BUFFER, transport.testConnection(), framesStore); - resumableDuplexConnection.receive().subscribe(); + resumableConnection.receive().subscribe(); final ServerChannelSession session = new ServerChannelSession( Unpooled.EMPTY_BUFFER, - resumableDuplexConnection, + resumableConnection, transport.testConnection(), framesStore, Duration.ofMinutes(1), @@ -142,7 +142,7 @@ void sessionTimeoutSmokeTest() { .typeOf(FrameType.ERROR) .matches(ReferenceCounted::release); - resumableDuplexConnection.onClose().as(StepVerifier::create).expectComplete().verify(); + resumableConnection.onClose().as(StepVerifier::create).expectComplete().verify(); transport.alloc().assertHasNoLeaks(); } finally { @@ -160,16 +160,16 @@ void shouldTerminateConnectionOnIllegalStateInKeepAliveFrame() { transport.connect().subscribe(); - final ResumableDuplexConnection resumableDuplexConnection = - new ResumableDuplexConnection( + final ResumableConnection resumableConnection = + new ResumableConnection( "test", Unpooled.EMPTY_BUFFER, transport.testConnection(), framesStore); - resumableDuplexConnection.receive().subscribe(); + resumableConnection.receive().subscribe(); final ServerChannelSession session = new ServerChannelSession( Unpooled.EMPTY_BUFFER, - resumableDuplexConnection, + resumableConnection, transport.testConnection(), framesStore, Duration.ofMinutes(1), @@ -200,7 +200,7 @@ void shouldTerminateConnectionOnIllegalStateInKeepAliveFrame() { .typeOf(FrameType.ERROR) .matches(ReferenceCounted::release); - resumableDuplexConnection.onClose().as(StepVerifier::create).expectError().verify(); + resumableConnection.onClose().as(StepVerifier::create).expectError().verify(); keepAliveSupport.dispose(); transport.alloc().assertHasNoLeaks(); } diff --git a/today-remoting/src/test/java/infra/remoting/test/util/LocalDuplexConnection.java b/today-remoting/src/test/java/infra/remoting/test/util/LocalConnection.java similarity index 96% rename from today-remoting/src/test/java/infra/remoting/test/util/LocalDuplexConnection.java rename to today-remoting/src/test/java/infra/remoting/test/util/LocalConnection.java index e3a788c..439f07a 100644 --- a/today-remoting/src/test/java/infra/remoting/test/util/LocalDuplexConnection.java +++ b/today-remoting/src/test/java/infra/remoting/test/util/LocalConnection.java @@ -23,7 +23,7 @@ import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufAllocator; -import infra.remoting.DuplexConnection; +import infra.remoting.Connection; import infra.remoting.ProtocolErrorException; import infra.remoting.frame.ErrorFrameCodec; import reactor.core.CoreSubscriber; @@ -33,14 +33,14 @@ import reactor.core.publisher.Operators; import reactor.core.publisher.Sinks; -public class LocalDuplexConnection implements DuplexConnection { +public class LocalConnection implements Connection { private final ByteBufAllocator allocator; private final Sinks.Many send; private final Sinks.Many receive; private final Sinks.Empty onClose; private final String name; - public LocalDuplexConnection( + public LocalConnection( String name, ByteBufAllocator allocator, Sinks.Many send, diff --git a/today-remoting/src/test/java/infra/remoting/test/util/TestClientTransport.java b/today-remoting/src/test/java/infra/remoting/test/util/TestClientTransport.java index 67acf86..b0d9314 100644 --- a/today-remoting/src/test/java/infra/remoting/test/util/TestClientTransport.java +++ b/today-remoting/src/test/java/infra/remoting/test/util/TestClientTransport.java @@ -19,30 +19,31 @@ import java.time.Duration; -import io.netty.buffer.ByteBufAllocator; -import infra.remoting.DuplexConnection; +import infra.remoting.Connection; import infra.remoting.buffer.LeaksTrackingByteBufAllocator; import infra.remoting.transport.ClientTransport; +import io.netty.buffer.ByteBufAllocator; import reactor.core.publisher.Mono; import static infra.remoting.frame.FrameLengthCodec.FRAME_LENGTH_MASK; public class TestClientTransport implements ClientTransport { + private final LeaksTrackingByteBufAllocator allocator = LeaksTrackingByteBufAllocator.instrument( ByteBufAllocator.DEFAULT, Duration.ofSeconds(1), "client"); - private volatile TestDuplexConnection testDuplexConnection; + private volatile TestConnection testConnection; int maxFrameLength = FRAME_LENGTH_MASK; @Override - public Mono connect() { - return Mono.fromSupplier(() -> testDuplexConnection = new TestDuplexConnection(allocator)); + public Mono connect() { + return Mono.fromSupplier(() -> testConnection = new TestConnection(allocator)); } - public TestDuplexConnection testConnection() { - return testDuplexConnection; + public TestConnection testConnection() { + return testConnection; } public LeaksTrackingByteBufAllocator alloc() { diff --git a/today-remoting/src/test/java/infra/remoting/test/util/TestDuplexConnection.java b/today-remoting/src/test/java/infra/remoting/test/util/TestConnection.java similarity index 75% rename from today-remoting/src/test/java/infra/remoting/test/util/TestDuplexConnection.java rename to today-remoting/src/test/java/infra/remoting/test/util/TestConnection.java index 197ca4a..80593b5 100644 --- a/today-remoting/src/test/java/infra/remoting/test/util/TestDuplexConnection.java +++ b/today-remoting/src/test/java/infra/remoting/test/util/TestConnection.java @@ -27,11 +27,11 @@ import infra.lang.NonNull; import infra.logging.Logger; import infra.logging.LoggerFactory; -import io.netty.buffer.ByteBuf; -import infra.remoting.DuplexConnection; +import infra.remoting.Connection; import infra.remoting.ProtocolErrorException; import infra.remoting.buffer.LeaksTrackingByteBufAllocator; import infra.remoting.frame.ErrorFrameCodec; +import io.netty.buffer.ByteBuf; import reactor.core.CoreSubscriber; import reactor.core.publisher.DirectProcessor; import reactor.core.publisher.Flux; @@ -41,12 +41,12 @@ import reactor.core.publisher.Operators; /** - * An implementation of {@link DuplexConnection} that provides functionality to modify the behavior + * An implementation of {@link Connection} that provides functionality to modify the behavior * dynamically. */ -public class TestDuplexConnection implements DuplexConnection { +public class TestConnection implements Connection { - private static final Logger logger = LoggerFactory.getLogger(TestDuplexConnection.class); + private static final Logger logger = LoggerFactory.getLogger(TestConnection.class); private final LinkedBlockingQueue sent; @@ -59,7 +59,7 @@ public class TestDuplexConnection implements DuplexConnection { private volatile double availability = 1; private volatile int initialSendRequestN = Integer.MAX_VALUE; - public TestDuplexConnection(LeaksTrackingByteBufAllocator allocator) { + public TestConnection(LeaksTrackingByteBufAllocator allocator) { this.allocator = allocator; this.sent = new LinkedBlockingQueue<>(); this.received = DirectProcessor.create(); @@ -81,31 +81,29 @@ public void sendFrame(int streamId, ByteBuf frame) { @Override public Flux receive() { - return received.transform( - Operators.lift( - (__, actual) -> - new CoreSubscriber() { - @Override - public void onSubscribe(Subscription s) { - actual.onSubscribe(s); - } - - @Override - public void onNext(ByteBuf byteBuf) { - actual.onNext(byteBuf); - byteBuf.release(); - } - - @Override - public void onError(Throwable t) { - actual.onError(t); - } - - @Override - public void onComplete() { - actual.onComplete(); - } - })); + return received.transform(Operators.lift((__, actual) -> + new CoreSubscriber<>() { + @Override + public void onSubscribe(Subscription s) { + actual.onSubscribe(s); + } + + @Override + public void onNext(ByteBuf byteBuf) { + actual.onNext(byteBuf); + byteBuf.release(); + } + + @Override + public void onError(Throwable t) { + actual.onError(t); + } + + @Override + public void onComplete() { + actual.onComplete(); + } + })); } @Override @@ -130,7 +128,7 @@ public LeaksTrackingByteBufAllocator alloc() { @Override public SocketAddress remoteAddress() { - return new TestLocalSocketAddress("TestDuplexConnection"); + return new TestLocalSocketAddress("TestConnection"); } @Override diff --git a/today-remoting/src/test/java/infra/remoting/test/util/TestServerTransport.java b/today-remoting/src/test/java/infra/remoting/test/util/TestServerTransport.java index 836fb55..3bc2bba 100644 --- a/today-remoting/src/test/java/infra/remoting/test/util/TestServerTransport.java +++ b/today-remoting/src/test/java/infra/remoting/test/util/TestServerTransport.java @@ -28,8 +28,8 @@ import static infra.remoting.frame.FrameLengthCodec.FRAME_LENGTH_MASK; public class TestServerTransport implements ServerTransport { - private final Sinks.One connSink = Sinks.one(); - private TestDuplexConnection connection; + private final Sinks.One connSink = Sinks.one(); + private TestConnection connection; private final LeaksTrackingByteBufAllocator allocator = LeaksTrackingByteBufAllocator.instrument(ByteBufAllocator.DEFAULT); @@ -63,14 +63,14 @@ public boolean isDisposed() { } private void disposeConnection() { - TestDuplexConnection c = connection; + TestConnection c = connection; if (c != null) { c.dispose(); } } - public TestDuplexConnection connect() { - TestDuplexConnection c = new TestDuplexConnection(allocator); + public TestConnection connect() { + TestConnection c = new TestConnection(allocator); connection = c; connSink.tryEmitValue(c); return c; diff --git a/today-remoting/src/testFixtures/java/infra/remoting/test/TestDuplexConnection.java b/today-remoting/src/testFixtures/java/infra/remoting/test/TestConnection.java similarity index 97% rename from today-remoting/src/testFixtures/java/infra/remoting/test/TestDuplexConnection.java rename to today-remoting/src/testFixtures/java/infra/remoting/test/TestConnection.java index f10891f..729a208 100644 --- a/today-remoting/src/testFixtures/java/infra/remoting/test/TestDuplexConnection.java +++ b/today-remoting/src/testFixtures/java/infra/remoting/test/TestConnection.java @@ -25,7 +25,7 @@ import infra.lang.Nullable; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufAllocator; -import infra.remoting.DuplexConnection; +import infra.remoting.Connection; import infra.remoting.ProtocolErrorException; import infra.remoting.frame.PayloadFrameCodec; import reactor.core.CoreSubscriber; @@ -36,14 +36,14 @@ import reactor.core.publisher.Operators; import reactor.core.publisher.Sinks; -public class TestDuplexConnection implements DuplexConnection { +public class TestConnection implements Connection { final ByteBufAllocator allocator; final Sinks.Many inbound = Sinks.unsafe().many().unicast().onBackpressureError(); final Sinks.Many outbound = Sinks.unsafe().many().unicast().onBackpressureError(); final Sinks.One close = Sinks.one(); - public TestDuplexConnection( + public TestConnection( CoreSubscriber outboundSubscriber, boolean trackLeaks) { this.outbound.asFlux().subscribe(outboundSubscriber); this.allocator = diff --git a/today-remoting/src/testFixtures/java/infra/remoting/test/TransportPair.java b/today-remoting/src/testFixtures/java/infra/remoting/test/TransportPair.java index 2d391ff..fd10343 100644 --- a/today-remoting/src/testFixtures/java/infra/remoting/test/TransportPair.java +++ b/today-remoting/src/testFixtures/java/infra/remoting/test/TransportPair.java @@ -31,7 +31,7 @@ import io.netty.util.ReferenceCounted; import io.netty.util.ResourceLeakDetector; import infra.remoting.Closeable; -import infra.remoting.DuplexConnection; +import infra.remoting.Connection; import infra.remoting.Channel; import infra.remoting.ProtocolErrorException; import infra.remoting.core.ChannelConnector; @@ -126,7 +126,7 @@ public TransportPair(Supplier addressSupplier, .interceptors(registry -> { if (runServerWithAsyncInterceptors && !withResumability) { logger.info("Perform Integration Test with Async Interceptors Enabled For Server"); - registry.forConnection((type, duplexConnection) -> new AsyncDuplexConnection(duplexConnection, "server")) + registry.forConnection((type, duplexConnection) -> new AsyncConnection(duplexConnection, "server")) .forChannelAcceptor(delegate -> (connectionSetupPayload, sendingSocket) -> delegate.accept(connectionSetupPayload, sendingSocket) .subscribeOn(Schedulers.parallel())); } @@ -134,7 +134,7 @@ public TransportPair(Supplier addressSupplier, if (withResumability) { registry.forConnection((type, duplexConnection) -> type == ConnectionDecorator.Type.SOURCE - ? new DisconnectingDuplexConnection( + ? new DisconnectingConnection( "Server", duplexConnection, Duration.ofMillis(ThreadLocalRandom.current().nextInt(100, 1000))) @@ -162,7 +162,7 @@ public TransportPair(Supplier addressSupplier, if (runClientWithAsyncInterceptors && !withResumability) { logger.info("Perform Integration Test with Async Interceptors Enabled For Client"); registry.forConnection((type, duplexConnection) -> - new AsyncDuplexConnection(duplexConnection, "client")) + new AsyncConnection(duplexConnection, "client")) .forChannelAcceptor(delegate -> (connectionSetupPayload, sendingSocket) -> delegate.accept(connectionSetupPayload, sendingSocket) .subscribeOn(Schedulers.parallel())); @@ -171,7 +171,7 @@ public TransportPair(Supplier addressSupplier, if (withResumability) { registry.forConnection((type, duplexConnection) -> type == ConnectionDecorator.Type.SOURCE - ? new DisconnectingDuplexConnection( + ? new DisconnectingConnection( "Client", duplexConnection, Duration.ofMillis( @@ -243,31 +243,31 @@ public void awaitClosed(Duration timeout) { logger.info("TransportPair has been terminated"); } - private static class AsyncDuplexConnection implements DuplexConnection { + private static class AsyncConnection implements Connection { - private final DuplexConnection duplexConnection; + private final Connection connection; private String tag; private final ByteBufReleaserOperator bufReleaserOperator; - public AsyncDuplexConnection(DuplexConnection duplexConnection, String tag) { - this.duplexConnection = duplexConnection; + public AsyncConnection(Connection connection, String tag) { + this.connection = connection; this.tag = tag; this.bufReleaserOperator = new ByteBufReleaserOperator(); } @Override public void sendFrame(int streamId, ByteBuf frame) { - duplexConnection.sendFrame(streamId, frame); + connection.sendFrame(streamId, frame); } @Override public void sendErrorAndClose(ProtocolErrorException e) { - duplexConnection.sendErrorAndClose(e); + connection.sendErrorAndClose(e); } @Override public Flux receive() { - return duplexConnection + return connection .receive() .doOnTerminate(() -> logger.info("[" + this + "] Receive is done before PO")) .subscribeOn(Schedulers.boundedElastic()) @@ -283,17 +283,17 @@ public Flux receive() { @Override public ByteBufAllocator alloc() { - return duplexConnection.alloc(); + return connection.alloc(); } @Override public SocketAddress remoteAddress() { - return duplexConnection.remoteAddress(); + return connection.remoteAddress(); } @Override public Mono onClose() { - return Mono.whenDelayError(duplexConnection.onClose() + return Mono.whenDelayError(connection.onClose() .doOnTerminate(() -> logger.info("[" + this + "] Source Connection is done")), bufReleaserOperator .onClose() @@ -302,14 +302,14 @@ public Mono onClose() { @Override public void dispose() { - duplexConnection.dispose(); + connection.dispose(); } @Override public String toString() { - return "AsyncDuplexConnection{" + return "AsyncConnection{" + "duplexConnection=" - + duplexConnection + + connection + ", tag='" + tag + '\'' @@ -319,14 +319,14 @@ public String toString() { } } - private static class DisconnectingDuplexConnection implements DuplexConnection { + private static class DisconnectingConnection implements Connection { private final String tag; - final DuplexConnection source; + final Connection source; final Duration delay; final Swap disposables = Disposables.swap(); - DisconnectingDuplexConnection(String tag, DuplexConnection source, Duration delay) { + DisconnectingConnection(String tag, Connection source, Duration delay) { this.tag = tag; this.source = source; this.delay = delay; @@ -388,7 +388,7 @@ public SocketAddress remoteAddress() { @Override public String toString() { - return "DisconnectingDuplexConnection{" + return "DisconnectingConnection{" + "tag='" + tag + '\'' From 38cecdf223e1e04c8fc282f9599d271e046b58dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Tue, 5 Aug 2025 21:44:30 +0800 Subject: [PATCH 028/104] :recycle: --- .../src/main/java/infra/remoting/Payload.java | 7 ++ .../frame/decoder/ZeroCopyPayloadDecoder.java | 6 +- .../remoting/protocol/ProtocolFrame.java | 66 ++++++++----------- .../infra/remoting/util/ByteBufPayload.java | 7 ++ .../infra/remoting/util/DefaultPayload.java | 7 ++ .../infra/remoting/util/EmptyPayload.java | 8 ++- 6 files changed, 58 insertions(+), 43 deletions(-) diff --git a/today-remoting/src/main/java/infra/remoting/Payload.java b/today-remoting/src/main/java/infra/remoting/Payload.java index d55035f..02f7008 100644 --- a/today-remoting/src/main/java/infra/remoting/Payload.java +++ b/today-remoting/src/main/java/infra/remoting/Payload.java @@ -91,6 +91,13 @@ public interface Payload extends ReferenceCounted { @Override Payload touch(Object hint); + /** + * Readable bytes + */ + default int length() { + return metadata().readableBytes() + data().readableBytes(); + } + default ByteBuffer getMetadata() { return sliceMetadata().nioBuffer(); } diff --git a/today-remoting/src/main/java/infra/remoting/frame/decoder/ZeroCopyPayloadDecoder.java b/today-remoting/src/main/java/infra/remoting/frame/decoder/ZeroCopyPayloadDecoder.java index 6b2f0f4..7733b8d 100644 --- a/today-remoting/src/main/java/infra/remoting/frame/decoder/ZeroCopyPayloadDecoder.java +++ b/today-remoting/src/main/java/infra/remoting/frame/decoder/ZeroCopyPayloadDecoder.java @@ -38,10 +38,10 @@ public class ZeroCopyPayloadDecoder implements PayloadDecoder { @Override public Payload decode(ByteBuf byteBuf) { - ByteBuf m; - ByteBuf d; FrameType type = FrameHeaderCodec.frameType(byteBuf); - m = switch (type) { + + ByteBuf d; + ByteBuf m = switch (type) { case REQUEST_FNF -> { d = RequestFireAndForgetFrameCodec.data(byteBuf); yield RequestFireAndForgetFrameCodec.metadata(byteBuf); diff --git a/today-remoting/src/main/java/infra/remoting/protocol/ProtocolFrame.java b/today-remoting/src/main/java/infra/remoting/protocol/ProtocolFrame.java index e525290..cdafaae 100644 --- a/today-remoting/src/main/java/infra/remoting/protocol/ProtocolFrame.java +++ b/today-remoting/src/main/java/infra/remoting/protocol/ProtocolFrame.java @@ -20,7 +20,9 @@ import java.util.concurrent.Flow; import infra.lang.Nullable; +import infra.remoting.Payload; import infra.remoting.frame.FrameType; +import infra.remoting.frame.decoder.PayloadDecoder; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufAllocator; import io.netty.buffer.ByteBufUtil; @@ -58,10 +60,7 @@ public class ProtocolFrame { public final FrameType frameType; - public final Metadata metadata; - - @Nullable - public final ByteBuf data; + public final Payload payload; private final int flags; @@ -70,23 +69,20 @@ public class ProtocolFrame { @Nullable private FrameType syntheticFrameType; - public ProtocolFrame(int streamId, FrameType frameType, int flags, Metadata metadata, ByteBuf data) { + public ProtocolFrame(int streamId, FrameType frameType, int flags, Payload payload) { this.streamId = streamId; this.frameType = frameType; this.flags = flags; - this.metadata = metadata; - this.data = data; + this.payload = payload; this.typeAndFlags = 0; } - public ProtocolFrame(int streamId, FrameType frameType, int flags, - int typeAndFlags, Metadata metadata, ByteBuf data) { + public ProtocolFrame(int streamId, FrameType frameType, int flags, int typeAndFlags, Payload payload) { this.streamId = streamId; this.frameType = frameType; this.flags = flags; this.typeAndFlags = typeAndFlags; - this.metadata = metadata; - this.data = data; + this.payload = payload; } public int getStreamId() { @@ -98,8 +94,8 @@ public FrameType syntheticFrameType() { if (result == null) { result = frameType; if (result == FrameType.PAYLOAD) { - boolean next = (flags & FLAGS_N) == FLAGS_N; - boolean complete = (flags & FLAGS_C) == FLAGS_C; + boolean next = hasFlag(FLAGS_N); + boolean complete = hasFlag(FLAGS_C); if (next && complete) { result = FrameType.NEXT_COMPLETE; } @@ -119,7 +115,7 @@ else if (next) { } public boolean hasMetadata() { - return metadata != Metadata.EMPTY; + return payload.hasMetadata(); } public boolean hasFollows() { @@ -130,25 +126,22 @@ public boolean hasComplete() { return hasFlag(flags, FLAGS_C); } - public Metadata getMetadata() { - return metadata; + public boolean hasFlag(int flag) { + return (flags & flag) == flag; } public int getLength() { - if (data != null) { - return HEADER_SIZE + data.readableBytes(); - } - return HEADER_SIZE; + return HEADER_SIZE + payload.length(); } public void release() { - if (data != null) { - data.release(); + if (payload != null) { + payload.release(); } } public ByteBuf serialize(ByteBufAllocator allocator) { - if (!frameType.canHaveMetadata() && ((flags & FLAGS_M) == FLAGS_M)) { + if (!frameType.canHaveMetadata() && hasFlag(FLAGS_M)) { throw new IllegalStateException("bad value for metadata flag"); } @@ -168,9 +161,14 @@ public String toString() { .append(" Length: ") .append(getLength()); + if (hasMetadata()) { + builder.append("\nMetadata:\n"); + ByteBufUtil.appendPrettyHexDump(builder, payload.metadata()); + } + builder.append("\nData:\n"); - if (data != null) { - ByteBufUtil.appendPrettyHexDump(builder, data); + if (payload != null) { + ByteBufUtil.appendPrettyHexDump(builder, payload.data()); } else { ByteBufUtil.appendPrettyHexDump(builder, Unpooled.EMPTY_BUFFER); @@ -188,24 +186,14 @@ public static boolean hasFlag(int flags, int flag) { * @param frame frame buffer * @throws ProtocolParsingException protocol parsing errors */ - public static ProtocolFrame parse(ByteBuf frame) throws ProtocolParsingException { - int streamId = frame.readUnsignedShort(); + public static ProtocolFrame parse(ByteBuf frame, PayloadDecoder decoder) throws ProtocolParsingException { + int streamId = frame.readInt(); int typeAndFlags = frame.readShort() & 0xFFFF; FrameType nativeFrameType = FrameType.forEncodedType(typeAndFlags >> FRAME_TYPE_SHIFT); final int flags = typeAndFlags & FRAME_FLAGS_MASK; - boolean hasMetadata = hasFlag(flags, FLAGS_M); - if (hasMetadata) { - int length = decodeLength(frame); - ByteBuf metadataBuf = frame.readSlice(length); - - } - ByteBuf data = frame.readableBytes() > 0 ? frame.readSlice(frame.readableBytes()) : Unpooled.EMPTY_BUFFER; - return new ProtocolFrame(streamId, nativeFrameType, flags, typeAndFlags, Metadata.EMPTY, data); - } - - private static int decodeLength(ByteBuf byteBuf) { - return byteBuf.readUnsignedMedium(); + Payload payload = decoder.decode(frame); + return new ProtocolFrame(streamId, nativeFrameType, flags, typeAndFlags, payload); } } diff --git a/today-remoting/src/main/java/infra/remoting/util/ByteBufPayload.java b/today-remoting/src/main/java/infra/remoting/util/ByteBufPayload.java index d4363bb..dc4801d 100644 --- a/today-remoting/src/main/java/infra/remoting/util/ByteBufPayload.java +++ b/today-remoting/src/main/java/infra/remoting/util/ByteBufPayload.java @@ -125,6 +125,13 @@ public static Payload create(Payload payload) { payload.hasMetadata() ? payload.sliceMetadata().retain() : null); } + @Override + public int length() { + return metadata == null + ? data.readableBytes() + : metadata.readableBytes() + data.readableBytes(); + } + @Override public boolean hasMetadata() { ensureAccessible(); diff --git a/today-remoting/src/main/java/infra/remoting/util/DefaultPayload.java b/today-remoting/src/main/java/infra/remoting/util/DefaultPayload.java index b27fa4b..9efcd80 100644 --- a/today-remoting/src/main/java/infra/remoting/util/DefaultPayload.java +++ b/today-remoting/src/main/java/infra/remoting/util/DefaultPayload.java @@ -125,6 +125,13 @@ private static byte[] toBytes(ByteBuf byteBuf) { return bytes; } + @Override + public int length() { + return metadata == null + ? data.remaining() + : metadata.remaining() + data.remaining(); + } + @Override public boolean hasMetadata() { return metadata != null; diff --git a/today-remoting/src/main/java/infra/remoting/util/EmptyPayload.java b/today-remoting/src/main/java/infra/remoting/util/EmptyPayload.java index 61bd99a..8d8fe1e 100644 --- a/today-remoting/src/main/java/infra/remoting/util/EmptyPayload.java +++ b/today-remoting/src/main/java/infra/remoting/util/EmptyPayload.java @@ -24,7 +24,13 @@ public class EmptyPayload implements Payload { public static final EmptyPayload INSTANCE = new EmptyPayload(); - private EmptyPayload() { } + private EmptyPayload() { + } + + @Override + public int length() { + return 0; + } @Override public boolean hasMetadata() { From 9b68cb7ebcb0c0316d894d1c4fcaa4b83fce698f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Tue, 5 Aug 2025 22:12:20 +0800 Subject: [PATCH 029/104] :art: --- .../java/infra/remoting/core/ServerSetup.java | 3 +- .../remoting/resume/ClientChannelSession.java | 185 ++++++-------- .../infra/remoting/resume/ClientResume.java | 40 --- .../resume/InMemoryResumableFramesStore.java | 175 ++++++------- .../remoting/resume/ResumableConnection.java | 229 +++++++----------- .../remoting/resume/ResumableFramesStore.java | 17 +- .../remoting/resume/ServerChannelSession.java | 91 +++---- .../infra/remoting/resume/SessionManager.java | 19 +- .../resume/ClientChannelSessionTests.java | 8 +- 9 files changed, 298 insertions(+), 469 deletions(-) delete mode 100644 today-remoting/src/main/java/infra/remoting/resume/ClientResume.java diff --git a/today-remoting/src/main/java/infra/remoting/core/ServerSetup.java b/today-remoting/src/main/java/infra/remoting/core/ServerSetup.java index 36a80e3..3e97fdf 100644 --- a/today-remoting/src/main/java/infra/remoting/core/ServerSetup.java +++ b/today-remoting/src/main/java/infra/remoting/core/ServerSetup.java @@ -147,12 +147,11 @@ public Mono acceptChannelResume(ByteBuf frame, Connection connection) { ServerChannelSession session = sessionManager.get(ResumeFrameCodec.token(frame)); if (session != null) { session.resumeWith(frame, connection); - return connection.onClose(); } else { sendError(connection, new RejectedResumeException("unknown resume token")); - return connection.onClose(); } + return connection.onClose(); } @Override diff --git a/today-remoting/src/main/java/infra/remoting/resume/ClientChannelSession.java b/today-remoting/src/main/java/infra/remoting/resume/ClientChannelSession.java index 6850a37..abcbfae 100644 --- a/today-remoting/src/main/java/infra/remoting/resume/ClientChannelSession.java +++ b/today-remoting/src/main/java/infra/remoting/resume/ClientChannelSession.java @@ -35,7 +35,6 @@ import infra.remoting.frame.ResumeOkFrameCodec; import infra.remoting.keepalive.KeepAliveSupport; import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufAllocator; import io.netty.util.CharsetUtil; import reactor.core.CoreSubscriber; import reactor.core.Disposable; @@ -44,106 +43,80 @@ import reactor.util.function.Tuple2; import reactor.util.retry.Retry; -public class ClientChannelSession implements ChannelSession, ResumeStateHolder, - CoreSubscriber> { +public class ClientChannelSession implements ChannelSession, ResumeStateHolder, CoreSubscriber> { private static final Logger logger = LoggerFactory.getLogger(ClientChannelSession.class); - final ResumableConnection resumableConnection; - final Mono> connectionFactory; - final ResumableFramesStore resumableFramesStore; + private final ResumableConnection resumableConnection; + private final Mono> connectionFactory; + private final ResumableFramesStore resumableFramesStore; - final ByteBufAllocator allocator; - final Duration resumeSessionDuration; - final Retry retry; - final boolean cleanupStoreOnKeepAlive; - final ByteBuf resumeToken; - final String session; - final Disposable reconnectDisposable; + private final Duration resumeSessionDuration; + private final Retry retry; + private final boolean cleanupStoreOnKeepAlive; + private final ByteBuf resumeToken; + private final String session; + private final Disposable reconnectDisposable; volatile Subscription s; static final AtomicReferenceFieldUpdater S = AtomicReferenceFieldUpdater.newUpdater(ClientChannelSession.class, Subscription.class, "s"); - KeepAliveSupport keepAliveSupport; - - public ClientChannelSession( - ByteBuf resumeToken, - ResumableConnection resumableConnection, - Mono connectionFactory, - Function>> connectionTransformer, - ResumableFramesStore resumableFramesStore, - Duration resumeSessionDuration, - Retry retry, - boolean cleanupStoreOnKeepAlive) { - this.resumeToken = resumeToken; + private KeepAliveSupport keepAliveSupport; + + public ClientChannelSession(ByteBuf resumeToken, ResumableConnection resumableConnection, + Mono connectionFactory, Function>> connectionTransformer, + ResumableFramesStore resumableFramesStore, Duration resumeSessionDuration, Retry retry, boolean cleanupStoreOnKeepAlive) { + this.retry = retry; this.session = resumeToken.toString(CharsetUtil.UTF_8); - this.connectionFactory = - connectionFactory - .doOnDiscard( - Connection.class, - c -> { - final ConnectionErrorException connectionErrorException = - new ConnectionErrorException("resumption_server=[Session Expired]"); - c.sendErrorAndClose(connectionErrorException); - c.receive().subscribe(); - }) - .flatMap( - dc -> { - final long impliedPosition = resumableFramesStore.frameImpliedPosition(); - final long position = resumableFramesStore.framePosition(); - dc.sendFrame( - 0, - ResumeFrameCodec.encode( - dc.alloc(), - resumeToken.retain(), - // server uses this to release its cache - impliedPosition, // observed on the client side - // server uses this to check whether there is no mismatch - position // sent from the client sent - )); - - if (logger.isDebugEnabled()) { - logger.debug( - "Side[client]|Session[{}]. ResumeFrame[impliedPosition[{}], position[{}]] has been sent.", - session, - impliedPosition, - position); - } - - return connectionTransformer.apply(dc); - }) - .doOnDiscard(Tuple2.class, this::tryReestablishSession); + this.resumeToken = resumeToken; + this.resumableConnection = resumableConnection; this.resumableFramesStore = resumableFramesStore; - this.allocator = resumableConnection.alloc(); this.resumeSessionDuration = resumeSessionDuration; - this.retry = retry; this.cleanupStoreOnKeepAlive = cleanupStoreOnKeepAlive; - this.resumableConnection = resumableConnection; - resumableConnection.onClose().doFinally(__ -> dispose()).subscribe(); + this.connectionFactory = connectionFactory + .doOnDiscard(Connection.class, c -> { + final ConnectionErrorException connectionErrorException = + new ConnectionErrorException("resumption_server=[Session Expired]"); + c.sendErrorAndClose(connectionErrorException); + c.receive().subscribe(); + }) + .flatMap(dc -> { + final long impliedPosition = resumableFramesStore.frameImpliedPosition(); + final long position = resumableFramesStore.framePosition(); + dc.sendFrame(0, ResumeFrameCodec.encode(dc.alloc(), + resumeToken.retain(), + // server uses this to release its cache + impliedPosition, // observed on the client side + // server uses this to check whether there is no mismatch + position // sent from the client sent + )); + + if (logger.isDebugEnabled()) { + logger.debug("Side[client]|Session[{}]. ResumeFrame[impliedPosition[{}], position[{}]] has been sent.", + session, impliedPosition, position); + } + + return connectionTransformer.apply(dc); + }) + .doOnDiscard(Tuple2.class, this::tryReestablishSession); - this.reconnectDisposable = - resumableConnection.onActiveConnectionClosed().subscribe(this::reconnect); + resumableConnection.onClose().doFinally(__ -> dispose()).subscribe(); + this.reconnectDisposable = resumableConnection.onActiveConnectionClosed().subscribe(this::reconnect); } - void reconnect(int index) { + private void reconnect(int index) { if (this.s == Operators.cancelledSubscription()) { if (logger.isDebugEnabled()) { - logger.debug( - "Side[client]|Session[{}]. Connection[{}] is lost. Reconnecting rejected since session is closed", - session, - index); + logger.debug("Side[client]|Session[{}]. Connection[{}] is lost. Reconnecting rejected since session is closed", session, index); } return; } keepAliveSupport.stop(); if (logger.isDebugEnabled()) { - logger.debug( - "Side[client]|Session[{}]. Connection[{}] is lost. Reconnecting to resume...", - session, - index); + logger.debug("Side[client]|Session[{}]. Connection[{}] is lost. Reconnecting to resume...", session, index); } connectionFactory .doOnNext(this::tryReestablishSession) @@ -196,7 +169,7 @@ public boolean isDisposed() { return resumableConnection.isDisposed(); } - void tryReestablishSession(Tuple2 tuple2) { + private void tryReestablishSession(Tuple2 tuple2) { if (logger.isDebugEnabled()) { logger.debug("Active subscription is canceled {}", s == Operators.cancelledSubscription()); } @@ -206,12 +179,9 @@ void tryReestablishSession(Tuple2 tuple2) { final int streamId = FrameHeaderCodec.streamId(shouldBeResumeOKFrame); if (streamId != 0) { if (logger.isDebugEnabled()) { - logger.debug( - "Side[client]|Session[{}]. Illegal first frame received. RESUME_OK frame must be received before any others. Terminating received connection", - session); + logger.debug("Side[client]|Session[{}]. Illegal first frame received. RESUME_OK frame must be received before any others. Terminating received connection", session); } - final ConnectionErrorException connectionErrorException = - new ConnectionErrorException("RESUME_OK frame must be received before any others"); + final var connectionErrorException = new ConnectionErrorException("RESUME_OK frame must be received before any others"); resumableConnection.dispose(nextConnection, connectionErrorException); nextConnection.sendErrorAndClose(connectionErrorException); nextConnection.receive().subscribe(); @@ -229,12 +199,8 @@ void tryReestablishSession(Tuple2 tuple2) { final long position = resumableFramesStore.framePosition(); final long impliedPosition = resumableFramesStore.frameImpliedPosition(); if (logger.isDebugEnabled()) { - logger.debug( - "Side[client]|Session[{}]. ResumeOK FRAME received. ServerResumeState[remoteImpliedPosition[{}]]. ClientResumeState[impliedPosition[{}], position[{}]]", - session, - remoteImpliedPos, - impliedPosition, - position); + logger.debug("Side[client]|Session[{}]. ResumeOK FRAME received. ServerResumeState[remoteImpliedPosition[{}]]. ClientResumeState[impliedPosition[{}], position[{}]]", + session, remoteImpliedPos, impliedPosition, position); } if (position <= remoteImpliedPos) { try { @@ -244,10 +210,7 @@ void tryReestablishSession(Tuple2 tuple2) { } catch (IllegalStateException e) { if (logger.isDebugEnabled()) { - logger.debug( - "Side[client]|Session[{}]. Exception occurred while releasing frames in the frameStore", - session, - e); + logger.debug("Side[client]|Session[{}]. Exception occurred while releasing frames in the frameStore", session, e); } final ConnectionErrorException t = new ConnectionErrorException(e.getMessage(), e); @@ -261,12 +224,9 @@ void tryReestablishSession(Tuple2 tuple2) { if (!tryCancelSessionTimeout()) { if (logger.isDebugEnabled()) { - logger.debug( - "Side[client]|Session[{}]. Session has already been expired. Terminating received connection", - session); + logger.debug("Side[client]|Session[{}]. Session has already been expired. Terminating received connection", session); } - final ConnectionErrorException connectionErrorException = - new ConnectionErrorException("resumption_server=[Session Expired]"); + final ConnectionErrorException connectionErrorException = new ConnectionErrorException("resumption_server=[Session Expired]"); nextConnection.sendErrorAndClose(connectionErrorException); nextConnection.receive().subscribe(); return; @@ -280,9 +240,7 @@ void tryReestablishSession(Tuple2 tuple2) { if (!resumableConnection.connect(nextConnection)) { if (logger.isDebugEnabled()) { - logger.debug( - "Side[client]|Session[{}]. Session has already been expired. Terminating received connection", - session); + logger.debug("Side[client]|Session[{}]. Session has already been expired. Terminating received connection", session); } final ConnectionErrorException connectionErrorException = new ConnectionErrorException("resumption_server_pos=[Session Expired]"); @@ -296,9 +254,7 @@ void tryReestablishSession(Tuple2 tuple2) { if (logger.isDebugEnabled()) { logger.debug( "Side[client]|Session[{}]. Mismatching remote and local state. Expected RemoteImpliedPosition[{}] to be greater or equal to the LocalPosition[{}]. Terminating received connection", - session, - remoteImpliedPos, - position); + session, remoteImpliedPos, position); } final ConnectionErrorException connectionErrorException = new ConnectionErrorException("resumption_server_pos=[" + remoteImpliedPos + "]"); @@ -312,10 +268,7 @@ void tryReestablishSession(Tuple2 tuple2) { else if (frameType == FrameType.ERROR) { final RuntimeException exception = Exceptions.from(0, shouldBeResumeOKFrame); if (logger.isDebugEnabled()) { - logger.debug( - "Side[client]|Session[{}]. Received error frame. Terminating received connection", - session, - exception); + logger.debug("Side[client]|Session[{}]. Received error frame. Terminating received connection", session, exception); } if (exception instanceof RejectedResumeException) { resumableConnection.dispose(nextConnection, exception); @@ -330,13 +283,9 @@ else if (frameType == FrameType.ERROR) { } else { if (logger.isDebugEnabled()) { - logger.debug( - "Side[client]|Session[{}]. Illegal first frame received. RESUME_OK frame must be received before any others. Terminating received connection", - session); + logger.debug("Side[client]|Session[{}]. Illegal first frame received. RESUME_OK frame must be received before any others. Terminating received connection", session); } - final ConnectionErrorException connectionErrorException = - new ConnectionErrorException("RESUME_OK frame must be received before any others"); - + final var connectionErrorException = new ConnectionErrorException("RESUME_OK frame must be received before any others"); resumableConnection.dispose(nextConnection, connectionErrorException); nextConnection.sendErrorAndClose(connectionErrorException); @@ -346,7 +295,7 @@ else if (frameType == FrameType.ERROR) { } } - boolean tryCancelSessionTimeout() { + private boolean tryCancelSessionTimeout() { for (; ; ) { final Subscription subscription = this.s; @@ -369,7 +318,8 @@ public void onSubscribe(Subscription s) { } @Override - public void onNext(Tuple2 objects) { } + public void onNext(Tuple2 objects) { + } @Override public void onError(Throwable t) { @@ -381,9 +331,12 @@ public void onError(Throwable t) { } @Override - public void onComplete() { } + public void onComplete() { + } + @Override public void setKeepAliveSupport(KeepAliveSupport keepAliveSupport) { this.keepAliveSupport = keepAliveSupport; } + } diff --git a/today-remoting/src/main/java/infra/remoting/resume/ClientResume.java b/today-remoting/src/main/java/infra/remoting/resume/ClientResume.java deleted file mode 100644 index 1b09654..0000000 --- a/today-remoting/src/main/java/infra/remoting/resume/ClientResume.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2021 - 2024 the original author or authors. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] - */ - -package infra.remoting.resume; - -import java.time.Duration; - -import io.netty.buffer.ByteBuf; - -public class ClientResume { - private final Duration sessionDuration; - private final ByteBuf resumeToken; - - public ClientResume(Duration sessionDuration, ByteBuf resumeToken) { - this.sessionDuration = sessionDuration; - this.resumeToken = resumeToken; - } - - public Duration sessionDuration() { - return sessionDuration; - } - - public ByteBuf resumeToken() { - return resumeToken; - } -} diff --git a/today-remoting/src/main/java/infra/remoting/resume/InMemoryResumableFramesStore.java b/today-remoting/src/main/java/infra/remoting/resume/InMemoryResumableFramesStore.java index d9a3f0a..601b057 100644 --- a/today-remoting/src/main/java/infra/remoting/resume/InMemoryResumableFramesStore.java +++ b/today-remoting/src/main/java/infra/remoting/resume/InMemoryResumableFramesStore.java @@ -43,40 +43,10 @@ * writes - n (where n is frequent, primary operation) reads - m (where m == KeepAliveFrequency) * skip - k -> 0 (where k is the rare operation which happens after disconnection */ -public class InMemoryResumableFramesStore extends Flux - implements ResumableFramesStore, Subscription { +public class InMemoryResumableFramesStore extends Flux implements ResumableFramesStore, Subscription { - private FramesSubscriber framesSubscriber; private static final Logger logger = LoggerFactory.getLogger(InMemoryResumableFramesStore.class); - final Sinks.Empty disposed = Sinks.empty(); - final Queue cachedFrames; - final String side; - final String session; - final int cacheLimit; - - volatile long impliedPosition; - static final AtomicLongFieldUpdater IMPLIED_POSITION = - AtomicLongFieldUpdater.newUpdater(InMemoryResumableFramesStore.class, "impliedPosition"); - - volatile long firstAvailableFramePosition; - static final AtomicLongFieldUpdater FIRST_AVAILABLE_FRAME_POSITION = - AtomicLongFieldUpdater.newUpdater( - InMemoryResumableFramesStore.class, "firstAvailableFramePosition"); - - long remoteImpliedPosition; - - int cacheSize; - - Throwable terminal; - - CoreSubscriber actual; - CoreSubscriber pendingActual; - - volatile long state; - static final AtomicLongFieldUpdater STATE = - AtomicLongFieldUpdater.newUpdater(InMemoryResumableFramesStore.class, "state"); - /** * Flag which indicates that {@link InMemoryResumableFramesStore} is finalized and all related * stores are cleaned @@ -124,6 +94,37 @@ public class InMemoryResumableFramesStore extends Flux static final long MAX_WORK_IN_PROGRESS = 0b0000_0000_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111L; + final Sinks.Empty disposed = Sinks.empty(); + final Queue cachedFrames; + final String side; + final String session; + final int cacheLimit; + + volatile long impliedPosition; + static final AtomicLongFieldUpdater IMPLIED_POSITION = + AtomicLongFieldUpdater.newUpdater(InMemoryResumableFramesStore.class, "impliedPosition"); + + volatile long firstAvailableFramePosition; + static final AtomicLongFieldUpdater FIRST_AVAILABLE_FRAME_POSITION = + AtomicLongFieldUpdater.newUpdater( + InMemoryResumableFramesStore.class, "firstAvailableFramePosition"); + + int cacheSize; + + private Throwable terminal; + + private long remoteImpliedPosition; + + private CoreSubscriber actual; + + private CoreSubscriber pendingActual; + + private FramesSubscriber framesSubscriber; + + volatile long state; + static final AtomicLongFieldUpdater STATE = + AtomicLongFieldUpdater.newUpdater(InMemoryResumableFramesStore.class, "state"); + public InMemoryResumableFramesStore(String side, ByteBuf session, int cacheSizeBytes) { this.side = side; this.session = session.toString(CharsetUtil.UTF_8); @@ -131,11 +132,11 @@ public InMemoryResumableFramesStore(String side, ByteBuf session, int cacheSizeB this.cachedFrames = new ArrayDeque<>(); } + @Override public Mono saveFrames(Flux frames) { return frames - .transform( - Operators.lift( - (__, actual) -> this.framesSubscriber = new FramesSubscriber(actual, this))) + .transform(Operators.lift((__, actual) -> + this.framesSubscriber = new FramesSubscriber(actual, this))) .then(); } @@ -157,7 +158,7 @@ public void releaseFrames(long remoteImpliedPos) { drain((previousState + 1) | REMOTE_IMPLIED_POSITION_CHANGED_FLAG); } - void drain(long expectedState) { + private void drain(long expectedState) { final Fuseable.QueueSubscription qs = this.framesSubscriber.qs; final Queue cachedFrames = this.cachedFrames; @@ -198,7 +199,7 @@ else if (hasFrames(expectedState)) { } } - long handlePendingRemoteImpliedPositionChanges(long expectedState, Queue cachedFrames) { + private long handlePendingRemoteImpliedPositionChanges(long expectedState, Queue cachedFrames) { final long remoteImpliedPosition = this.remoteImpliedPosition; final long firstAvailableFramePosition = this.firstAvailableFramePosition; final long toDropFromCache = Math.max(0, remoteImpliedPosition - firstAvailableFramePosition); @@ -207,33 +208,23 @@ long handlePendingRemoteImpliedPositionChanges(long expectedState, Queue droppedFromCache) { - this.terminal = - new IllegalStateException( - String.format( - "Local and remote state disagreement: " - + "need to remove additional %d bytes, but cache is empty", - toDropFromCache)); + this.terminal = new IllegalStateException( + "Local and remote state disagreement: need to remove additional %d bytes, but cache is empty".formatted(toDropFromCache)); expectedState = markTerminated(this) | TERMINATED_FLAG; } if (toDropFromCache < droppedFromCache) { - this.terminal = - new IllegalStateException( - "Local and remote state disagreement: local and remote frame sizes are not equal"); + this.terminal = new IllegalStateException( + "Local and remote state disagreement: local and remote frame sizes are not equal"); expectedState = markTerminated(this) | TERMINATED_FLAG; } FIRST_AVAILABLE_FRAME_POSITION.lazySet(this, firstAvailableFramePosition + droppedFromCache); if (this.cacheLimit != Integer.MAX_VALUE) { this.cacheSize -= droppedFromCache; - if (logger.isDebugEnabled()) { - logger.debug( - "Side[{}]|Session[{}]. Removed frames from cache to position[{}]. CacheSize[{}]", - this.side, - this.session, - this.remoteImpliedPosition, - this.cacheSize); + logger.debug("Side[{}]|Session[{}]. Removed frames from cache to position[{}]. CacheSize[{}]", + this.side, this.session, this.remoteImpliedPosition, this.cacheSize); } } } @@ -241,7 +232,7 @@ long handlePendingRemoteImpliedPositionChanges(long expectedState, Queue qs) { + private void handlePendingFrames(Fuseable.QueueSubscription qs) { for (; ; ) { final ByteBuf frame = qs.poll(); final boolean empty = frame == null; @@ -258,7 +249,7 @@ void handlePendingFrames(Fuseable.QueueSubscription qs) { } } - long handlePendingConnection(long expectedState, Queue cachedFrames) { + private long handlePendingConnection(long expectedState, Queue cachedFrames) { CoreSubscriber lastActual = null; for (; ; ) { final CoreSubscriber nextActual = this.pendingActual; @@ -272,12 +263,8 @@ long handlePendingConnection(long expectedState, Queue cachedFrames) { expectedState = markConnected(this, expectedState); if (isConnected(expectedState)) { if (logger.isDebugEnabled()) { - logger.debug( - "Side[{}]|Session[{}]. Connected at Position[{}] and ImpliedPosition[{}]", - side, - session, - firstAvailableFramePosition, - impliedPosition); + logger.debug("Side[{}]|Session[{}]. Connected at Position[{}] and ImpliedPosition[{}]", + side, session, firstAvailableFramePosition, impliedPosition); } this.actual = nextActual; @@ -293,9 +280,9 @@ long handlePendingConnection(long expectedState, Queue cachedFrames) { return expectedState; } - static int dropFramesFromCache(long toRemoveBytes, Queue cache) { + private static int dropFramesFromCache(long toRemoveBytes, Queue cache) { int removedBytes = 0; - while (toRemoveBytes > removedBytes && cache.size() > 0) { + while (toRemoveBytes > removedBytes && !cache.isEmpty()) { final ByteBuf cachedFrame = cache.poll(); final int frameSize = cachedFrame.readableBytes(); @@ -338,29 +325,24 @@ public boolean resumableFrameReceived(ByteBuf frame) { } } - void pauseImplied() { + private void pauseImplied() { for (; ; ) { final long impliedPosition = this.impliedPosition; if (IMPLIED_POSITION.compareAndSet(this, impliedPosition, impliedPosition | Long.MIN_VALUE)) { - logger.debug( - "Side[{}]|Session[{}]. Paused at position[{}]", side, session, impliedPosition); + logger.debug("Side[{}]|Session[{}]. Paused at position[{}]", side, session, impliedPosition); return; } } } - void resumeImplied() { + private void resumeImplied() { for (; ; ) { final long impliedPosition = this.impliedPosition; final long restoredImpliedPosition = impliedPosition & Long.MAX_VALUE; if (IMPLIED_POSITION.compareAndSet(this, impliedPosition, restoredImpliedPosition)) { - logger.debug( - "Side[{}]|Session[{}]. Resumed at position[{}]", - side, - session, - restoredImpliedPosition); + logger.debug("Side[{}]|Session[{}]. Resumed at position[{}]", side, session, restoredImpliedPosition); return; } } @@ -383,9 +365,9 @@ public void dispose() { drain((previousState + 1) | DISPOSED_FLAG); } - void clearCache() { - final Queue frames = this.cachedFrames; + private void clearCache() { this.cacheSize = 0; + final Queue frames = this.cachedFrames; ByteBuf frame; while ((frame = frames.poll()) != null) { @@ -489,12 +471,8 @@ public void cancel() { pauseImplied(); markDisconnected(this); if (logger.isDebugEnabled()) { - logger.debug( - "Side[{}]|Session[{}]. Disconnected at Position[{}] and ImpliedPosition[{}]", - side, - session, - firstAvailableFramePosition, - frameImpliedPosition()); + logger.debug("Side[{}]|Session[{}]. Disconnected at Position[{}] and ImpliedPosition[{}]", + side, session, firstAvailableFramePosition, frameImpliedPosition()); } } @@ -522,16 +500,15 @@ public void subscribe(CoreSubscriber actual) { drain((previousState + 1) | PENDING_CONNECTION_FLAG); } - static class FramesSubscriber - implements CoreSubscriber, Fuseable.QueueSubscription { + private static class FramesSubscriber implements CoreSubscriber, Fuseable.QueueSubscription { final CoreSubscriber actual; final InMemoryResumableFramesStore parent; - Fuseable.QueueSubscription qs; - boolean done; + public Fuseable.QueueSubscription qs; + FramesSubscriber(CoreSubscriber actual, InMemoryResumableFramesStore parent) { this.actual = actual; this.parent = parent; @@ -670,7 +647,7 @@ public boolean isEmpty() { public void clear() { } } - static long markFrameAdded(InMemoryResumableFramesStore store) { + private static long markFrameAdded(InMemoryResumableFramesStore store) { for (; ; ) { final long state = store.state; @@ -690,7 +667,7 @@ static long markFrameAdded(InMemoryResumableFramesStore store) { } } - static long markPendingConnection(InMemoryResumableFramesStore store) { + private static long markPendingConnection(InMemoryResumableFramesStore store) { for (; ; ) { final long state = store.state; @@ -710,7 +687,7 @@ static long markPendingConnection(InMemoryResumableFramesStore store) { } } - static long markRemoteImpliedPositionChanged(InMemoryResumableFramesStore store) { + private static long markRemoteImpliedPositionChanged(InMemoryResumableFramesStore store) { for (; ; ) { final long state = store.state; @@ -726,7 +703,7 @@ static long markRemoteImpliedPositionChanged(InMemoryResumableFramesStore store) } } - static long markDisconnected(InMemoryResumableFramesStore store) { + private static long markDisconnected(InMemoryResumableFramesStore store) { for (; ; ) { final long state = store.state; @@ -740,7 +717,7 @@ static long markDisconnected(InMemoryResumableFramesStore store) { } } - static long markWorkDone(InMemoryResumableFramesStore store, long expectedState) { + private static long markWorkDone(InMemoryResumableFramesStore store, long expectedState) { for (; ; ) { final long state = store.state; @@ -759,7 +736,7 @@ static long markWorkDone(InMemoryResumableFramesStore store, long expectedState) } } - static long markConnected(InMemoryResumableFramesStore store, long expectedState) { + private static long markConnected(InMemoryResumableFramesStore store, long expectedState) { for (; ; ) { final long state = store.state; @@ -778,7 +755,7 @@ static long markConnected(InMemoryResumableFramesStore store, long expectedState } } - static long markTerminated(InMemoryResumableFramesStore store) { + private static long markTerminated(InMemoryResumableFramesStore store) { for (; ; ) { final long state = store.state; @@ -794,7 +771,7 @@ static long markTerminated(InMemoryResumableFramesStore store) { } } - static long markDisposed(InMemoryResumableFramesStore store) { + private static long markDisposed(InMemoryResumableFramesStore store) { for (; ; ) { final long state = store.state; @@ -810,7 +787,7 @@ static long markDisposed(InMemoryResumableFramesStore store) { } } - static void clearAndFinalize(InMemoryResumableFramesStore store) { + private static void clearAndFinalize(InMemoryResumableFramesStore store) { final Fuseable.QueueSubscription qs = store.framesSubscriber.qs; for (; ; ) { final long state = store.state; @@ -830,31 +807,31 @@ static void clearAndFinalize(InMemoryResumableFramesStore store) { } } - static boolean isConnected(long state) { + private static boolean isConnected(long state) { return (state & CONNECTED_FLAG) == CONNECTED_FLAG; } - static boolean hasRemoteImpliedPositionChanged(long state) { + private static boolean hasRemoteImpliedPositionChanged(long state) { return (state & REMOTE_IMPLIED_POSITION_CHANGED_FLAG) == REMOTE_IMPLIED_POSITION_CHANGED_FLAG; } - static boolean hasPendingConnection(long state) { + private static boolean hasPendingConnection(long state) { return (state & PENDING_CONNECTION_FLAG) == PENDING_CONNECTION_FLAG; } - static boolean hasFrames(long state) { + private static boolean hasFrames(long state) { return (state & HAS_FRAME_FLAG) == HAS_FRAME_FLAG; } - static boolean isTerminated(long state) { + private static boolean isTerminated(long state) { return (state & TERMINATED_FLAG) == TERMINATED_FLAG; } - static boolean isDisposed(long state) { + private static boolean isDisposed(long state) { return (state & DISPOSED_FLAG) == DISPOSED_FLAG; } - static boolean isFinalized(long state) { + private static boolean isFinalized(long state) { return (state & FINALIZED_FLAG) == FINALIZED_FLAG; } diff --git a/today-remoting/src/main/java/infra/remoting/resume/ResumableConnection.java b/today-remoting/src/main/java/infra/remoting/resume/ResumableConnection.java index 6000294..53a7b13 100644 --- a/today-remoting/src/main/java/infra/remoting/resume/ResumableConnection.java +++ b/today-remoting/src/main/java/infra/remoting/resume/ResumableConnection.java @@ -43,19 +43,19 @@ import reactor.core.publisher.Operators; import reactor.core.publisher.Sinks; -public class ResumableConnection extends Flux - implements Connection, Subscription { +public class ResumableConnection extends Flux implements Connection, Subscription { static final Logger logger = LoggerFactory.getLogger(ResumableConnection.class); final String side; final String session; + final SocketAddress remoteAddress; + final ResumableFramesStore resumableFramesStore; final UnboundedProcessor savableFramesSender; final Sinks.Empty onQueueClose; final Sinks.Empty onLastConnectionClose; - final SocketAddress remoteAddress; final Sinks.Many onConnectionClosedSink; CoreSubscriber receiveSubscriber; @@ -73,21 +73,17 @@ public class ResumableConnection extends Flux int connectionIndex = 0; - public ResumableConnection( - String side, - ByteBuf session, - Connection initialConnection, - ResumableFramesStore resumableFramesStore) { + public ResumableConnection(String side, ByteBuf session, Connection initialConnection, ResumableFramesStore store) { this.side = side; this.session = session.toString(CharsetUtil.UTF_8); this.onConnectionClosedSink = Sinks.unsafe().many().unicast().onBackpressureBuffer(); - this.resumableFramesStore = resumableFramesStore; + this.resumableFramesStore = store; this.onQueueClose = Sinks.unsafe().empty(); this.onLastConnectionClose = Sinks.unsafe().empty(); this.savableFramesSender = new UnboundedProcessor(onQueueClose::tryEmitEmpty); this.remoteAddress = initialConnection.remoteAddress(); - resumableFramesStore.saveFrames(savableFramesSender).subscribe(); + store.saveFrames(savableFramesSender).subscribe(); ACTIVE_CONNECTION.lazySet(this, initialConnection); } @@ -111,58 +107,43 @@ public boolean connect(Connection nextConnection) { } } - void initConnection(Connection nextConnection) { + private void initConnection(Connection nextConnection) { final int nextConnectionIndex = this.connectionIndex + 1; - final FrameReceivingSubscriber frameReceivingSubscriber = - new FrameReceivingSubscriber(side, resumableFramesStore, receiveSubscriber); + final var frameReceivingSubscriber = new FrameReceivingSubscriber(side, resumableFramesStore, receiveSubscriber); this.connectionIndex = nextConnectionIndex; this.activeReceivingSubscriber = frameReceivingSubscriber; if (logger.isDebugEnabled()) { - logger.debug( - "Side[{}]|Session[{}]|Connection[{}]. Connecting", side, session, connectionIndex); + logger.debug("Side[{}]|Session[{}]|Connection[{}]. Connecting", side, session, connectionIndex); } - final Disposable resumeStreamSubscription = - resumableFramesStore - .resumeStream() - .subscribe( - f -> nextConnection.sendFrame(FrameHeaderCodec.streamId(f), f), - t -> { - dispose(nextConnection, t); - nextConnection.sendErrorAndClose(new ConnectionErrorException(t.getMessage(), t)); - }, - () -> { - final ConnectionErrorException e = - new ConnectionErrorException("Connection Closed Unexpectedly"); - dispose(nextConnection, e); - nextConnection.sendErrorAndClose(e); - }); + final Disposable resumeStreamSubscription = resumableFramesStore + .resumeStream() + .subscribe(f -> nextConnection.sendFrame(FrameHeaderCodec.streamId(f), f), + t -> { + dispose(nextConnection, t); + nextConnection.sendErrorAndClose(new ConnectionErrorException(t.getMessage(), t)); + }, + () -> { + final ConnectionErrorException e = + new ConnectionErrorException("Connection Closed Unexpectedly"); + dispose(nextConnection, e); + nextConnection.sendErrorAndClose(e); + }); nextConnection.receive().subscribe(frameReceivingSubscriber); - nextConnection - .onClose() - .doFinally( - __ -> { - frameReceivingSubscriber.dispose(); - resumeStreamSubscription.dispose(); - if (logger.isDebugEnabled()) { - logger.debug( - "Side[{}]|Session[{}]|Connection[{}]. Disconnected", - side, - session, - connectionIndex); - } - Sinks.EmitResult result = onConnectionClosedSink.tryEmitNext(nextConnectionIndex); - if (!result.equals(Sinks.EmitResult.OK)) { - logger.error( - "Side[{}]|Session[{}]|Connection[{}]. Failed to notify session of closed connection: {}", - side, - session, - connectionIndex, - result); - } - }) + nextConnection.onClose().doFinally(__ -> { + frameReceivingSubscriber.dispose(); + resumeStreamSubscription.dispose(); + if (logger.isDebugEnabled()) { + logger.debug("Side[{}]|Session[{}]|Connection[{}]. Disconnected", side, session, connectionIndex); + } + Sinks.EmitResult result = onConnectionClosedSink.tryEmitNext(nextConnectionIndex); + if (!result.equals(Sinks.EmitResult.OK)) { + logger.error("Side[{}]|Session[{}]|Connection[{}]. Failed to notify session of closed connection: {}", + side, session, connectionIndex, result); + } + }) .subscribe(); } @@ -203,25 +184,22 @@ public void sendErrorAndClose(ProtocolErrorException exception) { savableFramesSender.tryEmitFinal( ErrorFrameCodec.encode(activeConnection.alloc(), 0, exception)); - activeConnection - .onClose() - .subscribe( - null, - t -> { - onConnectionClosedSink.tryEmitComplete(); - onLastConnectionClose.tryEmitEmpty(); - }, - () -> { - onConnectionClosedSink.tryEmitComplete(); - - final Throwable cause = exception.getCause(); - if (cause == null) { - onLastConnectionClose.tryEmitEmpty(); - } - else { - onLastConnectionClose.tryEmitError(cause); - } - }); + activeConnection.onClose().subscribe(null, + t -> { + onConnectionClosedSink.tryEmitComplete(); + onLastConnectionClose.tryEmitEmpty(); + }, + () -> { + onConnectionClosedSink.tryEmitComplete(); + + final Throwable cause = exception.getCause(); + if (cause == null) { + onLastConnectionClose.tryEmitEmpty(); + } + else { + onLastConnectionClose.tryEmitError(cause); + } + }); } @Override @@ -242,55 +220,47 @@ public Mono onClose() { @Override public void dispose() { - final Connection activeConnection = - ACTIVE_CONNECTION.getAndSet(this, DisposedConnection.INSTANCE); + final Connection activeConnection = ACTIVE_CONNECTION.getAndSet(this, DisposedConnection.INSTANCE); if (activeConnection == DisposedConnection.INSTANCE) { return; } savableFramesSender.onComplete(); - activeConnection - .onClose() - .subscribe( - null, - t -> { - onConnectionClosedSink.tryEmitComplete(); - onLastConnectionClose.tryEmitEmpty(); - }, - () -> { - onConnectionClosedSink.tryEmitComplete(); - onLastConnectionClose.tryEmitEmpty(); - }); + activeConnection.onClose().subscribe(null, + t -> { + onConnectionClosedSink.tryEmitComplete(); + onLastConnectionClose.tryEmitEmpty(); + }, + () -> { + onConnectionClosedSink.tryEmitComplete(); + onLastConnectionClose.tryEmitEmpty(); + }); } void dispose(Connection nextConnection, @Nullable Throwable e) { - final Connection activeConnection = - ACTIVE_CONNECTION.getAndSet(this, DisposedConnection.INSTANCE); + final Connection activeConnection = ACTIVE_CONNECTION.getAndSet(this, DisposedConnection.INSTANCE); if (activeConnection == DisposedConnection.INSTANCE) { return; } savableFramesSender.onComplete(); - nextConnection - .onClose() - .subscribe( - null, - t -> { - if (e != null) { - onLastConnectionClose.tryEmitError(e); - } - else { - onLastConnectionClose.tryEmitEmpty(); - } - onConnectionClosedSink.tryEmitComplete(); - }, - () -> { - if (e != null) { - onLastConnectionClose.tryEmitError(e); - } - else { - onLastConnectionClose.tryEmitEmpty(); - } - onConnectionClosedSink.tryEmitComplete(); - }); + nextConnection.onClose().subscribe(null, + t -> { + if (e != null) { + onLastConnectionClose.tryEmitError(e); + } + else { + onLastConnectionClose.tryEmitEmpty(); + } + onConnectionClosedSink.tryEmitComplete(); + }, + () -> { + if (e != null) { + onLastConnectionClose.tryEmitError(e); + } + else { + onLastConnectionClose.tryEmitEmpty(); + } + onConnectionClosedSink.tryEmitComplete(); + }); } @Override @@ -332,29 +302,16 @@ static boolean isResumableFrame(ByteBuf frame) { @Override public String toString() { - return "ResumableConnection{" - + "side='" - + side - + '\'' - + ", session='" - + session - + '\'' - + ", remoteAddress=" - + remoteAddress - + ", state=" - + state - + ", activeConnection=" - + activeConnection - + ", connectionIndex=" - + connectionIndex - + '}'; + return "ResumableConnection{side='%s', session='%s', remoteAddress=%s, state=%d, activeConnection=%s, connectionIndex=%d}" + .formatted(side, session, remoteAddress, state, activeConnection, connectionIndex); } private static final class DisposedConnection implements Connection { static final DisposedConnection INSTANCE = new DisposedConnection(); - private DisposedConnection() { } + private DisposedConnection() { + } @Override public void dispose() { } @@ -365,7 +322,8 @@ public Mono onClose() { } @Override - public void sendFrame(int streamId, ByteBuf frame) { } + public void sendFrame(int streamId, ByteBuf frame) { + } @Override public Flux receive() { @@ -373,7 +331,8 @@ public Flux receive() { } @Override - public void sendErrorAndClose(ProtocolErrorException e) { } + public void sendErrorAndClose(ProtocolErrorException e) { + } @Override public ByteBufAllocator alloc() { @@ -387,12 +346,11 @@ public SocketAddress remoteAddress() { } } - private static final class FrameReceivingSubscriber - implements CoreSubscriber, Disposable { + private static final class FrameReceivingSubscriber implements CoreSubscriber, Disposable { - final ResumableFramesStore resumableFramesStore; - final CoreSubscriber actual; - final String tag; + private final ResumableFramesStore resumableFramesStore; + private final CoreSubscriber actual; + private final String tag; volatile Subscription s; static final AtomicReferenceFieldUpdater S = @@ -401,8 +359,7 @@ private static final class FrameReceivingSubscriber boolean cancelled; - private FrameReceivingSubscriber( - String tag, ResumableFramesStore store, CoreSubscriber actual) { + private FrameReceivingSubscriber(String tag, ResumableFramesStore store, CoreSubscriber actual) { this.tag = tag; this.resumableFramesStore = store; this.actual = actual; diff --git a/today-remoting/src/main/java/infra/remoting/resume/ResumableFramesStore.java b/today-remoting/src/main/java/infra/remoting/resume/ResumableFramesStore.java index aebfa02..82be602 100644 --- a/today-remoting/src/main/java/infra/remoting/resume/ResumableFramesStore.java +++ b/today-remoting/src/main/java/infra/remoting/resume/ResumableFramesStore.java @@ -22,7 +22,9 @@ import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; -/** Store for resumable frames */ +/** + * Store for resumable frames + */ public interface ResumableFramesStore extends Closeable { /** @@ -33,7 +35,9 @@ public interface ResumableFramesStore extends Closeable { */ Mono saveFrames(Flux frames); - /** Release frames from tail of the store up to remote implied position */ + /** + * Release frames from tail of the store up to remote implied position + */ void releaseFrames(long remoteImpliedPos); /** @@ -42,10 +46,14 @@ public interface ResumableFramesStore extends Closeable { */ Flux resumeStream(); - /** @return Local frame position as defined by protocol */ + /** + * @return Local frame position as defined by protocol + */ long framePosition(); - /** @return Implied frame position as defined by protocol */ + /** + * @return Implied frame position as defined by protocol + */ long frameImpliedPosition(); /** @@ -55,4 +63,5 @@ public interface ResumableFramesStore extends Closeable { * @return {@code true} if information about the frame has been stored */ boolean resumableFrameReceived(ByteBuf frame); + } diff --git a/today-remoting/src/main/java/infra/remoting/resume/ServerChannelSession.java b/today-remoting/src/main/java/infra/remoting/resume/ServerChannelSession.java index a3c2d25..d15917f 100644 --- a/today-remoting/src/main/java/infra/remoting/resume/ServerChannelSession.java +++ b/today-remoting/src/main/java/infra/remoting/resume/ServerChannelSession.java @@ -44,19 +44,24 @@ public class ServerChannelSession implements ChannelSession, ResumeStateHolder, private static final Logger logger = LoggerFactory.getLogger(ServerChannelSession.class); - final ResumableConnection resumableConnection; - final Duration resumeSessionDuration; - final ResumableFramesStore resumableFramesStore; - final String session; - final ByteBufAllocator allocator; - final boolean cleanupStoreOnKeepAlive; + private final String session; + + private final ByteBufAllocator allocator; + + private final Duration resumeSessionDuration; + + private final boolean cleanupStoreOnKeepAlive; + + private final ResumableFramesStore resumableFramesStore; /** * All incoming connections with the Resume intent are enqueued in this queue. Such an approach * ensure that the new connection will affect the resumption state anyhow until the previous * (active) connection is finally closed */ - final Queue connectionsQueue; + private final Queue connectionsQueue; + + final ResumableConnection resumableConnection; volatile int wip; static final AtomicIntegerFieldUpdater WIP = @@ -66,20 +71,16 @@ public class ServerChannelSession implements ChannelSession, ResumeStateHolder, static final AtomicReferenceFieldUpdater S = AtomicReferenceFieldUpdater.newUpdater(ServerChannelSession.class, Subscription.class, "s"); - KeepAliveSupport keepAliveSupport; + private KeepAliveSupport keepAliveSupport; - public ServerChannelSession(ByteBuf session, - ResumableConnection resumableConnection, - Connection initialConnection, - ResumableFramesStore resumableFramesStore, - Duration resumeSessionDuration, - boolean cleanupStoreOnKeepAlive) { + public ServerChannelSession(ByteBuf session, ResumableConnection resumableConnection, Connection initialConnection, + ResumableFramesStore resumableFramesStore, Duration resumeSessionDuration, boolean cleanupStoreOnKeepAlive) { this.session = session.toString(CharsetUtil.UTF_8); this.allocator = initialConnection.alloc(); - this.resumeSessionDuration = resumeSessionDuration; + this.resumableConnection = resumableConnection; this.resumableFramesStore = resumableFramesStore; + this.resumeSessionDuration = resumeSessionDuration; this.cleanupStoreOnKeepAlive = cleanupStoreOnKeepAlive; - this.resumableConnection = resumableConnection; this.connectionsQueue = Queues.unboundedMultiproducer().get(); WIP.lazySet(this, 1); @@ -88,7 +89,7 @@ public ServerChannelSession(ByteBuf session, resumableConnection.onActiveConnectionClosed().subscribe(__ -> tryTimeoutSession()); } - void tryTimeoutSession() { + private void tryTimeoutSession() { keepAliveSupport.stop(); if (logger.isDebugEnabled()) { @@ -130,15 +131,12 @@ public void resumeWith(ByteBuf resumeFrame, Connection nextConnection) { } } - void doResume(long remotePos, long remoteImpliedPos, Connection nextConnection) { + private void doResume(long remotePos, long remoteImpliedPos, Connection nextConnection) { if (!tryCancelSessionTimeout()) { if (logger.isDebugEnabled()) { - logger.debug( - "Side[server]|Session[{}]. Session has already been expired. Terminating received connection", - session); + logger.debug("Side[server]|Session[{}]. Session has already been expired. Terminating received connection", session); } - final RejectedResumeException rejectedResumeException = - new RejectedResumeException("resume_internal_error: Session Expired"); + final RejectedResumeException rejectedResumeException = new RejectedResumeException("resume_internal_error: Session Expired"); nextConnection.sendErrorAndClose(rejectedResumeException); nextConnection.receive().subscribe(); return; @@ -148,13 +146,8 @@ void doResume(long remotePos, long remoteImpliedPos, Connection nextConnection) long position = resumableFramesStore.framePosition(); if (logger.isDebugEnabled()) { - logger.debug( - "Side[server]|Session[{}]. Resume FRAME received. ServerResumeState[impliedPosition[{}], position[{}]]. ClientResumeState[remoteImpliedPosition[{}], remotePosition[{}]]", - session, - impliedPosition, - position, - remoteImpliedPos, - remotePos); + logger.debug("Side[server]|Session[{}]. Resume FRAME received. ServerResumeState[impliedPosition[{}], position[{}]]. ClientResumeState[remoteImpliedPosition[{}], remotePosition[{}]]", + session, impliedPosition, position, remoteImpliedPos, remotePos); } if (remotePos <= impliedPosition && position <= remoteImpliedPos) { @@ -164,24 +157,18 @@ void doResume(long remotePos, long remoteImpliedPos, Connection nextConnection) } nextConnection.sendFrame(0, ResumeOkFrameCodec.encode(allocator, impliedPosition)); if (logger.isDebugEnabled()) { - logger.debug( - "Side[server]|Session[{}]. ResumeOKFrame[impliedPosition[{}]] has been sent", - session, - impliedPosition); + logger.debug("Side[server]|Session[{}]. ResumeOKFrame[impliedPosition[{}]] has been sent", session, impliedPosition); } } catch (Throwable t) { if (logger.isDebugEnabled()) { - logger.debug( - "Side[server]|Session[{}]. Exception occurred while releasing frames in the frameStore", - session, - t); + logger.debug("Side[server]|Session[{}]. Exception occurred while releasing frames in the frameStore", + session, t); } dispose(); - final RejectedResumeException rejectedResumeException = - new RejectedResumeException(t.getMessage(), t); + final RejectedResumeException rejectedResumeException = new RejectedResumeException(t.getMessage(), t); nextConnection.sendErrorAndClose(rejectedResumeException); nextConnection.receive().subscribe(); @@ -196,9 +183,7 @@ void doResume(long remotePos, long remoteImpliedPos, Connection nextConnection) if (!resumableConnection.connect(nextConnection)) { if (logger.isDebugEnabled()) { - logger.debug( - "Side[server]|Session[{}]. Session has already been expired. Terminating received connection", - session); + logger.debug("Side[server]|Session[{}]. Session has already been expired. Terminating received connection", session); } final RejectedResumeException rejectedResumeException = new RejectedResumeException("resume_internal_error: Session Expired"); @@ -213,26 +198,20 @@ void doResume(long remotePos, long remoteImpliedPos, Connection nextConnection) if (logger.isDebugEnabled()) { logger.debug( "Side[server]|Session[{}]. Mismatching remote and local state. Expected RemoteImpliedPosition[{}] to be greater or equal to the LocalPosition[{}] and RemotePosition[{}] to be less or equal to LocalImpliedPosition[{}]. Terminating received connection", - session, - remoteImpliedPos, - position, - remotePos, - impliedPosition); + session, remoteImpliedPos, position, remotePos, impliedPosition); } dispose(); final RejectedResumeException rejectedResumeException = - new RejectedResumeException( - String.format( - "resumption_pos=[ remote: { pos: %d, impliedPos: %d }, local: { pos: %d, impliedPos: %d }]", - remotePos, remoteImpliedPos, position, impliedPosition)); + new RejectedResumeException(String.format("resumption_pos=[ remote: { pos: %d, impliedPos: %d }, local: { pos: %d, impliedPos: %d }]", + remotePos, remoteImpliedPos, position, impliedPosition)); nextConnection.sendErrorAndClose(rejectedResumeException); nextConnection.receive().subscribe(); } } - boolean tryCancelSessionTimeout() { + private boolean tryCancelSessionTimeout() { for (; ; ) { final Subscription subscription = this.s; @@ -281,10 +260,12 @@ public void onNext(Long aLong) { } @Override - public void onComplete() { } + public void onComplete() { + } @Override - public void onError(Throwable t) { } + public void onError(Throwable t) { + } public void setKeepAliveSupport(KeepAliveSupport keepAliveSupport) { this.keepAliveSupport = keepAliveSupport; diff --git a/today-remoting/src/main/java/infra/remoting/resume/SessionManager.java b/today-remoting/src/main/java/infra/remoting/resume/SessionManager.java index c21ecf9..3dbc96e 100644 --- a/today-remoting/src/main/java/infra/remoting/resume/SessionManager.java +++ b/today-remoting/src/main/java/infra/remoting/resume/SessionManager.java @@ -38,19 +38,12 @@ public ServerChannelSession save(ServerChannelSession session, ByteBuf resumeTok } else { final String token = resumeToken.toString(CharsetUtil.UTF_8); - session - .resumableConnection - .onClose() - .doFinally( - __ -> { - logger.debug( - "ResumableConnection has been closed. Removing associated session {" - + token - + "}"); - if (isDisposed || sessions.get(token) == session) { - sessions.remove(token); - } - }) + session.resumableConnection.onClose().doFinally(__ -> { + logger.debug("ResumableConnection has been closed. Removing associated session '{}'", token); + if (isDisposed || sessions.get(token) == session) { + sessions.remove(token); + } + }) .subscribe(); ServerChannelSession prevSession = sessions.remove(token); if (prevSession != null) { diff --git a/today-remoting/src/test/java/infra/remoting/resume/ClientChannelSessionTests.java b/today-remoting/src/test/java/infra/remoting/resume/ClientChannelSessionTests.java index 6867d75..fdb4afa 100644 --- a/today-remoting/src/test/java/infra/remoting/resume/ClientChannelSessionTests.java +++ b/today-remoting/src/test/java/infra/remoting/resume/ClientChannelSessionTests.java @@ -22,9 +22,6 @@ import java.time.Duration; import java.util.concurrent.atomic.AtomicBoolean; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; -import io.netty.util.ReferenceCounted; import infra.remoting.FrameAssert; import infra.remoting.error.ConnectionCloseException; import infra.remoting.error.RejectedResumeException; @@ -35,6 +32,9 @@ import infra.remoting.keepalive.KeepAliveSupport; import infra.remoting.test.util.TestClientTransport; import infra.remoting.test.util.TestConnection; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.util.ReferenceCounted; import reactor.core.publisher.Operators; import reactor.test.StepVerifier; import reactor.test.scheduler.VirtualTimeScheduler; @@ -43,7 +43,7 @@ import static org.assertj.core.api.Assertions.assertThat; -public class ClientChannelSessionTests { +class ClientChannelSessionTests { @Test void sessionTimeoutSmokeTest() { From a23359c1167e04a37dfc9f43b1444467a7c4efe4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Tue, 5 Aug 2025 22:15:37 +0800 Subject: [PATCH 030/104] :fire: --- .../infra/remoting/util/CharByteBufUtil.java | 240 ------------------ .../java/infra/remoting/util/NumberUtils.java | 166 ------------ .../infra/remoting/util/NumberUtilsTests.java | 191 -------------- 3 files changed, 597 deletions(-) delete mode 100644 today-remoting/src/main/java/infra/remoting/util/CharByteBufUtil.java delete mode 100644 today-remoting/src/main/java/infra/remoting/util/NumberUtils.java delete mode 100644 today-remoting/src/test/java/infra/remoting/util/NumberUtilsTests.java diff --git a/today-remoting/src/main/java/infra/remoting/util/CharByteBufUtil.java b/today-remoting/src/main/java/infra/remoting/util/CharByteBufUtil.java deleted file mode 100644 index 624e92c..0000000 --- a/today-remoting/src/main/java/infra/remoting/util/CharByteBufUtil.java +++ /dev/null @@ -1,240 +0,0 @@ -/* - * Copyright 2021 - 2024 the original author or authors. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] - */ - -package infra.remoting.util; - -import java.nio.ByteBuffer; -import java.nio.CharBuffer; -import java.nio.charset.CharacterCodingException; -import java.nio.charset.CharsetDecoder; -import java.nio.charset.CoderResult; -import java.util.Arrays; - -import io.netty.buffer.ByteBuf; -import io.netty.util.CharsetUtil; -import io.netty.util.internal.MathUtil; - -import static io.netty.util.internal.StringUtil.isSurrogate; - -public class CharByteBufUtil { - - private static final byte WRITE_UTF_UNKNOWN = (byte) '?'; - - private CharByteBufUtil() { } - - /** - * Returns the exact bytes length of UTF8 character sequence. - * - *

      This method is producing the exact length according to {@link #writeUtf8(ByteBuf, char[])}. - */ - public static int utf8Bytes(final char[] seq) { - return utf8ByteCount(seq, 0, seq.length); - } - - /** - * This method is producing the exact length according to {@link #writeUtf8(ByteBuf, char[], int, - * int)}. - */ - public static int utf8Bytes(final char[] seq, int start, int end) { - return utf8ByteCount(checkCharSequenceBounds(seq, start, end), start, end); - } - - private static int utf8ByteCount(final char[] seq, int start, int end) { - int i = start; - // ASCII fast path - while (i < end && seq[i] < 0x80) { - ++i; - } - // !ASCII is packed in a separate method to let the ASCII case be smaller - return i < end ? (i - start) + utf8BytesNonAscii(seq, i, end) : i - start; - } - - private static int utf8BytesNonAscii(final char[] seq, final int start, final int end) { - int encodedLength = 0; - for (int i = start; i < end; i++) { - final char c = seq[i]; - // making it 100% branchless isn't rewarding due to the many bit operations necessary! - if (c < 0x800) { - // branchless version of: (c <= 127 ? 0:1) + 1 - encodedLength += ((0x7f - c) >>> 31) + 1; - } - else if (isSurrogate(c)) { - if (!Character.isHighSurrogate(c)) { - encodedLength++; - // WRITE_UTF_UNKNOWN - continue; - } - final char c2; - try { - // Surrogate Pair consumes 2 characters. Optimistically try to get the next character to - // avoid - // duplicate bounds checking with charAt. - c2 = seq[++i]; - } - catch (IndexOutOfBoundsException ignored) { - encodedLength++; - // WRITE_UTF_UNKNOWN - break; - } - if (!Character.isLowSurrogate(c2)) { - // WRITE_UTF_UNKNOWN + (Character.isHighSurrogate(c2) ? WRITE_UTF_UNKNOWN : c2) - encodedLength += 2; - continue; - } - // See http://www.unicode.org/versions/Unicode7.0.0/ch03.pdf#G2630. - encodedLength += 4; - } - else { - encodedLength += 3; - } - } - return encodedLength; - } - - private static char[] checkCharSequenceBounds(char[] seq, int start, int end) { - if (MathUtil.isOutOfBounds(start, end - start, seq.length)) { - throw new IndexOutOfBoundsException( - "expected: 0 <= start(" - + start - + ") <= end (" - + end - + ") <= seq.length(" - + seq.length - + ')'); - } - return seq; - } - - /** - * Encode a {@code char[]} in UTF-8 and write it - * into {@link ByteBuf}. - * - *

      This method returns the actual number of bytes written. - */ - public static int writeUtf8(ByteBuf buf, char[] seq) { - return writeUtf8(buf, seq, 0, seq.length); - } - - /** - * Equivalent to {@link #writeUtf8(ByteBuf, char[]) writeUtf8(buf, seq.subSequence(start, end), - * reserveBytes)} but avoids subsequence object allocation if possible. - * - * @return actual number of bytes written - */ - public static int writeUtf8(ByteBuf buf, char[] seq, int start, int end) { - return writeUtf8(buf, buf.writerIndex(), checkCharSequenceBounds(seq, start, end), start, end); - } - - // Fast-Path implementation - static int writeUtf8(ByteBuf buffer, int writerIndex, char[] seq, int start, int end) { - int oldWriterIndex = writerIndex; - - // We can use the _set methods as these not need to do any index checks and reference checks. - // This is possible as we called ensureWritable(...) before. - for (int i = start; i < end; i++) { - char c = seq[i]; - if (c < 0x80) { - buffer.setByte(writerIndex++, (byte) c); - } - else if (c < 0x800) { - buffer.setByte(writerIndex++, (byte) (0xc0 | (c >> 6))); - buffer.setByte(writerIndex++, (byte) (0x80 | (c & 0x3f))); - } - else if (isSurrogate(c)) { - if (!Character.isHighSurrogate(c)) { - buffer.setByte(writerIndex++, WRITE_UTF_UNKNOWN); - continue; - } - final char c2; - if (seq.length > ++i) { - // Surrogate Pair consumes 2 characters. Optimistically try to get the next character to - // avoid - // duplicate bounds checking with charAt. If an IndexOutOfBoundsException is thrown we - // will - // re-throw a more informative exception describing the problem. - c2 = seq[i]; - } - else { - buffer.setByte(writerIndex++, WRITE_UTF_UNKNOWN); - break; - } - // Extra method to allow inlining the rest of writeUtf8 which is the most likely code path. - writerIndex = writeUtf8Surrogate(buffer, writerIndex, c, c2); - } - else { - buffer.setByte(writerIndex++, (byte) (0xe0 | (c >> 12))); - buffer.setByte(writerIndex++, (byte) (0x80 | ((c >> 6) & 0x3f))); - buffer.setByte(writerIndex++, (byte) (0x80 | (c & 0x3f))); - } - } - buffer.writerIndex(writerIndex); - return writerIndex - oldWriterIndex; - } - - private static int writeUtf8Surrogate(ByteBuf buffer, int writerIndex, char c, char c2) { - if (!Character.isLowSurrogate(c2)) { - buffer.setByte(writerIndex++, WRITE_UTF_UNKNOWN); - buffer.setByte(writerIndex++, Character.isHighSurrogate(c2) ? WRITE_UTF_UNKNOWN : c2); - return writerIndex; - } - int codePoint = Character.toCodePoint(c, c2); - // See http://www.unicode.org/versions/Unicode7.0.0/ch03.pdf#G2630. - buffer.setByte(writerIndex++, (byte) (0xf0 | (codePoint >> 18))); - buffer.setByte(writerIndex++, (byte) (0x80 | ((codePoint >> 12) & 0x3f))); - buffer.setByte(writerIndex++, (byte) (0x80 | ((codePoint >> 6) & 0x3f))); - buffer.setByte(writerIndex++, (byte) (0x80 | (codePoint & 0x3f))); - return writerIndex; - } - - public static char[] readUtf8(ByteBuf byteBuf, int length) { - CharsetDecoder charsetDecoder = CharsetUtil.UTF_8.newDecoder(); - int en = (int) (length * (double) charsetDecoder.maxCharsPerByte()); - char[] ca = new char[en]; - - CharBuffer charBuffer = CharBuffer.wrap(ca); - ByteBuffer byteBuffer = - byteBuf.nioBufferCount() == 1 - ? byteBuf.internalNioBuffer(byteBuf.readerIndex(), length) - : byteBuf.nioBuffer(byteBuf.readerIndex(), length); - byteBuffer.mark(); - try { - CoderResult cr = charsetDecoder.decode(byteBuffer, charBuffer, true); - if (!cr.isUnderflow()) - cr.throwException(); - cr = charsetDecoder.flush(charBuffer); - if (!cr.isUnderflow()) - cr.throwException(); - - byteBuffer.reset(); - byteBuf.skipBytes(length); - - return safeTrim(charBuffer.array(), charBuffer.position()); - } - catch (CharacterCodingException x) { - // Substitution is always enabled, - // so this shouldn't happen - throw new IllegalStateException("unable to decode char array from the given buffer", x); - } - } - - private static char[] safeTrim(char[] ca, int len) { - if (len == ca.length) - return ca; - else - return Arrays.copyOf(ca, len); - } -} diff --git a/today-remoting/src/main/java/infra/remoting/util/NumberUtils.java b/today-remoting/src/main/java/infra/remoting/util/NumberUtils.java deleted file mode 100644 index a43cc89..0000000 --- a/today-remoting/src/main/java/infra/remoting/util/NumberUtils.java +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Copyright 2021 - 2024 the original author or authors. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] - */ - -package infra.remoting.util; - -import java.util.Objects; - -import io.netty.buffer.ByteBuf; - -public final class NumberUtils { - - /** The size of a medium in {@code byte}s. */ - public static final int MEDIUM_BYTES = 3; - - private static final int UNSIGNED_BYTE_SIZE = 8; - - private static final int UNSIGNED_BYTE_MAX_VALUE = (1 << UNSIGNED_BYTE_SIZE) - 1; - - private static final int UNSIGNED_MEDIUM_SIZE = 24; - - private static final int UNSIGNED_MEDIUM_MAX_VALUE = (1 << UNSIGNED_MEDIUM_SIZE) - 1; - - private static final int UNSIGNED_SHORT_SIZE = 16; - - private static final int UNSIGNED_SHORT_MAX_VALUE = (1 << UNSIGNED_SHORT_SIZE) - 1; - - private NumberUtils() { } - - /** - * Requires that an {@code int} is greater than or equal to zero. - * - * @param i the {@code int} to test - * @param message detail message to be used in the event that a {@link IllegalArgumentException} - * is thrown - * @return the {@code int} if greater than or equal to zero - * @throws IllegalArgumentException if {@code i} is less than zero - */ - public static int requireNonNegative(int i, String message) { - Objects.requireNonNull(message, "message is required"); - - if (i < 0) { - throw new IllegalArgumentException(message); - } - - return i; - } - - /** - * Requires that a {@code long} is greater than zero. - * - * @param l the {@code long} to test - * @param message detail message to be used in the event that a {@link IllegalArgumentException} - * is thrown - * @return the {@code long} if greater than zero - * @throws IllegalArgumentException if {@code l} is less than or equal to zero - */ - public static long requirePositive(long l, String message) { - Objects.requireNonNull(message, "message is required"); - - if (l <= 0) { - throw new IllegalArgumentException(message); - } - - return l; - } - - /** - * Requires that an {@code int} is greater than zero. - * - * @param i the {@code int} to test - * @param message detail message to be used in the event that a {@link IllegalArgumentException} - * is thrown - * @return the {@code int} if greater than zero - * @throws IllegalArgumentException if {@code i} is less than or equal to zero - */ - public static int requirePositive(int i, String message) { - Objects.requireNonNull(message, "message is required"); - - if (i <= 0) { - throw new IllegalArgumentException(message); - } - - return i; - } - - /** - * Requires that an {@code int} can be represented as an unsigned {@code byte}. - * - * @param i the {@code int} to test - * @return the {@code int} if it can be represented as an unsigned {@code byte} - * @throws IllegalArgumentException if {@code i} cannot be represented as an unsigned {@code byte} - */ - public static int requireUnsignedByte(int i) { - if (i > UNSIGNED_BYTE_MAX_VALUE) { - throw new IllegalArgumentException( - String.format("%d is larger than %d bits", i, UNSIGNED_BYTE_SIZE)); - } - - return i; - } - - /** - * Requires that an {@code int} can be represented as an unsigned {@code medium}. - * - * @param i the {@code int} to test - * @return the {@code int} if it can be represented as an unsigned {@code medium} - * @throws IllegalArgumentException if {@code i} cannot be represented as an unsigned {@code - * medium} - */ - public static int requireUnsignedMedium(int i) { - if (i > UNSIGNED_MEDIUM_MAX_VALUE) { - throw new IllegalArgumentException( - String.format("%d is larger than %d bits", i, UNSIGNED_MEDIUM_SIZE)); - } - - return i; - } - - /** - * Requires that an {@code int} can be represented as an unsigned {@code short}. - * - * @param i the {@code int} to test - * @return the {@code int} if it can be represented as an unsigned {@code short} - * @throws IllegalArgumentException if {@code i} cannot be represented as an unsigned {@code - * short} - */ - public static int requireUnsignedShort(int i) { - if (i > UNSIGNED_SHORT_MAX_VALUE) { - throw new IllegalArgumentException( - String.format("%d is larger than %d bits", i, UNSIGNED_SHORT_SIZE)); - } - - return i; - } - - /** - * Encode an unsigned medium integer on 3 bytes / 24 bits. This can be decoded directly by the - * {@link ByteBuf#readUnsignedMedium()} method. - * - * @param byteBuf the {@link ByteBuf} into which to write the bits - * @param i the medium integer to encode - * @see #requireUnsignedMedium(int) - */ - public static void encodeUnsignedMedium(ByteBuf byteBuf, int i) { - requireUnsignedMedium(i); - // Write each byte separately in reverse order, this mean we can write 1 << 23 without - // overflowing. - byteBuf.writeByte(i >> 16); - byteBuf.writeByte(i >> 8); - byteBuf.writeByte(i); - } -} diff --git a/today-remoting/src/test/java/infra/remoting/util/NumberUtilsTests.java b/today-remoting/src/test/java/infra/remoting/util/NumberUtilsTests.java deleted file mode 100644 index 89135e0..0000000 --- a/today-remoting/src/test/java/infra/remoting/util/NumberUtilsTests.java +++ /dev/null @@ -1,191 +0,0 @@ -/* - * Copyright 2021 - 2024 the original author or authors. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] - */ - -package infra.remoting.util; - -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; - -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufAllocator; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; -import static org.assertj.core.api.Assertions.assertThatNullPointerException; - -final class NumberUtilsTests { - - @DisplayName("returns int value with postitive int") - @Test - void requireNonNegativeInt() { - assertThat(NumberUtils.requireNonNegative(Integer.MAX_VALUE, "test-message")) - .isEqualTo(Integer.MAX_VALUE); - } - - @DisplayName( - "requireNonNegative with int argument throws IllegalArgumentException with negative value") - @Test - void requireNonNegativeIntNegative() { - assertThatIllegalArgumentException() - .isThrownBy(() -> NumberUtils.requireNonNegative(Integer.MIN_VALUE, "test-message")) - .withMessage("test-message"); - } - - @DisplayName("requireNonNegative with int argument throws NullPointerException with null message") - @Test - void requireNonNegativeIntNullMessage() { - assertThatNullPointerException() - .isThrownBy(() -> NumberUtils.requireNonNegative(Integer.MIN_VALUE, null)) - .withMessage("message is required"); - } - - @DisplayName("requireNonNegative returns int value with zero") - @Test - void requireNonNegativeIntZero() { - assertThat(NumberUtils.requireNonNegative(0, "test-message")).isEqualTo(0); - } - - @DisplayName("requirePositive returns int value with positive int") - @Test - void requirePositiveInt() { - assertThat(NumberUtils.requirePositive(Integer.MAX_VALUE, "test-message")) - .isEqualTo(Integer.MAX_VALUE); - } - - @DisplayName( - "requirePositive with int argument throws IllegalArgumentException with negative value") - @Test - void requirePositiveIntNegative() { - assertThatIllegalArgumentException() - .isThrownBy(() -> NumberUtils.requirePositive(Integer.MIN_VALUE, "test-message")) - .withMessage("test-message"); - } - - @DisplayName("requirePositive with int argument throws NullPointerException with null message") - @Test - void requirePositiveIntNullMessage() { - assertThatNullPointerException() - .isThrownBy(() -> NumberUtils.requirePositive(Integer.MIN_VALUE, null)) - .withMessage("message is required"); - } - - @DisplayName("requirePositive with int argument throws IllegalArgumentException with zero value") - @Test - void requirePositiveIntZero() { - assertThatIllegalArgumentException() - .isThrownBy(() -> NumberUtils.requirePositive(0, "test-message")) - .withMessage("test-message"); - } - - @DisplayName("requirePositive returns long value with positive long") - @Test - void requirePositiveLong() { - assertThat(NumberUtils.requirePositive(Long.MAX_VALUE, "test-message")) - .isEqualTo(Long.MAX_VALUE); - } - - @DisplayName( - "requirePositive with long argument throws IllegalArgumentException with negative value") - @Test - void requirePositiveLongNegative() { - assertThatIllegalArgumentException() - .isThrownBy(() -> NumberUtils.requirePositive(Long.MIN_VALUE, "test-message")) - .withMessage("test-message"); - } - - @DisplayName("requirePositive with long argument throws NullPointerException with null message") - @Test - void requirePositiveLongNullMessage() { - assertThatNullPointerException() - .isThrownBy(() -> NumberUtils.requirePositive(Long.MIN_VALUE, null)) - .withMessage("message is required"); - } - - @DisplayName("requirePositive with long argument throws IllegalArgumentException with zero value") - @Test - void requirePositiveLongZero() { - assertThatIllegalArgumentException() - .isThrownBy(() -> NumberUtils.requirePositive(0L, "test-message")) - .withMessage("test-message"); - } - - @DisplayName("requireUnsignedByte returns length if 255") - @Test - void requireUnsignedByte() { - assertThat(NumberUtils.requireUnsignedByte((1 << 8) - 1)).isEqualTo(255); - } - - @DisplayName("requireUnsignedByte throws IllegalArgumentException if larger than 255") - @Test - void requireUnsignedByteOverFlow() { - assertThatIllegalArgumentException() - .isThrownBy(() -> NumberUtils.requireUnsignedByte(1 << 8)) - .withMessage("%d is larger than 8 bits", 1 << 8); - } - - @DisplayName("requireUnsignedMedium returns length if 16_777_215") - @Test - void requireUnsignedMedium() { - assertThat(NumberUtils.requireUnsignedMedium((1 << 24) - 1)).isEqualTo(16_777_215); - } - - @DisplayName("requireUnsignedMedium throws IllegalArgumentException if larger than 16_777_215") - @Test - void requireUnsignedMediumOverFlow() { - assertThatIllegalArgumentException() - .isThrownBy(() -> NumberUtils.requireUnsignedMedium(1 << 24)) - .withMessage("%d is larger than 24 bits", 1 << 24); - } - - @DisplayName("requireUnsignedShort returns length if 65_535") - @Test - void requireUnsignedShort() { - assertThat(NumberUtils.requireUnsignedShort((1 << 16) - 1)).isEqualTo(65_535); - } - - @DisplayName("requireUnsignedShort throws IllegalArgumentException if larger than 65_535") - @Test - void requireUnsignedShortOverFlow() { - assertThatIllegalArgumentException() - .isThrownBy(() -> NumberUtils.requireUnsignedShort(1 << 16)) - .withMessage("%d is larger than 16 bits", 1 << 16); - } - - @Test - void encodeUnsignedMedium() { - ByteBuf buffer = ByteBufAllocator.DEFAULT.buffer(); - NumberUtils.encodeUnsignedMedium(buffer, 129); - buffer.markReaderIndex(); - - assertThat(buffer.readUnsignedMedium()).as("reading as unsigned medium").isEqualTo(129); - - buffer.resetReaderIndex(); - assertThat(buffer.readMedium()).as("reading as signed medium").isEqualTo(129); - } - - @Test - void encodeUnsignedMediumLarge() { - ByteBuf buffer = ByteBufAllocator.DEFAULT.buffer(); - NumberUtils.encodeUnsignedMedium(buffer, 0xFFFFFC); - buffer.markReaderIndex(); - - assertThat(buffer.readUnsignedMedium()).as("reading as unsigned medium").isEqualTo(16777212); - - buffer.resetReaderIndex(); - assertThat(buffer.readMedium()).as("reading as signed medium").isEqualTo(-4); - } -} From c9ebe4e34dacdc4828fe9c7b270325488b3c3ac4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Tue, 5 Aug 2025 22:18:07 +0800 Subject: [PATCH 031/104] :art: --- .../micrometer/integration/IntegrationTests.java | 6 +++--- ...ceptor.java => ChannelAcceptorDecorator.java} | 4 ++-- .../plugins/InitializingInterceptorRegistry.java | 2 +- .../remoting/plugins/InterceptorRegistry.java | 16 ++++++++-------- 4 files changed, 14 insertions(+), 14 deletions(-) rename today-remoting/src/main/java/infra/remoting/plugins/{ChannelAcceptorInterceptor.java => ChannelAcceptorDecorator.java} (91%) diff --git a/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/IntegrationTests.java b/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/IntegrationTests.java index 0c7eee7..4238275 100644 --- a/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/IntegrationTests.java +++ b/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/IntegrationTests.java @@ -31,7 +31,7 @@ import infra.remoting.Payload; import infra.remoting.core.ChannelConnector; import infra.remoting.core.RemotingServer; -import infra.remoting.plugins.ChannelAcceptorInterceptor; +import infra.remoting.plugins.ChannelAcceptorDecorator; import infra.remoting.plugins.ChannelDecorator; import infra.remoting.plugins.ConnectionDecorator; import infra.remoting.test.TestSubscriber; @@ -53,8 +53,8 @@ public class IntegrationTests { private static final ChannelDecorator requesterInterceptor; private static final ChannelDecorator responderInterceptor; - private static final ChannelAcceptorInterceptor clientAcceptorInterceptor; - private static final ChannelAcceptorInterceptor serverAcceptorInterceptor; + private static final ChannelAcceptorDecorator clientAcceptorInterceptor; + private static final ChannelAcceptorDecorator serverAcceptorInterceptor; private static final ConnectionDecorator CONNECTION_DECORATOR; private static volatile boolean calledRequester = false; diff --git a/today-remoting/src/main/java/infra/remoting/plugins/ChannelAcceptorInterceptor.java b/today-remoting/src/main/java/infra/remoting/plugins/ChannelAcceptorDecorator.java similarity index 91% rename from today-remoting/src/main/java/infra/remoting/plugins/ChannelAcceptorInterceptor.java rename to today-remoting/src/main/java/infra/remoting/plugins/ChannelAcceptorDecorator.java index 35b7dc5..cbbfb92 100644 --- a/today-remoting/src/main/java/infra/remoting/plugins/ChannelAcceptorInterceptor.java +++ b/today-remoting/src/main/java/infra/remoting/plugins/ChannelAcceptorDecorator.java @@ -27,8 +27,8 @@ * ChannelInterceptor} and "responder" {@code ChannelInterceptor}. */ @FunctionalInterface -public interface ChannelAcceptorInterceptor { +public interface ChannelAcceptorDecorator { - ChannelAcceptor decorate(ChannelAcceptor channelAcceptor); + ChannelAcceptor decorate(ChannelAcceptor delegate); } diff --git a/today-remoting/src/main/java/infra/remoting/plugins/InitializingInterceptorRegistry.java b/today-remoting/src/main/java/infra/remoting/plugins/InitializingInterceptorRegistry.java index 9120097..6c864ca 100644 --- a/today-remoting/src/main/java/infra/remoting/plugins/InitializingInterceptorRegistry.java +++ b/today-remoting/src/main/java/infra/remoting/plugins/InitializingInterceptorRegistry.java @@ -69,7 +69,7 @@ public Channel decorateResponder(Channel channel) { } public ChannelAcceptor decorateAcceptor(ChannelAcceptor acceptor) { - for (ChannelAcceptorInterceptor interceptor : channelAcceptorInterceptors) { + for (ChannelAcceptorDecorator interceptor : channelAcceptorDecorators) { acceptor = interceptor.decorate(acceptor); } return acceptor; diff --git a/today-remoting/src/main/java/infra/remoting/plugins/InterceptorRegistry.java b/today-remoting/src/main/java/infra/remoting/plugins/InterceptorRegistry.java index e7408ae..4bf9615 100644 --- a/today-remoting/src/main/java/infra/remoting/plugins/InterceptorRegistry.java +++ b/today-remoting/src/main/java/infra/remoting/plugins/InterceptorRegistry.java @@ -29,7 +29,7 @@ * *

        *
      • {@link #forConnection(ConnectionDecorator)} -- transport level - *
      • {@link #forChannelAcceptor(ChannelAcceptorInterceptor)} -- for accepting new connections + *
      • {@link #forChannelAcceptor(ChannelAcceptorDecorator)} -- for accepting new connections *
      • {@link #forRequester(ChannelDecorator)} -- for performing of requests *
      • {@link #forResponder(ChannelDecorator)} -- for responding to requests *
      @@ -44,7 +44,7 @@ public class InterceptorRegistry { protected final ArrayList responderChannelDecorators = new ArrayList<>(); - protected final ArrayList channelAcceptorInterceptors = new ArrayList<>(); + protected final ArrayList channelAcceptorDecorators = new ArrayList<>(); protected final ArrayList connectionDecorators = new ArrayList<>(); @@ -106,19 +106,19 @@ public InterceptorRegistry forResponder(Consumer> consume } /** - * Add a {@link ChannelAcceptorInterceptor} that will intercept the accepting of new connections. + * Add a {@link ChannelAcceptorDecorator} that will intercept the accepting of new connections. */ - public InterceptorRegistry forChannelAcceptor(ChannelAcceptorInterceptor interceptor) { - channelAcceptorInterceptors.add(interceptor); + public InterceptorRegistry forChannelAcceptor(ChannelAcceptorDecorator interceptor) { + channelAcceptorDecorators.add(interceptor); return this; } /** - * Variant of {@link #forChannelAcceptor(ChannelAcceptorInterceptor)} with access to the list of + * Variant of {@link #forChannelAcceptor(ChannelAcceptorDecorator)} with access to the list of * existing registrations. */ - public InterceptorRegistry forChannelAcceptor(Consumer> consumer) { - consumer.accept(channelAcceptorInterceptors); + public InterceptorRegistry forChannelAcceptor(Consumer> consumer) { + consumer.accept(channelAcceptorDecorators); return this; } From 0ae5be1c6d390b936407e3490aa7ecb951182b63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Fri, 8 Aug 2025 23:31:26 +0800 Subject: [PATCH 032/104] =?UTF-8?q?:sparkles:=20=E5=9F=BA=E7=A1=80?= =?UTF-8?q?=E8=AE=BE=E6=96=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 2 + settings.gradle | 4 + today-cloud-core/build.gradle | 10 +- .../java/infra/cloud/DiscoveryClient.java | 101 ----------- .../{ => client}/DefaultServiceInstance.java | 77 +++++++-- .../cloud/{ => client}/ServiceInstance.java | 20 ++- .../core/serialize/KryoSerialization.java | 63 ------- .../main/java/infra/cloud/net/HostInfo.java | 88 ++++++++++ .../net/HostInfoEnvironmentPostProcessor.java | 61 +++++++ .../java/infra/cloud/net/InetProperties.java | 121 +++++++++++++ .../java/infra/cloud/net/InetService.java | 162 ++++++++++++++++++ .../main/java/infra/cloud/package-info.java | 23 +++ .../main/resources/META-INF/today.strategies | 4 + .../infra/cloud/net/InetServiceTests.java | 121 +++++++++++++ .../demo-tests/demo-registry/build.gradle | 3 +- .../taketoday/demo/RegistryApplication.java | 2 - .../src/main/resources/application.yaml | 8 +- .../demo-tests/demo-user-service/build.gradle | 5 +- .../src/main/resources/application.yaml | 10 +- today-service-api/build.gradle | 16 ++ .../src/main/java/infra/cloud/RpcMethod.java | 0 .../src/main/java/infra/cloud/RpcRequest.java | 0 .../main/java/infra/cloud/RpcResponse.java | 0 .../client/CompositeDiscoveryClient.java | 89 ++++++++++ .../infra/cloud/client/DiscoveryClient.java | 83 +++++++++ .../ConditionalOnDiscoveryEnabled.java | 29 ++-- .../DiscoveryClientAutoConfiguration.java | 54 ++++++ .../client/simple/SimpleDiscoveryClient.java | 69 ++++++++ .../simple/SimpleDiscoveryProperties.java | 63 +++++++ .../infra/cloud/serialize/ByteBufInput.java | 0 .../infra/cloud/serialize/ByteBufOutput.java | 0 .../ProtobufArgumentSerialization.java | 3 +- .../serialize/ReturnValueSerialization.java | 0 .../serialize/RpcArgumentSerialization.java | 0 .../serialize/RpcRequestSerialization.java | 0 .../serialize/RpcResponseSerialization.java | 0 .../SimpleValueArgumentSerialization.java | 0 .../serialize/ThrowableSerialization.java | 0 .../infra/cloud/serialize/package-info.java | 0 .../value/FuncValueSerialization.java | 0 .../serialize/value/ValueSerialization.java | 0 ...nnotation.config.AutoConfiguration.imports | 1 + .../main/resources/META-INF/today.strategies | 0 ...DiscoveryClientAutoConfigurationTests.java | 89 ++++++++++ .../CompositeDiscoveryClientOrderTest.java | 64 +++++++ .../client/CompositeDiscoveryClientTests.java | 77 +++++++++ .../CompositeDiscoveryClientTestsConfig.java | 93 ++++++++++ .../CompositeDiscoveryClientUnitTests.java | 98 +++++++++++ ...ryClientAutoConfigurationDefaultTests.java | 53 ++++++ ...DiscoveryClientPropertiesMappingTests.java | 90 ++++++++++ .../simple/SimpleDiscoveryClientTests.java | 78 +++++++++ today-service-client/build.gradle | 18 +- .../java/infra/cloud/JdkServiceProxy.java | 2 + .../infra/cloud/ServiceMethodInvoker.java | 1 + .../main/java/infra/cloud/ServiceProxy.java | 2 + .../cloud/http/HttpServiceClientConfig.java | 3 - .../cloud/protocol/http/HttpOperations.java | 5 +- .../http/HttpServiceMethodInvoker.java | 2 +- .../protocol/http/HttpServiceRegistry.java | 26 +-- today-service-provider/build.gradle | 5 +- .../cloud/provider/EnableServiceProvider.java | 13 -- .../cloud/provider/LocalServiceHolder.java | 47 +---- .../cloud/provider/ServicePublishConfig.java | 64 +------ .../build.gradle | 10 ++ .../registry/simple}/HttpRegistration.java | 26 +-- .../api/SimpleHttpServiceRegistryAPI.java | 55 ++++++ .../build.gradle | 10 ++ .../cloud/registry/simple/HttpOperations.java | 91 ++++++++++ .../simple/SimpleHttpServiceRegistry.java | 60 +++++++ .../build.gradle | 10 ++ .../SimpleHttpServiceRegistryEndpoint.java | 62 ++++--- ...ditional-infra-configuration-metadata.json | 10 ++ ...nnotation.config.AutoConfiguration.imports | 0 .../main/resources/META-INF/today.strategies | 0 today-service-registry/build.gradle | 5 +- .../AbstractAutoServiceRegistration.java | 152 ++++++++++++++++ .../registry/AutoServiceRegistration.java | 26 +++ ...oServiceRegistrationAutoConfiguration.java | 43 +++++ .../AutoServiceRegistrationConfiguration.java | 33 ++++ ...=> AutoServiceRegistrationProperties.java} | 57 +++--- .../cloud/registry/InstanceSelector.java | 2 +- .../registry/RandomInstanceSelector.java | 2 +- .../infra/cloud/registry}/Registration.java | 6 +- .../cloud/registry/RegistrationLifecycle.java | 61 +++++++ .../cloud/registry/ServiceDefinition.java | 101 ----------- .../ServiceRegisterFailedException.java | 1 - .../infra/cloud/registry/ServiceRegistry.java | 34 +++- .../event/InstancePreRegisteredEvent.java | 53 ++++++ .../event/InstanceRegisteredEvent.java | 50 ++++++ ...nnotation.config.AutoConfiguration.imports | 1 + 90 files changed, 2506 insertions(+), 577 deletions(-) delete mode 100644 today-cloud-core/src/main/java/infra/cloud/DiscoveryClient.java rename today-cloud-core/src/main/java/infra/cloud/{ => client}/DefaultServiceInstance.java (60%) rename today-cloud-core/src/main/java/infra/cloud/{ => client}/ServiceInstance.java (76%) delete mode 100644 today-cloud-core/src/main/java/infra/cloud/core/serialize/KryoSerialization.java create mode 100644 today-cloud-core/src/main/java/infra/cloud/net/HostInfo.java create mode 100644 today-cloud-core/src/main/java/infra/cloud/net/HostInfoEnvironmentPostProcessor.java create mode 100644 today-cloud-core/src/main/java/infra/cloud/net/InetProperties.java create mode 100644 today-cloud-core/src/main/java/infra/cloud/net/InetService.java create mode 100644 today-cloud-core/src/main/java/infra/cloud/package-info.java create mode 100644 today-cloud-core/src/main/resources/META-INF/today.strategies create mode 100644 today-cloud-core/src/test/java/infra/cloud/net/InetServiceTests.java create mode 100644 today-service-api/build.gradle rename {today-service-client => today-service-api}/src/main/java/infra/cloud/RpcMethod.java (100%) rename {today-service-client => today-service-api}/src/main/java/infra/cloud/RpcRequest.java (100%) rename {today-service-client => today-service-api}/src/main/java/infra/cloud/RpcResponse.java (100%) create mode 100644 today-service-api/src/main/java/infra/cloud/client/CompositeDiscoveryClient.java create mode 100644 today-service-api/src/main/java/infra/cloud/client/DiscoveryClient.java rename today-service-registry/src/main/java/infra/cloud/registry/EnableHttpRegistry.java => today-service-api/src/main/java/infra/cloud/client/annotation/ConditionalOnDiscoveryEnabled.java (63%) create mode 100644 today-service-api/src/main/java/infra/cloud/client/annotation/config/DiscoveryClientAutoConfiguration.java create mode 100644 today-service-api/src/main/java/infra/cloud/client/simple/SimpleDiscoveryClient.java create mode 100644 today-service-api/src/main/java/infra/cloud/client/simple/SimpleDiscoveryProperties.java rename {today-service-client => today-service-api}/src/main/java/infra/cloud/serialize/ByteBufInput.java (100%) rename {today-service-client => today-service-api}/src/main/java/infra/cloud/serialize/ByteBufOutput.java (100%) rename {today-service-client => today-service-api}/src/main/java/infra/cloud/serialize/ProtobufArgumentSerialization.java (97%) rename {today-service-client => today-service-api}/src/main/java/infra/cloud/serialize/ReturnValueSerialization.java (100%) rename {today-service-client => today-service-api}/src/main/java/infra/cloud/serialize/RpcArgumentSerialization.java (100%) rename {today-service-client => today-service-api}/src/main/java/infra/cloud/serialize/RpcRequestSerialization.java (100%) rename {today-service-client => today-service-api}/src/main/java/infra/cloud/serialize/RpcResponseSerialization.java (100%) rename {today-service-client => today-service-api}/src/main/java/infra/cloud/serialize/SimpleValueArgumentSerialization.java (100%) rename {today-service-client => today-service-api}/src/main/java/infra/cloud/serialize/ThrowableSerialization.java (100%) rename {today-service-client => today-service-api}/src/main/java/infra/cloud/serialize/package-info.java (100%) rename {today-service-client => today-service-api}/src/main/java/infra/cloud/serialize/value/FuncValueSerialization.java (100%) rename {today-service-client => today-service-api}/src/main/java/infra/cloud/serialize/value/ValueSerialization.java (100%) create mode 100644 today-service-api/src/main/resources/META-INF/config/infra.context.annotation.config.AutoConfiguration.imports create mode 100644 today-service-api/src/main/resources/META-INF/today.strategies create mode 100644 today-service-api/src/test/java/infra/cloud/client/CompositeDiscoveryClientAutoConfigurationTests.java create mode 100644 today-service-api/src/test/java/infra/cloud/client/CompositeDiscoveryClientOrderTest.java create mode 100644 today-service-api/src/test/java/infra/cloud/client/CompositeDiscoveryClientTests.java create mode 100644 today-service-api/src/test/java/infra/cloud/client/CompositeDiscoveryClientTestsConfig.java create mode 100644 today-service-api/src/test/java/infra/cloud/client/CompositeDiscoveryClientUnitTests.java create mode 100644 today-service-api/src/test/java/infra/cloud/client/simple/DiscoveryClientAutoConfigurationDefaultTests.java create mode 100644 today-service-api/src/test/java/infra/cloud/client/simple/SimpleDiscoveryClientPropertiesMappingTests.java create mode 100644 today-service-api/src/test/java/infra/cloud/client/simple/SimpleDiscoveryClientTests.java create mode 100644 today-service-registry-simple-api/build.gradle rename {today-service-registry/src/main/java/infra/cloud/registry => today-service-registry-simple-api/src/main/java/infra/cloud/registry/simple}/HttpRegistration.java (58%) create mode 100644 today-service-registry-simple-api/src/main/java/infra/cloud/registry/simple/api/SimpleHttpServiceRegistryAPI.java create mode 100644 today-service-registry-simple-client/build.gradle create mode 100644 today-service-registry-simple-client/src/main/java/infra/cloud/registry/simple/HttpOperations.java create mode 100644 today-service-registry-simple-client/src/main/java/infra/cloud/registry/simple/SimpleHttpServiceRegistry.java create mode 100644 today-service-registry-simple-server/build.gradle rename today-service-registry/src/main/java/infra/cloud/registry/HttpServiceRegistryEndpoint.java => today-service-registry-simple-server/src/main/java/infra/cloud/registry/simple/server/SimpleHttpServiceRegistryEndpoint.java (54%) create mode 100644 today-service-registry-simple-server/src/main/resources/META-INF/additional-infra-configuration-metadata.json create mode 100644 today-service-registry-simple-server/src/main/resources/META-INF/config/infra.context.annotation.config.AutoConfiguration.imports create mode 100644 today-service-registry-simple-server/src/main/resources/META-INF/today.strategies create mode 100644 today-service-registry/src/main/java/infra/cloud/registry/AbstractAutoServiceRegistration.java create mode 100644 today-service-registry/src/main/java/infra/cloud/registry/AutoServiceRegistration.java create mode 100644 today-service-registry/src/main/java/infra/cloud/registry/AutoServiceRegistrationAutoConfiguration.java create mode 100644 today-service-registry/src/main/java/infra/cloud/registry/AutoServiceRegistrationConfiguration.java rename today-service-registry/src/main/java/infra/cloud/registry/{RegistryProperties.java => AutoServiceRegistrationProperties.java} (50%) rename {today-cloud-core/src/main/java/infra/cloud => today-service-registry/src/main/java/infra/cloud/registry}/Registration.java (86%) create mode 100644 today-service-registry/src/main/java/infra/cloud/registry/RegistrationLifecycle.java delete mode 100644 today-service-registry/src/main/java/infra/cloud/registry/ServiceDefinition.java create mode 100644 today-service-registry/src/main/java/infra/cloud/registry/event/InstancePreRegisteredEvent.java create mode 100644 today-service-registry/src/main/java/infra/cloud/registry/event/InstanceRegisteredEvent.java create mode 100644 today-service-registry/src/main/resources/META-INF/config/infra.context.annotation.config.AutoConfiguration.imports diff --git a/build.gradle b/build.gradle index 591407c..b50a677 100644 --- a/build.gradle +++ b/build.gradle @@ -49,6 +49,8 @@ configure(javaProjects) { testImplementation("org.mockito:mockito-core") testImplementation("org.mockito:mockito-junit-jupiter") testImplementation("org.assertj:assertj-core") + testImplementation("cn.taketoday:today-test") + testImplementation("cn.taketoday:today-test-support") testImplementation 'org.projectlombok:lombok' testAnnotationProcessor("org.projectlombok:lombok") diff --git a/settings.gradle b/settings.gradle index ac39276..8e2fcb1 100644 --- a/settings.gradle +++ b/settings.gradle @@ -31,9 +31,13 @@ include 'today-cloud-core' include 'today-cloud-gateway' include 'today-cloud-config-server' +include 'today-service-api' include 'today-service-client' include 'today-service-provider' include 'today-service-registry' +include 'today-service-registry-simple-api' +include 'today-service-registry-simple-client' +include 'today-service-registry-simple-server' include 'today-remoting' include 'today-remoting-micrometer' diff --git a/today-cloud-core/build.gradle b/today-cloud-core/build.gradle index d16de18..c252acf 100644 --- a/today-cloud-core/build.gradle +++ b/today-cloud-core/build.gradle @@ -1,14 +1,14 @@ description = "TODAY Cloud Core Technologies" dependencies { - implementation 'cn.taketoday:today-core' - implementation 'cn.taketoday:today-starter-web' + api 'cn.taketoday:today-core' + api 'cn.taketoday:today-framework' - optional 'com.esotericsoftware:kryo:5.5.0' - - optional 'io.netty:netty-codec-http' + implementation 'cn.taketoday:today-context' // implementation 'org.msgpack:msgpack-core:0.9.8' implementation 'io.protostuff:protostuff-core:1.7.4' implementation 'io.protostuff:protostuff-runtime:1.7.4' + + annotationProcessor 'cn.taketoday:infra-configuration-processor' } \ No newline at end of file diff --git a/today-cloud-core/src/main/java/infra/cloud/DiscoveryClient.java b/today-cloud-core/src/main/java/infra/cloud/DiscoveryClient.java deleted file mode 100644 index b38270b..0000000 --- a/today-cloud-core/src/main/java/infra/cloud/DiscoveryClient.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright 2021 - 2024 the original author or authors. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] - */ - -package infra.cloud; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.LinkedHashSet; -import java.util.List; - -import infra.core.annotation.AnnotationAwareOrderComparator; - -/** - * Represents read operations commonly available to discovery - * services such as Netflix Eureka or consul.io. - * - * @author Harry Yang - * @since 1.0 - */ -public interface DiscoveryClient { - - /** - * Gets all ServiceInstances associated with a particular serviceId. - * - * @param serviceId The serviceId to query. - * @return A List of ServiceInstance. - */ - List getInstances(String serviceId); - - /** - * @return All known service IDs. - */ - List getServices(); - - static Composite composite(List clients) { - return new Composite(clients); - } - - /** - * A {@link DiscoveryClient} that is composed of other discovery clients and delegates - * calls to each of them in order. - * - * @author Harry Yang - */ - class Composite implements DiscoveryClient { - - private final List clients; - - public Composite(List clients) { - AnnotationAwareOrderComparator.sort(clients); - this.clients = clients; - } - - @Override - public List getInstances(String serviceId) { - if (this.clients != null) { - for (DiscoveryClient discoveryClient : this.clients) { - List instances = discoveryClient.getInstances(serviceId); - if (instances != null && !instances.isEmpty()) { - return instances; - } - } - } - return Collections.emptyList(); - } - - @Override - public List getServices() { - LinkedHashSet services = new LinkedHashSet<>(); - if (this.clients != null) { - for (DiscoveryClient discoveryClient : this.clients) { - List serviceForClient = discoveryClient.getServices(); - if (serviceForClient != null) { - services.addAll(serviceForClient); - } - } - } - return new ArrayList<>(services); - } - - public List getDiscoveryClients() { - return this.clients; - } - - } - -} diff --git a/today-cloud-core/src/main/java/infra/cloud/DefaultServiceInstance.java b/today-cloud-core/src/main/java/infra/cloud/client/DefaultServiceInstance.java similarity index 60% rename from today-cloud-core/src/main/java/infra/cloud/DefaultServiceInstance.java rename to today-cloud-core/src/main/java/infra/cloud/client/DefaultServiceInstance.java index 7174ecc..785a525 100644 --- a/today-cloud-core/src/main/java/infra/cloud/DefaultServiceInstance.java +++ b/today-cloud-core/src/main/java/infra/cloud/client/DefaultServiceInstance.java @@ -15,13 +15,15 @@ * along with this program. If not, see [http://www.gnu.org/licenses/] */ -package infra.cloud; +package infra.cloud.client; import java.net.URI; +import java.util.LinkedHashMap; +import java.util.Map; import java.util.Objects; -import infra.core.AttributeAccessorSupport; import infra.core.style.ToStringBuilder; +import infra.lang.Nullable; /** * Default implementation of {@link ServiceInstance}. @@ -29,7 +31,7 @@ * @author Harry Yang * @since 1.0 2023/11/19 20:52 */ -public class DefaultServiceInstance extends AttributeAccessorSupport implements ServiceInstance { +public class DefaultServiceInstance implements ServiceInstance { private String instanceId; @@ -39,10 +41,14 @@ public class DefaultServiceInstance extends AttributeAccessorSupport implements private int port; + private boolean secure; + + private Map metadata = new LinkedHashMap<>(); + + @Nullable private URI uri; public DefaultServiceInstance() { - } /** @@ -50,27 +56,44 @@ public DefaultServiceInstance() { * @param serviceId the id of the service. * @param host the host where the service instance can be found. * @param port the port on which the service is running. + * @param secure indicates whether or not the connection needs to be secure. + * @param metadata a map containing metadata. */ - public DefaultServiceInstance(String instanceId, String serviceId, String host, int port) { + public DefaultServiceInstance(String instanceId, String serviceId, String host, + int port, boolean secure, Map metadata) { this.instanceId = instanceId; this.serviceId = serviceId; this.host = host; this.port = port; + this.secure = secure; + this.metadata = metadata; + } + + /** + * @param instanceId the id of the instance. + * @param serviceId the id of the service. + * @param host the host where the service instance can be found. + * @param port the port on which the service is running. + * @param secure indicates whether or not the connection needs to be secure. + */ + public DefaultServiceInstance(String instanceId, String serviceId, String host, int port, boolean secure) { + this(instanceId, serviceId, host, port, secure, new LinkedHashMap<>()); } /** * Creates a URI from the given ServiceInstance's host:port. * * @param instance the ServiceInstance. - * @return URI of the form "host:port". Scheme port default used + * @return URI of the form (secure)?https:http + "host:port". Scheme port default used * if port not set. */ public static URI getUri(ServiceInstance instance) { + String scheme = (instance.isSecure()) ? "https" : "http"; int port = instance.getPort(); if (port <= 0) { - port = 80; + port = (instance.isSecure()) ? 443 : 80; } - String uri = String.format("http://%s:%s", instance.getHost(), port); + String uri = String.format("%s://%s:%s", scheme, instance.getHost(), port); return URI.create(uri); } @@ -82,6 +105,11 @@ public URI getHttpURI() { return uri; } + @Override + public Map getMetadata() { + return metadata; + } + @Override public String getInstanceId() { return instanceId; @@ -102,6 +130,11 @@ public int getPort() { return port; } + @Override + public boolean isSecure() { + return secure; + } + public void setInstanceId(String instanceId) { this.instanceId = instanceId; } @@ -118,10 +151,18 @@ public void setPort(int port) { this.port = port; } + public void setSecure(boolean secure) { + this.secure = secure; + } + public void setUri(URI uri) { this.uri = uri; this.host = this.uri.getHost(); this.port = this.uri.getPort(); + String scheme = this.uri.getScheme(); + if ("https".equals(scheme)) { + this.secure = true; + } } @Override @@ -131,28 +172,30 @@ public String toString() { .append("serviceId", serviceId) .append("host", host) .append("port", port) - .append("uri", uri) + .append("secure", secure) + .append("metadata", metadata) .toString(); } @Override - public boolean equals(Object object) { - if (this == object) + public boolean equals(Object o) { + if (this == o) { return true; - if (!(object instanceof DefaultServiceInstance that)) - return false; - if (!super.equals(object)) + } + if (o == null || getClass() != o.getClass()) { return false; - return port == that.port + } + DefaultServiceInstance that = (DefaultServiceInstance) o; + return port == that.port && secure == that.secure && Objects.equals(instanceId, that.instanceId) && Objects.equals(serviceId, that.serviceId) && Objects.equals(host, that.host) - && Objects.equals(uri, that.uri); + && Objects.equals(metadata, that.metadata); } @Override public int hashCode() { - return Objects.hash(super.hashCode(), instanceId, serviceId, host, port, uri); + return Objects.hash(instanceId, serviceId, host, port, secure, metadata); } } diff --git a/today-cloud-core/src/main/java/infra/cloud/ServiceInstance.java b/today-cloud-core/src/main/java/infra/cloud/client/ServiceInstance.java similarity index 76% rename from today-cloud-core/src/main/java/infra/cloud/ServiceInstance.java rename to today-cloud-core/src/main/java/infra/cloud/client/ServiceInstance.java index 8abefcf..14841e5 100644 --- a/today-cloud-core/src/main/java/infra/cloud/ServiceInstance.java +++ b/today-cloud-core/src/main/java/infra/cloud/client/ServiceInstance.java @@ -15,23 +15,25 @@ * along with this program. If not, see [http://www.gnu.org/licenses/] */ -package infra.cloud; +package infra.cloud.client; import java.net.URI; +import java.util.Map; -import infra.core.AttributeAccessor; +import infra.lang.Nullable; /** - * Represents an instance of a service in a discovery system. + * Represents an instance of a service. * * @author Harry Yang * @since 1.0 2023/11/19 20:52 */ -public interface ServiceInstance extends AttributeAccessor { +public interface ServiceInstance { /** * @return The unique instance ID as registered. */ + @Nullable default String getInstanceId() { return null; } @@ -51,9 +53,19 @@ default String getInstanceId() { */ int getPort(); + /** + * @return Whether the port of the registered service instance uses HTTPS. + */ + boolean isSecure(); + /** * @return The service URI address. */ URI getHttpURI(); + /** + * @return The key / value pair metadata associated with the service instance. + */ + Map getMetadata(); + } diff --git a/today-cloud-core/src/main/java/infra/cloud/core/serialize/KryoSerialization.java b/today-cloud-core/src/main/java/infra/cloud/core/serialize/KryoSerialization.java deleted file mode 100644 index b9a1c16..0000000 --- a/today-cloud-core/src/main/java/infra/cloud/core/serialize/KryoSerialization.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2021 - 2024 the original author or authors. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] - */ - -package infra.cloud.core.serialize; - -import com.esotericsoftware.kryo.Kryo; -import com.esotericsoftware.kryo.io.Input; -import com.esotericsoftware.kryo.io.Output; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; - -import infra.lang.Assert; - -/** - * Kryo Serialization - * - * @author TODAY 2021/7/21 22:12 - */ -public class KryoSerialization extends Serialization { - private final Kryo kryo; - - public KryoSerialization() { - this(new Kryo()); - } - - public KryoSerialization(Kryo kryo) { - Assert.notNull(kryo, "Kryo is required"); - this.kryo = kryo; - } - - @Override - public void serialize(Object object, OutputStream output) throws IOException { - Output kryoOutput = new Output(output); - kryo.writeClassAndObject(kryoOutput, object); - } - - @Override - public Object deserializeInternal(InputStream inputStream) { - Input input = new Input(inputStream); - return kryo.readClassAndObject(input); - } - - public Kryo getKryo() { - return kryo; - } - -} diff --git a/today-cloud-core/src/main/java/infra/cloud/net/HostInfo.java b/today-cloud-core/src/main/java/infra/cloud/net/HostInfo.java new file mode 100644 index 0000000..e3497b8 --- /dev/null +++ b/today-cloud-core/src/main/java/infra/cloud/net/HostInfo.java @@ -0,0 +1,88 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.net; + +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.nio.ByteBuffer; + +/** + * Host information. + * + * @author 海子 Yang + * @since 1.0 2025/8/6 23:07 + */ +public class HostInfo { + + /** + * Should override the host info. + */ + public boolean override; + + private String ipAddress; + + private String hostname; + + public HostInfo(String hostname, String ipAddress) { + this.hostname = hostname; + this.ipAddress = ipAddress; + } + + public HostInfo() { + } + + public int getIpAddressAsInt() { + InetAddress inetAddress; + String host = this.ipAddress; + if (host == null) { + host = this.hostname; + } + try { + inetAddress = InetAddress.getByName(host); + } + catch (final UnknownHostException e) { + throw new IllegalArgumentException(e); + } + return ByteBuffer.wrap(inetAddress.getAddress()).getInt(); + } + + public boolean isOverride() { + return this.override; + } + + public void setOverride(boolean override) { + this.override = override; + } + + public String getIpAddress() { + return this.ipAddress; + } + + public void setIpAddress(String ipAddress) { + this.ipAddress = ipAddress; + } + + public String getHostname() { + return this.hostname; + } + + public void setHostname(String hostname) { + this.hostname = hostname; + } + +} diff --git a/today-cloud-core/src/main/java/infra/cloud/net/HostInfoEnvironmentPostProcessor.java b/today-cloud-core/src/main/java/infra/cloud/net/HostInfoEnvironmentPostProcessor.java new file mode 100644 index 0000000..8108521 --- /dev/null +++ b/today-cloud-core/src/main/java/infra/cloud/net/HostInfoEnvironmentPostProcessor.java @@ -0,0 +1,61 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.net; + +import java.util.LinkedHashMap; + +import infra.app.Application; +import infra.app.context.config.ConfigDataEnvironmentPostProcessor; +import infra.app.env.EnvironmentPostProcessor; +import infra.context.properties.bind.Bindable; +import infra.context.properties.bind.Binder; +import infra.context.properties.source.ConfigurationPropertySources; +import infra.core.Ordered; +import infra.core.env.ConfigurableEnvironment; +import infra.core.env.MapPropertySource; + +/** + * @author 海子 Yang + */ +public class HostInfoEnvironmentPostProcessor implements EnvironmentPostProcessor, Ordered { + + private static final int ORDER = Math.addExact(ConfigDataEnvironmentPostProcessor.ORDER, 1); + + @Override + public int getOrder() { + return ORDER; + } + + @Override + public void postProcessEnvironment(ConfigurableEnvironment environment, Application application) { + HostInfo hostInfo = getFirstNonLoopbackHostInfo(environment); + LinkedHashMap map = new LinkedHashMap<>(); + map.put("infra.app.hostname", hostInfo.getHostname()); + map.put("infra.app.ip-address", hostInfo.getIpAddress()); + MapPropertySource propertySource = new MapPropertySource("infraAppHostInfo", map); + environment.getPropertySources().addLast(propertySource); + } + + private HostInfo getFirstNonLoopbackHostInfo(ConfigurableEnvironment environment) { + InetProperties target = new InetProperties(); + ConfigurationPropertySources.attach(environment); + Binder.get(environment).bind(InetProperties.PREFIX, Bindable.ofInstance(target)); + return new InetService(target).findFirstNonLoopbackHostInfo(); + } + +} diff --git a/today-cloud-core/src/main/java/infra/cloud/net/InetProperties.java b/today-cloud-core/src/main/java/infra/cloud/net/InetProperties.java new file mode 100644 index 0000000..8b56139 --- /dev/null +++ b/today-cloud-core/src/main/java/infra/cloud/net/InetProperties.java @@ -0,0 +1,121 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.net; + +import java.net.InetAddress; +import java.util.ArrayList; +import java.util.List; + +import infra.beans.factory.annotation.Value; +import infra.context.properties.ConfigurationProperties; + +/** + * Properties for {@link InetService}. + * + * @author Spencer Gibb + * @author 海子 Yang + */ +@ConfigurationProperties(InetProperties.PREFIX) +public class InetProperties { + + /** + * Prefix for the Inet properties. + */ + public static final String PREFIX = "cloud.inet"; + + /** + * The default hostname. Used in case of errors. + */ + private String defaultHostname = "localhost"; + + /** + * The default IP address. Used in case of errors. + */ + private String defaultIpAddress = "127.0.0.1"; + + /** + * Timeout, in seconds, for calculating hostname. + */ + @Value("${cloud.inet.timeout.sec:${CLOUD_INET_TIMEOUT_SEC:4}}") + private int timeoutSeconds = 1; + + /** + * List of Java regular expressions for network interfaces that will be ignored. + */ + private List ignoredInterfaces = new ArrayList<>(); + + /** + * Whether to use only interfaces with site local addresses. See + * {@link InetAddress#isSiteLocalAddress()} for more details. + */ + private boolean useOnlySiteLocalInterfaces = false; + + /** + * List of Java regular expressions for network addresses that will be preferred. + */ + private List preferredNetworks = new ArrayList<>(); + + public String getDefaultHostname() { + return this.defaultHostname; + } + + public void setDefaultHostname(String defaultHostname) { + this.defaultHostname = defaultHostname; + } + + public String getDefaultIpAddress() { + return this.defaultIpAddress; + } + + public void setDefaultIpAddress(String defaultIpAddress) { + this.defaultIpAddress = defaultIpAddress; + } + + public int getTimeoutSeconds() { + return this.timeoutSeconds; + } + + public void setTimeoutSeconds(int timeoutSeconds) { + this.timeoutSeconds = timeoutSeconds; + } + + public List getIgnoredInterfaces() { + return this.ignoredInterfaces; + } + + public void setIgnoredInterfaces(List ignoredInterfaces) { + this.ignoredInterfaces = ignoredInterfaces; + } + + public boolean isUseOnlySiteLocalInterfaces() { + return this.useOnlySiteLocalInterfaces; + } + + public void setUseOnlySiteLocalInterfaces(boolean useOnlySiteLocalInterfaces) { + this.useOnlySiteLocalInterfaces = useOnlySiteLocalInterfaces; + } + + public List getPreferredNetworks() { + return this.preferredNetworks; + } + + public void setPreferredNetworks(List preferredNetworks) { + this.preferredNetworks = preferredNetworks; + } + +} diff --git a/today-cloud-core/src/main/java/infra/cloud/net/InetService.java b/today-cloud-core/src/main/java/infra/cloud/net/InetService.java new file mode 100644 index 0000000..0dafd9c --- /dev/null +++ b/today-cloud-core/src/main/java/infra/cloud/net/InetService.java @@ -0,0 +1,162 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.net; + +import java.io.IOException; +import java.net.Inet4Address; +import java.net.InetAddress; +import java.net.NetworkInterface; +import java.net.UnknownHostException; +import java.util.Enumeration; +import java.util.List; +import java.util.concurrent.TimeUnit; + +import infra.logging.Logger; +import infra.logging.LoggerFactory; +import infra.util.concurrent.Future; + +import static infra.util.concurrent.Future.run; + +/** + * @author Spencer Gibb + * @author Sergey Tsypanov + * @author 海子 Yang + */ +public class InetService { + + private static final Logger log = LoggerFactory.getLogger(InetService.class); + + private final InetProperties properties; + + public InetService(InetProperties properties) { + this.properties = properties; + } + + public HostInfo findFirstNonLoopbackHostInfo() { + InetAddress address = findFirstNonLoopbackAddress(); + if (address != null) { + return convertAddress(address); + } + HostInfo hostInfo = new HostInfo(); + hostInfo.setHostname(this.properties.getDefaultHostname()); + hostInfo.setIpAddress(this.properties.getDefaultIpAddress()); + return hostInfo; + } + + public InetAddress findFirstNonLoopbackAddress() { + InetAddress result = null; + try { + int lowest = Integer.MAX_VALUE; + for (Enumeration nics = NetworkInterface.getNetworkInterfaces(); nics + .hasMoreElements(); ) { + NetworkInterface ifc = nics.nextElement(); + if (ifc.isUp()) { + log.trace("Testing interface: {}", ifc.getDisplayName()); + if (ifc.getIndex() < lowest || result == null) { + lowest = ifc.getIndex(); + } + else if (result != null) { + continue; + } + + // @formatter:off + if (!ignoreInterface(ifc.getDisplayName())) { + for (Enumeration addrs = ifc + .getInetAddresses(); addrs.hasMoreElements();) { + InetAddress address = addrs.nextElement(); + if (address instanceof Inet4Address + && !address.isLoopbackAddress() + && isPreferredAddress(address)) { + log.trace("Found non-loopback interface: {}" , ifc.getDisplayName()); + result = address; + } + } + } + // @formatter:on + } + } + } + catch (IOException ex) { + log.error("Cannot get first non-loopback address", ex); + } + + if (result != null) { + return result; + } + + try { + return InetAddress.getLocalHost(); + } + catch (UnknownHostException e) { + log.warn("Unable to retrieve localhost"); + } + + return null; + } + + // For testing. + boolean isPreferredAddress(InetAddress address) { + + if (this.properties.isUseOnlySiteLocalInterfaces()) { + final boolean siteLocalAddress = address.isSiteLocalAddress(); + if (!siteLocalAddress) { + log.trace("Ignoring address: {}", address.getHostAddress()); + } + return siteLocalAddress; + } + final List preferredNetworks = this.properties.getPreferredNetworks(); + if (preferredNetworks.isEmpty()) { + return true; + } + for (String regex : preferredNetworks) { + final String hostAddress = address.getHostAddress(); + if (hostAddress.matches(regex) || hostAddress.startsWith(regex)) { + return true; + } + } + log.trace("Ignoring address: {}", address.getHostAddress()); + return false; + } + + // For testing + boolean ignoreInterface(String interfaceName) { + for (String regex : this.properties.getIgnoredInterfaces()) { + if (interfaceName.matches(regex)) { + log.trace("Ignoring interface: {}", interfaceName); + return true; + } + } + return false; + } + + public HostInfo convertAddress(final InetAddress address) { + Future result = run(address::getHostName); + + String hostname; + try { + hostname = result.get(properties.getTimeoutSeconds(), TimeUnit.SECONDS); + } + catch (Exception e) { + result.cancel(true); + log.info("Cannot determine local hostname"); + hostname = "localhost"; + } + return new HostInfo(hostname, address.getHostAddress()); + } + +} diff --git a/today-cloud-core/src/main/java/infra/cloud/package-info.java b/today-cloud-core/src/main/java/infra/cloud/package-info.java new file mode 100644 index 0000000..2590f42 --- /dev/null +++ b/today-cloud-core/src/main/java/infra/cloud/package-info.java @@ -0,0 +1,23 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +@NonNullApi +@NonNullFields +package infra.cloud; + +import infra.lang.NonNullApi; +import infra.lang.NonNullFields; \ No newline at end of file diff --git a/today-cloud-core/src/main/resources/META-INF/today.strategies b/today-cloud-core/src/main/resources/META-INF/today.strategies new file mode 100644 index 0000000..bb850ef --- /dev/null +++ b/today-cloud-core/src/main/resources/META-INF/today.strategies @@ -0,0 +1,4 @@ +infra.app.env.EnvironmentPostProcessor=infra.cloud.net.HostInfoEnvironmentPostProcessor + + + diff --git a/today-cloud-core/src/test/java/infra/cloud/net/InetServiceTests.java b/today-cloud-core/src/test/java/infra/cloud/net/InetServiceTests.java new file mode 100644 index 0000000..fa88958 --- /dev/null +++ b/today-cloud-core/src/test/java/infra/cloud/net/InetServiceTests.java @@ -0,0 +1,121 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.net; + +import org.junit.jupiter.api.Test; + +import java.net.InetAddress; +import java.util.Arrays; +import java.util.Collections; + +import static org.assertj.core.api.BDDAssertions.then; + +/** + * @author 海子 Yang + * @since 1.0 2025/8/6 22:16 + */ +class InetServiceTests { + + @Test + public void testGetFirstNonLoopbackHostInfo() { + InetService inetService = new InetService(new InetProperties()); + then(inetService.findFirstNonLoopbackHostInfo()).isNotNull(); + } + + @Test + public void testGetFirstNonLoopbackAddress() { + InetService inetService = new InetService(new InetProperties()); + then(inetService.findFirstNonLoopbackAddress()).isNotNull(); + } + + @Test + public void testConvert() throws Exception { + InetService inetService = new InetService(new InetProperties()); + then(inetService.convertAddress(InetAddress.getByName("localhost"))).isNotNull(); + } + + @Test + public void testHostInfo() { + InetService inetService = new InetService(new InetProperties()); + HostInfo info = inetService.findFirstNonLoopbackHostInfo(); + then(info.getIpAddressAsInt()).isNotNull(); + } + + @Test + public void testIgnoreInterface() { + InetProperties properties = new InetProperties(); + properties.setIgnoredInterfaces(Arrays.asList("docker0", "veth.*")); + InetService inetService = new InetService(properties); + + then(inetService.ignoreInterface("docker0")).isTrue().as("docker0 not ignored"); + then(inetService.ignoreInterface("vethAQI2QT")).as("vethAQI2QT0 not ignored").isTrue(); + then(inetService.ignoreInterface("docker1")).as("docker1 ignored").isFalse(); + } + + @Test + public void testDefaultIgnoreInterface() { + InetService inetService = new InetService(new InetProperties()); + then(inetService.ignoreInterface("docker0")).as("docker0 ignored").isFalse(); + } + + @Test + public void testSiteLocalAddresses() throws Exception { + InetProperties properties = new InetProperties(); + properties.setUseOnlySiteLocalInterfaces(true); + + InetService inetService = new InetService(properties); + then(inetService.isPreferredAddress(InetAddress.getByName("192.168.0.1"))).isTrue(); + then(inetService.isPreferredAddress(InetAddress.getByName("5.5.8.1"))).isFalse(); + } + + @Test + public void testPreferredNetworksRegex() throws Exception { + InetProperties properties = new InetProperties(); + properties.setPreferredNetworks(Arrays.asList("192.168.*", "10.0.*")); + + InetService inetService = new InetService(properties); + then(inetService.isPreferredAddress(InetAddress.getByName("192.168.0.1"))).isTrue(); + then(inetService.isPreferredAddress(InetAddress.getByName("5.5.8.1"))).isFalse(); + then(inetService.isPreferredAddress(InetAddress.getByName("10.0.10.1"))).isTrue(); + then(inetService.isPreferredAddress(InetAddress.getByName("10.255.10.1"))).isFalse(); + } + + @Test + public void testPreferredNetworksSimple() throws Exception { + InetProperties properties = new InetProperties(); + properties.setPreferredNetworks(Arrays.asList("192", "10.0")); + + InetService inetService = new InetService(properties); + then(inetService.isPreferredAddress(InetAddress.getByName("192.168.0.1"))).isTrue(); + then(inetService.isPreferredAddress(InetAddress.getByName("5.5.8.1"))).isFalse(); + then(inetService.isPreferredAddress(InetAddress.getByName("10.255.10.1"))).isFalse(); + then(inetService.isPreferredAddress(InetAddress.getByName("10.0.10.1"))).isTrue(); + } + + @Test + public void testPreferredNetworksListIsEmpty() throws Exception { + InetProperties properties = new InetProperties(); + properties.setPreferredNetworks(Collections.emptyList()); + InetService inetService = new InetService(properties); + then(inetService.isPreferredAddress(InetAddress.getByName("192.168.0.1"))).isTrue(); + then(inetService.isPreferredAddress(InetAddress.getByName("5.5.8.1"))).isTrue(); + then(inetService.isPreferredAddress(InetAddress.getByName("10.255.10.1"))).isTrue(); + then(inetService.isPreferredAddress(InetAddress.getByName("10.0.10.1"))).isTrue(); + } + +} \ No newline at end of file diff --git a/today-cloud-samples/demo-tests/demo-registry/build.gradle b/today-cloud-samples/demo-tests/demo-registry/build.gradle index 437d1d6..5a18c66 100644 --- a/today-cloud-samples/demo-tests/demo-registry/build.gradle +++ b/today-cloud-samples/demo-tests/demo-registry/build.gradle @@ -23,7 +23,8 @@ infraJar { } dependencies { - implementation project(":today-service-registry") + implementation project(":today-service-registry-simple-server") + implementation 'cn.taketoday:today-starter-web' implementation 'cn.taketoday:today-starter-netty' implementation 'ch.qos.logback:logback-classic' diff --git a/today-cloud-samples/demo-tests/demo-registry/src/main/java/cn/taketoday/demo/RegistryApplication.java b/today-cloud-samples/demo-tests/demo-registry/src/main/java/cn/taketoday/demo/RegistryApplication.java index 69452d8..049f516 100644 --- a/today-cloud-samples/demo-tests/demo-registry/src/main/java/cn/taketoday/demo/RegistryApplication.java +++ b/today-cloud-samples/demo-tests/demo-registry/src/main/java/cn/taketoday/demo/RegistryApplication.java @@ -17,7 +17,6 @@ package cn.taketoday.demo; -import infra.cloud.registry.EnableHttpRegistry; import infra.app.Application; import infra.app.InfraApplication; @@ -25,7 +24,6 @@ * @author Harry Yang * @since 1.0 2022/10/18 00:02 */ -@EnableHttpRegistry @InfraApplication public class RegistryApplication { diff --git a/today-cloud-samples/demo-tests/demo-registry/src/main/resources/application.yaml b/today-cloud-samples/demo-tests/demo-registry/src/main/resources/application.yaml index f90bfbc..3fd37ec 100644 --- a/today-cloud-samples/demo-tests/demo-registry/src/main/resources/application.yaml +++ b/today-cloud-samples/demo-tests/demo-registry/src/main/resources/application.yaml @@ -1,9 +1,9 @@ server: port: 5000 -#registry: -# services: -# uri: '/services' +registry: + services: + uri: '/services' web: resources: @@ -13,7 +13,7 @@ infra: profiles: active: dev -configq: +config: server: etcd: endpoints: "http://localhost:2379" diff --git a/today-cloud-samples/demo-tests/demo-user-service/build.gradle b/today-cloud-samples/demo-tests/demo-user-service/build.gradle index 13479e7..8199b45 100644 --- a/today-cloud-samples/demo-tests/demo-user-service/build.gradle +++ b/today-cloud-samples/demo-tests/demo-user-service/build.gradle @@ -1,12 +1,15 @@ description = "Demo User Service" dependencies { + implementation project(":today-cloud-samples:demo-tests:demo-user-api") + implementation project(":today-service-provider") + implementation project(":today-service-registry-simple-client") implementation 'cn.taketoday:today-starter-web' implementation 'cn.taketoday:today-starter-netty' implementation 'ch.qos.logback:logback-classic' - implementation project(":today-cloud-samples:demo-tests:demo-user-api") + implementation "com.google.protobuf:protobuf-java" diff --git a/today-cloud-samples/demo-tests/demo-user-service/src/main/resources/application.yaml b/today-cloud-samples/demo-tests/demo-user-service/src/main/resources/application.yaml index fdc06d4..1d0550f 100644 --- a/today-cloud-samples/demo-tests/demo-user-service/src/main/resources/application.yaml +++ b/today-cloud-samples/demo-tests/demo-user-service/src/main/resources/application.yaml @@ -1,12 +1,6 @@ server: port: 9000 -registry: - http-url: 'http://localhost:5000/services' - - services: - uri: '/services' - web: resources: add-default-mappings: false @@ -14,6 +8,10 @@ web: infra: profiles: active: dev + cloud: + service-registry: + auto-registration: + port: 9000 logging: level: diff --git a/today-service-api/build.gradle b/today-service-api/build.gradle new file mode 100644 index 0000000..d8fa751 --- /dev/null +++ b/today-service-api/build.gradle @@ -0,0 +1,16 @@ +description = "TODAY Service API" + + +dependencies { + api project(":today-remoting") + api project(":today-cloud-core") + + implementation 'cn.taketoday:today-beans' + implementation 'cn.taketoday:today-context' + + implementation 'io.protostuff:protostuff-core:1.7.4' + implementation 'io.protostuff:protostuff-runtime:1.7.4' + + optional "com.google.protobuf:protobuf-java" + +} \ No newline at end of file diff --git a/today-service-client/src/main/java/infra/cloud/RpcMethod.java b/today-service-api/src/main/java/infra/cloud/RpcMethod.java similarity index 100% rename from today-service-client/src/main/java/infra/cloud/RpcMethod.java rename to today-service-api/src/main/java/infra/cloud/RpcMethod.java diff --git a/today-service-client/src/main/java/infra/cloud/RpcRequest.java b/today-service-api/src/main/java/infra/cloud/RpcRequest.java similarity index 100% rename from today-service-client/src/main/java/infra/cloud/RpcRequest.java rename to today-service-api/src/main/java/infra/cloud/RpcRequest.java diff --git a/today-service-client/src/main/java/infra/cloud/RpcResponse.java b/today-service-api/src/main/java/infra/cloud/RpcResponse.java similarity index 100% rename from today-service-client/src/main/java/infra/cloud/RpcResponse.java rename to today-service-api/src/main/java/infra/cloud/RpcResponse.java diff --git a/today-service-api/src/main/java/infra/cloud/client/CompositeDiscoveryClient.java b/today-service-api/src/main/java/infra/cloud/client/CompositeDiscoveryClient.java new file mode 100644 index 0000000..9e83f1d --- /dev/null +++ b/today-service-api/src/main/java/infra/cloud/client/CompositeDiscoveryClient.java @@ -0,0 +1,89 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.client; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedHashSet; +import java.util.List; + +import infra.core.annotation.AnnotationAwareOrderComparator; +import infra.util.CollectionUtils; + +/** + * A {@link DiscoveryClient} that is composed of other discovery clients and delegates + * calls to each of them in order. + * + * @author 海子 Yang + * @since 1.0 2025/8/8 14:21 + */ +public class CompositeDiscoveryClient implements DiscoveryClient { + + private final List discoveryClients; + + public CompositeDiscoveryClient(List discoveryClients) { +// AnnotationAwareOrderComparator.sort(discoveryClients); + this.discoveryClients = discoveryClients; + } + + @Override + public String getDescription() { + return "Composite Discovery Client"; + } + + @Override + public List getInstances(String serviceId) { + if (this.discoveryClients != null) { + for (DiscoveryClient discoveryClient : this.discoveryClients) { + List instances = discoveryClient.getInstances(serviceId); + if (CollectionUtils.isNotEmpty(instances)) { + return instances; + } + } + } + return Collections.emptyList(); + } + + @Override + public List getServices() { + LinkedHashSet services = new LinkedHashSet<>(); + if (this.discoveryClients != null) { + for (DiscoveryClient discoveryClient : this.discoveryClients) { + List serviceForClient = discoveryClient.getServices(); + if (serviceForClient != null) { + services.addAll(serviceForClient); + } + } + } + return new ArrayList<>(services); + } + + @Override + public void probe() { + if (this.discoveryClients != null) { + for (DiscoveryClient discoveryClient : this.discoveryClients) { + discoveryClient.probe(); + } + } + } + + public List getDiscoveryClients() { + return discoveryClients; + } + +} diff --git a/today-service-api/src/main/java/infra/cloud/client/DiscoveryClient.java b/today-service-api/src/main/java/infra/cloud/client/DiscoveryClient.java new file mode 100644 index 0000000..15336a0 --- /dev/null +++ b/today-service-api/src/main/java/infra/cloud/client/DiscoveryClient.java @@ -0,0 +1,83 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.client; + +import java.util.List; + +import infra.core.Ordered; +import infra.lang.Descriptive; + +/** + * Represents read operations commonly available to discovery + * services such as Netflix Eureka or consul.io. + * + * @author Harry Yang + * @since 1.0 + */ +public interface DiscoveryClient extends Descriptive, Ordered { + + /** + * Default order of the discovery client. + */ + int DEFAULT_ORDER = 0; + + /** + * A human-readable description of the implementation. + * + * @return The description. + */ + @Override + String getDescription(); + + /** + * Gets all ServiceInstances associated with a particular serviceId. + * + * @param serviceId The serviceId to query. + * @return A List of ServiceInstance. + */ + List getInstances(String serviceId); + + /** + * @return All known service IDs. + */ + List getServices(); + + /** + * Can be used to verify the client is valid and able to make calls. + *

      + * A successful invocation with no exception thrown implies the client is able to make + * calls. + *

      + * The default implementation simply calls {@link #getServices()} - client + * implementations can override with a lighter weight operation if they choose to. + */ + default void probe() { + getServices(); + } + + /** + * Default implementation for getting order of discovery clients. + * + * @return order + */ + @Override + default int getOrder() { + return DEFAULT_ORDER; + } + +} diff --git a/today-service-registry/src/main/java/infra/cloud/registry/EnableHttpRegistry.java b/today-service-api/src/main/java/infra/cloud/client/annotation/ConditionalOnDiscoveryEnabled.java similarity index 63% rename from today-service-registry/src/main/java/infra/cloud/registry/EnableHttpRegistry.java rename to today-service-api/src/main/java/infra/cloud/client/annotation/ConditionalOnDiscoveryEnabled.java index 058b91b..976d363 100644 --- a/today-service-registry/src/main/java/infra/cloud/registry/EnableHttpRegistry.java +++ b/today-service-api/src/main/java/infra/cloud/client/annotation/ConditionalOnDiscoveryEnabled.java @@ -15,33 +15,28 @@ * along with this program. If not, see [http://www.gnu.org/licenses/] */ -package infra.cloud.registry; +package infra.cloud.client.annotation; +import java.lang.annotation.Documented; import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import infra.context.annotation.Import; -import infra.stereotype.Component; +import infra.context.condition.ConditionalOnProperty; /** - * Enable Http registry + * Provides a more succinct conditional infra.cloud.discovery.enabled. * - * @author TODAY 2021/7/11 16:14 + * @author Olga Maciaszek-Sharma + * @author 海子 Yang */ -@Import(HttpRegistryConfig.class) +@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) -@Target({ ElementType.TYPE, ElementType.METHOD }) -public @interface EnableHttpRegistry { - -} - -final class HttpRegistryConfig { - - @Component - public HttpServiceRegistryEndpoint serviceRegistryEndpoint() { - return new HttpServiceRegistryEndpoint(); - } +@Documented +@Inherited +@ConditionalOnProperty(value = "infra.cloud.discovery.enabled", matchIfMissing = true) +public @interface ConditionalOnDiscoveryEnabled { } diff --git a/today-service-api/src/main/java/infra/cloud/client/annotation/config/DiscoveryClientAutoConfiguration.java b/today-service-api/src/main/java/infra/cloud/client/annotation/config/DiscoveryClientAutoConfiguration.java new file mode 100644 index 0000000..bfb9b90 --- /dev/null +++ b/today-service-api/src/main/java/infra/cloud/client/annotation/config/DiscoveryClientAutoConfiguration.java @@ -0,0 +1,54 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.client.annotation.config; + +import infra.beans.factory.ObjectProvider; +import infra.cloud.client.CompositeDiscoveryClient; +import infra.cloud.client.DiscoveryClient; +import infra.cloud.client.annotation.ConditionalOnDiscoveryEnabled; +import infra.cloud.client.simple.SimpleDiscoveryClient; +import infra.cloud.client.simple.SimpleDiscoveryProperties; +import infra.context.annotation.MissingBean; +import infra.context.annotation.Primary; +import infra.context.annotation.config.DisableDIAutoConfiguration; +import infra.context.properties.EnableConfigurationProperties; +import infra.stereotype.Component; + +/** + * Auto-configuration for discovery client. + * + * @author Biju Kunjummen + * @author 海子 Yang + */ +@DisableDIAutoConfiguration +@ConditionalOnDiscoveryEnabled +@EnableConfigurationProperties(SimpleDiscoveryProperties.class) +public class DiscoveryClientAutoConfiguration { + + @Primary + @Component + public static CompositeDiscoveryClient compositeDiscoveryClient(ObjectProvider discoveryClients) { + return new CompositeDiscoveryClient(discoveryClients.orderedList()); + } + + @MissingBean + public static SimpleDiscoveryClient simpleDiscoveryClient(SimpleDiscoveryProperties properties) { + return new SimpleDiscoveryClient(properties); + } + +} diff --git a/today-service-api/src/main/java/infra/cloud/client/simple/SimpleDiscoveryClient.java b/today-service-api/src/main/java/infra/cloud/client/simple/SimpleDiscoveryClient.java new file mode 100644 index 0000000..48c4b3c --- /dev/null +++ b/today-service-api/src/main/java/infra/cloud/client/simple/SimpleDiscoveryClient.java @@ -0,0 +1,69 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.client.simple; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import infra.cloud.client.DiscoveryClient; +import infra.cloud.client.ServiceInstance; + +/** + * A {@link infra.cloud.client.DiscoveryClient} that will use the + * properties file as a source of service instances. + * + * @author Biju Kunjummen + * @author Olga Maciaszek-Sharma + * @author Charu Covindane + * @author 海子 Yang + */ +public class SimpleDiscoveryClient implements DiscoveryClient { + + private final SimpleDiscoveryProperties properties; + + public SimpleDiscoveryClient(SimpleDiscoveryProperties properties) { + this.properties = properties; + } + + @Override + public String getDescription() { + return "Simple Discovery Client"; + } + + @Override + @SuppressWarnings({ "unchecked", "rawtypes" }) + public List getInstances(String serviceId) { + List instances = properties.getInstances().get(serviceId); + if (instances != null) { + return Collections.unmodifiableList(instances); + } + return Collections.emptyList(); + } + + @Override + public List getServices() { + return new ArrayList<>(properties.getInstances().keySet()); + } + + @Override + public int getOrder() { + return properties.getOrder(); + } + +} diff --git a/today-service-api/src/main/java/infra/cloud/client/simple/SimpleDiscoveryProperties.java b/today-service-api/src/main/java/infra/cloud/client/simple/SimpleDiscoveryProperties.java new file mode 100644 index 0000000..4afd661 --- /dev/null +++ b/today-service-api/src/main/java/infra/cloud/client/simple/SimpleDiscoveryProperties.java @@ -0,0 +1,63 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.client.simple; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import infra.beans.factory.InitializingBean; +import infra.cloud.client.DefaultServiceInstance; +import infra.context.properties.ConfigurationProperties; +import infra.core.OrderedSupport; + +/** + * Properties to hold the details of a {@link infra.cloud.client.DiscoveryClient} + * service instances for a given service. It also holds the user-configurable order + * that will be used to establish the precedence of this client in the list of clients + * used by {@link infra.cloud.client.CompositeDiscoveryClient}. + * + * @author Biju Kunjummen + * @author Olga Maciaszek-Sharma + * @author Tim Ysewyn + * @author Charu Covindane + * @author 海子 Yang + */ +@ConfigurationProperties(prefix = "infra.cloud.discovery.simple") +public class SimpleDiscoveryProperties extends OrderedSupport implements InitializingBean { + + private Map> instances = new HashMap<>(); + + public Map> getInstances() { + return this.instances; + } + + public void setInstances(Map> instances) { + this.instances = instances; + } + + @Override + public void afterPropertiesSet() { + for (String key : this.instances.keySet()) { + for (DefaultServiceInstance instance : this.instances.get(key)) { + instance.setServiceId(key); + } + } + } + +} diff --git a/today-service-client/src/main/java/infra/cloud/serialize/ByteBufInput.java b/today-service-api/src/main/java/infra/cloud/serialize/ByteBufInput.java similarity index 100% rename from today-service-client/src/main/java/infra/cloud/serialize/ByteBufInput.java rename to today-service-api/src/main/java/infra/cloud/serialize/ByteBufInput.java diff --git a/today-service-client/src/main/java/infra/cloud/serialize/ByteBufOutput.java b/today-service-api/src/main/java/infra/cloud/serialize/ByteBufOutput.java similarity index 100% rename from today-service-client/src/main/java/infra/cloud/serialize/ByteBufOutput.java rename to today-service-api/src/main/java/infra/cloud/serialize/ByteBufOutput.java diff --git a/today-service-client/src/main/java/infra/cloud/serialize/ProtobufArgumentSerialization.java b/today-service-api/src/main/java/infra/cloud/serialize/ProtobufArgumentSerialization.java similarity index 97% rename from today-service-client/src/main/java/infra/cloud/serialize/ProtobufArgumentSerialization.java rename to today-service-api/src/main/java/infra/cloud/serialize/ProtobufArgumentSerialization.java index cf9e3fd..8e00a7f 100644 --- a/today-service-client/src/main/java/infra/cloud/serialize/ProtobufArgumentSerialization.java +++ b/today-service-api/src/main/java/infra/cloud/serialize/ProtobufArgumentSerialization.java @@ -26,7 +26,6 @@ import infra.cloud.RpcMethod; import infra.cloud.core.serialize.DeserializeFailedException; import infra.core.MethodParameter; -import infra.http.converter.HttpMessageConversionException; import infra.lang.Nullable; import infra.util.ConcurrentReferenceHashMap; import io.netty.buffer.ByteBuf; @@ -76,7 +75,7 @@ private Message.Builder getMessageBuilder(Class clazz) { return (Message.Builder) method.invoke(clazz); } catch (Exception ex) { - throw new HttpMessageConversionException( + throw new DeserializeFailedException( "Invalid Protobuf Message type: no invocable newBuilder() method on " + clazz, ex); } } diff --git a/today-service-client/src/main/java/infra/cloud/serialize/ReturnValueSerialization.java b/today-service-api/src/main/java/infra/cloud/serialize/ReturnValueSerialization.java similarity index 100% rename from today-service-client/src/main/java/infra/cloud/serialize/ReturnValueSerialization.java rename to today-service-api/src/main/java/infra/cloud/serialize/ReturnValueSerialization.java diff --git a/today-service-client/src/main/java/infra/cloud/serialize/RpcArgumentSerialization.java b/today-service-api/src/main/java/infra/cloud/serialize/RpcArgumentSerialization.java similarity index 100% rename from today-service-client/src/main/java/infra/cloud/serialize/RpcArgumentSerialization.java rename to today-service-api/src/main/java/infra/cloud/serialize/RpcArgumentSerialization.java diff --git a/today-service-client/src/main/java/infra/cloud/serialize/RpcRequestSerialization.java b/today-service-api/src/main/java/infra/cloud/serialize/RpcRequestSerialization.java similarity index 100% rename from today-service-client/src/main/java/infra/cloud/serialize/RpcRequestSerialization.java rename to today-service-api/src/main/java/infra/cloud/serialize/RpcRequestSerialization.java diff --git a/today-service-client/src/main/java/infra/cloud/serialize/RpcResponseSerialization.java b/today-service-api/src/main/java/infra/cloud/serialize/RpcResponseSerialization.java similarity index 100% rename from today-service-client/src/main/java/infra/cloud/serialize/RpcResponseSerialization.java rename to today-service-api/src/main/java/infra/cloud/serialize/RpcResponseSerialization.java diff --git a/today-service-client/src/main/java/infra/cloud/serialize/SimpleValueArgumentSerialization.java b/today-service-api/src/main/java/infra/cloud/serialize/SimpleValueArgumentSerialization.java similarity index 100% rename from today-service-client/src/main/java/infra/cloud/serialize/SimpleValueArgumentSerialization.java rename to today-service-api/src/main/java/infra/cloud/serialize/SimpleValueArgumentSerialization.java diff --git a/today-service-client/src/main/java/infra/cloud/serialize/ThrowableSerialization.java b/today-service-api/src/main/java/infra/cloud/serialize/ThrowableSerialization.java similarity index 100% rename from today-service-client/src/main/java/infra/cloud/serialize/ThrowableSerialization.java rename to today-service-api/src/main/java/infra/cloud/serialize/ThrowableSerialization.java diff --git a/today-service-client/src/main/java/infra/cloud/serialize/package-info.java b/today-service-api/src/main/java/infra/cloud/serialize/package-info.java similarity index 100% rename from today-service-client/src/main/java/infra/cloud/serialize/package-info.java rename to today-service-api/src/main/java/infra/cloud/serialize/package-info.java diff --git a/today-service-client/src/main/java/infra/cloud/serialize/value/FuncValueSerialization.java b/today-service-api/src/main/java/infra/cloud/serialize/value/FuncValueSerialization.java similarity index 100% rename from today-service-client/src/main/java/infra/cloud/serialize/value/FuncValueSerialization.java rename to today-service-api/src/main/java/infra/cloud/serialize/value/FuncValueSerialization.java diff --git a/today-service-client/src/main/java/infra/cloud/serialize/value/ValueSerialization.java b/today-service-api/src/main/java/infra/cloud/serialize/value/ValueSerialization.java similarity index 100% rename from today-service-client/src/main/java/infra/cloud/serialize/value/ValueSerialization.java rename to today-service-api/src/main/java/infra/cloud/serialize/value/ValueSerialization.java diff --git a/today-service-api/src/main/resources/META-INF/config/infra.context.annotation.config.AutoConfiguration.imports b/today-service-api/src/main/resources/META-INF/config/infra.context.annotation.config.AutoConfiguration.imports new file mode 100644 index 0000000..0d14b8f --- /dev/null +++ b/today-service-api/src/main/resources/META-INF/config/infra.context.annotation.config.AutoConfiguration.imports @@ -0,0 +1 @@ +infra.cloud.client.annotation.config.DiscoveryClientAutoConfiguration \ No newline at end of file diff --git a/today-service-api/src/main/resources/META-INF/today.strategies b/today-service-api/src/main/resources/META-INF/today.strategies new file mode 100644 index 0000000..e69de29 diff --git a/today-service-api/src/test/java/infra/cloud/client/CompositeDiscoveryClientAutoConfigurationTests.java b/today-service-api/src/test/java/infra/cloud/client/CompositeDiscoveryClientAutoConfigurationTests.java new file mode 100644 index 0000000..dfb5faa --- /dev/null +++ b/today-service-api/src/test/java/infra/cloud/client/CompositeDiscoveryClientAutoConfigurationTests.java @@ -0,0 +1,89 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.client; + +import org.junit.jupiter.api.Test; + +import java.util.List; + +import infra.app.test.context.InfraTest; +import infra.beans.factory.annotation.Autowired; +import infra.cloud.client.simple.SimpleDiscoveryClient; +import infra.context.annotation.Bean; +import infra.context.annotation.Configuration; +import infra.context.annotation.config.EnableAutoConfiguration; + +import static org.assertj.core.api.BDDAssertions.then; + +/** + * Composite Discovery Client should be the one found by default. + * + * @author Biju Kunjummen + */ +@InfraTest +class CompositeDiscoveryClientAutoConfigurationTests { + + @Autowired + private DiscoveryClient discoveryClient; + + @Test + void compositeDiscoveryClientShouldBeTheDefault() { + then(this.discoveryClient).isInstanceOf(CompositeDiscoveryClient.class); + CompositeDiscoveryClient compositeDiscoveryClient = (CompositeDiscoveryClient) this.discoveryClient; + then(compositeDiscoveryClient.getDiscoveryClients()).hasSize(2); + then(compositeDiscoveryClient.getDiscoveryClients().get(0).getDescription()) + .isEqualTo("A custom discovery client"); + } + + @Test + void simpleDiscoveryClientShouldBeHaveTheLowestPrecedence() { + CompositeDiscoveryClient compositeDiscoveryClient = (CompositeDiscoveryClient) this.discoveryClient; + then(compositeDiscoveryClient.getDiscoveryClients().get(0).getDescription()) + .isEqualTo("A custom discovery client"); + then(compositeDiscoveryClient.getDiscoveryClients().get(1)).isInstanceOf(SimpleDiscoveryClient.class); + } + + @EnableAutoConfiguration + @Configuration(proxyBeanMethods = false) + public static class Config { + + @Bean + public DiscoveryClient customDiscoveryClient1() { + return new DiscoveryClient() { + + @Override + public String getDescription() { + return "A custom discovery client"; + } + + @Override + public List getInstances(String serviceId) { + return null; + } + + @Override + public List getServices() { + return null; + } + + }; + } + + } + +} diff --git a/today-service-api/src/test/java/infra/cloud/client/CompositeDiscoveryClientOrderTest.java b/today-service-api/src/test/java/infra/cloud/client/CompositeDiscoveryClientOrderTest.java new file mode 100644 index 0000000..c5709be --- /dev/null +++ b/today-service-api/src/test/java/infra/cloud/client/CompositeDiscoveryClientOrderTest.java @@ -0,0 +1,64 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.client; + +import org.junit.jupiter.api.Test; + +import java.util.List; + +import infra.app.test.context.InfraTest; +import infra.beans.factory.annotation.Autowired; + +import static infra.cloud.client.CompositeDiscoveryClientTestsConfig.CUSTOM_DISCOVERY_CLIENT; +import static infra.cloud.client.CompositeDiscoveryClientTestsConfig.CUSTOM_SERVICE_ID; +import static infra.cloud.client.CompositeDiscoveryClientTestsConfig.DEFAULT_ORDER_DISCOVERY_CLIENT; +import static infra.cloud.client.CompositeDiscoveryClientTestsConfig.FOURTH_DISCOVERY_CLIENT; +import static org.assertj.core.api.BDDAssertions.then; + +/** + * Tests for the support of ordered {@link DiscoveryClient} instances in + * {@link CompositeDiscoveryClient}. + * + * @author Olga Maciaszek-Sharma + */ +@InfraTest(properties = "infra.cloud.discovery.simple.order=2", + classes = CompositeDiscoveryClientTestsConfig.class) +class CompositeDiscoveryClientOrderTest { + + @Autowired + CompositeDiscoveryClient discoveryClient; + + @Test + void shouldGetOrderedDiscoveryClients() { + List discoveryClients = this.discoveryClient.getDiscoveryClients(); + + then(discoveryClients.get(0).getDescription()).isEqualTo(CUSTOM_DISCOVERY_CLIENT); + then(discoveryClients.get(1).getDescription()).isEqualTo(DEFAULT_ORDER_DISCOVERY_CLIENT); + then(discoveryClients.get(2).getDescription()).isEqualTo("Simple Discovery Client"); + then(discoveryClients.get(3).getDescription()).isEqualTo(FOURTH_DISCOVERY_CLIENT); + } + + @Test + void shouldOnlyReturnServiceInstancesForTheHighestPrecedenceDiscoveryClient() { + List serviceInstances = this.discoveryClient.getInstances(CUSTOM_SERVICE_ID); + + then(serviceInstances).hasSize(1); + then(serviceInstances.get(0).getPort()).isEqualTo(123); + } + +} diff --git a/today-service-api/src/test/java/infra/cloud/client/CompositeDiscoveryClientTests.java b/today-service-api/src/test/java/infra/cloud/client/CompositeDiscoveryClientTests.java new file mode 100644 index 0000000..1b140ce --- /dev/null +++ b/today-service-api/src/test/java/infra/cloud/client/CompositeDiscoveryClientTests.java @@ -0,0 +1,77 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.client; + +import org.junit.jupiter.api.Test; + +import infra.app.test.context.InfraTest; +import infra.beans.factory.annotation.Autowired; + +import static infra.cloud.client.CompositeDiscoveryClientTestsConfig.CUSTOM_SERVICE_ID; +import static org.assertj.core.api.BDDAssertions.then; + +/** + * Tests for behavior of Composite Discovery Client. + * + * @author Biju Kunjummen + */ +@InfraTest(properties = { "app.name=service0", + "infra.cloud.discovery.simple.instances.service1[0].uri=http://s11:8080", + "infra.cloud.discovery.simple.instances.service1[1].uri=https://s12:8443", + "infra.cloud.discovery.simple.instances.service2[0].uri=https://s21:8080", + "infra.cloud.discovery.simple.instances.service2[1].uri=https://s22:443" }, + classes = CompositeDiscoveryClientTestsConfig.class) +class CompositeDiscoveryClientTests { + + @Autowired + private DiscoveryClient discoveryClient; + + @Test + void getInstancesByServiceIdShouldDelegateCall() { + then(this.discoveryClient).isInstanceOf(CompositeDiscoveryClient.class); + + then(this.discoveryClient.getInstances("service1")).hasSize(2); + + ServiceInstance s1 = this.discoveryClient.getInstances("service1").get(0); + then(s1.getHost()).isEqualTo("s11"); + then(s1.getPort()).isEqualTo(8080); + then(s1.isSecure()).isEqualTo(false); + } + + @Test + void getServicesShouldAggregateAllServiceNames() { + then(this.discoveryClient.getServices()).containsOnlyOnce("service1", "service2", "custom"); + } + + @Test + void getDescriptionShouldBeComposite() { + then(this.discoveryClient.getDescription()).isEqualTo("Composite Discovery Client"); + } + + @Test + void getInstancesShouldRespectOrder() { + then(this.discoveryClient.getInstances(CUSTOM_SERVICE_ID)).hasSize(1); + then(this.discoveryClient.getInstances(CUSTOM_SERVICE_ID)).hasSize(1); + } + + @Test + void getInstancesByUnknownServiceIdShouldReturnAnEmptyList() { + then(this.discoveryClient.getInstances("unknown")).hasSize(0); + } + +} diff --git a/today-service-api/src/test/java/infra/cloud/client/CompositeDiscoveryClientTestsConfig.java b/today-service-api/src/test/java/infra/cloud/client/CompositeDiscoveryClientTestsConfig.java new file mode 100644 index 0000000..5053004 --- /dev/null +++ b/today-service-api/src/test/java/infra/cloud/client/CompositeDiscoveryClientTestsConfig.java @@ -0,0 +1,93 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.client; + +import java.util.Collections; +import java.util.List; + +import infra.context.annotation.Bean; +import infra.context.annotation.Configuration; +import infra.context.annotation.config.EnableAutoConfiguration; + +import static java.util.Collections.singletonList; + +/** + * Test configuration for {@link CompositeDiscoveryClient} tests. + * + * @author Olga Maciaszek-Sharma + * @author Tim Ysewyn + */ +@EnableAutoConfiguration +@Configuration(proxyBeanMethods = false) +public class CompositeDiscoveryClientTestsConfig { + + static final String DEFAULT_ORDER_DISCOVERY_CLIENT = "Default order discovery client"; + static final String CUSTOM_DISCOVERY_CLIENT = "A custom discovery client"; + static final String FOURTH_DISCOVERY_CLIENT = "Fourth discovery client"; + static final String CUSTOM_SERVICE_ID = "custom"; + + @Bean + public DiscoveryClient customDiscoveryClient() { + return aDiscoveryClient(-1, CUSTOM_DISCOVERY_CLIENT); + } + + @Bean + public DiscoveryClient thirdOrderCustomDiscoveryClient() { + return aDiscoveryClient(3, FOURTH_DISCOVERY_CLIENT); + } + + @Bean + public DiscoveryClient defaultOrderDiscoveryClient() { + return aDiscoveryClient(null, DEFAULT_ORDER_DISCOVERY_CLIENT); + } + + private DiscoveryClient aDiscoveryClient(Integer order, String description) { + class TestDiscoveryClient implements DiscoveryClient { + @Override + public String getDescription() { + return description; + } + + @Override + public List getInstances(String serviceId) { + if (serviceId.equals(CUSTOM_SERVICE_ID)) { + ServiceInstance s1 = new DefaultServiceInstance("customInstance", CUSTOM_SERVICE_ID, "host", 123, false); + return List.of(s1); + } + return Collections.emptyList(); + } + + @Override + public List getServices() { + return singletonList(CUSTOM_SERVICE_ID); + } + + @Override + public int getOrder() { + return order != null ? order : DiscoveryClient.super.getOrder(); + } + + @Override + public String toString() { + return description; + } + } + return new TestDiscoveryClient(); + } + +} diff --git a/today-service-api/src/test/java/infra/cloud/client/CompositeDiscoveryClientUnitTests.java b/today-service-api/src/test/java/infra/cloud/client/CompositeDiscoveryClientUnitTests.java new file mode 100644 index 0000000..81166c4 --- /dev/null +++ b/today-service-api/src/test/java/infra/cloud/client/CompositeDiscoveryClientUnitTests.java @@ -0,0 +1,98 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.client; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import static org.assertj.core.api.BDDAssertions.then; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +/** + * Mockito tests for Composite Discovery Client + * + * @author Sean Ruffatti + */ +@ExtendWith(MockitoExtension.class) +class CompositeDiscoveryClientUnitTests { + + private CompositeDiscoveryClient underTest; + + @Mock + private DiscoveryClient client1; + + @Mock + private DiscoveryClient client2; + + @BeforeEach + void setUp() { + underTest = new CompositeDiscoveryClient(Arrays.asList(client1, client2)); + } + + @Test + void shouldRetrieveInstancesByServiceId() { + ServiceInstance serviceInstance1 = new DefaultServiceInstance("instance1", "serviceId", "https://s1", 8443, + true); + when(client1.getInstances("serviceId")).thenReturn(Collections.singletonList(serviceInstance1)); + + List serviceInstances = underTest.getInstances("serviceId"); + + then(serviceInstances.get(0).getInstanceId()).isEqualTo("instance1"); + then(serviceInstances.get(0).getServiceId()).isEqualTo("serviceId"); + then(serviceInstances.get(0).getHost()).isEqualTo("https://s1"); + then(serviceInstances.get(0).getPort()).isEqualTo(8443); + } + + @Test + void shouldReturnServiceIds() { + when(client1.getServices()).thenReturn(Collections.singletonList("serviceId1")); + when(client2.getServices()).thenReturn(Collections.singletonList("serviceId2")); + + List services = underTest.getServices(); + + then(services.size()).isEqualTo(2); + then(services).containsOnlyOnce("serviceId1", "serviceId2"); + } + + @Test + void shouldReturnAllDiscoveryClients() { + then(underTest.getDiscoveryClients()).containsOnlyOnce(client1, client2); + } + + @Test + void shouldCallProbeOnAllDiscoveryClients() { + underTest.probe(); + + // Every DiscoveryClient bean should invoke DiscoveryClient.probe() when + // CompositeDiscoveryClient.probe() is invoked. + verify(client1, times(1)).probe(); + verify(client1, times(0)).getServices(); + verify(client2, times(1)).probe(); + verify(client2, times(0)).getServices(); + } + +} diff --git a/today-service-api/src/test/java/infra/cloud/client/simple/DiscoveryClientAutoConfigurationDefaultTests.java b/today-service-api/src/test/java/infra/cloud/client/simple/DiscoveryClientAutoConfigurationDefaultTests.java new file mode 100644 index 0000000..434d316 --- /dev/null +++ b/today-service-api/src/test/java/infra/cloud/client/simple/DiscoveryClientAutoConfigurationDefaultTests.java @@ -0,0 +1,53 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.client.simple; + +import org.junit.jupiter.api.Test; + +import infra.app.test.context.InfraTest; +import infra.beans.factory.annotation.Autowired; +import infra.cloud.client.CompositeDiscoveryClient; +import infra.cloud.client.DiscoveryClient; +import infra.context.annotation.Configuration; +import infra.context.annotation.config.EnableAutoConfiguration; + +import static org.assertj.core.api.BDDAssertions.then; + +/** + * DiscoveryClient implementation defaults to {@link CompositeDiscoveryClient}. + * + * @author Biju Kunjummen + */ +@InfraTest(classes = DiscoveryClientAutoConfigurationDefaultTests.Config.class) +class DiscoveryClientAutoConfigurationDefaultTests { + + @Autowired + private DiscoveryClient discoveryClient; + + @Test + void simpleDiscoveryClientShouldBeTheDefault() { + then(this.discoveryClient).isInstanceOf(CompositeDiscoveryClient.class); + } + + @EnableAutoConfiguration + @Configuration(proxyBeanMethods = false) + public static class Config { + + } + +} diff --git a/today-service-api/src/test/java/infra/cloud/client/simple/SimpleDiscoveryClientPropertiesMappingTests.java b/today-service-api/src/test/java/infra/cloud/client/simple/SimpleDiscoveryClientPropertiesMappingTests.java new file mode 100644 index 0000000..0905430 --- /dev/null +++ b/today-service-api/src/test/java/infra/cloud/client/simple/SimpleDiscoveryClientPropertiesMappingTests.java @@ -0,0 +1,90 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.client.simple; + +import org.junit.jupiter.api.Test; + +import infra.app.test.context.InfraTest; +import infra.beans.factory.annotation.Autowired; +import infra.cloud.client.ServiceInstance; +import infra.context.annotation.Configuration; +import infra.context.annotation.config.EnableAutoConfiguration; + +import static org.assertj.core.api.BDDAssertions.then; + +/** + * Tests for mapping properties to instances in {@link SimpleDiscoveryClient}. + * + * @author Biju Kunjummen + */ +@InfraTest(properties = { "app.name=service0", + "infra.cloud.discovery.simple.instances.service1[0].uri=http://s11:8080", + "infra.cloud.discovery.simple.instances.service1[1].uri=https://s12:8443", + "infra.cloud.discovery.simple.instances.service2[0].uri=https://s21:8080", + "infra.cloud.discovery.simple.instances.service2[1].uri=https://s22:443" }) +class SimpleDiscoveryClientPropertiesMappingTests { + + @Autowired + private SimpleDiscoveryProperties props; + + @Autowired + private SimpleDiscoveryClient discoveryClient; + + @Test + void propsShouldGetCleanlyMapped() { + then(this.props.getInstances().size()).isEqualTo(2); + then(this.props.getInstances().get("service1").size()).isEqualTo(2); + then(this.props.getInstances().get("service1").get(0).getHost()).isEqualTo("s11"); + then(this.props.getInstances().get("service1").get(0).getPort()).isEqualTo(8080); + then(this.props.getInstances().get("service1").get(0).isSecure()).isEqualTo(false); + + then(this.props.getInstances().get("service2").size()).isEqualTo(2); + then(this.props.getInstances().get("service2").get(0).getHost()).isEqualTo("s21"); + then(this.props.getInstances().get("service2").get(0).getPort()).isEqualTo(8080); + then(this.props.getInstances().get("service2").get(0).isSecure()).isEqualTo(true); + } + + @Test + void testDiscoveryClientShouldResolveSimpleValues() { + then(this.discoveryClient.getDescription()).isEqualTo("Simple Discovery Client"); + then(this.discoveryClient.getInstances("service1")).hasSize(2); + + ServiceInstance s1 = this.discoveryClient.getInstances("service1").get(0); + then(s1.getHost()).isEqualTo("s11"); + then(s1.getPort()).isEqualTo(8080); + then(s1.isSecure()).isEqualTo(false); + } + + @Test + void testGetServices() { + then(this.discoveryClient.getServices()).containsExactlyInAnyOrder("service1", "service2"); + } + + @Test + void testGetANonExistentServiceShouldReturnAnEmptyList() { + then(this.discoveryClient.getInstances("nonexistent")).isNotNull(); + then(this.discoveryClient.getInstances("nonexistent")).isEmpty(); + } + + @Configuration(proxyBeanMethods = false) + @EnableAutoConfiguration + public static class SampleConfig { + + } + +} diff --git a/today-service-api/src/test/java/infra/cloud/client/simple/SimpleDiscoveryClientTests.java b/today-service-api/src/test/java/infra/cloud/client/simple/SimpleDiscoveryClientTests.java new file mode 100644 index 0000000..9e54ed8 --- /dev/null +++ b/today-service-api/src/test/java/infra/cloud/client/simple/SimpleDiscoveryClientTests.java @@ -0,0 +1,78 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.client.simple; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import infra.cloud.client.DefaultServiceInstance; +import infra.cloud.client.ServiceInstance; + +import static org.assertj.core.api.BDDAssertions.then; + +/** + * @author 海子 Yang + * @since 1.0 2025/8/8 20:58 + */ +class SimpleDiscoveryClientTests { + + private SimpleDiscoveryClient simpleDiscoveryClient; + + @BeforeEach + void setUp() { + SimpleDiscoveryProperties simpleDiscoveryProperties = new SimpleDiscoveryProperties(); + + Map> map = new HashMap<>(); + DefaultServiceInstance service1Inst1 = new DefaultServiceInstance(null, null, "host1", 8080, false); + DefaultServiceInstance service1Inst2 = new DefaultServiceInstance(null, null, "host2", 0, true); + DefaultServiceInstance service1Inst3 = new DefaultServiceInstance(null, null, "host3", 0, false); + map.put("service1", Arrays.asList(service1Inst1, service1Inst2, service1Inst3)); + simpleDiscoveryProperties.setInstances(map); + simpleDiscoveryProperties.afterPropertiesSet(); + this.simpleDiscoveryClient = new SimpleDiscoveryClient(simpleDiscoveryProperties); + } + + @Test + void shouldBeAbleToRetrieveServiceDetailsByName() { + List instances = this.simpleDiscoveryClient.getInstances("service1"); + then(instances.size()).isEqualTo(3); + then(instances.get(0).getServiceId()).isEqualTo("service1"); + then(instances.get(0).getHost()).isEqualTo("host1"); + then(instances.get(0).getPort()).isEqualTo(8080); + then(instances.get(0).isSecure()).isEqualTo(false); + then(instances.get(0).getMetadata()).isNotNull(); + + then(instances.get(1).getServiceId()).isEqualTo("service1"); + then(instances.get(1).getHost()).isEqualTo("host2"); + then(instances.get(1).getPort()).isEqualTo(0); + then(instances.get(1).isSecure()).isEqualTo(true); + then(instances.get(1).getMetadata()).isNotNull(); + + then(instances.get(2).getServiceId()).isEqualTo("service1"); + then(instances.get(2).getHost()).isEqualTo("host3"); + then(instances.get(2).getPort()).isEqualTo(0); + then(instances.get(2).isSecure()).isEqualTo(false); + then(instances.get(2).getMetadata()).isNotNull(); + } + +} \ No newline at end of file diff --git a/today-service-client/build.gradle b/today-service-client/build.gradle index b51d195..9ee881a 100644 --- a/today-service-client/build.gradle +++ b/today-service-client/build.gradle @@ -1,20 +1,3 @@ -/* - * Copyright 2021 - 2024 the original author or authors. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] - */ - description = "TODAY Service Client" @@ -22,6 +5,7 @@ dependencies { api project(":today-remoting") api project(":today-cloud-core") + api project(":today-service-api") api project(":today-service-registry") optional 'io.netty:netty-transport' diff --git a/today-service-client/src/main/java/infra/cloud/JdkServiceProxy.java b/today-service-client/src/main/java/infra/cloud/JdkServiceProxy.java index 21341c5..79be869 100644 --- a/today-service-client/src/main/java/infra/cloud/JdkServiceProxy.java +++ b/today-service-client/src/main/java/infra/cloud/JdkServiceProxy.java @@ -23,6 +23,8 @@ import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; +import infra.cloud.client.DiscoveryClient; +import infra.cloud.client.ServiceInstance; import infra.cloud.registry.ServiceNotFoundException; /** diff --git a/today-service-client/src/main/java/infra/cloud/ServiceMethodInvoker.java b/today-service-client/src/main/java/infra/cloud/ServiceMethodInvoker.java index f2abe92..cde9a4e 100644 --- a/today-service-client/src/main/java/infra/cloud/ServiceMethodInvoker.java +++ b/today-service-client/src/main/java/infra/cloud/ServiceMethodInvoker.java @@ -21,6 +21,7 @@ import java.util.ArrayList; import java.util.List; +import infra.cloud.client.ServiceInstance; import infra.cloud.registry.InstanceSelector; import infra.cloud.registry.RandomInstanceSelector; import infra.lang.Assert; diff --git a/today-service-client/src/main/java/infra/cloud/ServiceProxy.java b/today-service-client/src/main/java/infra/cloud/ServiceProxy.java index ed237eb..363103d 100644 --- a/today-service-client/src/main/java/infra/cloud/ServiceProxy.java +++ b/today-service-client/src/main/java/infra/cloud/ServiceProxy.java @@ -17,6 +17,8 @@ package infra.cloud; +import infra.cloud.client.DiscoveryClient; + /** * @author TODAY 2021/7/4 22:58 */ diff --git a/today-service-client/src/main/java/infra/cloud/http/HttpServiceClientConfig.java b/today-service-client/src/main/java/infra/cloud/http/HttpServiceClientConfig.java index 3109457..c3d293b 100644 --- a/today-service-client/src/main/java/infra/cloud/http/HttpServiceClientConfig.java +++ b/today-service-client/src/main/java/infra/cloud/http/HttpServiceClientConfig.java @@ -22,7 +22,6 @@ import infra.beans.factory.ObjectProvider; import infra.cloud.core.serialize.JdkSerialization; import infra.cloud.core.serialize.Serialization; -import infra.cloud.registry.RegistryProperties; import infra.cloud.serialize.ReturnValueSerialization; import infra.cloud.serialize.RpcArgumentSerialization; import infra.cloud.serialize.RpcRequestSerialization; @@ -30,7 +29,6 @@ import infra.cloud.serialize.ThrowableSerialization; import infra.context.annotation.Configuration; import infra.context.annotation.MissingBean; -import infra.context.properties.EnableConfigurationProperties; import infra.lang.TodayStrategies; import infra.stereotype.Component; @@ -39,7 +37,6 @@ * @since 1.0 2023/9/5 09:56 */ @Configuration(proxyBeanMethods = false) -@EnableConfigurationProperties(RegistryProperties.class) public class HttpServiceClientConfig { @Component diff --git a/today-service-client/src/main/java/infra/cloud/protocol/http/HttpOperations.java b/today-service-client/src/main/java/infra/cloud/protocol/http/HttpOperations.java index 56dfc95..c7da4b7 100644 --- a/today-service-client/src/main/java/infra/cloud/protocol/http/HttpOperations.java +++ b/today-service-client/src/main/java/infra/cloud/protocol/http/HttpOperations.java @@ -20,10 +20,10 @@ import java.util.List; import java.util.Map; -import infra.cloud.DefaultServiceInstance; +import infra.cloud.client.DefaultServiceInstance; import infra.cloud.RpcRequest; import infra.cloud.RpcResponse; -import infra.cloud.ServiceInstance; +import infra.cloud.client.ServiceInstance; import infra.cloud.core.serialize.Serialization; import infra.cloud.registry.ServiceNotFoundException; import infra.core.ParameterizedTypeReference; @@ -39,6 +39,7 @@ * @author Harry Yang * @since 1.0 2023/8/14 17:46 */ +@Deprecated(forRemoval = true) final class HttpOperations { private static final ParameterizedTypeReference> reference = new ParameterizedTypeReference<>() { }; diff --git a/today-service-client/src/main/java/infra/cloud/protocol/http/HttpServiceMethodInvoker.java b/today-service-client/src/main/java/infra/cloud/protocol/http/HttpServiceMethodInvoker.java index 9202141..e334a92 100644 --- a/today-service-client/src/main/java/infra/cloud/protocol/http/HttpServiceMethodInvoker.java +++ b/today-service-client/src/main/java/infra/cloud/protocol/http/HttpServiceMethodInvoker.java @@ -21,7 +21,7 @@ import infra.cloud.RpcRequest; import infra.cloud.RpcResponse; -import infra.cloud.ServiceInstance; +import infra.cloud.client.ServiceInstance; import infra.cloud.ServiceMethodInvoker; import infra.util.concurrent.Future; diff --git a/today-service-client/src/main/java/infra/cloud/protocol/http/HttpServiceRegistry.java b/today-service-client/src/main/java/infra/cloud/protocol/http/HttpServiceRegistry.java index c1b7ab5..8c7d1ce 100644 --- a/today-service-client/src/main/java/infra/cloud/protocol/http/HttpServiceRegistry.java +++ b/today-service-client/src/main/java/infra/cloud/protocol/http/HttpServiceRegistry.java @@ -20,25 +20,20 @@ import java.util.ArrayList; import java.util.List; -import infra.cloud.DiscoveryClient; import infra.cloud.JdkServiceProxy; import infra.cloud.RpcResponse; -import infra.cloud.ServiceInstance; import infra.cloud.ServiceMethodInvoker; import infra.cloud.ServiceProvider; import infra.cloud.ServiceProxy; +import infra.cloud.client.ServiceInstance; import infra.cloud.core.serialize.JdkSerialization; import infra.cloud.core.serialize.Serialization; -import infra.cloud.registry.HttpRegistration; -import infra.cloud.registry.ServiceRegisterFailedException; -import infra.cloud.registry.ServiceRegistry; import infra.core.style.ToStringBuilder; -import infra.web.client.RestClientException; /** * @author TODAY 2021/7/3 23:48 */ -public class HttpServiceRegistry implements ServiceRegistry, ServiceProvider, DiscoveryClient { +public class HttpServiceRegistry implements ServiceProvider { private ServiceProxy serviceProxy; @@ -76,27 +71,10 @@ protected JdkServiceProxy createServiceProxy() { return new JdkServiceProxy(); } - @Override - public void register(HttpRegistration registration) { - try { - httpOperations.register(registration); - } - catch (RestClientException e) { - throw new ServiceRegisterFailedException(registration, e); - } - } - - @Override - public void unregister(HttpRegistration registration) { - httpOperations.delete(registration); - } - - @Override public List getServices() { return new ArrayList<>(httpOperations.getServices().keySet()); } - @Override @SuppressWarnings("unchecked") public List getInstances(String serviceId) { return httpOperations.getInstances(serviceId); diff --git a/today-service-provider/build.gradle b/today-service-provider/build.gradle index 68652e3..361be72 100644 --- a/today-service-provider/build.gradle +++ b/today-service-provider/build.gradle @@ -22,13 +22,10 @@ dependencies { api project(":today-remoting") api project(":today-cloud-core") + api project(":today-service-api") - implementation project(":today-service-client") implementation project(":today-service-registry") - optional 'cn.taketoday:today-web' - implementation 'cn.taketoday:today-framework' - optional 'io.netty:netty-transport' optional 'io.netty:netty-codec' optional 'io.netty:netty-handler' diff --git a/today-service-provider/src/main/java/infra/cloud/provider/EnableServiceProvider.java b/today-service-provider/src/main/java/infra/cloud/provider/EnableServiceProvider.java index 77a24a5..a3cf8dc 100644 --- a/today-service-provider/src/main/java/infra/cloud/provider/EnableServiceProvider.java +++ b/today-service-provider/src/main/java/infra/cloud/provider/EnableServiceProvider.java @@ -23,13 +23,8 @@ import java.lang.annotation.Target; import infra.beans.factory.ObjectProvider; -import infra.cloud.RpcResponse; import infra.cloud.core.serialize.JdkSerialization; import infra.cloud.core.serialize.Serialization; -import infra.cloud.protocol.http.HttpServiceRegistry; -import infra.cloud.registry.HttpRegistration; -import infra.cloud.registry.RegistryProperties; -import infra.cloud.registry.ServiceRegistry; import infra.cloud.serialize.ReturnValueSerialization; import infra.cloud.serialize.RpcArgumentSerialization; import infra.cloud.serialize.RpcResponseSerialization; @@ -37,10 +32,8 @@ import infra.context.annotation.Configuration; import infra.context.annotation.Import; import infra.context.annotation.MissingBean; -import infra.context.properties.EnableConfigurationProperties; import infra.lang.TodayStrategies; import infra.stereotype.Component; -import infra.web.server.ServerProperties; /** * @author Harry Yang @@ -55,14 +48,8 @@ @Import(ServicePublishConfig.class) @Configuration(proxyBeanMethods = false) -@EnableConfigurationProperties({ ServerProperties.class, RegistryProperties.class }) class TcpServiceProviderConfig { - @MissingBean - static ServiceRegistry serviceRegistry(RegistryProperties properties, Serialization serialization) { - return HttpServiceRegistry.ofURL(properties.getHttpUrl(), serialization); - } - @MissingBean static Serialization requestSerialization() { return new JdkSerialization<>(); diff --git a/today-service-provider/src/main/java/infra/cloud/provider/LocalServiceHolder.java b/today-service-provider/src/main/java/infra/cloud/provider/LocalServiceHolder.java index 8ec3fdf..26d7f17 100644 --- a/today-service-provider/src/main/java/infra/cloud/provider/LocalServiceHolder.java +++ b/today-service-provider/src/main/java/infra/cloud/provider/LocalServiceHolder.java @@ -17,19 +17,15 @@ package infra.cloud.provider; -import java.net.InetAddress; -import java.util.ArrayList; import java.util.HashMap; import java.util.List; import infra.beans.factory.SmartInitializingSingleton; -import infra.cloud.registry.ServiceDefinition; import infra.context.ApplicationContext; import infra.context.support.ApplicationObjectSupport; import infra.lang.Nullable; import infra.stereotype.Service; import infra.util.ClassUtils; -import infra.util.ExceptionUtils; import infra.util.ObjectUtils; /** @@ -38,35 +34,12 @@ */ public class LocalServiceHolder extends ApplicationObjectSupport implements SmartInitializingSingleton { - private final InetAddress localHost = ExceptionUtils.sneakyThrow(InetAddress::getLocalHost); - - private String localHostName; - - private final int port; - - private final HashMap localServices = new HashMap<>(); - - private final ArrayList definitions = new ArrayList<>(); - - public LocalServiceHolder(int port) { - this.port = port; - } - - public void setLocalHostName(String localHostName) { - this.localHostName = localHostName; - } - - public ArrayList getServices() { - return definitions; - } - - public int getPort() { - return port; - } + private final HashMap, Object> localServices = new HashMap<>(); @Nullable - public Object getService(String serviceName) { - return localServices.get(serviceName); + @SuppressWarnings("unchecked") + public T getService(Class serviceName) { + return (T) localServices.get(serviceName); } @Override @@ -90,16 +63,8 @@ public void afterSingletonsInstantiated() { } } - ServiceDefinition definition = new ServiceDefinition(); - - definition.setHost(localHostName == null ? localHost.getHostAddress() : localHostName); - - definition.setPort(port); - definition.setName(interfaceToUse.getName()); - - logger.info("add service: [{}] to interface: [{}]", service, definition.getName()); - definitions.add(definition); - localServices.put(interfaceToUse.getName(), service); // register object + logger.info("add service: [{}] to interface: [{}]", service, interfaceToUse.getName()); + localServices.put(interfaceToUse, service); // register object } } diff --git a/today-service-provider/src/main/java/infra/cloud/provider/ServicePublishConfig.java b/today-service-provider/src/main/java/infra/cloud/provider/ServicePublishConfig.java index 0f18f8f..6f189dc 100644 --- a/today-service-provider/src/main/java/infra/cloud/provider/ServicePublishConfig.java +++ b/today-service-provider/src/main/java/infra/cloud/provider/ServicePublishConfig.java @@ -17,16 +17,10 @@ package infra.cloud.provider; -import java.util.concurrent.atomic.AtomicBoolean; - -import infra.cloud.registry.HttpRegistration; -import infra.cloud.registry.ServiceRegistry; -import infra.context.SmartLifecycle; import infra.context.annotation.Configuration; import infra.logging.Logger; import infra.logging.LoggerFactory; import infra.stereotype.Component; -import infra.stereotype.Singleton; /** * @author Harry Yang @@ -37,63 +31,9 @@ class ServicePublishConfig { private static final Logger log = LoggerFactory.getLogger(ServicePublishConfig.class); - @Singleton - static LocalServiceHolder localServiceHolder() { - return new LocalServiceHolder(9001); - } - @Component - static ServiceProviderLifecycle serviceProviderLifecycle(ServiceRegistry serviceRegistry, LocalServiceHolder serviceHolder) { - return new ServiceProviderLifecycle(serviceRegistry, serviceHolder); - } - - static class ServiceProviderLifecycle implements SmartLifecycle { - final LocalServiceHolder serviceHolder; - - final ServiceRegistry serviceRegistry; - - private final AtomicBoolean started = new AtomicBoolean(); - - ServiceProviderLifecycle(ServiceRegistry serviceRegistry, LocalServiceHolder serviceHolder) { - this.serviceRegistry = serviceRegistry; - this.serviceHolder = serviceHolder; - } - - @Override - public void start() { - if (started.compareAndSet(false, true)) { - log.info("Registering services to registry: [{}]", serviceRegistry); - serviceRegistry.register(new HttpRegistration(serviceHolder.getServices())); // register to registry - } - } - - @Override - public void stop() { - throw new UnsupportedOperationException("Stop must not be invoked directly"); - } - - /** - * Go offline to delete the service registered on the machine - */ - @Override - public void stop(Runnable callback) { - if (started.compareAndSet(true, false)) { - log.info("Un-Registering services: [{}]", serviceRegistry); - try { - HttpRegistration registration = new HttpRegistration(serviceHolder.getServices()); - serviceRegistry.unregister(registration); - } - finally { - callback.run(); - } - } - } - - @Override - public boolean isRunning() { - return started.get(); - } - + static LocalServiceHolder localServiceHolder() { + return new LocalServiceHolder(); } } diff --git a/today-service-registry-simple-api/build.gradle b/today-service-registry-simple-api/build.gradle new file mode 100644 index 0000000..a714a36 --- /dev/null +++ b/today-service-registry-simple-api/build.gradle @@ -0,0 +1,10 @@ +description = "TODAY Service Simple Registry API" + + +dependencies { + api project(":today-service-registry") + + api 'cn.taketoday:today-starter-web' + + annotationProcessor 'cn.taketoday:infra-configuration-processor' +} \ No newline at end of file diff --git a/today-service-registry/src/main/java/infra/cloud/registry/HttpRegistration.java b/today-service-registry-simple-api/src/main/java/infra/cloud/registry/simple/HttpRegistration.java similarity index 58% rename from today-service-registry/src/main/java/infra/cloud/registry/HttpRegistration.java rename to today-service-registry-simple-api/src/main/java/infra/cloud/registry/simple/HttpRegistration.java index 45bbe12..2e05124 100644 --- a/today-service-registry/src/main/java/infra/cloud/registry/HttpRegistration.java +++ b/today-service-registry-simple-api/src/main/java/infra/cloud/registry/simple/HttpRegistration.java @@ -15,32 +15,24 @@ * along with this program. If not, see [http://www.gnu.org/licenses/] */ -package infra.cloud.registry; +package infra.cloud.registry.simple; -import java.util.List; - -import infra.cloud.Registration; +import infra.cloud.client.DefaultServiceInstance; +import infra.cloud.registry.Registration; /** * @author Harry Yang * @since 1.0 2023/11/20 21:59 */ -public class HttpRegistration implements Registration { - - private List serviceDefinitions; +public class HttpRegistration extends DefaultServiceInstance implements Registration { - public HttpRegistration() { } + private String status; - public HttpRegistration(List serviceDefinitions) { - this.serviceDefinitions = serviceDefinitions; + public String getStatus() { + return status; } - public void setServiceDefinitions(List serviceDefinitions) { - this.serviceDefinitions = serviceDefinitions; + public void setStatus(String status) { + this.status = status; } - - public List getServiceDefinitions() { - return serviceDefinitions; - } - } diff --git a/today-service-registry-simple-api/src/main/java/infra/cloud/registry/simple/api/SimpleHttpServiceRegistryAPI.java b/today-service-registry-simple-api/src/main/java/infra/cloud/registry/simple/api/SimpleHttpServiceRegistryAPI.java new file mode 100644 index 0000000..6e42386 --- /dev/null +++ b/today-service-registry-simple-api/src/main/java/infra/cloud/registry/simple/api/SimpleHttpServiceRegistryAPI.java @@ -0,0 +1,55 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.registry.simple.api; + +import java.util.List; + +import infra.cloud.registry.simple.HttpRegistration; +import infra.http.MediaType; +import infra.util.MultiValueMap; +import infra.web.annotation.DELETE; +import infra.web.annotation.GET; +import infra.web.annotation.POST; +import infra.web.annotation.PUT; +import infra.web.annotation.PathVariable; +import infra.web.annotation.RequestBody; +import infra.web.annotation.RequestMapping; + +/** + * @author 海子 Yang + * @since 1.0 2025/8/8 11:18 + */ +@RequestMapping("${registry.services.uri:/services}") +public interface SimpleHttpServiceRegistryAPI { + + @GET(produces = MediaType.APPLICATION_JSON_VALUE) + MultiValueMap services(); + + @GET("/{name}") + List lookup(@PathVariable String name); + + @POST + void register(@RequestBody HttpRegistration registration); + + @DELETE + void unregister(@RequestBody HttpRegistration registration); + + @PUT + void update(@RequestBody HttpRegistration registration); + +} diff --git a/today-service-registry-simple-client/build.gradle b/today-service-registry-simple-client/build.gradle new file mode 100644 index 0000000..dbd40e1 --- /dev/null +++ b/today-service-registry-simple-client/build.gradle @@ -0,0 +1,10 @@ +description = "TODAY Service Simple Registry" + + +dependencies { + api project(":today-service-registry-simple-api") + + implementation 'cn.taketoday:today-starter-web' + + annotationProcessor 'cn.taketoday:infra-configuration-processor' +} \ No newline at end of file diff --git a/today-service-registry-simple-client/src/main/java/infra/cloud/registry/simple/HttpOperations.java b/today-service-registry-simple-client/src/main/java/infra/cloud/registry/simple/HttpOperations.java new file mode 100644 index 0000000..250781c --- /dev/null +++ b/today-service-registry-simple-client/src/main/java/infra/cloud/registry/simple/HttpOperations.java @@ -0,0 +1,91 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.registry.simple; + +import java.util.List; +import java.util.Map; + +import infra.cloud.client.DefaultServiceInstance; +import infra.cloud.registry.ServiceNotFoundException; +import infra.core.ParameterizedTypeReference; +import infra.core.style.ToStringBuilder; +import infra.http.HttpEntity; +import infra.http.HttpMethod; +import infra.web.client.HttpClientErrorException; +import infra.web.client.RestClient; +import infra.web.client.RestClientException; +import infra.web.client.RestTemplate; + +/** + * @author Harry Yang + * @since 1.0 2023/8/14 17:46 + */ +final class HttpOperations { + private static final ParameterizedTypeReference> reference = new ParameterizedTypeReference<>() { }; + + private final RestTemplate restOperations = new RestTemplate(); + + private final RestClient restClient = RestClient.create(restOperations); + + private final String registryURL; + + public HttpOperations(String registryURL) { + this.registryURL = registryURL; + } + + @SuppressWarnings("rawtypes") + public List getInstances(String name) { + try { + return restOperations.exchange(buildGetServiceDefinitionURL(name), HttpMethod.GET, HttpEntity.EMPTY, reference).getBody(); + } + catch (HttpClientErrorException.NotFound e) { + throw new ServiceNotFoundException(name, e); + } + } + + private String buildGetServiceDefinitionURL(String serviceInterface) { + return registryURL + '/' + serviceInterface; + } + + public void register(Object body) throws RestClientException { + restClient.post() + .uri(registryURL) + .body(body) + .execute(); + } + + public void delete(Object body) { + restClient.delete() + .uri(registryURL) + .body(body) + .execute(); + } + + public Map getServices() { + return restClient.get() + .uri(registryURL) + .retrieve().body(new ParameterizedTypeReference>() { }); + } + + @Override + public String toString() { + return ToStringBuilder.forInstance(this) + .append("registryURL", registryURL) + .toString(); + } +} diff --git a/today-service-registry-simple-client/src/main/java/infra/cloud/registry/simple/SimpleHttpServiceRegistry.java b/today-service-registry-simple-client/src/main/java/infra/cloud/registry/simple/SimpleHttpServiceRegistry.java new file mode 100644 index 0000000..61fc6e1 --- /dev/null +++ b/today-service-registry-simple-client/src/main/java/infra/cloud/registry/simple/SimpleHttpServiceRegistry.java @@ -0,0 +1,60 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.registry.simple; + +import infra.cloud.registry.ServiceRegistry; +import infra.cloud.registry.simple.api.SimpleHttpServiceRegistryAPI; + +/** + * @author 海子 Yang + * @since 1.0 2025/8/7 20:40 + */ +public class SimpleHttpServiceRegistry implements ServiceRegistry { + + private final SimpleHttpServiceRegistryAPI serviceRegistryAPI; + + public SimpleHttpServiceRegistry(SimpleHttpServiceRegistryAPI serviceRegistryAPI) { + this.serviceRegistryAPI = serviceRegistryAPI; + } + + @Override + public void register(HttpRegistration registration) { + serviceRegistryAPI.register(registration); + } + + @Override + public void unregister(HttpRegistration registration) { + serviceRegistryAPI.unregister(registration); + } + + @Override + public void close() { + + } + + @Override + public void setStatus(HttpRegistration registration, String status) { + registration.setStatus(status); + } + + @Override + public String getStatus(HttpRegistration registration) { + return registration.getStatus(); + } + +} diff --git a/today-service-registry-simple-server/build.gradle b/today-service-registry-simple-server/build.gradle new file mode 100644 index 0000000..d9b1b58 --- /dev/null +++ b/today-service-registry-simple-server/build.gradle @@ -0,0 +1,10 @@ +description = "TODAY Service Simple Registry Server" + + +dependencies { + api project(":today-service-registry-simple-api") + + implementation 'cn.taketoday:today-starter-web' + + annotationProcessor 'cn.taketoday:infra-configuration-processor' +} \ No newline at end of file diff --git a/today-service-registry/src/main/java/infra/cloud/registry/HttpServiceRegistryEndpoint.java b/today-service-registry-simple-server/src/main/java/infra/cloud/registry/simple/server/SimpleHttpServiceRegistryEndpoint.java similarity index 54% rename from today-service-registry/src/main/java/infra/cloud/registry/HttpServiceRegistryEndpoint.java rename to today-service-registry-simple-server/src/main/java/infra/cloud/registry/simple/server/SimpleHttpServiceRegistryEndpoint.java index 6085b86..38e6ff8 100644 --- a/today-service-registry/src/main/java/infra/cloud/registry/HttpServiceRegistryEndpoint.java +++ b/today-service-registry-simple-server/src/main/java/infra/cloud/registry/simple/server/SimpleHttpServiceRegistryEndpoint.java @@ -15,15 +15,15 @@ * along with this program. If not, see [http://www.gnu.org/licenses/] */ -package infra.cloud.registry; +package infra.cloud.registry.simple.server; -import java.util.ArrayList; import java.util.List; import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; -import infra.cloud.DefaultServiceInstance; -import infra.cloud.ServiceInstance; +import infra.cloud.registry.ServiceNotFoundException; +import infra.cloud.registry.simple.HttpRegistration; +import infra.cloud.registry.simple.api.SimpleHttpServiceRegistryAPI; import infra.http.HttpStatus; import infra.http.MediaType; import infra.logging.Logger; @@ -34,6 +34,7 @@ import infra.web.annotation.ExceptionHandler; import infra.web.annotation.GET; import infra.web.annotation.POST; +import infra.web.annotation.PUT; import infra.web.annotation.PathVariable; import infra.web.annotation.RequestBody; import infra.web.annotation.RequestMapping; @@ -44,53 +45,58 @@ * @author TODAY 2021/7/9 23:08 */ @RestController -@RequestMapping("${registry.services.uri}") -public class HttpServiceRegistryEndpoint implements ServiceRegistry { +@RequestMapping("${registry.services.uri:/services}") +class SimpleHttpServiceRegistryEndpoint implements SimpleHttpServiceRegistryAPI { - private static final Logger log = LoggerFactory.getLogger(HttpServiceRegistryEndpoint.class); + private static final Logger log = LoggerFactory.getLogger(SimpleHttpServiceRegistryEndpoint.class); - private final MultiValueMap serviceMapping + private final MultiValueMap serviceMapping = MultiValueMap.forAdaption(new ConcurrentHashMap<>()); + @Override @GET(produces = MediaType.APPLICATION_JSON_VALUE) - public MultiValueMap services() { + public MultiValueMap services() { return serviceMapping; } @GET("/{name}") - public List lookup(@PathVariable String name) { - List serviceDefinitions = serviceMapping.get(name); - if (CollectionUtils.isEmpty(serviceDefinitions)) { + @Override + public List lookup(@PathVariable String name) { + List registrations = serviceMapping.get(name); + if (CollectionUtils.isEmpty(registrations)) { throw new ServiceNotFoundException(name); } - ArrayList instances = new ArrayList<>(); - for (ServiceDefinition definition : serviceDefinitions) { - var instance = new DefaultServiceInstance(definition.getHost() + ":" + definition.getPort(), - definition.getName(), definition.getHost(), definition.getPort()); - instances.add(instance); - } - return instances; + return registrations; } @POST @Override public void register(@RequestBody HttpRegistration registration) { - for (ServiceDefinition definition : registration.getServiceDefinitions()) { - log.info("Registering service: [{}] ", definition); - serviceMapping.add(definition.getName(), definition); + log.info("Registering service: [{}] ", registration); + serviceMapping.add(registration.getServiceId(), registration); + } + + @PUT + @Override + public void update(HttpRegistration registration) { + log.info("Updating service: [{}] ", registration); + List registrations = serviceMapping.get(registration.getServiceId()); + if (CollectionUtils.isEmpty(registrations)) { + throw new ServiceNotFoundException(registration.getServiceId()); + } + else { + registrations.removeIf(r -> r.getInstanceId().equals(registration.getInstanceId())); } } @DELETE @Override public void unregister(@RequestBody HttpRegistration registration) { - for (ServiceDefinition definition : registration.getServiceDefinitions()) { - List serviceDefinitions = serviceMapping.get(definition.getName()); - if (CollectionUtils.isNotEmpty(serviceDefinitions) - && serviceDefinitions.removeIf(def -> Objects.equals(def, definition))) { - log.info("un-register service: [{}] ", definition); - } + List serviceDefinitions = serviceMapping.get(registration.getServiceId()); + if (CollectionUtils.isNotEmpty(serviceDefinitions) + && serviceDefinitions.removeIf(def -> Objects.equals(def, registration))) { + log.info("un-register service: [{}] ", registration); } } diff --git a/today-service-registry-simple-server/src/main/resources/META-INF/additional-infra-configuration-metadata.json b/today-service-registry-simple-server/src/main/resources/META-INF/additional-infra-configuration-metadata.json new file mode 100644 index 0000000..d4c884d --- /dev/null +++ b/today-service-registry-simple-server/src/main/resources/META-INF/additional-infra-configuration-metadata.json @@ -0,0 +1,10 @@ +{ + "properties": [ + { + "name": "registry.services.uri", + "type": "java.lang.String", + "description": "Simple service registry URI.", + "defaultValue": "/services" + } + ] +} diff --git a/today-service-registry-simple-server/src/main/resources/META-INF/config/infra.context.annotation.config.AutoConfiguration.imports b/today-service-registry-simple-server/src/main/resources/META-INF/config/infra.context.annotation.config.AutoConfiguration.imports new file mode 100644 index 0000000..e69de29 diff --git a/today-service-registry-simple-server/src/main/resources/META-INF/today.strategies b/today-service-registry-simple-server/src/main/resources/META-INF/today.strategies new file mode 100644 index 0000000..e69de29 diff --git a/today-service-registry/build.gradle b/today-service-registry/build.gradle index d814b15..12adf93 100644 --- a/today-service-registry/build.gradle +++ b/today-service-registry/build.gradle @@ -1,8 +1,9 @@ description = "TODAY Service Registry" dependencies { - implementation project(":today-cloud-core") - implementation 'cn.taketoday:today-starter-web' + api project(":today-cloud-core") + api 'cn.taketoday:today-core' + api 'cn.taketoday:today-context' annotationProcessor 'cn.taketoday:infra-configuration-processor' diff --git a/today-service-registry/src/main/java/infra/cloud/registry/AbstractAutoServiceRegistration.java b/today-service-registry/src/main/java/infra/cloud/registry/AbstractAutoServiceRegistration.java new file mode 100644 index 0000000..ebb5ae0 --- /dev/null +++ b/today-service-registry/src/main/java/infra/cloud/registry/AbstractAutoServiceRegistration.java @@ -0,0 +1,152 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.registry; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; + +import infra.cloud.registry.event.InstancePreRegisteredEvent; +import infra.cloud.registry.event.InstanceRegisteredEvent; +import infra.context.SmartLifecycle; +import infra.context.support.ApplicationObjectSupport; + +/** + * Lifecycle methods that may be useful and common to {@link ServiceRegistry} + * implementations. + * + * @param Registration type passed to the {@link ServiceRegistry}. + * @author Spencer Gibb + * @author Zen Huifer + * @author 海子 Yang + */ +public abstract class AbstractAutoServiceRegistration + extends ApplicationObjectSupport implements AutoServiceRegistration, SmartLifecycle { + + protected final ServiceRegistry serviceRegistry; + + private final AtomicBoolean running = new AtomicBoolean(false); + + private final List> registrationLifecycles; + + protected AbstractAutoServiceRegistration(ServiceRegistry serviceRegistry) { + this.serviceRegistry = serviceRegistry; + this.registrationLifecycles = new ArrayList<>(); + } + + protected AbstractAutoServiceRegistration(ServiceRegistry serviceRegistry, List> registrationLifecycles) { + this.serviceRegistry = serviceRegistry; + this.registrationLifecycles = registrationLifecycles; + } + + public void addRegistrationLifecycle(RegistrationLifecycle registrationLifecycle) { + this.registrationLifecycles.add(registrationLifecycle); + } + + @Override + public void start() { + if (!isEnabled()) { + if (logger.isDebugEnabled()) { + logger.debug("Discovery Lifecycle disabled. Not starting"); + } + return; + } + + logger.info("Registering services to registry: [{}]", serviceRegistry); + + if (!running.get()) { + R registration = getRegistration(); + obtainApplicationContext().publishEvent(new InstancePreRegisteredEvent(this, registration)); + + for (RegistrationLifecycle lifecycle : registrationLifecycles) { + lifecycle.postProcessBeforeStartRegister(registration); + } + register(); + for (RegistrationLifecycle lifecycle : registrationLifecycles) { + lifecycle.postProcessAfterStartRegister(registration); + } + + obtainApplicationContext().publishEvent(new InstanceRegisteredEvent<>(this, getConfiguration())); + running.compareAndSet(false, true); + } + } + + @Override + public boolean isRunning() { + return running.get(); + } + + @Override + public int getPhase() { + return 0; + } + + /** + * Register the local service with the {@link ServiceRegistry}. + */ + protected void register() { + serviceRegistry.register(getRegistration()); + } + + /** + * un-register the local service with the {@link ServiceRegistry}. + */ + protected void unregister() { + serviceRegistry.unregister(getRegistration()); + } + + /** + * Go offline to delete the service registered on the machine + */ + @Override + public void stop() { + if (running.compareAndSet(true, false) && isEnabled()) { + logger.info("Un-Registering services: [{}]", serviceRegistry); + + R registration = getRegistration(); + for (RegistrationLifecycle lifecycle : registrationLifecycles) { + lifecycle.postProcessBeforeStopRegister(registration); + } + + unregister(); + + for (RegistrationLifecycle lifecycle : registrationLifecycles) { + lifecycle.postProcessAfterStopRegister(registration); + } + + serviceRegistry.close(); + } + } + + /** + * @return The object used to configure the registration. + */ + protected abstract Object getConfiguration(); + + /** + * @return True, if this is enabled. + */ + protected boolean isEnabled() { + return true; + } + + protected abstract R getRegistration(); + + protected abstract R getManagementRegistration(); + +} diff --git a/today-service-registry/src/main/java/infra/cloud/registry/AutoServiceRegistration.java b/today-service-registry/src/main/java/infra/cloud/registry/AutoServiceRegistration.java new file mode 100644 index 0000000..1eaf3c7 --- /dev/null +++ b/today-service-registry/src/main/java/infra/cloud/registry/AutoServiceRegistration.java @@ -0,0 +1,26 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.registry; + +/** + * @author Spencer Gibb + * @author 海子 Yang + */ +public interface AutoServiceRegistration { + +} diff --git a/today-service-registry/src/main/java/infra/cloud/registry/AutoServiceRegistrationAutoConfiguration.java b/today-service-registry/src/main/java/infra/cloud/registry/AutoServiceRegistrationAutoConfiguration.java new file mode 100644 index 0000000..b9f59c0 --- /dev/null +++ b/today-service-registry/src/main/java/infra/cloud/registry/AutoServiceRegistrationAutoConfiguration.java @@ -0,0 +1,43 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.registry; + +import infra.beans.factory.annotation.DisableDependencyInjection; +import infra.context.annotation.Configuration; +import infra.context.annotation.Import; +import infra.context.condition.ConditionalOnProperty; +import infra.lang.Nullable; + +/** + * @author Spencer Gibb + * @author 海子 Yang + */ +@DisableDependencyInjection +@Configuration(proxyBeanMethods = false) +@Import(AutoServiceRegistrationConfiguration.class) +@ConditionalOnProperty(value = "infra.cloud.service-registry.auto-registration.enabled", matchIfMissing = true) +public class AutoServiceRegistrationAutoConfiguration { + + public AutoServiceRegistrationAutoConfiguration(@Nullable AutoServiceRegistration autoRegistration, AutoServiceRegistrationProperties properties) { + if (autoRegistration == null && properties.isFailFast()) { + throw new IllegalStateException( + "Auto Service Registration has been requested, but there is no AutoServiceRegistration bean"); + } + } + +} diff --git a/today-service-registry/src/main/java/infra/cloud/registry/AutoServiceRegistrationConfiguration.java b/today-service-registry/src/main/java/infra/cloud/registry/AutoServiceRegistrationConfiguration.java new file mode 100644 index 0000000..5ce3bb8 --- /dev/null +++ b/today-service-registry/src/main/java/infra/cloud/registry/AutoServiceRegistrationConfiguration.java @@ -0,0 +1,33 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.registry; + +import infra.context.annotation.Configuration; +import infra.context.condition.ConditionalOnProperty; +import infra.context.properties.EnableConfigurationProperties; + +/** + * @author Spencer Gibb + * @author 海子 Yang + */ +@Configuration(proxyBeanMethods = false) +@EnableConfigurationProperties(AutoServiceRegistrationProperties.class) +@ConditionalOnProperty(value = "infra.cloud.service-registry.auto-registration.enabled", matchIfMissing = true) +public class AutoServiceRegistrationConfiguration { + +} diff --git a/today-service-registry/src/main/java/infra/cloud/registry/RegistryProperties.java b/today-service-registry/src/main/java/infra/cloud/registry/AutoServiceRegistrationProperties.java similarity index 50% rename from today-service-registry/src/main/java/infra/cloud/registry/RegistryProperties.java rename to today-service-registry/src/main/java/infra/cloud/registry/AutoServiceRegistrationProperties.java index 3a28759..5800396 100644 --- a/today-service-registry/src/main/java/infra/cloud/registry/RegistryProperties.java +++ b/today-service-registry/src/main/java/infra/cloud/registry/AutoServiceRegistrationProperties.java @@ -20,51 +20,48 @@ import infra.context.properties.ConfigurationProperties; /** - * @author Harry Yang - * @since 1.0 2023/9/4 16:28 + * @author Spencer Gibb + * @author 海子 Yang */ -@ConfigurationProperties("registry") -public class RegistryProperties { +@ConfigurationProperties("infra.cloud.service-registry.auto-registration") +public class AutoServiceRegistrationProperties { /** - * Service Registry HTTP URL + * Whether service auto-registration is enabled. Defaults to true. */ - private String httpUrl; + private boolean enabled = true; /** - * services + * Whether startup fails if there is no AutoServiceRegistration. Defaults to false. */ - private final Services services = new Services(); + private boolean failFast = false; - public void setHttpUrl(String httpUrl) { - this.httpUrl = httpUrl; - } + /** + * Service provider port + */ + private int port = 9000; - public String getHttpUrl() { - return httpUrl; + public boolean isEnabled() { + return this.enabled; } - public Services getServices() { - return services; + public void setEnabled(boolean enabled) { + this.enabled = enabled; } - /** - * Services - */ - public static class Services { - - /** - * Service Registry HTTP URI. - */ - private String uri; + public boolean isFailFast() { + return this.failFast; + } - public void setUri(String uri) { - this.uri = uri; - } + public void setFailFast(boolean failFast) { + this.failFast = failFast; + } - public String getUri() { - return uri; - } + public void setPort(int port) { + this.port = port; } + public int getPort() { + return port; + } } diff --git a/today-service-registry/src/main/java/infra/cloud/registry/InstanceSelector.java b/today-service-registry/src/main/java/infra/cloud/registry/InstanceSelector.java index 9e20bcb..47c0724 100644 --- a/today-service-registry/src/main/java/infra/cloud/registry/InstanceSelector.java +++ b/today-service-registry/src/main/java/infra/cloud/registry/InstanceSelector.java @@ -19,7 +19,7 @@ import java.util.List; -import infra.cloud.ServiceInstance; +import infra.cloud.client.ServiceInstance; /** * @author TODAY 2021/7/9 23:18 diff --git a/today-service-registry/src/main/java/infra/cloud/registry/RandomInstanceSelector.java b/today-service-registry/src/main/java/infra/cloud/registry/RandomInstanceSelector.java index 4472e49..07b3253 100644 --- a/today-service-registry/src/main/java/infra/cloud/registry/RandomInstanceSelector.java +++ b/today-service-registry/src/main/java/infra/cloud/registry/RandomInstanceSelector.java @@ -20,7 +20,7 @@ import java.util.List; import java.util.Random; -import infra.cloud.ServiceInstance; +import infra.cloud.client.ServiceInstance; import infra.lang.Assert; /** diff --git a/today-cloud-core/src/main/java/infra/cloud/Registration.java b/today-service-registry/src/main/java/infra/cloud/registry/Registration.java similarity index 86% rename from today-cloud-core/src/main/java/infra/cloud/Registration.java rename to today-service-registry/src/main/java/infra/cloud/registry/Registration.java index d4f3ab4..8b4ca24 100644 --- a/today-cloud-core/src/main/java/infra/cloud/Registration.java +++ b/today-service-registry/src/main/java/infra/cloud/registry/Registration.java @@ -15,12 +15,14 @@ * along with this program. If not, see [http://www.gnu.org/licenses/] */ -package infra.cloud; +package infra.cloud.registry; + +import infra.cloud.client.ServiceInstance; /** * @author Harry Yang * @since 1.0 2023/11/20 21:50 */ -public interface Registration { +public interface Registration extends ServiceInstance { } diff --git a/today-service-registry/src/main/java/infra/cloud/registry/RegistrationLifecycle.java b/today-service-registry/src/main/java/infra/cloud/registry/RegistrationLifecycle.java new file mode 100644 index 0000000..316955d --- /dev/null +++ b/today-service-registry/src/main/java/infra/cloud/registry/RegistrationLifecycle.java @@ -0,0 +1,61 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.registry; + +/** + * Service registration life cycle. This life cycle is only related to + * {@link Registration}. + * + * @author Zen Huifer + * @author 海子 Yang + */ +public interface RegistrationLifecycle { + + /** + * A method executed before registering the local service with the + * {@link ServiceRegistry}. + * + * @param registration registration + */ + void postProcessBeforeStartRegister(R registration); + + /** + * A method executed after registering the local service with the + * {@link ServiceRegistry}. + * + * @param registration registration + */ + void postProcessAfterStartRegister(R registration); + + /** + * A method executed before de-registering the local service with the + * {@link ServiceRegistry}. + * + * @param registration registration + */ + void postProcessBeforeStopRegister(R registration); + + /** + * A method executed after de-registering the local service with the + * {@link ServiceRegistry}. + * + * @param registration registration + */ + void postProcessAfterStopRegister(R registration); + +} diff --git a/today-service-registry/src/main/java/infra/cloud/registry/ServiceDefinition.java b/today-service-registry/src/main/java/infra/cloud/registry/ServiceDefinition.java deleted file mode 100644 index d5123af..0000000 --- a/today-service-registry/src/main/java/infra/cloud/registry/ServiceDefinition.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright 2021 - 2024 the original author or authors. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] - */ - -package infra.cloud.registry; - -import java.io.Serial; -import java.io.Serializable; -import java.util.Objects; - -import infra.core.style.ToStringBuilder; - -/** - * @author TODAY 2021/7/4 00:36 - */ -public class ServiceDefinition implements Serializable { - - @Serial - private static final long serialVersionUID = 1L; - - private int port; - - private String host; - - private String name; // service name - - private String version; - - public void setVersion(String version) { - this.version = version; - } - - public String getVersion() { - return version; - } - - public void setName(String name) { - this.name = name; - } - - public void setHost(String host) { - this.host = host; - } - - public void setPort(int port) { - this.port = port; - } - - public String getName() { - return name; - } - - public int getPort() { - return port; - } - - public String getHost() { - return host; - } - - @Override - public boolean equals(Object o) { - if (this == o) - return true; - if (!(o instanceof ServiceDefinition that)) - return false; - return port == that.port - && Objects.equals(host, that.host) - && Objects.equals(name, that.name) - && Objects.equals(version, that.version); - } - - @Override - public int hashCode() { - return Objects.hash(port, host, name, version); - } - - @Override - public String toString() { - return ToStringBuilder.forInstance(this) - .append("port", port) - .append("host", host) - .append("name", name) - .append("version", version) - .toString(); - } - -} diff --git a/today-service-registry/src/main/java/infra/cloud/registry/ServiceRegisterFailedException.java b/today-service-registry/src/main/java/infra/cloud/registry/ServiceRegisterFailedException.java index e92c37c..ef3cb7d 100644 --- a/today-service-registry/src/main/java/infra/cloud/registry/ServiceRegisterFailedException.java +++ b/today-service-registry/src/main/java/infra/cloud/registry/ServiceRegisterFailedException.java @@ -19,7 +19,6 @@ import java.io.Serial; -import infra.cloud.Registration; import infra.cloud.RemotingException; import infra.lang.Nullable; diff --git a/today-service-registry/src/main/java/infra/cloud/registry/ServiceRegistry.java b/today-service-registry/src/main/java/infra/cloud/registry/ServiceRegistry.java index 8cd5e2f..fac41d7 100644 --- a/today-service-registry/src/main/java/infra/cloud/registry/ServiceRegistry.java +++ b/today-service-registry/src/main/java/infra/cloud/registry/ServiceRegistry.java @@ -17,12 +17,16 @@ package infra.cloud.registry; -import infra.cloud.Registration; - /** - * @author TODAY 2021/7/4 23:12 + * Contract to register and deregister instances with a Service Registry. + * + * @param registration meta data + * @param The type of the status. + * @author Spencer Gibb + * @author 海子 Yang + * @since 2021/7/4 23:12 */ -public interface ServiceRegistry { +public interface ServiceRegistry { /** * Registers the registration. A registration typically has information about an @@ -40,4 +44,26 @@ public interface ServiceRegistry { */ void unregister(R registration); + /** + * Sets the status of the registration. The status values are determined by the + * individual implementations. + * + * @param registration The registration to update. + * @param status The status to set. + */ + void setStatus(R registration, S status); + + /** + * Gets the status of a particular registration. + * + * @param registration The registration to query. + * @return The status of the registration. + */ + S getStatus(R registration); + + /** + * Closes the ServiceRegistry. This is a lifecycle method. + */ + void close(); + } diff --git a/today-service-registry/src/main/java/infra/cloud/registry/event/InstancePreRegisteredEvent.java b/today-service-registry/src/main/java/infra/cloud/registry/event/InstancePreRegisteredEvent.java new file mode 100644 index 0000000..ec79b17 --- /dev/null +++ b/today-service-registry/src/main/java/infra/cloud/registry/event/InstancePreRegisteredEvent.java @@ -0,0 +1,53 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.registry.event; + +import infra.cloud.registry.Registration; +import infra.context.ApplicationEvent; + +/** + * An event to fire before a service is registered. + * + * @author Ryan Baxter + * @author 海子 Yang + */ +public class InstancePreRegisteredEvent extends ApplicationEvent { + + private final Registration registration; + + /** + * Create a new pre-registration event. + * + * @param source the object on which the event initially occurred (never {@code null}) + * @param registration the registration meta data + */ + public InstancePreRegisteredEvent(Object source, Registration registration) { + super(source); + this.registration = registration; + } + + /** + * Get the registration data. + * + * @return the registration data + */ + public Registration getRegistration() { + return this.registration; + } + +} diff --git a/today-service-registry/src/main/java/infra/cloud/registry/event/InstanceRegisteredEvent.java b/today-service-registry/src/main/java/infra/cloud/registry/event/InstanceRegisteredEvent.java new file mode 100644 index 0000000..27887aa --- /dev/null +++ b/today-service-registry/src/main/java/infra/cloud/registry/event/InstanceRegisteredEvent.java @@ -0,0 +1,50 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.registry.event; + +import infra.context.ApplicationEvent; + +/** + * Event to be published after the local service instance registers itself with a + * discovery service. + * + * @param - type of configuration + * @author Spencer Gibb + * @author 海子 Yang + */ +@SuppressWarnings("serial") +public class InstanceRegisteredEvent extends ApplicationEvent { + + private final T config; + + /** + * Creates a new {@link InstanceRegisteredEvent} instance. + * + * @param source The component that published the event (never {@code null}). + * @param config The configuration of the instance. + */ + public InstanceRegisteredEvent(Object source, T config) { + super(source); + this.config = config; + } + + public T getConfig() { + return this.config; + } + +} diff --git a/today-service-registry/src/main/resources/META-INF/config/infra.context.annotation.config.AutoConfiguration.imports b/today-service-registry/src/main/resources/META-INF/config/infra.context.annotation.config.AutoConfiguration.imports new file mode 100644 index 0000000..55812bd --- /dev/null +++ b/today-service-registry/src/main/resources/META-INF/config/infra.context.annotation.config.AutoConfiguration.imports @@ -0,0 +1 @@ +infra.cloud.registry.AutoServiceRegistrationAutoConfiguration \ No newline at end of file From e5e9bc5599b9253df34f8cf81ed9ea06332f39a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Sun, 10 Aug 2025 18:59:40 +0800 Subject: [PATCH 033/104] =?UTF-8?q?:sparkles:=20=E6=8A=BD=E8=B1=A1=20Clien?= =?UTF-8?q?t=20=E5=B1=82=E8=B0=83=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../infra/cloud/client/ServiceInstance.java | 5 +- today-cloud-samples/build.gradle | 24 +++ .../demo-tests/demo-user-api/build.gradle | 7 + .../cn/taketoday/demo/ClientApplication.java | 2 - .../src/main/resources/application.yaml | 1 + .../infra/remoting/core/ChannelConnector.java | 2 +- ...tractServiceInterfaceMetadataProvider.java | 57 ++++++ .../infra/cloud/service/InvocationResult.java | 58 ++++++ .../infra/cloud/service/InvocationType.java | 62 ++++++ .../PackageInfoServiceMetadataProvider.java | 34 ++-- .../service/ServiceInterfaceMetadata.java | 53 ++++++ .../ServiceInterfaceMetadataProvider.java | 12 +- .../infra/cloud/service/ServiceMetadata.java | 43 +++++ .../service/ServiceMetadataProvider.java | 14 +- .../infra/cloud/service/ServiceMethod.java | 52 +++++ .../infra/cloud/service/package-info.java | 15 +- today-service-client/build.gradle | 15 +- .../java/infra/cloud/JdkServiceProxy.java | 70 ------- .../infra/cloud/ServiceMethodInvoker.java | 148 --------------- .../cloud/SimpleRemoteExceptionHandler.java | 60 ------ .../ServiceDependencyResolvingStrategy.java | 5 +- .../{ => annotation}/ServiceReference.java | 2 +- .../ServiceClientAutoConfiguration.java | 68 +++++++ .../cloud/http/HttpServiceClientConfig.java | 63 ------ .../cloud/protocol/http/HttpOperations.java | 112 ----------- .../http/HttpServiceMethodInvoker.java | 55 ------ .../protocol/http/HttpServiceRegistry.java | 116 ------------ .../AbstractInvocationResult.java} | 16 +- .../cloud/service/ClientInterceptor.java | 47 +++++ ...faultServiceInterfaceMetadataProvider.java | 150 +++++++++++++++ .../service/DefaultServiceProxyFactory.java | 108 +++++++++++ .../service/MethodServiceInvocation.java | 81 ++++++++ .../cloud/service/ReturnValueResolver.java | 36 ++++ .../cloud/service/ServiceInterfaceMethod.java | 99 ++++++++++ .../cloud/service/ServiceInvocation.java | 64 +++++++ .../infra/cloud/service/ServiceInvoker.java | 39 ++++ .../cloud/service/ServiceMethodInvoker.java | 179 ++++++++++++++++++ .../cloud/{ => service}/ServiceProvider.java | 2 +- .../ServiceProxyFactory.java} | 31 +-- ...nnotation.config.AutoConfiguration.imports | 1 + .../main/resources/META-INF/today.strategies | 2 +- .../ServiceClientAutoConfigurationTests.java | 53 ++++++ ...ServiceInterfaceMetadataProviderTests.java | 112 +++++++++++ .../service/ServiceInvokerFactoryTests.java | 42 ++++ 44 files changed, 1495 insertions(+), 722 deletions(-) create mode 100644 today-cloud-samples/build.gradle create mode 100644 today-service-api/src/main/java/infra/cloud/service/AbstractServiceInterfaceMetadataProvider.java create mode 100644 today-service-api/src/main/java/infra/cloud/service/InvocationResult.java create mode 100644 today-service-api/src/main/java/infra/cloud/service/InvocationType.java rename today-service-registry/src/main/java/infra/cloud/registry/RandomInstanceSelector.java => today-service-api/src/main/java/infra/cloud/service/PackageInfoServiceMetadataProvider.java (53%) create mode 100644 today-service-api/src/main/java/infra/cloud/service/ServiceInterfaceMetadata.java rename today-service-client/src/main/java/infra/cloud/ServiceProxy.java => today-service-api/src/main/java/infra/cloud/service/ServiceInterfaceMetadataProvider.java (72%) create mode 100644 today-service-api/src/main/java/infra/cloud/service/ServiceMetadata.java rename today-service-registry/src/main/java/infra/cloud/registry/InstanceSelector.java => today-service-api/src/main/java/infra/cloud/service/ServiceMetadataProvider.java (76%) create mode 100644 today-service-api/src/main/java/infra/cloud/service/ServiceMethod.java rename today-service-client/src/main/java/infra/cloud/RemoteExceptionHandler.java => today-service-api/src/main/java/infra/cloud/service/package-info.java (77%) delete mode 100644 today-service-client/src/main/java/infra/cloud/JdkServiceProxy.java delete mode 100644 today-service-client/src/main/java/infra/cloud/ServiceMethodInvoker.java delete mode 100644 today-service-client/src/main/java/infra/cloud/SimpleRemoteExceptionHandler.java rename today-service-client/src/main/java/infra/cloud/{protocol => client/annotation}/ServiceDependencyResolvingStrategy.java (94%) rename today-service-client/src/main/java/infra/cloud/client/{ => annotation}/ServiceReference.java (96%) create mode 100644 today-service-client/src/main/java/infra/cloud/client/annotation/config/ServiceClientAutoConfiguration.java delete mode 100644 today-service-client/src/main/java/infra/cloud/http/HttpServiceClientConfig.java delete mode 100644 today-service-client/src/main/java/infra/cloud/protocol/http/HttpOperations.java delete mode 100644 today-service-client/src/main/java/infra/cloud/protocol/http/HttpServiceMethodInvoker.java delete mode 100644 today-service-client/src/main/java/infra/cloud/protocol/http/HttpServiceRegistry.java rename today-service-client/src/main/java/infra/cloud/{ServiceMethod.java => service/AbstractInvocationResult.java} (72%) create mode 100644 today-service-client/src/main/java/infra/cloud/service/ClientInterceptor.java create mode 100644 today-service-client/src/main/java/infra/cloud/service/DefaultServiceInterfaceMetadataProvider.java create mode 100644 today-service-client/src/main/java/infra/cloud/service/DefaultServiceProxyFactory.java create mode 100644 today-service-client/src/main/java/infra/cloud/service/MethodServiceInvocation.java create mode 100644 today-service-client/src/main/java/infra/cloud/service/ReturnValueResolver.java create mode 100644 today-service-client/src/main/java/infra/cloud/service/ServiceInterfaceMethod.java create mode 100644 today-service-client/src/main/java/infra/cloud/service/ServiceInvocation.java create mode 100644 today-service-client/src/main/java/infra/cloud/service/ServiceInvoker.java create mode 100644 today-service-client/src/main/java/infra/cloud/service/ServiceMethodInvoker.java rename today-service-client/src/main/java/infra/cloud/{ => service}/ServiceProvider.java (97%) rename today-service-client/src/main/java/infra/cloud/{http/EnableHttpServiceClient.java => service/ServiceProxyFactory.java} (56%) create mode 100644 today-service-client/src/main/resources/META-INF/config/infra.context.annotation.config.AutoConfiguration.imports create mode 100644 today-service-client/src/test/java/infra/cloud/client/annotation/config/ServiceClientAutoConfigurationTests.java create mode 100644 today-service-client/src/test/java/infra/cloud/service/DefaultServiceInterfaceMetadataProviderTests.java create mode 100644 today-service-client/src/test/java/infra/cloud/service/ServiceInvokerFactoryTests.java diff --git a/today-cloud-core/src/main/java/infra/cloud/client/ServiceInstance.java b/today-cloud-core/src/main/java/infra/cloud/client/ServiceInstance.java index 14841e5..124b9f5 100644 --- a/today-cloud-core/src/main/java/infra/cloud/client/ServiceInstance.java +++ b/today-cloud-core/src/main/java/infra/cloud/client/ServiceInstance.java @@ -20,8 +20,6 @@ import java.net.URI; import java.util.Map; -import infra.lang.Nullable; - /** * Represents an instance of a service. * @@ -33,9 +31,8 @@ public interface ServiceInstance { /** * @return The unique instance ID as registered. */ - @Nullable default String getInstanceId() { - return null; + return getHost() + ":" + getPort(); } /** diff --git a/today-cloud-samples/build.gradle b/today-cloud-samples/build.gradle new file mode 100644 index 0000000..67e05b9 --- /dev/null +++ b/today-cloud-samples/build.gradle @@ -0,0 +1,24 @@ +import java.time.Instant + +description = "TODAY Cloud samples" + +dependencies { + +} + + +configure(subprojects) { + jar { + manifest.attributes["Implementation-Title"] = project.name + manifest.attributes["Implementation-Version"] = project.version + manifest.attributes["Implementation-Build"] = Instant.now() + manifest.attributes["Implementation-Vendor"] = 'TODAY Tech' + manifest.attributes["Implementation-Vendor-Id"] = 'cn.taketoday' + manifest.attributes["Automatic-Module-Name"] = project.name.replace('-', '.') // for Jigsaw + manifest.attributes["Created-By"] = + "${System.getProperty("java.version")} (${System.getProperty("java.specification.vendor")})" + } + +} + + diff --git a/today-cloud-samples/demo-tests/demo-user-api/build.gradle b/today-cloud-samples/demo-tests/demo-user-api/build.gradle index 4b0df1d..bb654be 100644 --- a/today-cloud-samples/demo-tests/demo-user-api/build.gradle +++ b/today-cloud-samples/demo-tests/demo-user-api/build.gradle @@ -6,4 +6,11 @@ dependencies { compileOnly("org.projectlombok:lombok") annotationProcessor("org.projectlombok:lombok") +} + +jar { + manifest.attributes["Specification-Title"] = project.name + manifest.attributes["Specification-Version"] = project.version + manifest.attributes["Specification-Vendor"] = 'TODAY Tech' + manifest.attributes["Specification-Vendor-Id"] = 'cn.taketoday' } \ No newline at end of file diff --git a/today-cloud-samples/demo-tests/demo-user-rest/src/main/java/cn/taketoday/demo/ClientApplication.java b/today-cloud-samples/demo-tests/demo-user-rest/src/main/java/cn/taketoday/demo/ClientApplication.java index 2f40fa3..4b84588 100644 --- a/today-cloud-samples/demo-tests/demo-user-rest/src/main/java/cn/taketoday/demo/ClientApplication.java +++ b/today-cloud-samples/demo-tests/demo-user-rest/src/main/java/cn/taketoday/demo/ClientApplication.java @@ -17,7 +17,6 @@ package cn.taketoday.demo; -import infra.cloud.http.EnableHttpServiceClient; import infra.app.ApplicationType; import infra.app.InfraApplication; import infra.app.builder.ApplicationBuilder; @@ -27,7 +26,6 @@ * @since 1.0 2022/10/18 00:06 */ @InfraApplication -@EnableHttpServiceClient public class ClientApplication { public static void main(String[] args) { diff --git a/today-cloud-samples/demo-tests/demo-user-service/src/main/resources/application.yaml b/today-cloud-samples/demo-tests/demo-user-service/src/main/resources/application.yaml index 1d0550f..2518700 100644 --- a/today-cloud-samples/demo-tests/demo-user-service/src/main/resources/application.yaml +++ b/today-cloud-samples/demo-tests/demo-user-service/src/main/resources/application.yaml @@ -12,6 +12,7 @@ infra: service-registry: auto-registration: port: 9000 + fail-fast: true logging: level: diff --git a/today-remoting/src/main/java/infra/remoting/core/ChannelConnector.java b/today-remoting/src/main/java/infra/remoting/core/ChannelConnector.java index 2f08f96..4c9edad 100644 --- a/today-remoting/src/main/java/infra/remoting/core/ChannelConnector.java +++ b/today-remoting/src/main/java/infra/remoting/core/ChannelConnector.java @@ -26,8 +26,8 @@ import infra.lang.Nullable; import infra.remoting.Channel; import infra.remoting.ChannelAcceptor; -import infra.remoting.ConnectionSetupPayload; import infra.remoting.Connection; +import infra.remoting.ConnectionSetupPayload; import infra.remoting.Payload; import infra.remoting.frame.SetupFrameCodec; import infra.remoting.frame.decoder.PayloadDecoder; diff --git a/today-service-api/src/main/java/infra/cloud/service/AbstractServiceInterfaceMetadataProvider.java b/today-service-api/src/main/java/infra/cloud/service/AbstractServiceInterfaceMetadataProvider.java new file mode 100644 index 0000000..8df3e69 --- /dev/null +++ b/today-service-api/src/main/java/infra/cloud/service/AbstractServiceInterfaceMetadataProvider.java @@ -0,0 +1,57 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.service; + +import java.lang.reflect.Method; +import java.util.List; + +import infra.core.MethodIntrospector; +import infra.lang.Assert; +import infra.util.ReflectionUtils; + +/** + * @author 海子 Yang + * @since 1.0 2025/8/10 16:53 + */ +public abstract class AbstractServiceInterfaceMetadataProvider implements ServiceInterfaceMetadataProvider { + + private final ServiceMetadataProvider serviceMetadataProvider; + + protected AbstractServiceInterfaceMetadataProvider(ServiceMetadataProvider serviceMetadataProvider) { + Assert.notNull(serviceMetadataProvider, "serviceMetadataProvider is required"); + this.serviceMetadataProvider = serviceMetadataProvider; + } + + @Override + public ServiceInterfaceMetadata getMetadata(Class serviceInterface) { + ServiceMetadata serviceMetadata = serviceMetadataProvider.getMetadata(serviceInterface); + + List serviceMethods = MethodIntrospector.filterMethods(serviceInterface, this::isServiceMethod).stream() + .map(method -> createServiceMethod(serviceMetadata, serviceInterface, method)) + .toList(); + + return new ServiceInterfaceMetadata<>(serviceInterface, serviceMetadata, serviceMethods); + } + + protected abstract M createServiceMethod(ServiceMetadata serviceMetadata, Class service, Method method); + + protected boolean isServiceMethod(Method method) { + return !ReflectionUtils.isObjectMethod(method); + } + +} diff --git a/today-service-api/src/main/java/infra/cloud/service/InvocationResult.java b/today-service-api/src/main/java/infra/cloud/service/InvocationResult.java new file mode 100644 index 0000000..e1a2f78 --- /dev/null +++ b/today-service-api/src/main/java/infra/cloud/service/InvocationResult.java @@ -0,0 +1,58 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.service; + +import org.reactivestreams.Publisher; + +import infra.core.AttributeAccessor; +import infra.lang.Nullable; +import infra.util.concurrent.Future; + +/** + * Remote service invocation result + * + * @author 海子 Yang + * @since 1.0 2025/8/9 12:10 + */ +public interface InvocationResult extends AttributeAccessor { + + @Nullable + Object getValue(); + + boolean isFailed(); + + @Nullable + Throwable getException(); + + InvocationType getType(); + + default boolean isRequestResponse() { + return getType() == InvocationType.REQUEST_RESPONSE; + } + + /** + * Only for {@link InvocationType#REQUEST_RESPONSE} + * + * @see InvocationType#REQUEST_RESPONSE + * @see #isRequestResponse() + */ + Future future(); + + Publisher publisher(); + +} diff --git a/today-service-api/src/main/java/infra/cloud/service/InvocationType.java b/today-service-api/src/main/java/infra/cloud/service/InvocationType.java new file mode 100644 index 0000000..9593148 --- /dev/null +++ b/today-service-api/src/main/java/infra/cloud/service/InvocationType.java @@ -0,0 +1,62 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.service; + +/** + * @author 海子 Yang + * @since 1.0 2025/8/9 15:45 + */ +public enum InvocationType { + + /** + * One request message without response. + */ + FIRE_AND_FORGET, + + /** + * One request message followed by one response message. + */ + REQUEST_RESPONSE, + + /** + * One request message followed by zero or more response messages. + */ + RESPONSE_STREAMING, + + /** + * Zero or more request and response messages arbitrarily interleaved in time. + */ + DUPLEX_STREAMING; + + /** + * Returns {@code true} for {@code UNARY} and {@code RESPONSE_STREAMING}, which do not permit the + * client to stream. + */ + public final boolean clientSendsOneMessage() { + return this == REQUEST_RESPONSE || this == RESPONSE_STREAMING; + } + + /** + * Returns {@code true} for {@code UNARY} and {@code CLIENT_STREAMING}, which do not permit the + * server to stream. + */ + public final boolean serverSendsOneMessage() { + return this == REQUEST_RESPONSE; + } + +} diff --git a/today-service-registry/src/main/java/infra/cloud/registry/RandomInstanceSelector.java b/today-service-api/src/main/java/infra/cloud/service/PackageInfoServiceMetadataProvider.java similarity index 53% rename from today-service-registry/src/main/java/infra/cloud/registry/RandomInstanceSelector.java rename to today-service-api/src/main/java/infra/cloud/service/PackageInfoServiceMetadataProvider.java index 07b3253..5a66953 100644 --- a/today-service-registry/src/main/java/infra/cloud/registry/RandomInstanceSelector.java +++ b/today-service-api/src/main/java/infra/cloud/service/PackageInfoServiceMetadataProvider.java @@ -15,34 +15,22 @@ * along with this program. If not, see [http://www.gnu.org/licenses/] */ -package infra.cloud.registry; - -import java.util.List; -import java.util.Random; - -import infra.cloud.client.ServiceInstance; -import infra.lang.Assert; +package infra.cloud.service; /** - * @author TODAY 2021/7/9 23:20 + * Read ServiceMetadata from {@link Package} MANIFEST.MF file + * + * @author 海子 Yang + * @since 1.0 2025/8/9 21:55 */ -public class RandomInstanceSelector implements InstanceSelector { - private final Random random; - - public RandomInstanceSelector() { - this(new Random()); - } - - public RandomInstanceSelector(Random random) { - Assert.notNull(random, "Random is required"); - this.random = random; - } +public class PackageInfoServiceMetadataProvider implements ServiceMetadataProvider { @Override - public ServiceInstance select(List instances) { - final int size = instances.size(); - final int idx = random.nextInt(size); - return instances.get(idx); + public ServiceMetadata getMetadata(Class serviceInterface) { + Package servicePackage = serviceInterface.getPackage(); + String specificationVersion = servicePackage.getSpecificationVersion(); + String specificationTitle = servicePackage.getSpecificationTitle(); + return new ServiceMetadata(specificationTitle, specificationVersion); } } diff --git a/today-service-api/src/main/java/infra/cloud/service/ServiceInterfaceMetadata.java b/today-service-api/src/main/java/infra/cloud/service/ServiceInterfaceMetadata.java new file mode 100644 index 0000000..29c30a7 --- /dev/null +++ b/today-service-api/src/main/java/infra/cloud/service/ServiceInterfaceMetadata.java @@ -0,0 +1,53 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.service; + +import java.util.Collections; +import java.util.List; + +/** + * @author 海子 Yang + * @since 1.0 2025/8/9 21:59 + */ +public class ServiceInterfaceMetadata { + + private final Class serviceInterface; + + private final ServiceMetadata serviceMetadata; + + private final List serviceMethods; + + public ServiceInterfaceMetadata(Class serviceInterface, ServiceMetadata serviceMetadata, List serviceMethods) { + this.serviceInterface = serviceInterface; + this.serviceMetadata = serviceMetadata; + this.serviceMethods = serviceMethods; + } + + public Class getServiceInterface() { + return serviceInterface; + } + + public ServiceMetadata getServiceMetadata() { + return serviceMetadata; + } + + public List getServiceMethods() { + return Collections.unmodifiableList(serviceMethods); + } + +} diff --git a/today-service-client/src/main/java/infra/cloud/ServiceProxy.java b/today-service-api/src/main/java/infra/cloud/service/ServiceInterfaceMetadataProvider.java similarity index 72% rename from today-service-client/src/main/java/infra/cloud/ServiceProxy.java rename to today-service-api/src/main/java/infra/cloud/service/ServiceInterfaceMetadataProvider.java index 363103d..d122129 100644 --- a/today-service-client/src/main/java/infra/cloud/ServiceProxy.java +++ b/today-service-api/src/main/java/infra/cloud/service/ServiceInterfaceMetadataProvider.java @@ -15,14 +15,14 @@ * along with this program. If not, see [http://www.gnu.org/licenses/] */ -package infra.cloud; - -import infra.cloud.client.DiscoveryClient; +package infra.cloud.service; /** - * @author TODAY 2021/7/4 22:58 + * @author 海子 Yang + * @since 1.0 2025/8/10 08:22 */ -public interface ServiceProxy { +public interface ServiceInterfaceMetadataProvider { + + ServiceInterfaceMetadata getMetadata(Class serviceInterface); - T getProxy(Class serviceInterface, DiscoveryClient discoveryClient, ServiceMethodInvoker methodInvoker); } diff --git a/today-service-api/src/main/java/infra/cloud/service/ServiceMetadata.java b/today-service-api/src/main/java/infra/cloud/service/ServiceMetadata.java new file mode 100644 index 0000000..e3b27e3 --- /dev/null +++ b/today-service-api/src/main/java/infra/cloud/service/ServiceMetadata.java @@ -0,0 +1,43 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.service; + +/** + * @author 海子 Yang + * @since 1.0 2025/8/9 21:51 + */ +public class ServiceMetadata { + + private final String name; + + private final String version; + + public ServiceMetadata(String name, String version) { + this.name = name; + this.version = version; + } + + public String getName() { + return name; + } + + public String getVersion() { + return version; + } + +} diff --git a/today-service-registry/src/main/java/infra/cloud/registry/InstanceSelector.java b/today-service-api/src/main/java/infra/cloud/service/ServiceMetadataProvider.java similarity index 76% rename from today-service-registry/src/main/java/infra/cloud/registry/InstanceSelector.java rename to today-service-api/src/main/java/infra/cloud/service/ServiceMetadataProvider.java index 47c0724..65db170 100644 --- a/today-service-registry/src/main/java/infra/cloud/registry/InstanceSelector.java +++ b/today-service-api/src/main/java/infra/cloud/service/ServiceMetadataProvider.java @@ -15,16 +15,14 @@ * along with this program. If not, see [http://www.gnu.org/licenses/] */ -package infra.cloud.registry; - -import java.util.List; - -import infra.cloud.client.ServiceInstance; +package infra.cloud.service; /** - * @author TODAY 2021/7/9 23:18 + * @author 海子 Yang + * @since 1.0 2025/8/9 21:50 */ -public interface InstanceSelector { +public interface ServiceMetadataProvider { + + ServiceMetadata getMetadata(Class serviceInterface); - ServiceInstance select(List instances); } diff --git a/today-service-api/src/main/java/infra/cloud/service/ServiceMethod.java b/today-service-api/src/main/java/infra/cloud/service/ServiceMethod.java new file mode 100644 index 0000000..f90aaa4 --- /dev/null +++ b/today-service-api/src/main/java/infra/cloud/service/ServiceMethod.java @@ -0,0 +1,52 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.service; + +import java.lang.reflect.Method; + +/** + * @author 海子 Yang + * @since 1.0 2025/8/10 08:20 + */ +public class ServiceMethod { + + protected final ServiceMetadata serviceMetadata; + + protected final Class serviceInterface; + + protected final Method method; + + public ServiceMethod(ServiceMetadata serviceMetadata, Class serviceInterface, Method method) { + this.serviceMetadata = serviceMetadata; + this.serviceInterface = serviceInterface; + this.method = method; + } + + public ServiceMetadata getServiceMetadata() { + return serviceMetadata; + } + + public Class getServiceInterface() { + return serviceInterface; + } + + public Method getMethod() { + return method; + } + +} diff --git a/today-service-client/src/main/java/infra/cloud/RemoteExceptionHandler.java b/today-service-api/src/main/java/infra/cloud/service/package-info.java similarity index 77% rename from today-service-client/src/main/java/infra/cloud/RemoteExceptionHandler.java rename to today-service-api/src/main/java/infra/cloud/service/package-info.java index 298c37e..9b1fd46 100644 --- a/today-service-client/src/main/java/infra/cloud/RemoteExceptionHandler.java +++ b/today-service-api/src/main/java/infra/cloud/service/package-info.java @@ -15,14 +15,9 @@ * along with this program. If not, see [http://www.gnu.org/licenses/] */ -package infra.cloud; +@NonNullApi +@NonNullFields +package infra.cloud.service; -import infra.util.concurrent.Future; - -/** - * @author TODAY 2021/7/9 21:54 - */ -public interface RemoteExceptionHandler { - - Object handle(Future throwable) throws Throwable; -} +import infra.lang.NonNullApi; +import infra.lang.NonNullFields; \ No newline at end of file diff --git a/today-service-client/build.gradle b/today-service-client/build.gradle index 9ee881a..36ed6c9 100644 --- a/today-service-client/build.gradle +++ b/today-service-client/build.gradle @@ -3,24 +3,13 @@ description = "TODAY Service Client" dependencies { api project(":today-remoting") - api project(":today-cloud-core") api project(":today-service-api") api project(":today-service-registry") - optional 'io.netty:netty-transport' - optional 'io.netty:netty-codec' - optional 'io.netty:netty-handler' - - implementation 'cn.taketoday:today-web' - implementation 'cn.taketoday:today-framework' - implementation 'io.projectreactor:reactor-core' // :3.6.1 - - implementation 'org.apache.commons:commons-pool2:2.12.0' + api project(":today-remoting-transport-tcp") - implementation 'io.protostuff:protostuff-core:1.7.4' - implementation 'io.protostuff:protostuff-runtime:1.7.4' - optional "com.google.protobuf:protobuf-java" + testImplementation project(":today-cloud-samples:demo-tests:demo-user-api") } \ No newline at end of file diff --git a/today-service-client/src/main/java/infra/cloud/JdkServiceProxy.java b/today-service-client/src/main/java/infra/cloud/JdkServiceProxy.java deleted file mode 100644 index 79be869..0000000 --- a/today-service-client/src/main/java/infra/cloud/JdkServiceProxy.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 2021 - 2024 the original author or authors. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] - */ - -package infra.cloud; - -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.Method; -import java.lang.reflect.Proxy; -import java.util.List; -import java.util.concurrent.CopyOnWriteArrayList; - -import infra.cloud.client.DiscoveryClient; -import infra.cloud.client.ServiceInstance; -import infra.cloud.registry.ServiceNotFoundException; - -/** - * @author TODAY 2021/7/4 22:58 - */ -public class JdkServiceProxy implements ServiceProxy { - - @Override - @SuppressWarnings("unchecked") - public T getProxy(Class serviceInterface, DiscoveryClient discoveryClient, ServiceMethodInvoker rpcInvoker) { - return (T) Proxy.newProxyInstance(serviceInterface.getClassLoader(), new Class[] { serviceInterface }, - new ServiceInvocationHandler(serviceInterface, discoveryClient, rpcInvoker)); - } - - static final class ServiceInvocationHandler implements InvocationHandler { - private final CopyOnWriteArrayList serviceInstances = new CopyOnWriteArrayList<>(); - - private final Class serviceInterface; - - private final DiscoveryClient discoveryClient; - - private final ServiceMethodInvoker rpcInvoker; - - public ServiceInvocationHandler(Class serviceInterface, DiscoveryClient discoveryClient, ServiceMethodInvoker rpcInvoker) { - this.serviceInterface = serviceInterface; - this.discoveryClient = discoveryClient; - this.rpcInvoker = rpcInvoker; - } - - @Override - public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { - CopyOnWriteArrayList serviceInstances = this.serviceInstances; - if (serviceInstances.isEmpty()) { - List instances = discoveryClient.getInstances(serviceInterface.getName()); - serviceInstances.addAll(instances); - if (serviceInstances.isEmpty()) { - throw new ServiceNotFoundException(serviceInterface); - } - } - return rpcInvoker.invoke(serviceInstances, method, args); - } - } -} diff --git a/today-service-client/src/main/java/infra/cloud/ServiceMethodInvoker.java b/today-service-client/src/main/java/infra/cloud/ServiceMethodInvoker.java deleted file mode 100644 index cde9a4e..0000000 --- a/today-service-client/src/main/java/infra/cloud/ServiceMethodInvoker.java +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright 2021 - 2024 the original author or authors. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] - */ - -package infra.cloud; - -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.List; - -import infra.cloud.client.ServiceInstance; -import infra.cloud.registry.InstanceSelector; -import infra.cloud.registry.RandomInstanceSelector; -import infra.lang.Assert; -import infra.util.concurrent.Future; -import reactor.core.publisher.Mono; - -/** - * Service Method Invoker - * - * @author TODAY 2021/7/4 01:58 - */ -public abstract class ServiceMethodInvoker { - - protected InstanceSelector instanceSelector = new RandomInstanceSelector(); - - protected RemoteExceptionHandler exceptionHandler = new SimpleRemoteExceptionHandler(); - - private final ArrayList resolvers = new ArrayList<>(); - - public ServiceMethodInvoker() { - resolvers.add(new ListenableFutureReturnValueResolver()); - resolvers.add(new MonoFutureReturnValueResolver()); - resolvers.add(new BlockFutureReturnValueResolver()); - } - - public Object invoke(List instances, Method method, Object[] args) throws Throwable { - ServiceInstance selected = instanceSelector.select(instances); - try { - Future response = invokeInternal(selected, method, args); - return resolveReturnValue(response, method); - } - catch (Throwable e) { - return handleException(e, instances, selected, method, args); - } - } - - private Object resolveReturnValue(Future response, Method method) throws Throwable { - for (ReturnValueResolver resolver : resolvers) { - if (resolver.supports(method)) { - return resolver.resolve(response, method); - } - } - return null; - } - - protected RpcResponse handleException(Throwable e, List instances, - ServiceInstance selected, Method method, Object[] args) throws Throwable { - - throw e; - } - - protected abstract Future invokeInternal(ServiceInstance selected, Method method, Object[] args) - throws Throwable; - - public void setExceptionHandler(RemoteExceptionHandler exceptionHandler) { - Assert.notNull(exceptionHandler, "exceptionHandler is required"); - this.exceptionHandler = exceptionHandler; - } - - public RemoteExceptionHandler getExceptionHandler() { - return exceptionHandler; - } - - public void setServiceSelector(InstanceSelector instanceSelector) { - Assert.notNull(instanceSelector, "serviceSelector is required"); - this.instanceSelector = instanceSelector; - } - - public InstanceSelector getServiceSelector() { - return instanceSelector; - } - - interface ReturnValueResolver { - - boolean supports(Method method); - - Object resolve(Future response, Method method) throws Throwable; - - } - - static class ListenableFutureReturnValueResolver implements ReturnValueResolver { - - @Override - public boolean supports(Method method) { - return method.getReturnType() == Future.class; - } - - @Override - public Object resolve(Future response, Method method) { - return response; - } - - } - - static class BlockFutureReturnValueResolver implements ReturnValueResolver { - - @Override - public boolean supports(Method method) { - return true; - } - - @Override - public Object resolve(Future response, Method method) { - response.syncUninterruptibly(); - return response.getNow(); - } - - } - - static class MonoFutureReturnValueResolver implements ReturnValueResolver { - - @Override - public boolean supports(Method method) { - return method.getReturnType() == Mono.class; - } - - @Override - public Object resolve(Future response, Method method) { - return Mono.fromFuture(response.completable()); - } - - } - -} diff --git a/today-service-client/src/main/java/infra/cloud/SimpleRemoteExceptionHandler.java b/today-service-client/src/main/java/infra/cloud/SimpleRemoteExceptionHandler.java deleted file mode 100644 index 2f5caf0..0000000 --- a/today-service-client/src/main/java/infra/cloud/SimpleRemoteExceptionHandler.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright 2021 - 2024 the original author or authors. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] - */ - -package infra.cloud; - -import java.util.concurrent.ExecutionException; - -import infra.util.concurrent.Future; - -/** - * @author TODAY 2021/7/9 21:55 - */ -public class SimpleRemoteExceptionHandler implements RemoteExceptionHandler { - - @Override - public Object handle(Future response) throws Throwable { - throw exceptionNow(response); - } - - Throwable exceptionNow(Future response) { - if (!response.isDone()) - throw new IllegalStateException("Task has not completed"); - if (response.isCancelled()) - throw new IllegalStateException("Task was cancelled"); - boolean interrupted = false; - try { - while (true) { - try { - response.get(); - throw new IllegalStateException("Task completed with a result"); - } - catch (InterruptedException e) { - interrupted = true; - } - catch (ExecutionException e) { - return e.getCause(); - } - } - } - finally { - if (interrupted) - Thread.currentThread().interrupt(); - } - } - -} diff --git a/today-service-client/src/main/java/infra/cloud/protocol/ServiceDependencyResolvingStrategy.java b/today-service-client/src/main/java/infra/cloud/client/annotation/ServiceDependencyResolvingStrategy.java similarity index 94% rename from today-service-client/src/main/java/infra/cloud/protocol/ServiceDependencyResolvingStrategy.java rename to today-service-client/src/main/java/infra/cloud/client/annotation/ServiceDependencyResolvingStrategy.java index 7f18422..4393d54 100644 --- a/today-service-client/src/main/java/infra/cloud/protocol/ServiceDependencyResolvingStrategy.java +++ b/today-service-client/src/main/java/infra/cloud/client/annotation/ServiceDependencyResolvingStrategy.java @@ -15,12 +15,11 @@ * along with this program. If not, see [http://www.gnu.org/licenses/] */ -package infra.cloud.protocol; +package infra.cloud.client.annotation; import infra.beans.factory.config.DependencyDescriptor; import infra.beans.factory.support.DependencyResolvingStrategy; -import infra.cloud.ServiceProvider; -import infra.cloud.client.ServiceReference; +import infra.cloud.service.ServiceProvider; import infra.context.ApplicationContext; import infra.lang.Nullable; import infra.stereotype.Service; diff --git a/today-service-client/src/main/java/infra/cloud/client/ServiceReference.java b/today-service-client/src/main/java/infra/cloud/client/annotation/ServiceReference.java similarity index 96% rename from today-service-client/src/main/java/infra/cloud/client/ServiceReference.java rename to today-service-client/src/main/java/infra/cloud/client/annotation/ServiceReference.java index 332b60f..eac080e 100644 --- a/today-service-client/src/main/java/infra/cloud/client/ServiceReference.java +++ b/today-service-client/src/main/java/infra/cloud/client/annotation/ServiceReference.java @@ -15,7 +15,7 @@ * along with this program. If not, see [http://www.gnu.org/licenses/] */ -package infra.cloud.client; +package infra.cloud.client.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; diff --git a/today-service-client/src/main/java/infra/cloud/client/annotation/config/ServiceClientAutoConfiguration.java b/today-service-client/src/main/java/infra/cloud/client/annotation/config/ServiceClientAutoConfiguration.java new file mode 100644 index 0000000..eace9dc --- /dev/null +++ b/today-service-client/src/main/java/infra/cloud/client/annotation/config/ServiceClientAutoConfiguration.java @@ -0,0 +1,68 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.client.annotation.config; + +import infra.beans.factory.ObjectProvider; +import infra.cloud.client.DiscoveryClient; +import infra.cloud.client.annotation.ConditionalOnDiscoveryEnabled; +import infra.cloud.client.simple.SimpleDiscoveryProperties; +import infra.cloud.service.ClientInterceptor; +import infra.cloud.service.DefaultServiceInterfaceMetadataProvider; +import infra.cloud.service.DefaultServiceProxyFactory; +import infra.cloud.service.PackageInfoServiceMetadataProvider; +import infra.cloud.service.ReturnValueResolver; +import infra.cloud.service.ServiceInterfaceMetadataProvider; +import infra.cloud.service.ServiceInterfaceMethod; +import infra.cloud.service.ServiceMetadataProvider; +import infra.context.annotation.config.DisableDIAutoConfiguration; +import infra.context.condition.ConditionalOnMissingBean; +import infra.context.properties.EnableConfigurationProperties; +import infra.stereotype.Component; + +/** + * Auto-configuration for remote service client. + * + * @author 海子 Yang + * @since 1.0 2025/8/9 22:14 + */ +@DisableDIAutoConfiguration +@ConditionalOnDiscoveryEnabled +@EnableConfigurationProperties(SimpleDiscoveryProperties.class) +public class ServiceClientAutoConfiguration { + + @Component + public static DefaultServiceProxyFactory serviceProxyFactory( + ServiceInterfaceMetadataProvider metadataProvider, + DiscoveryClient discoveryClient, ObjectProvider clientInterceptors) { + return new DefaultServiceProxyFactory(discoveryClient, metadataProvider, clientInterceptors.orderedList()); + } + + @Component + @ConditionalOnMissingBean + public static ServiceMetadataProvider serviceMetadataProvider() { + return new PackageInfoServiceMetadataProvider(); + } + + @Component + @ConditionalOnMissingBean + public static ServiceInterfaceMetadataProvider serviceInterfaceMetadataProvider( + ServiceMetadataProvider serviceMetadataProvider, ObjectProvider resolvers) { + return new DefaultServiceInterfaceMetadataProvider(serviceMetadataProvider, resolvers.orderedList()); + } + +} diff --git a/today-service-client/src/main/java/infra/cloud/http/HttpServiceClientConfig.java b/today-service-client/src/main/java/infra/cloud/http/HttpServiceClientConfig.java deleted file mode 100644 index c3d293b..0000000 --- a/today-service-client/src/main/java/infra/cloud/http/HttpServiceClientConfig.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2021 - 2024 the original author or authors. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] - */ - -package infra.cloud.http; - -import java.util.List; - -import infra.beans.factory.ObjectProvider; -import infra.cloud.core.serialize.JdkSerialization; -import infra.cloud.core.serialize.Serialization; -import infra.cloud.serialize.ReturnValueSerialization; -import infra.cloud.serialize.RpcArgumentSerialization; -import infra.cloud.serialize.RpcRequestSerialization; -import infra.cloud.serialize.RpcResponseSerialization; -import infra.cloud.serialize.ThrowableSerialization; -import infra.context.annotation.Configuration; -import infra.context.annotation.MissingBean; -import infra.lang.TodayStrategies; -import infra.stereotype.Component; - -/** - * @author Harry Yang - * @since 1.0 2023/9/5 09:56 - */ -@Configuration(proxyBeanMethods = false) -public class HttpServiceClientConfig { - - @Component - @SuppressWarnings({ "rawtypes" }) - static RpcRequestSerialization rpcRequestSerialization(ObjectProvider serializations) { - List list = TodayStrategies.find(RpcArgumentSerialization.class); - serializations.addOrderedTo(list); - return new RpcRequestSerialization(list); - } - - @Component - @SuppressWarnings({ "rawtypes" }) - static RpcResponseSerialization responseSerialization(ObjectProvider serializations) { - List list = TodayStrategies.find(ReturnValueSerialization.class); - serializations.addOrderedTo(list); - return new RpcResponseSerialization(list, new ThrowableSerialization()); - } - - @MissingBean - static Serialization requestSerialization() { - return new JdkSerialization<>(); - } - -} diff --git a/today-service-client/src/main/java/infra/cloud/protocol/http/HttpOperations.java b/today-service-client/src/main/java/infra/cloud/protocol/http/HttpOperations.java deleted file mode 100644 index c7da4b7..0000000 --- a/today-service-client/src/main/java/infra/cloud/protocol/http/HttpOperations.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright 2021 - 2024 the original author or authors. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] - */ - -package infra.cloud.protocol.http; - -import java.util.List; -import java.util.Map; - -import infra.cloud.client.DefaultServiceInstance; -import infra.cloud.RpcRequest; -import infra.cloud.RpcResponse; -import infra.cloud.client.ServiceInstance; -import infra.cloud.core.serialize.Serialization; -import infra.cloud.registry.ServiceNotFoundException; -import infra.core.ParameterizedTypeReference; -import infra.core.style.ToStringBuilder; -import infra.http.HttpEntity; -import infra.http.HttpMethod; -import infra.web.client.HttpClientErrorException; -import infra.web.client.RestClient; -import infra.web.client.RestClientException; -import infra.web.client.RestTemplate; - -/** - * @author Harry Yang - * @since 1.0 2023/8/14 17:46 - */ -@Deprecated(forRemoval = true) -final class HttpOperations { - private static final ParameterizedTypeReference> reference = new ParameterizedTypeReference<>() { }; - - private final Serialization serialization; - - private final RestTemplate restOperations = new RestTemplate(); - - private final RestClient restClient = RestClient.create(restOperations); - - private final String registryURL; - - public HttpOperations(String registryURL, Serialization serialization) { - this.registryURL = registryURL; - this.serialization = serialization; - } - - public RpcResponse execute(ServiceInstance selected, RpcRequest rpcRequest) { - return restOperations.execute(selected.getHttpURI(), HttpMethod.POST, - request -> serialization.serialize(rpcRequest, request.getBody()), - response -> { - try { - return serialization.deserialize(response.getBody()); - } - catch (ClassNotFoundException e) { - throw new ServiceNotFoundException(e); - } - }); - } - - @SuppressWarnings("rawtypes") - public List getInstances(String name) { - try { - return restOperations.exchange(buildGetServiceDefinitionURL(name), HttpMethod.GET, HttpEntity.EMPTY, reference).getBody(); - } - catch (HttpClientErrorException.NotFound e) { - throw new ServiceNotFoundException(name, e); - } - } - - private String buildGetServiceDefinitionURL(String serviceInterface) { - return registryURL + '/' + serviceInterface; - } - - public void register(Object body) throws RestClientException { - restClient.post() - .uri(registryURL) - .body(body) - .execute(); - } - - public void delete(Object body) { - restClient.delete() - .uri(registryURL) - .body(body) - .execute(); - } - - public Map getServices() { - return restClient.get() - .uri(registryURL) - .retrieve().body(new ParameterizedTypeReference>() { }); - } - - @Override - public String toString() { - return ToStringBuilder.forInstance(this) - .append("registryURL", registryURL) - .toString(); - } -} diff --git a/today-service-client/src/main/java/infra/cloud/protocol/http/HttpServiceMethodInvoker.java b/today-service-client/src/main/java/infra/cloud/protocol/http/HttpServiceMethodInvoker.java deleted file mode 100644 index e334a92..0000000 --- a/today-service-client/src/main/java/infra/cloud/protocol/http/HttpServiceMethodInvoker.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2021 - 2024 the original author or authors. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] - */ - -package infra.cloud.protocol.http; - -import java.lang.reflect.Method; - -import infra.cloud.RpcRequest; -import infra.cloud.RpcResponse; -import infra.cloud.client.ServiceInstance; -import infra.cloud.ServiceMethodInvoker; -import infra.util.concurrent.Future; - -/** - * @author Harry Yang - * @since 2021/7/4 23:10 - */ -final class HttpServiceMethodInvoker extends ServiceMethodInvoker { - - private final HttpOperations httpOperations; - - HttpServiceMethodInvoker(HttpOperations httpOperations) { - this.httpOperations = httpOperations; - } - - @Override - protected Future invokeInternal(ServiceInstance selected, Method method, Object[] args) { - RpcRequest rpcRequest = new RpcRequest(); - rpcRequest.setMethodName(method.getName()); - rpcRequest.setServiceName(selected.getServiceId()); - rpcRequest.setParameterTypes(method.getParameterTypes()); - rpcRequest.setArguments(args); - RpcResponse execute = httpOperations.execute(selected, rpcRequest); - Throwable exception = execute.getException(); - if (exception != null) { - return Future.failed(exception); - } - return Future.ok(execute.getResult()); - } - -} diff --git a/today-service-client/src/main/java/infra/cloud/protocol/http/HttpServiceRegistry.java b/today-service-client/src/main/java/infra/cloud/protocol/http/HttpServiceRegistry.java deleted file mode 100644 index 8c7d1ce..0000000 --- a/today-service-client/src/main/java/infra/cloud/protocol/http/HttpServiceRegistry.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright 2021 - 2024 the original author or authors. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] - */ - -package infra.cloud.protocol.http; - -import java.util.ArrayList; -import java.util.List; - -import infra.cloud.JdkServiceProxy; -import infra.cloud.RpcResponse; -import infra.cloud.ServiceMethodInvoker; -import infra.cloud.ServiceProvider; -import infra.cloud.ServiceProxy; -import infra.cloud.client.ServiceInstance; -import infra.cloud.core.serialize.JdkSerialization; -import infra.cloud.core.serialize.Serialization; -import infra.core.style.ToStringBuilder; - -/** - * @author TODAY 2021/7/3 23:48 - */ -public class HttpServiceRegistry implements ServiceProvider { - - private ServiceProxy serviceProxy; - - private final HttpOperations httpOperations; - - private final ServiceMethodInvoker methodInvoker; - - public HttpServiceRegistry(String registryURL) { - this.httpOperations = new HttpOperations(registryURL, new JdkSerialization<>()); - this.methodInvoker = new HttpServiceMethodInvoker(httpOperations); - } - - HttpServiceRegistry(HttpOperations httpOperations) { - this.httpOperations = httpOperations; - this.methodInvoker = new HttpServiceMethodInvoker(httpOperations); - } - - HttpServiceRegistry(HttpOperations httpOperations, ServiceMethodInvoker methodInvoker) { - this.httpOperations = httpOperations; - this.methodInvoker = methodInvoker; - } - - public void setServiceProxy(ServiceProxy serviceProxy) { - this.serviceProxy = serviceProxy; - } - - public ServiceProxy getServiceProxy() { - if (serviceProxy == null) { - serviceProxy = createServiceProxy(); - } - return serviceProxy; - } - - protected JdkServiceProxy createServiceProxy() { - return new JdkServiceProxy(); - } - - public List getServices() { - return new ArrayList<>(httpOperations.getServices().keySet()); - } - - @SuppressWarnings("unchecked") - public List getInstances(String serviceId) { - return httpOperations.getInstances(serviceId); - } - - /** - * lookup for a target service - * - * @param serviceInterface target service interface - * @param service type - * @return target service interface - */ - @Override - public T getService(Class serviceInterface) { - return getServiceProxy().getProxy(serviceInterface, this, methodInvoker); - } - - @Override - public String toString() { - return ToStringBuilder.forInstance(this) - .append("httpOperations", httpOperations) - .toString(); - } - - // static - - public static HttpServiceRegistry ofURL(String registryURL) { - return new HttpServiceRegistry(registryURL); - } - - public static HttpServiceRegistry ofURL(String registryURL, Serialization serialization) { - return new HttpServiceRegistry(new HttpOperations(registryURL, serialization)); - } - - public static HttpServiceRegistry ofURL(String registryURL, Serialization serialization, ServiceMethodInvoker methodInvoker) { - return new HttpServiceRegistry(new HttpOperations(registryURL, serialization), methodInvoker); - } - -} diff --git a/today-service-client/src/main/java/infra/cloud/ServiceMethod.java b/today-service-client/src/main/java/infra/cloud/service/AbstractInvocationResult.java similarity index 72% rename from today-service-client/src/main/java/infra/cloud/ServiceMethod.java rename to today-service-client/src/main/java/infra/cloud/service/AbstractInvocationResult.java index 0cc61a1..c67af07 100644 --- a/today-service-client/src/main/java/infra/cloud/ServiceMethod.java +++ b/today-service-client/src/main/java/infra/cloud/service/AbstractInvocationResult.java @@ -15,20 +15,14 @@ * along with this program. If not, see [http://www.gnu.org/licenses/] */ -package infra.cloud; +package infra.cloud.service; -import java.lang.reflect.Method; +import infra.core.AttributeAccessorSupport; /** - * @author Harry Yang - * @since 1.0 2024/1/7 21:03 + * @author 海子 Yang + * @since 1.0 2025/8/9 16:17 */ -public class ServiceMethod { - - public final Method method; - - public ServiceMethod(Method method) { - this.method = method; - } +public abstract class AbstractInvocationResult extends AttributeAccessorSupport implements InvocationResult { } diff --git a/today-service-client/src/main/java/infra/cloud/service/ClientInterceptor.java b/today-service-client/src/main/java/infra/cloud/service/ClientInterceptor.java new file mode 100644 index 0000000..c870ae9 --- /dev/null +++ b/today-service-client/src/main/java/infra/cloud/service/ClientInterceptor.java @@ -0,0 +1,47 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.service; + +/** + * Intercepts calls on an interface on its way to the target. These are nested + * "on top" of the target. + * + *

      + * The user should implement the {@link #intercept(ServiceInvocation)} method to + * modify the original behavior. E.g. the following class implements a tracing + * interceptor (traces all the calls on the intercepted method(s)): + * + *

      {@code
      + * class TracingInterceptor implements ServiceInterceptor {
      + *    public Object intercept(ServiceInvocation i) throws Throwable {
      + *         System.out.println("before service " + i + " with args " + i.getArguments());
      + *         Object ret = i.proceed();
      + *         System.out.println("after service " + i + " returns " + ret);
      + *         return ret;
      + *     }
      + * }
      + * }
      + * + * @author 海子 Yang + * @since 1.0 2025/8/9 15:39 + */ +public interface ClientInterceptor { + + InvocationResult intercept(ServiceInvocation invocation) throws Throwable; + +} diff --git a/today-service-client/src/main/java/infra/cloud/service/DefaultServiceInterfaceMetadataProvider.java b/today-service-client/src/main/java/infra/cloud/service/DefaultServiceInterfaceMetadataProvider.java new file mode 100644 index 0000000..85dfe49 --- /dev/null +++ b/today-service-client/src/main/java/infra/cloud/service/DefaultServiceInterfaceMetadataProvider.java @@ -0,0 +1,150 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.service; + +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; + +import infra.util.concurrent.Future; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +/** + * @author 海子 Yang + * @since 1.0 2025/8/10 08:22 + */ +public class DefaultServiceInterfaceMetadataProvider extends AbstractServiceInterfaceMetadataProvider { + + private final ArrayList resolvers = new ArrayList<>(); + + public DefaultServiceInterfaceMetadataProvider(ServiceMetadataProvider serviceMetadataProvider, + List returnValueResolvers) { + super(serviceMetadataProvider); + resolvers.addAll(returnValueResolvers); + + resolvers.add(new MonoReturnValueResolver()); + resolvers.add(new FluxReturnValueResolver()); + resolvers.add(new BlockReturnValueResolver()); + resolvers.add(new FutureReturnValueResolver()); + } + + @Override + protected ServiceInterfaceMethod createServiceMethod(ServiceMetadata serviceMetadata, Class service, Method method) { + return new ServiceInterfaceMethod(serviceMetadata, service, method, resolvers); + } + + static class FutureReturnValueResolver implements ReturnValueResolver { + + @Override + public boolean supportsMethod(ServiceInterfaceMethod invocation) { + return invocation.getMethod().getReturnType() == Future.class; + } + + @Override + public InvocationType getInvocationType(ServiceInterfaceMethod method) { + return InvocationType.REQUEST_RESPONSE; + } + + @Override + public Object resolve(ServiceInterfaceMethod method, InvocationResult result) throws Throwable { + return result.future(); + } + + @Override + public boolean isBlocking() { + return false; + } + } + + static class BlockReturnValueResolver implements ReturnValueResolver { + + @Override + public boolean supportsMethod(ServiceInterfaceMethod method) { + return true; + } + + @Override + public InvocationType getInvocationType(ServiceInterfaceMethod method) { + return InvocationType.REQUEST_RESPONSE; + } + + @Override + public Object resolve(ServiceInterfaceMethod method, InvocationResult result) throws Throwable { + result.future().syncUninterruptibly(); + return result.future().getNow(); + } + + @Override + public boolean isBlocking() { + return true; + } + + } + + static class MonoReturnValueResolver implements ReturnValueResolver { + + @Override + public boolean supportsMethod(ServiceInterfaceMethod method) { + return method.getMethod().getReturnType() == Mono.class; + } + + @Override + public InvocationType getInvocationType(ServiceInterfaceMethod method) { + return InvocationType.REQUEST_RESPONSE; + } + + @Override + public Object resolve(ServiceInterfaceMethod method, InvocationResult result) throws Throwable { + return Mono.fromFuture(result.future().completable()); + } + + @Override + public boolean isBlocking() { + return false; + } + + } + + static class FluxReturnValueResolver implements ReturnValueResolver { + + @Override + public boolean supportsMethod(ServiceInterfaceMethod method) { + return method.getMethod().getReturnType() == Flux.class; + } + + @Override + public InvocationType getInvocationType(ServiceInterfaceMethod method) { + if (method.getParameters().length == 1 && method.getParameters()[0].getParameterType() == Flux.class) { + return InvocationType.DUPLEX_STREAMING; + } + return InvocationType.RESPONSE_STREAMING; + } + + @Override + public Object resolve(ServiceInterfaceMethod method, InvocationResult result) throws Throwable { + return Flux.from(result.publisher()); + } + + @Override + public boolean isBlocking() { + return false; + } + + } +} diff --git a/today-service-client/src/main/java/infra/cloud/service/DefaultServiceProxyFactory.java b/today-service-client/src/main/java/infra/cloud/service/DefaultServiceProxyFactory.java new file mode 100644 index 0000000..e8fc36d --- /dev/null +++ b/today-service-client/src/main/java/infra/cloud/service/DefaultServiceProxyFactory.java @@ -0,0 +1,108 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.service; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; + +import infra.cloud.client.DiscoveryClient; +import infra.lang.Assert; +import infra.lang.Nullable; +import infra.util.ReflectionUtils; + +/** + * @author 海子 Yang + * @since 2021/7/4 22:58 + */ +public class DefaultServiceProxyFactory implements ServiceProxyFactory { + + private final DiscoveryClient discoveryClient; + + private final ClientInterceptor[] interceptors; + + private final ServiceInterfaceMetadataProvider metadataProvider; + + public DefaultServiceProxyFactory(DiscoveryClient discoveryClient, + ServiceInterfaceMetadataProvider metadataProvider, List interceptors) { + this.discoveryClient = discoveryClient; + this.metadataProvider = metadataProvider; + this.interceptors = interceptors.toArray(new ClientInterceptor[0]); + } + + @Override + @SuppressWarnings("unchecked") + public S getService(Class serviceInterface) { + Assert.isTrue(serviceInterface.isInterface(), "service must be an interface"); + var metadata = metadataProvider.getMetadata(serviceInterface); + ServiceInvoker serviceInvoker = new ServiceMethodInvoker(metadata, discoveryClient, interceptors); + List serviceMethods = metadata.getServiceMethods(); + + return (S) Proxy.newProxyInstance(serviceInterface.getClassLoader(), new Class[] { serviceInterface }, + new ServiceInvocationHandler(serviceInterface, serviceMethods, serviceInvoker)); + } + + static final class ServiceInvocationHandler implements InvocationHandler { + + private final Class serviceInterface; + + private final ServiceInvoker serviceInvoker; + + private final Map serviceMethods; + + public ServiceInvocationHandler(Class serviceInterface, List methods, ServiceInvoker serviceInvoker) { + this.serviceInterface = serviceInterface; + this.serviceInvoker = serviceInvoker; + this.serviceMethods = methods.stream() + .collect(Collectors.toMap(ServiceInterfaceMethod::getMethod, Function.identity())); + } + + @Nullable + @Override + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + ServiceInterfaceMethod serviceMethod = serviceMethods.get(method); + if (serviceMethod != null) { + var result = serviceInvoker.invoke(serviceMethod, args); + return serviceMethod.resolveResult(result); + } + + if (method.isDefault()) { + return InvocationHandler.invokeDefault(proxy, method, args); + } + + if (ReflectionUtils.isEqualsMethod(method)) { + // Only consider equal when proxies are identical. + return (proxy == args[0]); + } + else if (ReflectionUtils.isHashCodeMethod(method)) { + // Use hashCode of service proxy. + return System.identityHashCode(proxy); + } + else if (ReflectionUtils.isToStringMethod(method)) { + return "Remote service proxy: " + serviceInterface; + } + + throw new IllegalStateException("Unexpected method invocation: " + method); + } + } + +} diff --git a/today-service-client/src/main/java/infra/cloud/service/MethodServiceInvocation.java b/today-service-client/src/main/java/infra/cloud/service/MethodServiceInvocation.java new file mode 100644 index 0000000..a9d5972 --- /dev/null +++ b/today-service-client/src/main/java/infra/cloud/service/MethodServiceInvocation.java @@ -0,0 +1,81 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.service; + +import infra.core.AttributeAccessorSupport; + +/** + * @author 海子 Yang + * @since 1.0 2025/8/9 14:11 + */ +public abstract class MethodServiceInvocation extends AttributeAccessorSupport implements ServiceInvocation { + + private final ServiceInterfaceMethod serviceMethod; + + private final Object[] args; + + private final ClientInterceptor[] interceptors; + + private int currentIndex = 0; + + private final int interceptorSize; + + public MethodServiceInvocation(ServiceInterfaceMethod serviceMethod, Object[] args, ClientInterceptor[] interceptors) { + this.serviceMethod = serviceMethod; + this.args = args; + this.interceptors = interceptors; + this.interceptorSize = interceptors.length; + } + + @Override + public InvocationResult proceed() throws Throwable { + if (currentIndex < interceptorSize) { + return interceptors[currentIndex++].intercept(this); + } + + return invokeRemoting(args); + } + + protected abstract InvocationResult invokeRemoting(Object[] args); + + @Override + public ServiceInterfaceMethod getMethod() { + return serviceMethod; + } + + @Override + public ServiceMetadata getServiceMetadata() { + return serviceMethod.serviceMetadata; + } + + @Override + public String getServiceName() { + return serviceMethod.serviceMetadata.getName(); + } + + @Override + public Object[] getArguments() { + return args; + } + + @Override + public InvocationType getType() { + return serviceMethod.getInvocationType(); + } + +} diff --git a/today-service-client/src/main/java/infra/cloud/service/ReturnValueResolver.java b/today-service-client/src/main/java/infra/cloud/service/ReturnValueResolver.java new file mode 100644 index 0000000..4bc0cc1 --- /dev/null +++ b/today-service-client/src/main/java/infra/cloud/service/ReturnValueResolver.java @@ -0,0 +1,36 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.service; + +import infra.lang.Nullable; + +/** + * @author 海子 Yang + * @since 1.0 2025/8/9 14:17 + */ +public interface ReturnValueResolver { + + boolean supportsMethod(ServiceInterfaceMethod method); + + InvocationType getInvocationType(ServiceInterfaceMethod method); + + @Nullable + Object resolve(ServiceInterfaceMethod method, InvocationResult result) throws Throwable; + + boolean isBlocking(); +} diff --git a/today-service-client/src/main/java/infra/cloud/service/ServiceInterfaceMethod.java b/today-service-client/src/main/java/infra/cloud/service/ServiceInterfaceMethod.java new file mode 100644 index 0000000..377ee8a --- /dev/null +++ b/today-service-client/src/main/java/infra/cloud/service/ServiceInterfaceMethod.java @@ -0,0 +1,99 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.service; + +import java.lang.reflect.Method; +import java.util.ArrayList; + +import infra.core.MethodParameter; +import infra.lang.Nullable; + +/** + * @author Harry Yang + * @since 1.0 2024/1/7 21:03 + */ +public class ServiceInterfaceMethod extends ServiceMethod { + + private final MethodParameter[] parameters; + + private final InvocationType invocationType; + + private final ReturnValueResolver returnValueResolver; + + private final boolean blocking; + + @Nullable + private MethodParameter returnTypeParameter; + + ServiceInterfaceMethod(ServiceMetadata serviceMetadata, Class serviceInterface, Method method, ArrayList resolvers) { + super(serviceMetadata, serviceInterface, method); + this.parameters = initMethodParameters(method); + this.returnValueResolver = findReturnValueResolver(resolvers); + this.blocking = returnValueResolver.isBlocking(); + this.invocationType = returnValueResolver.getInvocationType(this); + } + + public boolean isBlocking() { + return blocking; + } + + public InvocationType getInvocationType() { + return invocationType; + } + + public MethodParameter[] getParameters() { + return parameters; + } + + public MethodParameter getReturnType() { + MethodParameter returnType = returnTypeParameter; + if (returnType == null) { + returnType = MethodParameter.forExecutable(method, -1); + this.returnTypeParameter = returnType; + } + return returnType; + } + + @Nullable + public Object resolveResult(InvocationResult result) throws Throwable { + return returnValueResolver.resolve(this, result); + } + + private MethodParameter[] initMethodParameters(Method method) { + int count = method.getParameterCount(); + if (count == 0) { + return MethodParameter.EMPTY_ARRAY; + } + + MethodParameter[] result = new MethodParameter[count]; + for (int i = 0; i < count; i++) { + result[i] = new MethodParameter(method, i); + } + return result; + } + + private ReturnValueResolver findReturnValueResolver(ArrayList resolvers) { + for (ReturnValueResolver resolver : resolvers) { + if (resolver.supportsMethod(this)) { + return resolver; + } + } + throw new IllegalArgumentException("No ReturnValueResolver found for method: " + method); + } + +} diff --git a/today-service-client/src/main/java/infra/cloud/service/ServiceInvocation.java b/today-service-client/src/main/java/infra/cloud/service/ServiceInvocation.java new file mode 100644 index 0000000..b76b42f --- /dev/null +++ b/today-service-client/src/main/java/infra/cloud/service/ServiceInvocation.java @@ -0,0 +1,64 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.service; + +import infra.core.AttributeAccessor; + +/** + * This interface represents a service invocation. + * + * @author 海子 Yang + * @since 1.0 2025/8/9 10:12 + */ +public interface ServiceInvocation extends AttributeAccessor { + + /** + * Proceeds to the next interceptor in the chain. + * + * @return see the children interfaces' proceed definition. + * @throws Throwable if the invocation throws an exception. + */ + InvocationResult proceed() throws Throwable; + + /** + * Service name + * + */ + String getServiceName(); + + /** + * Service metadata + */ + ServiceMetadata getServiceMetadata(); + + /** + * service method metadata + */ + ServiceInterfaceMethod getMethod(); + + /** + * Get the arguments as an array object. It is possible to change element values + * within this array to change the arguments. + * + * @return the argument of the invocation + */ + Object[] getArguments(); + + InvocationType getType(); + +} diff --git a/today-service-client/src/main/java/infra/cloud/service/ServiceInvoker.java b/today-service-client/src/main/java/infra/cloud/service/ServiceInvoker.java new file mode 100644 index 0000000..457a865 --- /dev/null +++ b/today-service-client/src/main/java/infra/cloud/service/ServiceInvoker.java @@ -0,0 +1,39 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.service; + +/** + * @author 海子 Yang + * @since 1.0 2025/8/9 12:01 + */ +public interface ServiceInvoker { + + /** + * Implement this method to perform extra treatments before and after the + * invocation. Polite implementations would certainly like to invoke + * {@link ServiceInvocation#proceed()}. + * + * @param serviceMethod the service method + * @param args invocation args + * @return the result of the call to {@link ServiceInvocation#proceed()}, might be + * intercepted by the interceptor. + * @throws Throwable if the interceptors or the target-object throws an exception. + */ + InvocationResult invoke(ServiceInterfaceMethod serviceMethod, Object[] args) throws Throwable; + +} diff --git a/today-service-client/src/main/java/infra/cloud/service/ServiceMethodInvoker.java b/today-service-client/src/main/java/infra/cloud/service/ServiceMethodInvoker.java new file mode 100644 index 0000000..1492d44 --- /dev/null +++ b/today-service-client/src/main/java/infra/cloud/service/ServiceMethodInvoker.java @@ -0,0 +1,179 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.service; + +import org.reactivestreams.Publisher; + +import java.time.Duration; +import java.util.ArrayList; +import java.util.List; +import java.util.function.Function; + +import infra.cloud.client.DiscoveryClient; +import infra.cloud.client.ServiceInstance; +import infra.lang.Nullable; +import infra.remoting.Payload; +import infra.remoting.core.RemotingClient; +import infra.remoting.lb.LoadBalanceTarget; +import infra.remoting.transport.netty.client.TcpClientTransport; +import infra.util.concurrent.Future; +import infra.util.concurrent.Promise; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +/** + * Service Method Invoker + * + * @author TODAY 2021/7/4 01:58 + */ +public class ServiceMethodInvoker implements ServiceInvoker { + + private final DiscoveryClient discoveryClient; + + private final ServiceInterfaceMetadata metadata; + + private final ClientInterceptor[] interceptors; + + private Duration discoveryPeriod = Duration.ofSeconds(10); + + ServiceMethodInvoker(ServiceInterfaceMetadata metadata, + DiscoveryClient discoveryClient, ClientInterceptor[] interceptors) { + this.metadata = metadata; + this.discoveryClient = discoveryClient; + this.interceptors = interceptors; + } + + /** + * service discovery reload period + */ + public void setDiscoveryPeriod(Duration discoveryPeriod) { + this.discoveryPeriod = discoveryPeriod; + } + + @Override + public InvocationResult invoke(ServiceInterfaceMethod serviceMethod, Object[] args) throws Throwable { + MethodServiceInvocation invocation = new MethodServiceInvocation0(serviceMethod, args, interceptors); + + return invocation.proceed(); + } + + class MethodServiceInvocation0 extends MethodServiceInvocation + implements Function, List> { + + public MethodServiceInvocation0(ServiceInterfaceMethod serviceMethod, Object[] args, ClientInterceptor[] interceptors) { + super(serviceMethod, args, interceptors); + } + + @Override + protected InvocationResult invokeRemoting(Object[] args) { + RemotingClient client = RemotingClient.forLoadBalance(Flux.interval(discoveryPeriod) + .map(i -> discoveryClient.getInstances(getServiceMetadata().getName())) + .map(this)) + .roundRobinLoadBalanceStrategy() + .build(); + + Publisher publisher = switch (getType()) { + case FIRE_AND_FORGET -> client.fireAndForget(createMonoPayload(args)).cast(Payload.class); + case REQUEST_RESPONSE -> client.requestResponse(createMonoPayload(args)); + case RESPONSE_STREAMING -> client.requestStream(createMonoPayload(args)); + case DUPLEX_STREAMING -> client.requestChannel(createChannelPayload(args)); + }; + + return new InvocationResult0(null, getType(), publisher); + } + + private Mono createMonoPayload(Object[] args) { + return null; + } + + private Publisher createChannelPayload(Object[] args) { + + return null; + } + + @Override + public List apply(List serviceInstances) { + var targets = new ArrayList(serviceInstances.size()); + for (ServiceInstance instance : serviceInstances) { + targets.add(LoadBalanceTarget.of(instance.getInstanceId(), + TcpClientTransport.create(instance.getHost(), instance.getPort()))); + } + return targets; + } + } + + private Object deserialize(Payload payload) { + return null; + } + + class InvocationResult0 extends AbstractInvocationResult { + + @Nullable + private final Throwable throwable; + + private final InvocationType invocationType; + + private final Publisher publisher; + + private final Promise resultPromise = Future.forPromise(); + + public InvocationResult0(@Nullable Throwable throwable, InvocationType invocationType, Publisher publisher) { + this.throwable = throwable; + this.invocationType = invocationType; + this.publisher = publisher; + } + + @Override + public Object getValue() { + return future().join(); + } + + @Override + public boolean isFailed() { + return throwable != null; + } + + @Nullable + @Override + public Throwable getException() { + return throwable; + } + + @Override + public InvocationType getType() { + return invocationType; + } + + @Override + public Future future() { + // TODO + return resultPromise; + } + + @Override + public Publisher publisher() { + return switch (getType()) { + case FIRE_AND_FORGET -> Mono.from(publisher); + case REQUEST_RESPONSE -> Mono.from(publisher).map(ServiceMethodInvoker.this::deserialize); + case RESPONSE_STREAMING, DUPLEX_STREAMING -> Flux.from(publisher).map(ServiceMethodInvoker.this::deserialize); + }; + } + + } + +} diff --git a/today-service-client/src/main/java/infra/cloud/ServiceProvider.java b/today-service-client/src/main/java/infra/cloud/service/ServiceProvider.java similarity index 97% rename from today-service-client/src/main/java/infra/cloud/ServiceProvider.java rename to today-service-client/src/main/java/infra/cloud/service/ServiceProvider.java index 7f44447..318b942 100644 --- a/today-service-client/src/main/java/infra/cloud/ServiceProvider.java +++ b/today-service-client/src/main/java/infra/cloud/service/ServiceProvider.java @@ -15,7 +15,7 @@ * along with this program. If not, see [http://www.gnu.org/licenses/] */ -package infra.cloud; +package infra.cloud.service; import infra.cloud.registry.ServiceNotFoundException; diff --git a/today-service-client/src/main/java/infra/cloud/http/EnableHttpServiceClient.java b/today-service-client/src/main/java/infra/cloud/service/ServiceProxyFactory.java similarity index 56% rename from today-service-client/src/main/java/infra/cloud/http/EnableHttpServiceClient.java rename to today-service-client/src/main/java/infra/cloud/service/ServiceProxyFactory.java index 3b10c2f..0e48838 100644 --- a/today-service-client/src/main/java/infra/cloud/http/EnableHttpServiceClient.java +++ b/today-service-client/src/main/java/infra/cloud/service/ServiceProxyFactory.java @@ -15,22 +15,25 @@ * along with this program. If not, see [http://www.gnu.org/licenses/] */ -package infra.cloud.http; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -import infra.context.annotation.Import; +package infra.cloud.service; /** - * @author Harry Yang - * @since 1.0 2023/9/5 10:03 + * Factory to create a client proxy from a REMOTE service interface + * + * @author 海子 Yang + * @since 2021/7/4 22:58 */ -@Import(HttpServiceClientConfig.class) -@Retention(RetentionPolicy.RUNTIME) -@Target({ ElementType.TYPE, ElementType.METHOD }) -public @interface EnableHttpServiceClient { +public interface ServiceProxyFactory extends ServiceProvider { + + /** + * Return a proxy that implements the given service interface to perform + * requests and retrieve responses through a client. + * + * @param service the service to create a proxy for + * @param the service type + * @return the created proxy + */ + @Override + S getService(Class service); } diff --git a/today-service-client/src/main/resources/META-INF/config/infra.context.annotation.config.AutoConfiguration.imports b/today-service-client/src/main/resources/META-INF/config/infra.context.annotation.config.AutoConfiguration.imports new file mode 100644 index 0000000..21835ff --- /dev/null +++ b/today-service-client/src/main/resources/META-INF/config/infra.context.annotation.config.AutoConfiguration.imports @@ -0,0 +1 @@ +infra.cloud.client.annotation.config.ServiceClientAutoConfiguration \ No newline at end of file diff --git a/today-service-client/src/main/resources/META-INF/today.strategies b/today-service-client/src/main/resources/META-INF/today.strategies index fbb92ce..43e4be3 100644 --- a/today-service-client/src/main/resources/META-INF/today.strategies +++ b/today-service-client/src/main/resources/META-INF/today.strategies @@ -15,7 +15,7 @@ # along with this program. If not, see [http://www.gnu.org/licenses/] # infra.beans.factory.support.DependencyResolvingStrategy=\ - infra.remoting.ServiceDependencyResolvingStrategy + infra.cloud.client.annotation.ServiceDependencyResolvingStrategy infra.cloud.serialize.RpcArgumentSerialization=\ diff --git a/today-service-client/src/test/java/infra/cloud/client/annotation/config/ServiceClientAutoConfigurationTests.java b/today-service-client/src/test/java/infra/cloud/client/annotation/config/ServiceClientAutoConfigurationTests.java new file mode 100644 index 0000000..e73d5dc --- /dev/null +++ b/today-service-client/src/test/java/infra/cloud/client/annotation/config/ServiceClientAutoConfigurationTests.java @@ -0,0 +1,53 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.client.annotation.config; + +import org.junit.jupiter.api.Test; + +import cn.taketoday.demo.service.UserService; +import infra.app.test.context.InfraTest; +import infra.beans.factory.annotation.Autowired; +import infra.cloud.service.ServiceProxyFactory; +import infra.context.annotation.Configuration; +import infra.context.annotation.config.EnableAutoConfiguration; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author 海子 Yang + * @since 1.0 2025/8/9 22:20 + */ +@InfraTest +class ServiceClientAutoConfigurationTests { + + @Autowired + ServiceProxyFactory serviceProxyFactory; + + @Test + void serviceProxyFactory() { + UserService userService = serviceProxyFactory.getService(UserService.class); + assertThat(userService).isNotNull(); + } + + @EnableAutoConfiguration + @Configuration(proxyBeanMethods = false) + public static class Config { + + } + +} \ No newline at end of file diff --git a/today-service-client/src/test/java/infra/cloud/service/DefaultServiceInterfaceMetadataProviderTests.java b/today-service-client/src/test/java/infra/cloud/service/DefaultServiceInterfaceMetadataProviderTests.java new file mode 100644 index 0000000..b9dfc05 --- /dev/null +++ b/today-service-client/src/test/java/infra/cloud/service/DefaultServiceInterfaceMetadataProviderTests.java @@ -0,0 +1,112 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.service; + +import org.junit.jupiter.api.Test; + +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import infra.core.ResolvableType; +import infra.util.concurrent.Future; +import reactor.core.publisher.Flux; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +/** + * @author 海子 Yang + * @since 1.0 2025/8/10 16:56 + */ +class DefaultServiceInterfaceMetadataProviderTests { + + @Test + void getMetadata() { + + ServiceMetadataProvider serviceMetadataProvider = serviceInterface -> { + return new ServiceMetadata("demo-user-service", "1.0"); + }; + + var metadataProvider = new DefaultServiceInterfaceMetadataProvider(serviceMetadataProvider, List.of()); + + var metadata = metadataProvider.getMetadata(DemoUserService.class); + List serviceMethods = metadata.getServiceMethods(); + + assertThat(metadata.getServiceMetadata().getVersion()).isEqualTo("1.0"); + assertThat(metadata.getServiceMetadata().getName()).isEqualTo("demo-user-service"); + assertThat(metadata.getServiceInterface()).isEqualTo(DemoUserService.class); + + assertThat(serviceMethods).hasSize(4); + assertThatThrownBy(() -> serviceMethods.remove(1)) + .isInstanceOf(UnsupportedOperationException.class); + + Map methodMap = serviceMethods.stream().collect(Collectors.toMap(me -> me.getMethod().getName(), me -> me)); + + ServiceInterfaceMethod getById = methodMap.get("getById"); + assertThat(getById.getServiceInterface()).isSameAs(metadata.getServiceInterface()); + assertThat(getById.getInvocationType()).isEqualTo(InvocationType.REQUEST_RESPONSE); + assertThat(getById.getParameters().length).isEqualTo(1); + assertThat(getById.getReturnType().getParameterType()).isEqualTo(User.class); + + ServiceInterfaceMethod listUsers = methodMap.get("listUsers"); + assertThat(listUsers.getInvocationType()).isEqualTo(InvocationType.REQUEST_RESPONSE); + assertThat(listUsers.getParameters().length).isEqualTo(0); + assertThat(listUsers.getReturnType().getParameterType()).isEqualTo(List.class); + assertThat(ResolvableType.forMethodParameter(listUsers.getReturnType()).getGeneric().resolve()).isEqualTo(User.class); + + ServiceInterfaceMethod listUsersFuture = methodMap.get("listUsersFuture"); + assertThat(listUsersFuture.getInvocationType()).isEqualTo(InvocationType.REQUEST_RESPONSE); + assertThat(listUsersFuture.getParameters().length).isEqualTo(0); + assertThat(listUsersFuture.getReturnType().getParameterType()).isEqualTo(Future.class); + + assertThat(listUsersFuture.getInvocationType().clientSendsOneMessage()).isTrue(); + assertThat(listUsersFuture.getInvocationType().serverSendsOneMessage()).isTrue(); + + ResolvableType resolvableType = ResolvableType.forMethodParameter(listUsersFuture.getReturnType()); + assertThat(resolvableType.getGeneric().resolve()).isEqualTo(List.class); + assertThat(resolvableType.getGeneric().getGeneric().resolve()).isEqualTo(User.class); + // + + ServiceInterfaceMethod listUsersFlux = methodMap.get("listUsersFlux"); + assertThat(listUsersFlux.getInvocationType()).isEqualTo(InvocationType.RESPONSE_STREAMING); + assertThat(listUsersFlux.getParameters().length).isEqualTo(0); + assertThat(listUsersFlux.getReturnType().getParameterType()).isEqualTo(Flux.class); + assertThat(ResolvableType.forMethodParameter(listUsers.getReturnType()).getGeneric().resolve()).isEqualTo(User.class); + + assertThat(listUsersFlux.getInvocationType().clientSendsOneMessage()).isTrue(); + assertThat(listUsersFlux.getInvocationType().serverSendsOneMessage()).isFalse(); + + } + + interface DemoUserService { + + User getById(int id); + + List listUsers(); + + Future> listUsersFuture(); + + Flux listUsersFlux(); + } + + static class User { + + } + +} \ No newline at end of file diff --git a/today-service-client/src/test/java/infra/cloud/service/ServiceInvokerFactoryTests.java b/today-service-client/src/test/java/infra/cloud/service/ServiceInvokerFactoryTests.java new file mode 100644 index 0000000..df0c59b --- /dev/null +++ b/today-service-client/src/test/java/infra/cloud/service/ServiceInvokerFactoryTests.java @@ -0,0 +1,42 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.service; + +import org.junit.jupiter.api.Test; + +import cn.taketoday.demo.service.UserService; +import infra.cloud.client.simple.SimpleDiscoveryClient; +import infra.cloud.client.simple.SimpleDiscoveryProperties; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author 海子 Yang + * @since 1.0 2025/8/9 20:43 + */ +class ServiceInvokerFactoryTests { + + @Test + void create() { + +// ServiceInvokerFactory factory = new ServiceInvokerFactory(new SimpleDiscoveryClient(new SimpleDiscoveryProperties())); +// ServiceInvoker serviceInvoker = factory.create(UserService.class); +// assertThat(serviceInvoker).isNotNull(); + } + +} \ No newline at end of file From 84ae6309eb29a63faf90e68aa7be2c69be6be91c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Sun, 10 Aug 2025 22:37:55 +0800 Subject: [PATCH 034/104] =?UTF-8?q?:sparkles:=20=E6=8A=BD=E8=B1=A1=20Clien?= =?UTF-8?q?t=20=E5=B1=82=E8=B0=83=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/infra/remoting/Channel.java | 2 +- .../infra/remoting/RemotingOperations.java | 41 ++++------ .../infra/remoting/core/RemotingClient.java | 8 +- .../service/ServiceInterfaceMetadata.java | 4 +- .../ServiceClientAutoConfiguration.java | 12 ++- .../DefaultRemotingOperationsProvider.java | 76 +++++++++++++++++++ .../service/DefaultServiceProxyFactory.java | 11 ++- .../service/RemotingOperationsProvider.java | 30 ++++++++ .../cloud/service/ServiceMethodInvoker.java | 59 ++++---------- 9 files changed, 160 insertions(+), 83 deletions(-) create mode 100644 today-service-client/src/main/java/infra/cloud/service/DefaultRemotingOperationsProvider.java create mode 100644 today-service-client/src/main/java/infra/cloud/service/RemotingOperationsProvider.java diff --git a/today-remoting/src/main/java/infra/remoting/Channel.java b/today-remoting/src/main/java/infra/remoting/Channel.java index 464883d..975ffd9 100644 --- a/today-remoting/src/main/java/infra/remoting/Channel.java +++ b/today-remoting/src/main/java/infra/remoting/Channel.java @@ -28,7 +28,7 @@ * * @author 海子 Yang */ -public interface Channel extends Availability, Closeable, RemotingOperations { +public interface Channel extends Availability, Closeable { /** * Fire and Forget interaction model of protocol. diff --git a/today-remoting/src/main/java/infra/remoting/RemotingOperations.java b/today-remoting/src/main/java/infra/remoting/RemotingOperations.java index 4057f90..f28934c 100644 --- a/today-remoting/src/main/java/infra/remoting/RemotingOperations.java +++ b/today-remoting/src/main/java/infra/remoting/RemotingOperations.java @@ -29,46 +29,33 @@ public interface RemotingOperations { /** - * Fire and Forget interaction model of protocol. - * - * @param payload Request payload. - * @return {@code Publisher} that completes when the passed {@code payload} is successfully - * handled, otherwise errors. + * Perform a Fire-and-Forget interaction via {@link Channel#fireAndForget(Payload)}. Allows + * multiple subscriptions and performs a request per subscriber. */ - Mono fireAndForget(Payload payload); + Mono fireAndForget(Mono payloadMono); /** - * Request-Response interaction model of protocol. - * - * @param payload Request payload. - * @return {@code Publisher} containing at most a single {@code Payload} representing the - * response. + * Perform a Request-Response interaction via {@link Channel#requestResponse(Payload)}. Allows + * multiple subscriptions and performs a request per subscriber. */ - Mono requestResponse(Payload payload); + Mono requestResponse(Mono payloadMono); /** - * Request-Stream interaction model of protocol. - * - * @param payload Request payload. - * @return {@code Publisher} containing the stream of {@code Payload}s representing the response. + * Perform a Request-Stream interaction via {@link Channel#requestStream(Payload)}. Allows + * multiple subscriptions and performs a request per subscriber. */ - Flux requestStream(Payload payload); + Flux requestStream(Mono payloadMono); /** - * Request-Channel interaction model of protocol. - * - * @param payloads Stream of request payloads. - * @return Stream of response payloads. + * Perform a Request-Channel interaction via {@link Channel#requestChannel(Publisher)}. Allows + * multiple subscriptions and performs a request per subscriber. */ Flux requestChannel(Publisher payloads); /** - * Metadata-Push interaction model of protocol. - * - * @param payload Request payloads. - * @return {@code Publisher} that completes when the passed {@code payload} is successfully - * handled, otherwise errors. + * Perform a Metadata Push via {@link Channel#metadataPush(Payload)}. Allows multiple + * subscriptions and performs a request per subscriber. */ - Mono metadataPush(Payload payload); + Mono metadataPush(Mono payloadMono); } diff --git a/today-remoting/src/main/java/infra/remoting/core/RemotingClient.java b/today-remoting/src/main/java/infra/remoting/core/RemotingClient.java index 4fae6b7..3d3ff95 100644 --- a/today-remoting/src/main/java/infra/remoting/core/RemotingClient.java +++ b/today-remoting/src/main/java/infra/remoting/core/RemotingClient.java @@ -24,6 +24,7 @@ import infra.remoting.Channel; import infra.remoting.Closeable; import infra.remoting.Payload; +import infra.remoting.RemotingOperations; import infra.remoting.lb.LoadBalanceRemotingClient; import infra.remoting.lb.LoadBalanceTarget; import reactor.core.publisher.Flux; @@ -75,7 +76,7 @@ * @author 海子 Yang * @see LoadBalanceRemotingClient */ -public interface RemotingClient extends Closeable { +public interface RemotingClient extends Closeable, RemotingOperations { /** * Connect to the remote endpoint, if not yet connected. This method is a shortcut for @@ -101,30 +102,35 @@ default Mono onClose() { * Perform a Fire-and-Forget interaction via {@link Channel#fireAndForget(Payload)}. Allows * multiple subscriptions and performs a request per subscriber. */ + @Override Mono fireAndForget(Mono payloadMono); /** * Perform a Request-Response interaction via {@link Channel#requestResponse(Payload)}. Allows * multiple subscriptions and performs a request per subscriber. */ + @Override Mono requestResponse(Mono payloadMono); /** * Perform a Request-Stream interaction via {@link Channel#requestStream(Payload)}. Allows * multiple subscriptions and performs a request per subscriber. */ + @Override Flux requestStream(Mono payloadMono); /** * Perform a Request-Channel interaction via {@link Channel#requestChannel(Publisher)}. Allows * multiple subscriptions and performs a request per subscriber. */ + @Override Flux requestChannel(Publisher payloads); /** * Perform a Metadata Push via {@link Channel#metadataPush(Payload)}. Allows multiple * subscriptions and performs a request per subscriber. */ + @Override Mono metadataPush(Mono payloadMono); /** diff --git a/today-service-api/src/main/java/infra/cloud/service/ServiceInterfaceMetadata.java b/today-service-api/src/main/java/infra/cloud/service/ServiceInterfaceMetadata.java index 29c30a7..bb2ee7d 100644 --- a/today-service-api/src/main/java/infra/cloud/service/ServiceInterfaceMetadata.java +++ b/today-service-api/src/main/java/infra/cloud/service/ServiceInterfaceMetadata.java @@ -26,10 +26,10 @@ */ public class ServiceInterfaceMetadata { - private final Class serviceInterface; - private final ServiceMetadata serviceMetadata; + private final Class serviceInterface; + private final List serviceMethods; public ServiceInterfaceMetadata(Class serviceInterface, ServiceMetadata serviceMetadata, List serviceMethods) { diff --git a/today-service-client/src/main/java/infra/cloud/client/annotation/config/ServiceClientAutoConfiguration.java b/today-service-client/src/main/java/infra/cloud/client/annotation/config/ServiceClientAutoConfiguration.java index eace9dc..e603913 100644 --- a/today-service-client/src/main/java/infra/cloud/client/annotation/config/ServiceClientAutoConfiguration.java +++ b/today-service-client/src/main/java/infra/cloud/client/annotation/config/ServiceClientAutoConfiguration.java @@ -22,9 +22,11 @@ import infra.cloud.client.annotation.ConditionalOnDiscoveryEnabled; import infra.cloud.client.simple.SimpleDiscoveryProperties; import infra.cloud.service.ClientInterceptor; +import infra.cloud.service.DefaultRemotingOperationsProvider; import infra.cloud.service.DefaultServiceInterfaceMetadataProvider; import infra.cloud.service.DefaultServiceProxyFactory; import infra.cloud.service.PackageInfoServiceMetadataProvider; +import infra.cloud.service.RemotingOperationsProvider; import infra.cloud.service.ReturnValueResolver; import infra.cloud.service.ServiceInterfaceMetadataProvider; import infra.cloud.service.ServiceInterfaceMethod; @@ -48,8 +50,14 @@ public class ServiceClientAutoConfiguration { @Component public static DefaultServiceProxyFactory serviceProxyFactory( ServiceInterfaceMetadataProvider metadataProvider, - DiscoveryClient discoveryClient, ObjectProvider clientInterceptors) { - return new DefaultServiceProxyFactory(discoveryClient, metadataProvider, clientInterceptors.orderedList()); + RemotingOperationsProvider remotingOperationsProvider, ObjectProvider clientInterceptors) { + return new DefaultServiceProxyFactory(remotingOperationsProvider, metadataProvider, clientInterceptors.orderedList()); + } + + @Component + @ConditionalOnMissingBean + public static RemotingOperationsProvider remotingOperationsProvider(DiscoveryClient discoveryClient) { + return new DefaultRemotingOperationsProvider(discoveryClient); } @Component diff --git a/today-service-client/src/main/java/infra/cloud/service/DefaultRemotingOperationsProvider.java b/today-service-client/src/main/java/infra/cloud/service/DefaultRemotingOperationsProvider.java new file mode 100644 index 0000000..2a1c753 --- /dev/null +++ b/today-service-client/src/main/java/infra/cloud/service/DefaultRemotingOperationsProvider.java @@ -0,0 +1,76 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.service; + +import java.time.Duration; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Function; + +import infra.cloud.client.DiscoveryClient; +import infra.cloud.client.ServiceInstance; +import infra.remoting.RemotingOperations; +import infra.remoting.core.RemotingClient; +import infra.remoting.lb.LoadBalanceTarget; +import infra.remoting.transport.netty.client.TcpClientTransport; +import reactor.core.publisher.Flux; + +/** + * @author 海子 Yang + * @since 1.0 2025/8/10 22:08 + */ +public class DefaultRemotingOperationsProvider implements RemotingOperationsProvider, Function, List> { + + private final DiscoveryClient discoveryClient; + + private final ConcurrentHashMap remotingClientMap = new ConcurrentHashMap<>(); + + private Duration discoveryPeriod = Duration.ofSeconds(10); + + public DefaultRemotingOperationsProvider(DiscoveryClient discoveryClient) { + this.discoveryClient = discoveryClient; + } + + /** + * service discovery reload period + */ + public void setDiscoveryPeriod(Duration discoveryPeriod) { + this.discoveryPeriod = discoveryPeriod; + } + + @Override + public RemotingOperations getRemotingOperations(String serviceName) { + return remotingClientMap.computeIfAbsent(serviceName, name -> RemotingClient.forLoadBalance(Flux.interval(discoveryPeriod) + .map(i -> discoveryClient.getInstances(name)) + .map(this)) + .roundRobinLoadBalanceStrategy() + .build()); + } + + @Override + public List apply(List serviceInstances) { + var targets = new ArrayList(serviceInstances.size()); + for (ServiceInstance instance : serviceInstances) { + targets.add(LoadBalanceTarget.of(instance.getInstanceId(), + TcpClientTransport.create(instance.getHost(), instance.getPort()))); + } + return targets; + } + +} diff --git a/today-service-client/src/main/java/infra/cloud/service/DefaultServiceProxyFactory.java b/today-service-client/src/main/java/infra/cloud/service/DefaultServiceProxyFactory.java index e8fc36d..0e26e34 100644 --- a/today-service-client/src/main/java/infra/cloud/service/DefaultServiceProxyFactory.java +++ b/today-service-client/src/main/java/infra/cloud/service/DefaultServiceProxyFactory.java @@ -25,7 +25,6 @@ import java.util.function.Function; import java.util.stream.Collectors; -import infra.cloud.client.DiscoveryClient; import infra.lang.Assert; import infra.lang.Nullable; import infra.util.ReflectionUtils; @@ -36,16 +35,16 @@ */ public class DefaultServiceProxyFactory implements ServiceProxyFactory { - private final DiscoveryClient discoveryClient; - private final ClientInterceptor[] interceptors; + private final RemotingOperationsProvider remotingOperationsProvider; + private final ServiceInterfaceMetadataProvider metadataProvider; - public DefaultServiceProxyFactory(DiscoveryClient discoveryClient, + public DefaultServiceProxyFactory(RemotingOperationsProvider remotingOperationsProvider, ServiceInterfaceMetadataProvider metadataProvider, List interceptors) { - this.discoveryClient = discoveryClient; this.metadataProvider = metadataProvider; + this.remotingOperationsProvider = remotingOperationsProvider; this.interceptors = interceptors.toArray(new ClientInterceptor[0]); } @@ -54,7 +53,7 @@ public DefaultServiceProxyFactory(DiscoveryClient discoveryClient, public S getService(Class serviceInterface) { Assert.isTrue(serviceInterface.isInterface(), "service must be an interface"); var metadata = metadataProvider.getMetadata(serviceInterface); - ServiceInvoker serviceInvoker = new ServiceMethodInvoker(metadata, discoveryClient, interceptors); + ServiceInvoker serviceInvoker = new ServiceMethodInvoker(metadata, interceptors, remotingOperationsProvider); List serviceMethods = metadata.getServiceMethods(); return (S) Proxy.newProxyInstance(serviceInterface.getClassLoader(), new Class[] { serviceInterface }, diff --git a/today-service-client/src/main/java/infra/cloud/service/RemotingOperationsProvider.java b/today-service-client/src/main/java/infra/cloud/service/RemotingOperationsProvider.java new file mode 100644 index 0000000..3d86281 --- /dev/null +++ b/today-service-client/src/main/java/infra/cloud/service/RemotingOperationsProvider.java @@ -0,0 +1,30 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.service; + +import infra.remoting.RemotingOperations; + +/** + * @author 海子 Yang + * @since 1.0 2025/8/10 22:10 + */ +public interface RemotingOperationsProvider { + + RemotingOperations getRemotingOperations(String serviceName); + +} diff --git a/today-service-client/src/main/java/infra/cloud/service/ServiceMethodInvoker.java b/today-service-client/src/main/java/infra/cloud/service/ServiceMethodInvoker.java index 1492d44..148f900 100644 --- a/today-service-client/src/main/java/infra/cloud/service/ServiceMethodInvoker.java +++ b/today-service-client/src/main/java/infra/cloud/service/ServiceMethodInvoker.java @@ -19,18 +19,9 @@ import org.reactivestreams.Publisher; -import java.time.Duration; -import java.util.ArrayList; -import java.util.List; -import java.util.function.Function; - -import infra.cloud.client.DiscoveryClient; -import infra.cloud.client.ServiceInstance; import infra.lang.Nullable; import infra.remoting.Payload; -import infra.remoting.core.RemotingClient; -import infra.remoting.lb.LoadBalanceTarget; -import infra.remoting.transport.netty.client.TcpClientTransport; +import infra.remoting.RemotingOperations; import infra.util.concurrent.Future; import infra.util.concurrent.Promise; import reactor.core.publisher.Flux; @@ -43,26 +34,17 @@ */ public class ServiceMethodInvoker implements ServiceInvoker { - private final DiscoveryClient discoveryClient; - - private final ServiceInterfaceMetadata metadata; - private final ClientInterceptor[] interceptors; - private Duration discoveryPeriod = Duration.ofSeconds(10); + private final RemotingOperationsProvider remotingOperationsProvider; + + private final ServiceInterfaceMetadata metadata; ServiceMethodInvoker(ServiceInterfaceMetadata metadata, - DiscoveryClient discoveryClient, ClientInterceptor[] interceptors) { + ClientInterceptor[] interceptors, RemotingOperationsProvider remotingOperationsProvider) { this.metadata = metadata; - this.discoveryClient = discoveryClient; this.interceptors = interceptors; - } - - /** - * service discovery reload period - */ - public void setDiscoveryPeriod(Duration discoveryPeriod) { - this.discoveryPeriod = discoveryPeriod; + this.remotingOperationsProvider = remotingOperationsProvider; } @Override @@ -72,8 +54,7 @@ public InvocationResult invoke(ServiceInterfaceMethod serviceMethod, Object[] ar return invocation.proceed(); } - class MethodServiceInvocation0 extends MethodServiceInvocation - implements Function, List> { + class MethodServiceInvocation0 extends MethodServiceInvocation { public MethodServiceInvocation0(ServiceInterfaceMethod serviceMethod, Object[] args, ClientInterceptor[] interceptors) { super(serviceMethod, args, interceptors); @@ -81,40 +62,30 @@ public MethodServiceInvocation0(ServiceInterfaceMethod serviceMethod, Object[] a @Override protected InvocationResult invokeRemoting(Object[] args) { - RemotingClient client = RemotingClient.forLoadBalance(Flux.interval(discoveryPeriod) - .map(i -> discoveryClient.getInstances(getServiceMetadata().getName())) - .map(this)) - .roundRobinLoadBalanceStrategy() - .build(); + RemotingOperations operations = remotingOperationsProvider.getRemotingOperations(getServiceName()); Publisher publisher = switch (getType()) { - case FIRE_AND_FORGET -> client.fireAndForget(createMonoPayload(args)).cast(Payload.class); - case REQUEST_RESPONSE -> client.requestResponse(createMonoPayload(args)); - case RESPONSE_STREAMING -> client.requestStream(createMonoPayload(args)); - case DUPLEX_STREAMING -> client.requestChannel(createChannelPayload(args)); + case FIRE_AND_FORGET -> operations.fireAndForget(createMonoPayload(args)).cast(Payload.class); + case REQUEST_RESPONSE -> operations.requestResponse(createMonoPayload(args)); + case RESPONSE_STREAMING -> operations.requestStream(createMonoPayload(args)); + case DUPLEX_STREAMING -> operations.requestChannel(createChannelPayload(args)); }; return new InvocationResult0(null, getType(), publisher); } private Mono createMonoPayload(Object[] args) { + return null; } + @SuppressWarnings("unchecked") private Publisher createChannelPayload(Object[] args) { + Flux flux = (Flux) args[0]; return null; } - @Override - public List apply(List serviceInstances) { - var targets = new ArrayList(serviceInstances.size()); - for (ServiceInstance instance : serviceInstances) { - targets.add(LoadBalanceTarget.of(instance.getInstanceId(), - TcpClientTransport.create(instance.getHost(), instance.getPort()))); - } - return targets; - } } private Object deserialize(Payload payload) { From 0a1874c1219625f9b1ca8876a83dcf1510d82283 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Sun, 10 Aug 2025 22:38:22 +0800 Subject: [PATCH 035/104] =?UTF-8?q?:sparkles:=20LocalServiceHolder=20?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3=E6=89=AB=E6=8F=8F=EF=BC=8C=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cloud/provider/EnableServiceProvider.java | 74 --------------- .../cloud/provider/LocalServiceHolder.java | 26 +++--- .../ServiceProviderAutoConfiguration.java} | 22 ++--- ...nnotation.config.AutoConfiguration.imports | 1 + .../main/resources/META-INF/today.strategies | 0 .../cloud/registry/simple/HttpOperations.java | 91 ------------------- ...oServiceRegistrationAutoConfiguration.java | 4 +- .../AutoServiceRegistrationConfiguration.java | 3 +- ...nnotation.config.AutoConfiguration.imports | 2 +- 9 files changed, 30 insertions(+), 193 deletions(-) delete mode 100644 today-service-provider/src/main/java/infra/cloud/provider/EnableServiceProvider.java rename today-service-provider/src/main/java/infra/cloud/provider/{ServicePublishConfig.java => annotation/config/ServiceProviderAutoConfiguration.java} (56%) create mode 100644 today-service-provider/src/main/resources/META-INF/config/infra.context.annotation.config.AutoConfiguration.imports create mode 100644 today-service-provider/src/main/resources/META-INF/today.strategies delete mode 100644 today-service-registry-simple-client/src/main/java/infra/cloud/registry/simple/HttpOperations.java rename today-service-registry/src/main/java/infra/cloud/registry/{ => annotation/config}/AutoServiceRegistrationAutoConfiguration.java (91%) rename today-service-registry/src/main/java/infra/cloud/registry/{ => annotation/config}/AutoServiceRegistrationConfiguration.java (91%) diff --git a/today-service-provider/src/main/java/infra/cloud/provider/EnableServiceProvider.java b/today-service-provider/src/main/java/infra/cloud/provider/EnableServiceProvider.java deleted file mode 100644 index a3cf8dc..0000000 --- a/today-service-provider/src/main/java/infra/cloud/provider/EnableServiceProvider.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright 2021 - 2024 the original author or authors. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] - */ - -package infra.cloud.provider; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -import infra.beans.factory.ObjectProvider; -import infra.cloud.core.serialize.JdkSerialization; -import infra.cloud.core.serialize.Serialization; -import infra.cloud.serialize.ReturnValueSerialization; -import infra.cloud.serialize.RpcArgumentSerialization; -import infra.cloud.serialize.RpcResponseSerialization; -import infra.cloud.serialize.ThrowableSerialization; -import infra.context.annotation.Configuration; -import infra.context.annotation.Import; -import infra.context.annotation.MissingBean; -import infra.lang.TodayStrategies; -import infra.stereotype.Component; - -/** - * @author Harry Yang - * @since 1.0 2023/11/28 20:45 - */ -@Import(TcpServiceProviderConfig.class) -@Retention(RetentionPolicy.RUNTIME) -@Target({ ElementType.TYPE, ElementType.METHOD }) -public @interface EnableServiceProvider { - -} - -@Import(ServicePublishConfig.class) -@Configuration(proxyBeanMethods = false) -class TcpServiceProviderConfig { - - @MissingBean - static Serialization requestSerialization() { - return new JdkSerialization<>(); - } - - @Component - @SuppressWarnings({ "rawtypes" }) - static RpcRequestDeserializer rpcRequestDeserializer(ObjectProvider serializations) { - var list = TodayStrategies.find(RpcArgumentSerialization.class); - serializations.addOrderedTo(list); - return new RpcRequestDeserializer(list); - } - - @Component - @SuppressWarnings({ "rawtypes" }) - static RpcResponseSerialization responseSerialization(ObjectProvider serializations) { - var list = TodayStrategies.find(ReturnValueSerialization.class); - serializations.addOrderedTo(list); - return new RpcResponseSerialization(list, new ThrowableSerialization()); - } - -} diff --git a/today-service-provider/src/main/java/infra/cloud/provider/LocalServiceHolder.java b/today-service-provider/src/main/java/infra/cloud/provider/LocalServiceHolder.java index 26d7f17..476f756 100644 --- a/today-service-provider/src/main/java/infra/cloud/provider/LocalServiceHolder.java +++ b/today-service-provider/src/main/java/infra/cloud/provider/LocalServiceHolder.java @@ -19,6 +19,7 @@ import java.util.HashMap; import java.util.List; +import java.util.Set; import infra.beans.factory.SmartInitializingSingleton; import infra.context.ApplicationContext; @@ -26,7 +27,6 @@ import infra.lang.Nullable; import infra.stereotype.Service; import infra.util.ClassUtils; -import infra.util.ObjectUtils; /** * @author Harry Yang @@ -38,33 +38,31 @@ public class LocalServiceHolder extends ApplicationObjectSupport implements Smar @Nullable @SuppressWarnings("unchecked") - public T getService(Class serviceName) { - return (T) localServices.get(serviceName); + public T getService(Class serviceInterface) { + return (T) localServices.get(serviceInterface); } @Override public void afterSingletonsInstantiated() { ApplicationContext context = obtainApplicationContext(); List services = context.getAnnotatedBeans(Service.class); + for (Object service : services) { Class serviceImpl = ClassUtils.getUserClass(service); - Class[] interfaces = serviceImpl.getInterfaces(); - if (ObjectUtils.isEmpty(interfaces)) { + Set> interfaces = ClassUtils.getAllInterfacesForClassAsSet(serviceImpl); + if (interfaces.isEmpty()) { continue; } - Class interfaceToUse = interfaces[0]; - if (interfaces.length > 1) { - for (final Class anInterface : interfaces) { - if (anInterface.isAnnotationPresent(Service.class)) { - interfaceToUse = anInterface; - break; + for (final Class anInterface : interfaces) { + if (anInterface.isAnnotationPresent(Service.class)) { + Object object = localServices.put(anInterface, service); + if (object != null) { + throw new IllegalStateException("Service '%s' is already registered: [%s]".formatted(anInterface.getName(), object)); } + logger.info("add service: [{}] to interface: [{}]", service, anInterface.getName()); } } - - logger.info("add service: [{}] to interface: [{}]", service, interfaceToUse.getName()); - localServices.put(interfaceToUse, service); // register object } } diff --git a/today-service-provider/src/main/java/infra/cloud/provider/ServicePublishConfig.java b/today-service-provider/src/main/java/infra/cloud/provider/annotation/config/ServiceProviderAutoConfiguration.java similarity index 56% rename from today-service-provider/src/main/java/infra/cloud/provider/ServicePublishConfig.java rename to today-service-provider/src/main/java/infra/cloud/provider/annotation/config/ServiceProviderAutoConfiguration.java index 6f189dc..5dd2202 100644 --- a/today-service-provider/src/main/java/infra/cloud/provider/ServicePublishConfig.java +++ b/today-service-provider/src/main/java/infra/cloud/provider/annotation/config/ServiceProviderAutoConfiguration.java @@ -15,24 +15,24 @@ * along with this program. If not, see [http://www.gnu.org/licenses/] */ -package infra.cloud.provider; +package infra.cloud.provider.annotation.config; -import infra.context.annotation.Configuration; -import infra.logging.Logger; -import infra.logging.LoggerFactory; +import infra.cloud.client.annotation.ConditionalOnDiscoveryEnabled; +import infra.cloud.provider.LocalServiceHolder; +import infra.cloud.registry.annotation.config.AutoServiceRegistrationAutoConfiguration; +import infra.context.annotation.config.DisableDIAutoConfiguration; import infra.stereotype.Component; /** - * @author Harry Yang - * @since 1.0 2023/11/28 20:51 + * @author 海子 Yang + * @since 1.0 2025/8/10 22:31 */ -@Configuration(proxyBeanMethods = false) -class ServicePublishConfig { - - private static final Logger log = LoggerFactory.getLogger(ServicePublishConfig.class); +@ConditionalOnDiscoveryEnabled +@DisableDIAutoConfiguration(before = AutoServiceRegistrationAutoConfiguration.class) +public class ServiceProviderAutoConfiguration { @Component - static LocalServiceHolder localServiceHolder() { + public static LocalServiceHolder localServiceHolder() { return new LocalServiceHolder(); } diff --git a/today-service-provider/src/main/resources/META-INF/config/infra.context.annotation.config.AutoConfiguration.imports b/today-service-provider/src/main/resources/META-INF/config/infra.context.annotation.config.AutoConfiguration.imports new file mode 100644 index 0000000..b51f47b --- /dev/null +++ b/today-service-provider/src/main/resources/META-INF/config/infra.context.annotation.config.AutoConfiguration.imports @@ -0,0 +1 @@ +infra.cloud.provider.annotation.config.ServiceProviderAutoConfiguration \ No newline at end of file diff --git a/today-service-provider/src/main/resources/META-INF/today.strategies b/today-service-provider/src/main/resources/META-INF/today.strategies new file mode 100644 index 0000000..e69de29 diff --git a/today-service-registry-simple-client/src/main/java/infra/cloud/registry/simple/HttpOperations.java b/today-service-registry-simple-client/src/main/java/infra/cloud/registry/simple/HttpOperations.java deleted file mode 100644 index 250781c..0000000 --- a/today-service-registry-simple-client/src/main/java/infra/cloud/registry/simple/HttpOperations.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright 2021 - 2024 the original author or authors. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] - */ - -package infra.cloud.registry.simple; - -import java.util.List; -import java.util.Map; - -import infra.cloud.client.DefaultServiceInstance; -import infra.cloud.registry.ServiceNotFoundException; -import infra.core.ParameterizedTypeReference; -import infra.core.style.ToStringBuilder; -import infra.http.HttpEntity; -import infra.http.HttpMethod; -import infra.web.client.HttpClientErrorException; -import infra.web.client.RestClient; -import infra.web.client.RestClientException; -import infra.web.client.RestTemplate; - -/** - * @author Harry Yang - * @since 1.0 2023/8/14 17:46 - */ -final class HttpOperations { - private static final ParameterizedTypeReference> reference = new ParameterizedTypeReference<>() { }; - - private final RestTemplate restOperations = new RestTemplate(); - - private final RestClient restClient = RestClient.create(restOperations); - - private final String registryURL; - - public HttpOperations(String registryURL) { - this.registryURL = registryURL; - } - - @SuppressWarnings("rawtypes") - public List getInstances(String name) { - try { - return restOperations.exchange(buildGetServiceDefinitionURL(name), HttpMethod.GET, HttpEntity.EMPTY, reference).getBody(); - } - catch (HttpClientErrorException.NotFound e) { - throw new ServiceNotFoundException(name, e); - } - } - - private String buildGetServiceDefinitionURL(String serviceInterface) { - return registryURL + '/' + serviceInterface; - } - - public void register(Object body) throws RestClientException { - restClient.post() - .uri(registryURL) - .body(body) - .execute(); - } - - public void delete(Object body) { - restClient.delete() - .uri(registryURL) - .body(body) - .execute(); - } - - public Map getServices() { - return restClient.get() - .uri(registryURL) - .retrieve().body(new ParameterizedTypeReference>() { }); - } - - @Override - public String toString() { - return ToStringBuilder.forInstance(this) - .append("registryURL", registryURL) - .toString(); - } -} diff --git a/today-service-registry/src/main/java/infra/cloud/registry/AutoServiceRegistrationAutoConfiguration.java b/today-service-registry/src/main/java/infra/cloud/registry/annotation/config/AutoServiceRegistrationAutoConfiguration.java similarity index 91% rename from today-service-registry/src/main/java/infra/cloud/registry/AutoServiceRegistrationAutoConfiguration.java rename to today-service-registry/src/main/java/infra/cloud/registry/annotation/config/AutoServiceRegistrationAutoConfiguration.java index b9f59c0..3311888 100644 --- a/today-service-registry/src/main/java/infra/cloud/registry/AutoServiceRegistrationAutoConfiguration.java +++ b/today-service-registry/src/main/java/infra/cloud/registry/annotation/config/AutoServiceRegistrationAutoConfiguration.java @@ -15,9 +15,11 @@ * along with this program. If not, see [http://www.gnu.org/licenses/] */ -package infra.cloud.registry; +package infra.cloud.registry.annotation.config; import infra.beans.factory.annotation.DisableDependencyInjection; +import infra.cloud.registry.AutoServiceRegistration; +import infra.cloud.registry.AutoServiceRegistrationProperties; import infra.context.annotation.Configuration; import infra.context.annotation.Import; import infra.context.condition.ConditionalOnProperty; diff --git a/today-service-registry/src/main/java/infra/cloud/registry/AutoServiceRegistrationConfiguration.java b/today-service-registry/src/main/java/infra/cloud/registry/annotation/config/AutoServiceRegistrationConfiguration.java similarity index 91% rename from today-service-registry/src/main/java/infra/cloud/registry/AutoServiceRegistrationConfiguration.java rename to today-service-registry/src/main/java/infra/cloud/registry/annotation/config/AutoServiceRegistrationConfiguration.java index 5ce3bb8..8501c4a 100644 --- a/today-service-registry/src/main/java/infra/cloud/registry/AutoServiceRegistrationConfiguration.java +++ b/today-service-registry/src/main/java/infra/cloud/registry/annotation/config/AutoServiceRegistrationConfiguration.java @@ -15,8 +15,9 @@ * along with this program. If not, see [http://www.gnu.org/licenses/] */ -package infra.cloud.registry; +package infra.cloud.registry.annotation.config; +import infra.cloud.registry.AutoServiceRegistrationProperties; import infra.context.annotation.Configuration; import infra.context.condition.ConditionalOnProperty; import infra.context.properties.EnableConfigurationProperties; diff --git a/today-service-registry/src/main/resources/META-INF/config/infra.context.annotation.config.AutoConfiguration.imports b/today-service-registry/src/main/resources/META-INF/config/infra.context.annotation.config.AutoConfiguration.imports index 55812bd..5a47b54 100644 --- a/today-service-registry/src/main/resources/META-INF/config/infra.context.annotation.config.AutoConfiguration.imports +++ b/today-service-registry/src/main/resources/META-INF/config/infra.context.annotation.config.AutoConfiguration.imports @@ -1 +1 @@ -infra.cloud.registry.AutoServiceRegistrationAutoConfiguration \ No newline at end of file +infra.cloud.registry.annotation.config.AutoServiceRegistrationAutoConfiguration \ No newline at end of file From 0f291335be36cdcf512b929808ee74391acecf40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Mon, 11 Aug 2025 21:18:48 +0800 Subject: [PATCH 036/104] =?UTF-8?q?:recycle:=20=E9=80=9A=E8=AE=AF=E5=B1=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../integration/TcpIntegrationTests.java | 2 +- .../ObservationIntegrationTests.java | 4 +- ...ctoryNettyTransportFragmentationTests.java | 5 +- .../build.gradle | 2 + ...ctoryNettyTransportFragmentationTests.java | 95 ++++++++++++++++++ .../websocket}/SetupRejectionTests.java | 13 +-- .../src/main/java/infra/remoting/Channel.java | 74 +------------- .../java/infra/remoting/ChannelHandler.java | 96 +++++++++++++++++++ .../main/java/infra/remoting/Closeable.java | 4 +- .../infra/remoting/core/ChannelConnector.java | 28 +++--- .../infra/remoting/core/ChannelSupport.java | 4 +- .../core/ClientServerInputMultiplexer.java | 27 ++---- .../remoting/core/DefaultRemotingClient.java | 3 +- .../core/FireAndForgetRequesterMono.java | 2 - .../core/MetadataPushRequesterMono.java | 2 - .../infra/remoting/core/RemotingServer.java | 11 +-- .../core/RequestChannelRequesterFlux.java | 3 - .../core/RequestResponseRequesterMono.java | 2 - .../core/RequestStreamRequesterFlux.java | 2 - .../core/SlowFireAndForgetRequesterMono.java | 2 - .../remoting/core/ChannelConnectorTests.java | 2 +- .../remoting/core/RemotingServerTests.java | 4 +- .../remoting/core/ResponderChannelTests.java | 54 +++++------ ...ingWithServerSideNotificationsExample.java | 4 +- .../common/LimitBasedLeaseSender.java | 7 +- .../tcp/lease/simple/LeaseExample.java | 4 +- .../internal/subscriber/AssertSubscriber.java | 2 - .../remoting/test/util/TestConnection.java | 2 - .../infra/remoting/test/TransportPair.java | 6 +- 29 files changed, 271 insertions(+), 195 deletions(-) create mode 100644 today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/ChannelFactoryNettyTransportFragmentationTests.java rename {today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty => today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket}/SetupRejectionTests.java (91%) create mode 100644 today-remoting/src/main/java/infra/remoting/ChannelHandler.java diff --git a/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/TcpIntegrationTests.java b/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/TcpIntegrationTests.java index 62b3d4a..9106716 100644 --- a/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/TcpIntegrationTests.java +++ b/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/TcpIntegrationTests.java @@ -49,7 +49,7 @@ public class TcpIntegrationTests { @BeforeEach public void startup() { - server = RemotingServer.create((setup, sendingSocket) -> Mono.just(new ChannelWrapper(handler))) + server = RemotingServer.create((setup, channel) -> Mono.just(new ChannelWrapper(handler))) .bind(TcpServerTransport.create("localhost", 0)) .block(); } diff --git a/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/observation/ObservationIntegrationTests.java b/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/observation/ObservationIntegrationTests.java index 746d1d9..f52119b 100644 --- a/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/observation/ObservationIntegrationTests.java +++ b/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/observation/ObservationIntegrationTests.java @@ -134,8 +134,8 @@ private void testFireAndForget() { public SampleTestRunnerConsumer yourCode() { return (bb, meterRegistry) -> { counter = new AtomicInteger(); - server = RemotingServer.create((setup, sendingSocket) -> { - sendingSocket.onClose().subscribe(); + server = RemotingServer.create((setup, channel) -> { + channel.onClose().subscribe(); return Mono.just( new Channel() { diff --git a/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/ChannelFactoryNettyTransportFragmentationTests.java b/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/ChannelFactoryNettyTransportFragmentationTests.java index 323ad6f..762a1db 100644 --- a/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/ChannelFactoryNettyTransportFragmentationTests.java +++ b/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/ChannelFactoryNettyTransportFragmentationTests.java @@ -32,14 +32,15 @@ import infra.remoting.transport.netty.client.TcpClientTransport; import infra.remoting.transport.netty.server.CloseableChannel; import infra.remoting.transport.netty.server.TcpServerTransport; -import infra.remoting.transport.netty.server.WebsocketServerTransport; import reactor.core.publisher.Mono; import reactor.test.StepVerifier; class ChannelFactoryNettyTransportFragmentationTests { static Stream> arguments() { - return Stream.of(TcpServerTransport.create(0), WebsocketServerTransport.create(0)); + return Stream.of(TcpServerTransport.create(0) +// , WebsocketServerTransport.create(0) + ); } @ParameterizedTest diff --git a/today-remoting-transport-websocket/build.gradle b/today-remoting-transport-websocket/build.gradle index fbc3a29..a2929b1 100644 --- a/today-remoting-transport-websocket/build.gradle +++ b/today-remoting-transport-websocket/build.gradle @@ -13,6 +13,7 @@ dependencies { optional 'io.netty:netty-transport-classes-epoll' testImplementation 'io.projectreactor:reactor-test' + testImplementation project(":today-remoting-transport-tcp") testRuntimeOnly 'org.bouncycastle:bcpkix-jdk15on:1.70' testRuntimeOnly 'ch.qos.logback:logback-classic' @@ -20,5 +21,6 @@ dependencies { testImplementation testFixtures(project(":today-remoting")) + } diff --git a/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/ChannelFactoryNettyTransportFragmentationTests.java b/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/ChannelFactoryNettyTransportFragmentationTests.java new file mode 100644 index 0000000..2cc5354 --- /dev/null +++ b/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/ChannelFactoryNettyTransportFragmentationTests.java @@ -0,0 +1,95 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.remoting.transport.websocket; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +import org.mockito.Mockito; + +import java.time.Duration; +import java.util.stream.Stream; + +import infra.remoting.Channel; +import infra.remoting.ChannelAcceptor; +import infra.remoting.core.ChannelConnector; +import infra.remoting.core.RemotingServer; +import infra.remoting.transport.ServerTransport; +import reactor.core.publisher.Mono; +import reactor.test.StepVerifier; + +class ChannelFactoryNettyTransportFragmentationTests { + + static Stream> arguments() { + return Stream.of(WebsocketServerTransport.create(0)); + } + + @ParameterizedTest + @MethodSource("arguments") + void serverSucceedsWithEnabledFragmentationOnSufficientMtu( + ServerTransport serverTransport) { + Mono server = + RemotingServer.create(mockAcceptor()) + .fragment(100) + .bind(serverTransport) + .doOnNext(CloseableChannel::dispose); + StepVerifier.create(server).expectNextCount(1).expectComplete().verify(Duration.ofSeconds(5)); + } + + @ParameterizedTest + @MethodSource("arguments") + void serverSucceedsWithDisabledFragmentation(ServerTransport serverTransport) { + Mono server = + RemotingServer.create(mockAcceptor()) + .bind(serverTransport) + .doOnNext(CloseableChannel::dispose); + StepVerifier.create(server).expectNextCount(1).expectComplete().verify(Duration.ofSeconds(5)); + } + + @ParameterizedTest + @MethodSource("arguments") + void clientSucceedsWithEnabledFragmentationOnSufficientMtu( + ServerTransport serverTransport) { + CloseableChannel server = + RemotingServer.create(mockAcceptor()).fragment(100).bind(serverTransport).block(); + + Mono channel = + ChannelConnector.create() + .fragment(100) + .connect(WebsocketClientTransport.create(server.address())) + .doFinally(s -> server.dispose()); + StepVerifier.create(channel).expectNextCount(1).expectComplete().verify(Duration.ofSeconds(5)); + } + + @ParameterizedTest + @MethodSource("arguments") + void clientSucceedsWithDisabledFragmentation(ServerTransport serverTransport) { + CloseableChannel server = RemotingServer.create(mockAcceptor()).bind(serverTransport).block(); + + Mono channel = + ChannelConnector.connectWith(WebsocketClientTransport.create(server.address())) + .doFinally(s -> server.dispose()); + StepVerifier.create(channel).expectNextCount(1).expectComplete().verify(Duration.ofSeconds(5)); + } + + private ChannelAcceptor mockAcceptor() { + ChannelAcceptor mock = Mockito.mock(ChannelAcceptor.class); + Mockito.when(mock.accept(Mockito.any(), Mockito.any())) + .thenReturn(Mono.just(Mockito.mock(Channel.class))); + return mock; + } +} diff --git a/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/SetupRejectionTests.java b/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/SetupRejectionTests.java similarity index 91% rename from today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/SetupRejectionTests.java rename to today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/SetupRejectionTests.java index d433ef4..db7af51 100644 --- a/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/SetupRejectionTests.java +++ b/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/SetupRejectionTests.java @@ -14,7 +14,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see [http://www.gnu.org/licenses/] */ -package infra.remoting.transport.netty; +package infra.remoting.transport.websocket; import org.junit.jupiter.params.provider.Arguments; @@ -24,19 +24,16 @@ import java.util.function.Function; import java.util.stream.Stream; -import infra.remoting.ConnectionSetupPayload; import infra.remoting.Channel; import infra.remoting.ChannelAcceptor; +import infra.remoting.ConnectionSetupPayload; import infra.remoting.core.ChannelConnector; import infra.remoting.core.RemotingServer; import infra.remoting.error.RejectedSetupException; import infra.remoting.transport.ClientTransport; import infra.remoting.transport.ServerTransport; import infra.remoting.transport.netty.client.TcpClientTransport; -import infra.remoting.transport.netty.client.WebsocketClientTransport; -import infra.remoting.transport.netty.server.CloseableChannel; import infra.remoting.transport.netty.server.TcpServerTransport; -import infra.remoting.transport.netty.server.WebsocketServerTransport; import infra.remoting.util.DefaultPayload; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; @@ -92,10 +89,8 @@ void rejectSetupTcp( } static Stream transports() { - Function> tcpServer = - TcpServerTransport::create; - Function> wsServer = - WebsocketServerTransport::create; + Function> tcpServer = TcpServerTransport::create; + Function> wsServer = WebsocketServerTransport::create; Function tcpClient = TcpClientTransport::create; Function wsClient = WebsocketClientTransport::create; diff --git a/today-remoting/src/main/java/infra/remoting/Channel.java b/today-remoting/src/main/java/infra/remoting/Channel.java index 975ffd9..6cd33ba 100644 --- a/today-remoting/src/main/java/infra/remoting/Channel.java +++ b/today-remoting/src/main/java/infra/remoting/Channel.java @@ -17,89 +17,17 @@ package infra.remoting; -import org.reactivestreams.Publisher; - -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; - /** * A contract providing different interaction models for protocol. * * @author 海子 Yang */ -public interface Channel extends Availability, Closeable { - - /** - * Fire and Forget interaction model of protocol. - * - * @param payload Request payload. - * @return {@code Publisher} that completes when the passed {@code payload} is successfully - * handled, otherwise errors. - */ - default Mono fireAndForget(Payload payload) { - return ChannelAdapter.fireAndForget(payload); - } - - /** - * Request-Response interaction model of protocol. - * - * @param payload Request payload. - * @return {@code Publisher} containing at most a single {@code Payload} representing the - * response. - */ - default Mono requestResponse(Payload payload) { - return ChannelAdapter.requestResponse(payload); - } - - /** - * Request-Stream interaction model of protocol. - * - * @param payload Request payload. - * @return {@code Publisher} containing the stream of {@code Payload}s representing the response. - */ - default Flux requestStream(Payload payload) { - return ChannelAdapter.requestStream(payload); - } - - /** - * Request-Channel interaction model of protocol. - * - * @param payloads Stream of request payloads. - * @return Stream of response payloads. - */ - default Flux requestChannel(Publisher payloads) { - return ChannelAdapter.requestChannel(payloads); - } - - /** - * Metadata-Push interaction model of protocol. - * - * @param payload Request payloads. - * @return {@code Publisher} that completes when the passed {@code payload} is successfully - * handled, otherwise errors. - */ - default Mono metadataPush(Payload payload) { - return ChannelAdapter.metadataPush(payload); - } +public interface Channel extends Availability, ChannelHandler { @Override default double availability() { return isDisposed() ? 0.0 : 1.0; } - @Override - default void dispose() { - } - - @Override - default boolean isDisposed() { - return false; - } - - @Override - default Mono onClose() { - return Mono.never(); - } - } diff --git a/today-remoting/src/main/java/infra/remoting/ChannelHandler.java b/today-remoting/src/main/java/infra/remoting/ChannelHandler.java new file mode 100644 index 0000000..e2d4980 --- /dev/null +++ b/today-remoting/src/main/java/infra/remoting/ChannelHandler.java @@ -0,0 +1,96 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.remoting; + +import org.reactivestreams.Publisher; + +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +/** + * A contract providing different interaction models for protocol. + * + * @author 海子 Yang + * @since 1.0 2025/8/11 17:51 + */ +public interface ChannelHandler extends Closeable { + + /** + * Fire and Forget interaction model of protocol. + * + * @param payload Request payload. + * @return {@code Publisher} that completes when the passed {@code payload} is successfully + * handled, otherwise errors. + */ + default Mono fireAndForget(Payload payload) { + return ChannelAdapter.fireAndForget(payload); + } + + /** + * Request-Response interaction model of protocol. + * + * @param payload Request payload. + * @return {@code Publisher} containing at most a single {@code Payload} representing the + * response. + */ + default Mono requestResponse(Payload payload) { + return ChannelAdapter.requestResponse(payload); + } + + /** + * Request-Stream interaction model of protocol. + * + * @param payload Request payload. + * @return {@code Publisher} containing the stream of {@code Payload}s representing the response. + */ + default Flux requestStream(Payload payload) { + return ChannelAdapter.requestStream(payload); + } + + /** + * Request-Channel interaction model of protocol. + * + * @param payloads Stream of request payloads. + * @return Stream of response payloads. + */ + default Flux requestChannel(Publisher payloads) { + return ChannelAdapter.requestChannel(payloads); + } + + /** + * Metadata-Push interaction model of protocol. + * + * @param payload Request payloads. + * @return {@code Publisher} that completes when the passed {@code payload} is successfully + * handled, otherwise errors. + */ + default Mono metadataPush(Payload payload) { + return ChannelAdapter.metadataPush(payload); + } + + @Override + default void dispose() { + } + + @Override + default Mono onClose() { + return Mono.never(); + } + +} diff --git a/today-remoting/src/main/java/infra/remoting/Closeable.java b/today-remoting/src/main/java/infra/remoting/Closeable.java index 1ac0db3..7aa98a4 100644 --- a/today-remoting/src/main/java/infra/remoting/Closeable.java +++ b/today-remoting/src/main/java/infra/remoting/Closeable.java @@ -17,8 +17,6 @@ package infra.remoting; -import org.reactivestreams.Subscriber; - import reactor.core.Disposable; import reactor.core.publisher.Mono; @@ -31,7 +29,7 @@ public interface Closeable extends Disposable { * Returns a {@link Mono} that terminates when the instance is terminated by any reason. Note, in * case of error termination, the cause of error will be propagated as an error signal through * {@link org.reactivestreams.Subscriber#onError(Throwable)}. Otherwise, {@link - * Subscriber#onComplete()} will be called. + * org.reactivestreams.Subscriber#onComplete()} will be called. * * @return a {@link Mono} to track completion with success or error of the underlying resource. * When the underlying resource is an `Channel`, the {@code Mono} exposes stream 0 (i.e. diff --git a/today-remoting/src/main/java/infra/remoting/core/ChannelConnector.java b/today-remoting/src/main/java/infra/remoting/core/ChannelConnector.java index 4c9edad..f9d783b 100644 --- a/today-remoting/src/main/java/infra/remoting/core/ChannelConnector.java +++ b/today-remoting/src/main/java/infra/remoting/core/ChannelConnector.java @@ -26,6 +26,7 @@ import infra.lang.Nullable; import infra.remoting.Channel; import infra.remoting.ChannelAcceptor; +import infra.remoting.Closeable; import infra.remoting.Connection; import infra.remoting.ConnectionSetupPayload; import infra.remoting.Payload; @@ -47,7 +48,6 @@ import infra.remoting.util.EmptyPayload; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; -import reactor.core.Disposable; import reactor.core.publisher.Mono; import reactor.core.publisher.Sinks; import reactor.util.function.Tuples; @@ -540,22 +540,16 @@ public Mono connect(Supplier transportSupplier) { resumeToken = Unpooled.EMPTY_BUFFER; } - ByteBuf setupFrame = SetupFrameCodec.encode(sourceConnection.alloc(), - leaseEnabled, - (int) keepAliveInterval.toMillis(), - (int) keepAliveMaxLifeTime.toMillis(), - resumeToken, - metadataMimeType, - dataMimeType, - setupPayload); + ByteBuf setupFrame = SetupFrameCodec.encode(sourceConnection.alloc(), leaseEnabled, + (int) keepAliveInterval.toMillis(), (int) keepAliveMaxLifeTime.toMillis(), + resumeToken, metadataMimeType, dataMimeType, setupPayload); sourceConnection.sendFrame(0, setupFrame.retainedSlice()); return clientSetup.init(sourceConnection).flatMap(tuple -> { final Connection clientServerConnection = tuple.getT2(); - final KeepAliveHandler keepAliveHandler; final Connection wrappedConnection; - final InitializingInterceptorRegistry interceptors = this.interceptors; + final KeepAliveHandler keepAliveHandler; if (resumeEnabled) { final ResumableClientSetup resumableClientSetup = new ResumableClientSetup(); @@ -572,6 +566,7 @@ public Mono connect(Supplier transportSupplier) { wrappedConnection = clientServerConnection; } + final InitializingInterceptorRegistry interceptors = this.interceptors; var multiplexer = new ClientServerInputMultiplexer(wrappedConnection, interceptors, true); final LeaseSpec leases; @@ -609,11 +604,10 @@ public Mono connect(Supplier transportSupplier) { ? new ResponderLeaseTracker(CLIENT_TAG, wrappedConnection, leases.sender) : null; - Channel responderChannel = new ResponderChannel(multiplexer.asServerConnection(), wrappedChannelHandler, - payloadDecoder, responderLeaseTracker, mtu, maxFrameLength, maxInboundPayloadSize, - leaseEnabled && leases.sender instanceof TrackingLeaseSender - ? channel -> interceptors.initResponderRequestInterceptor(channel, (TrackingLeaseSender) leases.sender) - : interceptors::initResponderRequestInterceptor, responderOnAllClosedSink); + new ResponderChannel(multiplexer.asServerConnection(), wrappedChannelHandler, payloadDecoder, responderLeaseTracker, + mtu, maxFrameLength, maxInboundPayloadSize, leaseEnabled && leases.sender instanceof TrackingLeaseSender + ? channel -> interceptors.initResponderRequestInterceptor(channel, (TrackingLeaseSender) leases.sender) + : interceptors::initResponderRequestInterceptor, responderOnAllClosedSink); return wrappedChannelRequester; }) @@ -623,7 +617,7 @@ public Mono connect(Supplier transportSupplier) { }).as(source -> { if (retrySpec != null) { return new ReconnectMono<>( - source.retryWhen(retrySpec), Disposable::dispose, INVALIDATE_FUNCTION); + source.retryWhen(retrySpec), Closeable::dispose, INVALIDATE_FUNCTION); } else { return source; diff --git a/today-remoting/src/main/java/infra/remoting/core/ChannelSupport.java b/today-remoting/src/main/java/infra/remoting/core/ChannelSupport.java index 798e2e0..844e11f 100644 --- a/today-remoting/src/main/java/infra/remoting/core/ChannelSupport.java +++ b/today-remoting/src/main/java/infra/remoting/core/ChannelSupport.java @@ -29,7 +29,7 @@ import io.netty.util.collection.IntObjectHashMap; import io.netty.util.collection.IntObjectMap; -class ChannelSupport { +class ChannelSupport implements Channel { public final int mtu; @@ -63,7 +63,7 @@ public ChannelSupport(int mtu, int maxFrameLength, int maxInboundPayloadSize, this.allocator = connection.alloc(); this.streamIdProvider = streamIdProvider; this.connection = connection; - this.requestInterceptor = requestInterceptorFunction.apply((Channel) this); + this.requestInterceptor = requestInterceptorFunction.apply(this); } public int getMtu() { diff --git a/today-remoting/src/main/java/infra/remoting/core/ClientServerInputMultiplexer.java b/today-remoting/src/main/java/infra/remoting/core/ClientServerInputMultiplexer.java index 95d7ac0..701d3d0 100644 --- a/today-remoting/src/main/java/infra/remoting/core/ClientServerInputMultiplexer.java +++ b/today-remoting/src/main/java/infra/remoting/core/ClientServerInputMultiplexer.java @@ -65,8 +65,7 @@ class ClientServerInputMultiplexer implements CoreSubscriber, Closeable private static final AtomicIntegerFieldUpdater STATE = AtomicIntegerFieldUpdater.newUpdater(ClientServerInputMultiplexer.class, "state"); - public ClientServerInputMultiplexer( - Connection source, InitializingInterceptorRegistry registry, boolean isClient) { + public ClientServerInputMultiplexer(Connection source, InitializingInterceptorRegistry registry, boolean isClient) { this.source = source; this.isClient = isClient; @@ -224,11 +223,11 @@ public String toString() { + '}'; } - private static class InternalConnection extends Flux - implements Subscription, Connection { + private static class InternalConnection extends Flux implements Subscription, Connection { + private final Type type; - private final ClientServerInputMultiplexer clientServerInputMultiplexer; private final Connection source; + private final ClientServerInputMultiplexer clientServerInputMultiplexer; private volatile int state; static final AtomicIntegerFieldUpdater STATE = @@ -236,10 +235,7 @@ private static class InternalConnection extends Flux CoreSubscriber actual; - public InternalConnection( - Type type, - ClientServerInputMultiplexer clientServerInputMultiplexer, - Connection source) { + public InternalConnection(Type type, ClientServerInputMultiplexer clientServerInputMultiplexer, Connection source) { this.type = type; this.clientServerInputMultiplexer = clientServerInputMultiplexer; this.source = source; @@ -252,9 +248,7 @@ public void subscribe(CoreSubscriber actual) { actual.onSubscribe(this); } else { - Operators.error( - actual, - new IllegalStateException("InternalConnection allows only single subscription")); + Operators.error(actual, new IllegalStateException("InternalConnection allows only single subscription")); } } @@ -342,14 +336,7 @@ public double availability() { @Override public String toString() { - return "InternalConnection{" - + "type=" - + type - + ", source=" - + source - + ", state=" - + state - + '}'; + return "InternalConnection{type=%s, source=%s, state=%d}".formatted(type, source, state); } } } diff --git a/today-remoting/src/main/java/infra/remoting/core/DefaultRemotingClient.java b/today-remoting/src/main/java/infra/remoting/core/DefaultRemotingClient.java index 9121623..bb7d9ab 100644 --- a/today-remoting/src/main/java/infra/remoting/core/DefaultRemotingClient.java +++ b/today-remoting/src/main/java/infra/remoting/core/DefaultRemotingClient.java @@ -45,8 +45,7 @@ /** * Default implementation of {@link RemotingClient} */ -class DefaultRemotingClient extends ResolvingOperator - implements CoreSubscriber, CorePublisher, RemotingClient { +class DefaultRemotingClient extends ResolvingOperator implements CoreSubscriber, CorePublisher, RemotingClient { static final Consumer DISCARD_ELEMENTS_CONSUMER = data -> { if (data instanceof ReferenceCounted rc) { diff --git a/today-remoting/src/main/java/infra/remoting/core/FireAndForgetRequesterMono.java b/today-remoting/src/main/java/infra/remoting/core/FireAndForgetRequesterMono.java index d58a0da..bbd7db3 100644 --- a/today-remoting/src/main/java/infra/remoting/core/FireAndForgetRequesterMono.java +++ b/today-remoting/src/main/java/infra/remoting/core/FireAndForgetRequesterMono.java @@ -21,7 +21,6 @@ import java.time.Duration; import java.util.concurrent.atomic.AtomicLongFieldUpdater; -import infra.lang.NonNull; import infra.lang.Nullable; import infra.remoting.Payload; import infra.remoting.frame.FrameType; @@ -280,7 +279,6 @@ public Object scanUnsafe(Scannable.Attr key) { } @Override - @NonNull public String stepName() { return "source(FireAndForgetMono)"; } diff --git a/today-remoting/src/main/java/infra/remoting/core/MetadataPushRequesterMono.java b/today-remoting/src/main/java/infra/remoting/core/MetadataPushRequesterMono.java index 9ddb2eb..bd9d93c 100644 --- a/today-remoting/src/main/java/infra/remoting/core/MetadataPushRequesterMono.java +++ b/today-remoting/src/main/java/infra/remoting/core/MetadataPushRequesterMono.java @@ -19,7 +19,6 @@ import java.time.Duration; import java.util.concurrent.atomic.AtomicLongFieldUpdater; -import infra.lang.NonNull; import infra.lang.Nullable; import infra.remoting.Payload; import infra.remoting.frame.MetadataPushFrameCodec; @@ -188,7 +187,6 @@ public Object scanUnsafe(Attr key) { } @Override - @NonNull public String stepName() { return "source(MetadataPushMono)"; } diff --git a/today-remoting/src/main/java/infra/remoting/core/RemotingServer.java b/today-remoting/src/main/java/infra/remoting/core/RemotingServer.java index 79bffa5..0ed2186 100644 --- a/today-remoting/src/main/java/infra/remoting/core/RemotingServer.java +++ b/today-remoting/src/main/java/infra/remoting/core/RemotingServer.java @@ -25,8 +25,8 @@ import infra.remoting.Channel; import infra.remoting.ChannelAcceptor; import infra.remoting.Closeable; -import infra.remoting.ConnectionSetupPayload; import infra.remoting.Connection; +import infra.remoting.ConnectionSetupPayload; import infra.remoting.Payload; import infra.remoting.ProtocolErrorException; import infra.remoting.error.InvalidSetupException; @@ -412,11 +412,10 @@ wrappedConnection, rejectedSetupError(err))) ? new ResponderLeaseTracker(SERVER_TAG, clientConnection, leases.sender) : null; - Channel channelResponder = new ResponderChannel(clientConnection, wrappedChannelHandler, payloadDecoder, responderLeaseTracker, - mtu, maxFrameLength, maxInboundPayloadSize, - leaseEnabled && leases.sender instanceof TrackingLeaseSender - ? channel -> interceptors.initResponderRequestInterceptor(channel, (TrackingLeaseSender) leases.sender) - : interceptors::initResponderRequestInterceptor, responderOnAllClosedSink); + new ResponderChannel(clientConnection, wrappedChannelHandler, payloadDecoder, responderLeaseTracker, + mtu, maxFrameLength, maxInboundPayloadSize, leaseEnabled && leases.sender instanceof TrackingLeaseSender + ? channel -> interceptors.initResponderRequestInterceptor(channel, (TrackingLeaseSender) leases.sender) + : interceptors::initResponderRequestInterceptor, responderOnAllClosedSink); }) .doFinally(signalType -> setupPayload.release()) .then(); diff --git a/today-remoting/src/main/java/infra/remoting/core/RequestChannelRequesterFlux.java b/today-remoting/src/main/java/infra/remoting/core/RequestChannelRequesterFlux.java index a20cb96..8735192 100644 --- a/today-remoting/src/main/java/infra/remoting/core/RequestChannelRequesterFlux.java +++ b/today-remoting/src/main/java/infra/remoting/core/RequestChannelRequesterFlux.java @@ -24,7 +24,6 @@ import java.util.concurrent.CancellationException; import java.util.concurrent.atomic.AtomicLongFieldUpdater; -import infra.lang.NonNull; import infra.lang.Nullable; import infra.remoting.Connection; import infra.remoting.Payload; @@ -795,7 +794,6 @@ public void handleNext(ByteBuf frame, boolean hasFollows, boolean isLastPayload) } @Override - @NonNull public Context currentContext() { long state = this.state; @@ -837,7 +835,6 @@ public Object scanUnsafe(Attr key) { } @Override - @NonNull public String stepName() { return "source(RequestChannelFlux)"; } diff --git a/today-remoting/src/main/java/infra/remoting/core/RequestResponseRequesterMono.java b/today-remoting/src/main/java/infra/remoting/core/RequestResponseRequesterMono.java index 1c2a6dd..673d874 100644 --- a/today-remoting/src/main/java/infra/remoting/core/RequestResponseRequesterMono.java +++ b/today-remoting/src/main/java/infra/remoting/core/RequestResponseRequesterMono.java @@ -20,7 +20,6 @@ import java.util.concurrent.atomic.AtomicLongFieldUpdater; -import infra.lang.NonNull; import infra.lang.Nullable; import infra.remoting.Connection; import infra.remoting.Payload; @@ -395,7 +394,6 @@ public Object scanUnsafe(Attr key) { } @Override - @NonNull public String stepName() { return "source(RequestResponseMono)"; } diff --git a/today-remoting/src/main/java/infra/remoting/core/RequestStreamRequesterFlux.java b/today-remoting/src/main/java/infra/remoting/core/RequestStreamRequesterFlux.java index 430f993..a195d17 100644 --- a/today-remoting/src/main/java/infra/remoting/core/RequestStreamRequesterFlux.java +++ b/today-remoting/src/main/java/infra/remoting/core/RequestStreamRequesterFlux.java @@ -20,7 +20,6 @@ import java.util.concurrent.atomic.AtomicLongFieldUpdater; -import infra.lang.NonNull; import infra.lang.Nullable; import infra.remoting.Connection; import infra.remoting.Payload; @@ -449,7 +448,6 @@ public Object scanUnsafe(Attr key) { } @Override - @NonNull public String stepName() { return "source(RequestStreamFlux)"; } diff --git a/today-remoting/src/main/java/infra/remoting/core/SlowFireAndForgetRequesterMono.java b/today-remoting/src/main/java/infra/remoting/core/SlowFireAndForgetRequesterMono.java index 015a4dc..0663c49 100644 --- a/today-remoting/src/main/java/infra/remoting/core/SlowFireAndForgetRequesterMono.java +++ b/today-remoting/src/main/java/infra/remoting/core/SlowFireAndForgetRequesterMono.java @@ -20,7 +20,6 @@ import java.util.concurrent.atomic.AtomicLongFieldUpdater; -import infra.lang.NonNull; import infra.lang.Nullable; import infra.remoting.Payload; import infra.remoting.frame.FrameType; @@ -242,7 +241,6 @@ public Object scanUnsafe(Attr key) { } @Override - @NonNull public String stepName() { return "source(FireAndForgetMono)"; } diff --git a/today-remoting/src/test/java/infra/remoting/core/ChannelConnectorTests.java b/today-remoting/src/test/java/infra/remoting/core/ChannelConnectorTests.java index 60577e9..3d12809 100644 --- a/today-remoting/src/test/java/infra/remoting/core/ChannelConnectorTests.java +++ b/today-remoting/src/test/java/infra/remoting/core/ChannelConnectorTests.java @@ -118,7 +118,7 @@ public void ensuresThatSetupPayloadCanBeRetained() { ChannelConnector.create() .setupPayload(ByteBufPayload.create(data)) - .acceptor((setup, sendingSocket) -> { + .acceptor((setup, channel) -> { retainedSetupPayload.set(setup.retain()); return Mono.just(new Channel() { }); }) diff --git a/today-remoting/src/test/java/infra/remoting/core/RemotingServerTests.java b/today-remoting/src/test/java/infra/remoting/core/RemotingServerTests.java index 33df2d3..2b7ed0c 100644 --- a/today-remoting/src/test/java/infra/remoting/core/RemotingServerTests.java +++ b/today-remoting/src/test/java/infra/remoting/core/RemotingServerTests.java @@ -141,7 +141,7 @@ public void unexpectedFramesBeforeSetup() { Closeable server = RemotingServer.create() .acceptor( - (setup, sendingSocket) -> { + (setup, channel) -> { connectedSink.tryEmitEmpty(); return Mono.just(new Channel() { }); }) @@ -176,7 +176,7 @@ public void unexpectedFramesBeforeSetup() { public void ensuresErrorFrameDeliveredPriorConnectionDisposal() { TestServerTransport transport = new TestServerTransport(); Closeable server = RemotingServer.create() - .acceptor((setup, sendingSocket) -> Mono.error(new RejectedSetupException("ACCESS_DENIED"))) + .acceptor((setup, channel) -> Mono.error(new RejectedSetupException("ACCESS_DENIED"))) .bind(transport) .block(); diff --git a/today-remoting/src/test/java/infra/remoting/core/ResponderChannelTests.java b/today-remoting/src/test/java/infra/remoting/core/ResponderChannelTests.java index 5e8645e..5f73ccc 100644 --- a/today-remoting/src/test/java/infra/remoting/core/ResponderChannelTests.java +++ b/today-remoting/src/test/java/infra/remoting/core/ResponderChannelTests.java @@ -141,7 +141,7 @@ public void testHandleResponseFrameNoError() { final int streamId = 4; rule.connection.clearSendReceiveBuffers(); final TestPublisher testPublisher = TestPublisher.create(); - rule.setAcceptingSocket( + rule.setAcceptingChannel( new Channel() { @Override public Mono requestResponse(Payload payload) { @@ -172,7 +172,7 @@ public void testCancel() { ByteBufAllocator allocator = rule.alloc(); final int streamId = 4; final AtomicBoolean cancelled = new AtomicBoolean(); - rule.setAcceptingSocket( + rule.setAcceptingChannel( new Channel() { @Override public Mono requestResponse(Payload payload) { @@ -232,7 +232,7 @@ protected void hookOnSubscribe(Subscription subscription) { return Flux.just(payload).doOnCancel(() -> cancelled.set(true)); } }; - rule.setAcceptingSocket(acceptingSocket); + rule.setAcceptingChannel(acceptingSocket); final Runnable[] runnables = { () -> rule.sendRequest(streamId, FrameType.REQUEST_RESPONSE), @@ -268,7 +268,7 @@ public void checkNoLeaksOnRacingCancelFromRequestChannelAndNextFromUpstream() { AssertSubscriber assertSubscriber = AssertSubscriber.create(); final Sinks.One sink = Sinks.one(); - rule.setAcceptingSocket( + rule.setAcceptingChannel( new Channel() { @Override public Flux requestChannel(Publisher payloads) { @@ -328,7 +328,7 @@ public void checkNoLeaksOnRacingBetweenDownstreamCancelAndOnNextFromRequestChann FluxSink[] sinks = new FluxSink[1]; - rule.setAcceptingSocket( + rule.setAcceptingChannel( new Channel() { @Override public Flux requestChannel(Publisher payloads) { @@ -371,7 +371,7 @@ public void checkNoLeaksOnRacingBetweenDownstreamCancelAndOnNextFromRequestChann FluxSink[] sinks = new FluxSink[1]; - rule.setAcceptingSocket( + rule.setAcceptingChannel( new Channel() { @Override public Flux requestChannel(Publisher payloads) { @@ -414,7 +414,7 @@ public Flux requestChannel(Publisher payloads) { for (int i = 0; i < RaceTestConstants.REPEATS; i++) { FluxSink[] sinks = new FluxSink[1]; AssertSubscriber assertSubscriber = AssertSubscriber.create(); - rule.setAcceptingSocket( + rule.setAcceptingChannel( new Channel() { @Override public Flux requestChannel(Publisher payloads) { @@ -509,7 +509,7 @@ public void checkNoLeaksOnRacingBetweenDownstreamCancelAndOnNextFromRequestStrea for (int i = 0; i < RaceTestConstants.REPEATS; i++) { FluxSink[] sinks = new FluxSink[1]; - rule.setAcceptingSocket( + rule.setAcceptingChannel( new Channel() { @Override public Flux requestStream(Payload payload) { @@ -548,7 +548,7 @@ public void checkNoLeaksOnRacingBetweenDownstreamCancelAndOnNextFromRequestRespo for (int i = 0; i < RaceTestConstants.REPEATS; i++) { Operators.MonoSubscriber[] sources = new Operators.MonoSubscriber[1]; - rule.setAcceptingSocket( + rule.setAcceptingChannel( new Channel() { @Override public Mono requestResponse(Payload payload) { @@ -594,7 +594,7 @@ public void simpleDiscardRequestStreamTest() { ByteBufAllocator allocator = rule.alloc(); FluxSink[] sinks = new FluxSink[1]; - rule.setAcceptingSocket( + rule.setAcceptingChannel( new Channel() { @Override public Flux requestStream(Payload payload) { @@ -623,7 +623,7 @@ public Flux requestStream(Payload payload) { public void simpleDiscardRequestChannelTest() { ByteBufAllocator allocator = rule.alloc(); - rule.setAcceptingSocket( + rule.setAcceptingChannel( new Channel() { @Override public Flux requestChannel(Publisher payloads) { @@ -673,7 +673,7 @@ public void verifiesThatFrameWithNoMetadataHasDecodedCorrectlyIntoPayload( AssertSubscriber assertSubscriber = AssertSubscriber.create(framesCnt); TestPublisher testPublisher = TestPublisher.create(); - rule.setAcceptingSocket( + rule.setAcceptingChannel( new Channel() { @Override public Mono fireAndForget(Payload payload) { @@ -768,7 +768,7 @@ static Stream encodeDecodePayloadCases() { @ParameterizedTest @MethodSource("refCntCases") public void ensureSendsErrorOnIllegalRefCntPayload(FrameType frameType) { - rule.setAcceptingSocket( + rule.setAcceptingChannel( new Channel() { @Override public Mono requestResponse(Payload payload) { @@ -818,7 +818,7 @@ public void testWorkaround858() { TestPublisher testPublisher = TestPublisher.create(); - rule.setAcceptingSocket( + rule.setAcceptingChannel( new Channel() { @Override public Flux requestChannel(Publisher payloads) { @@ -855,7 +855,7 @@ static Stream requestCases() { @MethodSource("requestCases") void reassemblePayload(FrameType frameType) { AtomicReference receivedPayload = new AtomicReference<>(); - rule.setAcceptingSocket( + rule.setAcceptingChannel( new Channel() { @Override public Mono fireAndForget(Payload payload) { @@ -910,7 +910,7 @@ public Flux requestChannel(Publisher payloads) { @MethodSource("requestCases") void reassembleMetadataOnly(FrameType frameType) { AtomicReference receivedPayload = new AtomicReference<>(); - rule.setAcceptingSocket( + rule.setAcceptingChannel( new Channel() { @Override public Mono fireAndForget(Payload payload) { @@ -970,7 +970,7 @@ public void errorTooBigPayload(FrameType frameType) { final int maxInboundPayloadSize = ThreadLocalRandom.current().nextInt(mtu + 1, 4096); AtomicReference receivedPayload = new AtomicReference<>(); rule.setMaxInboundPayloadSize(maxInboundPayloadSize); - rule.setAcceptingSocket( + rule.setAcceptingChannel( new Channel() { @Override public Mono fireAndForget(Payload payload) { @@ -1021,7 +1021,7 @@ public Flux requestChannel(Publisher payloads) { public void errorFragmentTooSmall(FrameType frameType) { final int mtu = 32; AtomicReference receivedPayload = new AtomicReference<>(); - rule.setAcceptingSocket( + rule.setAcceptingChannel( new Channel() { @Override public Mono fireAndForget(Payload payload) { @@ -1071,7 +1071,7 @@ void receivingRequestOnStreamIdThaIsAlreadyInUseMUSTBeIgnored_ReassemblyCase( FrameType requestType) { AtomicReference receivedPayload = new AtomicReference<>(); final Sinks.Empty delayer = Sinks.empty(); - rule.setAcceptingSocket( + rule.setAcceptingChannel( new Channel() { @Override @@ -1141,7 +1141,7 @@ void receivingRequestOnStreamIdThaIsAlreadyInUseMUSTBeIgnored(FrameType requestT Assumptions.assumeThat(requestType).isNotEqualTo(REQUEST_FNF); AtomicReference receivedPayload = new AtomicReference<>(); final Sinks.One delayer = Sinks.one(); - rule.setAcceptingSocket( + rule.setAcceptingChannel( new Channel() { @Override public Mono requestResponse(Payload payload) { @@ -1184,14 +1184,14 @@ public Flux requestChannel(Publisher payloads) { public static class ServerChannelRule extends AbstractChannelRule { - private Channel acceptingSocket; + private Channel acceptingChannel; private volatile int prefetch; private RequestInterceptor requestInterceptor; protected Sinks.Empty onCloseSink; @Override protected void doInit() { - acceptingSocket = + acceptingChannel = new Channel() { @Override public Mono requestResponse(Payload payload) { @@ -1201,8 +1201,8 @@ public Mono requestResponse(Payload payload) { super.doInit(); } - public void setAcceptingSocket(Channel acceptingSocket) { - this.acceptingSocket = acceptingSocket; + public void setAcceptingChannel(Channel acceptingSocket) { + this.acceptingChannel = acceptingSocket; connection = new TestConnection(alloc()); connectSub = TestSubscriber.create(); this.prefetch = Integer.MAX_VALUE; @@ -1214,8 +1214,8 @@ public void setRequestInterceptor(RequestInterceptor requestInterceptor) { super.doInit(); } - public void setAcceptingSocket(Channel acceptingSocket, int prefetch) { - this.acceptingSocket = acceptingSocket; + public void setAcceptingChannel(Channel channel, int prefetch) { + this.acceptingChannel = channel; connection = new TestConnection(alloc()); connectSub = TestSubscriber.create(); this.prefetch = prefetch; @@ -1227,7 +1227,7 @@ protected ResponderChannel newChannel() { onCloseSink = Sinks.empty(); return new ResponderChannel( connection, - acceptingSocket, + acceptingChannel, PayloadDecoder.ZERO_COPY, null, 0, diff --git a/today-remoting/src/test/java/infra/remoting/examples/tcp/fnf/TaskProcessingWithServerSideNotificationsExample.java b/today-remoting/src/test/java/infra/remoting/examples/tcp/fnf/TaskProcessingWithServerSideNotificationsExample.java index ba8698e..8fb1ffa 100644 --- a/today-remoting/src/test/java/infra/remoting/examples/tcp/fnf/TaskProcessingWithServerSideNotificationsExample.java +++ b/today-remoting/src/test/java/infra/remoting/examples/tcp/fnf/TaskProcessingWithServerSideNotificationsExample.java @@ -205,9 +205,9 @@ public ChannelTaskHandler( ConcurrentMap idToChannelMap, Sinks.Many tasksToProcess, String id, - Channel sendingSocket) { + Channel channel) { this.id = id; - this.channel = sendingSocket; + this.channel = channel; this.idToChannelMap = idToChannelMap; this.tasksToProcess = tasksToProcess; } diff --git a/today-remoting/src/test/java/infra/remoting/examples/tcp/lease/advanced/common/LimitBasedLeaseSender.java b/today-remoting/src/test/java/infra/remoting/examples/tcp/lease/advanced/common/LimitBasedLeaseSender.java index 3c5a3f4..2b6fa27 100644 --- a/today-remoting/src/test/java/infra/remoting/examples/tcp/lease/advanced/common/LimitBasedLeaseSender.java +++ b/today-remoting/src/test/java/infra/remoting/examples/tcp/lease/advanced/common/LimitBasedLeaseSender.java @@ -19,11 +19,10 @@ import com.netflix.concurrency.limits.Limit; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import java.time.Duration; +import infra.logging.Logger; +import infra.logging.LoggerFactory; import infra.remoting.lease.Lease; import infra.remoting.lease.TrackingLeaseSender; import reactor.core.publisher.Flux; @@ -46,7 +45,7 @@ public LimitBasedLeaseSender( @Override public Flux send() { - logger.info("Received new leased Connection[" + connectionId + "]"); + logger.info("Received new leased Connection[{}]", connectionId); leaseManager.register(this); diff --git a/today-remoting/src/test/java/infra/remoting/examples/tcp/lease/simple/LeaseExample.java b/today-remoting/src/test/java/infra/remoting/examples/tcp/lease/simple/LeaseExample.java index 575c6d0..7e2dd45 100644 --- a/today-remoting/src/test/java/infra/remoting/examples/tcp/lease/simple/LeaseExample.java +++ b/today-remoting/src/test/java/infra/remoting/examples/tcp/lease/simple/LeaseExample.java @@ -69,7 +69,7 @@ public static void main(String[] args) { workerThread.start(); - CloseableChannel server = RemotingServer.create((setup, sendingSocket) -> + CloseableChannel server = RemotingServer.create((setup, channel) -> Mono.just(new Channel() { @Override public Mono fireAndForget(Payload payload) { @@ -79,7 +79,7 @@ public Mono fireAndForget(Payload payload) { try { if (!messagesQueue.offer(payload.getDataUtf8())) { logger.error("Queue has been overflowed. Terminating execution"); - sendingSocket.dispose(); + channel.dispose(); workerThread.interrupt(); } } diff --git a/today-remoting/src/test/java/infra/remoting/internal/subscriber/AssertSubscriber.java b/today-remoting/src/test/java/infra/remoting/internal/subscriber/AssertSubscriber.java index baceb24..608ec80 100644 --- a/today-remoting/src/test/java/infra/remoting/internal/subscriber/AssertSubscriber.java +++ b/today-remoting/src/test/java/infra/remoting/internal/subscriber/AssertSubscriber.java @@ -38,7 +38,6 @@ import java.util.function.Consumer; import java.util.function.Supplier; -import infra.lang.NonNull; import reactor.core.CoreSubscriber; import reactor.core.Fuseable; import reactor.core.Scannable; @@ -1082,7 +1081,6 @@ public void request(long n) { } @Override - @NonNull public Context currentContext() { return context; } diff --git a/today-remoting/src/test/java/infra/remoting/test/util/TestConnection.java b/today-remoting/src/test/java/infra/remoting/test/util/TestConnection.java index 80593b5..e1ccb05 100644 --- a/today-remoting/src/test/java/infra/remoting/test/util/TestConnection.java +++ b/today-remoting/src/test/java/infra/remoting/test/util/TestConnection.java @@ -24,7 +24,6 @@ import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; -import infra.lang.NonNull; import infra.logging.Logger; import infra.logging.LoggerFactory; import infra.remoting.Connection; @@ -155,7 +154,6 @@ public boolean isEmpty() { return sent.isEmpty(); } - @NonNull public ByteBuf awaitFrame() { try { return sent.take(); diff --git a/today-remoting/src/testFixtures/java/infra/remoting/test/TransportPair.java b/today-remoting/src/testFixtures/java/infra/remoting/test/TransportPair.java index fd10343..4a1b47e 100644 --- a/today-remoting/src/testFixtures/java/infra/remoting/test/TransportPair.java +++ b/today-remoting/src/testFixtures/java/infra/remoting/test/TransportPair.java @@ -127,7 +127,7 @@ public TransportPair(Supplier addressSupplier, if (runServerWithAsyncInterceptors && !withResumability) { logger.info("Perform Integration Test with Async Interceptors Enabled For Server"); registry.forConnection((type, duplexConnection) -> new AsyncConnection(duplexConnection, "server")) - .forChannelAcceptor(delegate -> (connectionSetupPayload, sendingSocket) -> delegate.accept(connectionSetupPayload, sendingSocket) + .forChannelAcceptor(delegate -> (connectionSetupPayload, channel) -> delegate.accept(connectionSetupPayload, channel) .subscribeOn(Schedulers.parallel())); } @@ -163,8 +163,8 @@ public TransportPair(Supplier addressSupplier, logger.info("Perform Integration Test with Async Interceptors Enabled For Client"); registry.forConnection((type, duplexConnection) -> new AsyncConnection(duplexConnection, "client")) - .forChannelAcceptor(delegate -> (connectionSetupPayload, sendingSocket) -> - delegate.accept(connectionSetupPayload, sendingSocket) + .forChannelAcceptor(delegate -> (connectionSetupPayload, channel) -> + delegate.accept(connectionSetupPayload, channel) .subscribeOn(Schedulers.parallel())); } From 29210a55c78760ffceeb1850440b5e0eb993a74e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Mon, 11 Aug 2025 21:19:34 +0800 Subject: [PATCH 037/104] :art: --- .../demo/service/UserServiceApplication.java | 2 - today-service-api/build.gradle | 1 + .../cloud/service/MethodIdGenerator.java | 75 +++++++++++++++++++ .../infra/cloud/service/ServiceMetadata.java | 10 +-- .../infra/cloud/service/ServiceMethod.java | 4 + .../cloud/service/MethodIdGeneratorTests.java | 42 +++++++++++ .../DefaultRemotingOperationsProvider.java | 8 +- .../service/MethodServiceInvocation.java | 6 +- .../service/RemotingOperationsProvider.java | 2 +- .../cloud/service/ServiceInvocation.java | 5 +- .../cloud/service/ServiceMethodInvoker.java | 2 +- ...ServiceInterfaceMetadataProviderTests.java | 2 +- 12 files changed, 141 insertions(+), 18 deletions(-) create mode 100644 today-service-api/src/main/java/infra/cloud/service/MethodIdGenerator.java create mode 100644 today-service-api/src/test/java/infra/cloud/service/MethodIdGeneratorTests.java diff --git a/today-cloud-samples/demo-tests/demo-user-service/src/main/java/cn/taketoday/demo/service/UserServiceApplication.java b/today-cloud-samples/demo-tests/demo-user-service/src/main/java/cn/taketoday/demo/service/UserServiceApplication.java index ab9c21d..879eed9 100644 --- a/today-cloud-samples/demo-tests/demo-user-service/src/main/java/cn/taketoday/demo/service/UserServiceApplication.java +++ b/today-cloud-samples/demo-tests/demo-user-service/src/main/java/cn/taketoday/demo/service/UserServiceApplication.java @@ -20,14 +20,12 @@ import infra.app.ApplicationType; import infra.app.InfraApplication; import infra.app.builder.ApplicationBuilder; -import infra.cloud.provider.EnableServiceProvider; /** * @author Harry Yang * @since 1.0 2022/10/18 00:04 */ @InfraApplication -@EnableServiceProvider public class UserServiceApplication { public static void main(String[] args) { diff --git a/today-service-api/build.gradle b/today-service-api/build.gradle index d8fa751..20694b9 100644 --- a/today-service-api/build.gradle +++ b/today-service-api/build.gradle @@ -13,4 +13,5 @@ dependencies { optional "com.google.protobuf:protobuf-java" + testImplementation project(":today-cloud-samples:demo-tests:demo-user-api") } \ No newline at end of file diff --git a/today-service-api/src/main/java/infra/cloud/service/MethodIdGenerator.java b/today-service-api/src/main/java/infra/cloud/service/MethodIdGenerator.java new file mode 100644 index 0000000..974e926 --- /dev/null +++ b/today-service-api/src/main/java/infra/cloud/service/MethodIdGenerator.java @@ -0,0 +1,75 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.service; + +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +public class MethodIdGenerator { + + public static Map generateMethodIds(Set> serviceInterfaces) { + List allMethods = new ArrayList<>(); + for (Class serviceInterface : serviceInterfaces) { + collectMethods(serviceInterface, allMethods); + } + + allMethods.sort((m1, m2) -> { + int cmp = m1.getDeclaringClass().getName().compareTo(m2.getDeclaringClass().getName()); + if (cmp != 0) + return cmp; + + cmp = m1.getName().compareTo(m2.getName()); + if (cmp != 0) + return cmp; + + Class[] params1 = m1.getParameterTypes(); + Class[] params2 = m2.getParameterTypes(); + cmp = Integer.compare(params1.length, params2.length); + if (cmp != 0) + return cmp; + + for (int i = 0; i < params1.length; i++) { + cmp = params1[i].getName().compareTo(params2[i].getName()); + if (cmp != 0) + return cmp; + } + return 0; + }); + + Map methodIds = new HashMap<>(); + int id = 1; + for (Method method : allMethods) { + methodIds.put(method, id++); + } + return methodIds; + } + + private static void collectMethods(Class interfaceClass, List methods) { + methods.addAll(Arrays.asList(interfaceClass.getDeclaredMethods())); + + for (Class parent : interfaceClass.getInterfaces()) { + collectMethods(parent, methods); + } + } + +} \ No newline at end of file diff --git a/today-service-api/src/main/java/infra/cloud/service/ServiceMetadata.java b/today-service-api/src/main/java/infra/cloud/service/ServiceMetadata.java index e3b27e3..a179f74 100644 --- a/today-service-api/src/main/java/infra/cloud/service/ServiceMetadata.java +++ b/today-service-api/src/main/java/infra/cloud/service/ServiceMetadata.java @@ -23,17 +23,17 @@ */ public class ServiceMetadata { - private final String name; + private final String id; private final String version; - public ServiceMetadata(String name, String version) { - this.name = name; + public ServiceMetadata(String id, String version) { + this.id = id; this.version = version; } - public String getName() { - return name; + public String getId() { + return id; } public String getVersion() { diff --git a/today-service-api/src/main/java/infra/cloud/service/ServiceMethod.java b/today-service-api/src/main/java/infra/cloud/service/ServiceMethod.java index f90aaa4..21b17cc 100644 --- a/today-service-api/src/main/java/infra/cloud/service/ServiceMethod.java +++ b/today-service-api/src/main/java/infra/cloud/service/ServiceMethod.java @@ -37,6 +37,10 @@ public ServiceMethod(ServiceMetadata serviceMetadata, Class serviceInterface, this.method = method; } + public String getServiceId() { + return serviceMetadata.getId(); + } + public ServiceMetadata getServiceMetadata() { return serviceMetadata; } diff --git a/today-service-api/src/test/java/infra/cloud/service/MethodIdGeneratorTests.java b/today-service-api/src/test/java/infra/cloud/service/MethodIdGeneratorTests.java new file mode 100644 index 0000000..aee4cab --- /dev/null +++ b/today-service-api/src/test/java/infra/cloud/service/MethodIdGeneratorTests.java @@ -0,0 +1,42 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.service; + +import org.junit.jupiter.api.Test; + +import java.lang.reflect.Method; +import java.util.Map; +import java.util.Set; + +import cn.taketoday.demo.service.UserService; + +/** + * @author 海子 Yang + * @since 1.0 2025/8/11 15:20 + */ +class MethodIdGeneratorTests { + + @Test + void test() { + Map methodIntegerMap = MethodIdGenerator.generateMethodIds(Set.of(UserService.class)); + methodIntegerMap.forEach((key, value) -> { + System.out.println(value + " -> " + key); + }); + } + +} \ No newline at end of file diff --git a/today-service-client/src/main/java/infra/cloud/service/DefaultRemotingOperationsProvider.java b/today-service-client/src/main/java/infra/cloud/service/DefaultRemotingOperationsProvider.java index 2a1c753..ef2b62a 100644 --- a/today-service-client/src/main/java/infra/cloud/service/DefaultRemotingOperationsProvider.java +++ b/today-service-client/src/main/java/infra/cloud/service/DefaultRemotingOperationsProvider.java @@ -55,8 +55,12 @@ public void setDiscoveryPeriod(Duration discoveryPeriod) { } @Override - public RemotingOperations getRemotingOperations(String serviceName) { - return remotingClientMap.computeIfAbsent(serviceName, name -> RemotingClient.forLoadBalance(Flux.interval(discoveryPeriod) + public RemotingOperations getRemotingOperations(ServiceMethod serviceMethod) { + return getRemotingOperations(serviceMethod.getServiceId()); + } + + public RemotingOperations getRemotingOperations(String serviceId) { + return remotingClientMap.computeIfAbsent(serviceId, name -> RemotingClient.forLoadBalance(Flux.interval(discoveryPeriod) .map(i -> discoveryClient.getInstances(name)) .map(this)) .roundRobinLoadBalanceStrategy() diff --git a/today-service-client/src/main/java/infra/cloud/service/MethodServiceInvocation.java b/today-service-client/src/main/java/infra/cloud/service/MethodServiceInvocation.java index a9d5972..faa7ae4 100644 --- a/today-service-client/src/main/java/infra/cloud/service/MethodServiceInvocation.java +++ b/today-service-client/src/main/java/infra/cloud/service/MethodServiceInvocation.java @@ -54,7 +54,7 @@ public InvocationResult proceed() throws Throwable { protected abstract InvocationResult invokeRemoting(Object[] args); @Override - public ServiceInterfaceMethod getMethod() { + public ServiceInterfaceMethod getServiceMethod() { return serviceMethod; } @@ -64,8 +64,8 @@ public ServiceMetadata getServiceMetadata() { } @Override - public String getServiceName() { - return serviceMethod.serviceMetadata.getName(); + public String getServiceId() { + return serviceMethod.getServiceId(); } @Override diff --git a/today-service-client/src/main/java/infra/cloud/service/RemotingOperationsProvider.java b/today-service-client/src/main/java/infra/cloud/service/RemotingOperationsProvider.java index 3d86281..330362d 100644 --- a/today-service-client/src/main/java/infra/cloud/service/RemotingOperationsProvider.java +++ b/today-service-client/src/main/java/infra/cloud/service/RemotingOperationsProvider.java @@ -25,6 +25,6 @@ */ public interface RemotingOperationsProvider { - RemotingOperations getRemotingOperations(String serviceName); + RemotingOperations getRemotingOperations(ServiceMethod serviceMethod); } diff --git a/today-service-client/src/main/java/infra/cloud/service/ServiceInvocation.java b/today-service-client/src/main/java/infra/cloud/service/ServiceInvocation.java index b76b42f..13e9397 100644 --- a/today-service-client/src/main/java/infra/cloud/service/ServiceInvocation.java +++ b/today-service-client/src/main/java/infra/cloud/service/ServiceInvocation.java @@ -37,9 +37,8 @@ public interface ServiceInvocation extends AttributeAccessor { /** * Service name - * */ - String getServiceName(); + String getServiceId(); /** * Service metadata @@ -49,7 +48,7 @@ public interface ServiceInvocation extends AttributeAccessor { /** * service method metadata */ - ServiceInterfaceMethod getMethod(); + ServiceInterfaceMethod getServiceMethod(); /** * Get the arguments as an array object. It is possible to change element values diff --git a/today-service-client/src/main/java/infra/cloud/service/ServiceMethodInvoker.java b/today-service-client/src/main/java/infra/cloud/service/ServiceMethodInvoker.java index 148f900..c1efc23 100644 --- a/today-service-client/src/main/java/infra/cloud/service/ServiceMethodInvoker.java +++ b/today-service-client/src/main/java/infra/cloud/service/ServiceMethodInvoker.java @@ -62,7 +62,7 @@ public MethodServiceInvocation0(ServiceInterfaceMethod serviceMethod, Object[] a @Override protected InvocationResult invokeRemoting(Object[] args) { - RemotingOperations operations = remotingOperationsProvider.getRemotingOperations(getServiceName()); + RemotingOperations operations = remotingOperationsProvider.getRemotingOperations(getServiceMethod()); Publisher publisher = switch (getType()) { case FIRE_AND_FORGET -> operations.fireAndForget(createMonoPayload(args)).cast(Payload.class); diff --git a/today-service-client/src/test/java/infra/cloud/service/DefaultServiceInterfaceMetadataProviderTests.java b/today-service-client/src/test/java/infra/cloud/service/DefaultServiceInterfaceMetadataProviderTests.java index b9dfc05..2164968 100644 --- a/today-service-client/src/test/java/infra/cloud/service/DefaultServiceInterfaceMetadataProviderTests.java +++ b/today-service-client/src/test/java/infra/cloud/service/DefaultServiceInterfaceMetadataProviderTests.java @@ -49,7 +49,7 @@ void getMetadata() { List serviceMethods = metadata.getServiceMethods(); assertThat(metadata.getServiceMetadata().getVersion()).isEqualTo("1.0"); - assertThat(metadata.getServiceMetadata().getName()).isEqualTo("demo-user-service"); + assertThat(metadata.getServiceMetadata().getId()).isEqualTo("demo-user-service"); assertThat(metadata.getServiceInterface()).isEqualTo(DemoUserService.class); assertThat(serviceMethods).hasSize(4); From e5333741216451d2ca0d75bea764eb69b0850921 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Mon, 11 Aug 2025 21:19:42 +0800 Subject: [PATCH 038/104] :art: ServiceInstance#getInstanceId --- .../src/main/java/infra/cloud/client/ServiceInstance.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/today-cloud-core/src/main/java/infra/cloud/client/ServiceInstance.java b/today-cloud-core/src/main/java/infra/cloud/client/ServiceInstance.java index 124b9f5..61ca598 100644 --- a/today-cloud-core/src/main/java/infra/cloud/client/ServiceInstance.java +++ b/today-cloud-core/src/main/java/infra/cloud/client/ServiceInstance.java @@ -32,7 +32,7 @@ public interface ServiceInstance { * @return The unique instance ID as registered. */ default String getInstanceId() { - return getHost() + ":" + getPort(); + return getHost() + ":" + getPort() + ":" + getServiceId(); } /** From ccf8e3e479ca1ab7c6956ba7b4d11b113c4db6e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Mon, 11 Aug 2025 21:30:41 +0800 Subject: [PATCH 039/104] =?UTF-8?q?:recycle:=20=E9=80=9A=E8=AE=AF=E5=B1=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../websocket/SetupRejectionTests.java | 2 +- .../src/main/java/infra/remoting/Channel.java | 68 ++++++++++++- .../java/infra/remoting/ChannelAcceptor.java | 4 +- .../java/infra/remoting/ChannelHandler.java | 96 ------------------- .../infra/remoting/core/RemotingServer.java | 3 +- .../infra/remoting/core/RequesterChannel.java | 2 +- .../java/infra/remoting/lb/ChannelPool.java | 88 ++++++++--------- .../java/infra/remoting/lb/PooledChannel.java | 28 +++--- .../plugins/ChannelAcceptorDecorator.java | 2 +- .../remoting/plugins/ChannelDecorator.java | 3 + .../remoting/plugins/RateLimitDecorator.java | 4 +- .../tcp/channel/ChannelEchoClient.java | 6 +- .../plugins/LimitRateInterceptorExample.java | 8 +- .../tcp/requestresponse/HelloWorldClient.java | 6 +- .../tcp/stream/ClientStreamingToServer.java | 6 +- 15 files changed, 149 insertions(+), 177 deletions(-) delete mode 100644 today-remoting/src/main/java/infra/remoting/ChannelHandler.java diff --git a/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/SetupRejectionTests.java b/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/SetupRejectionTests.java index db7af51..972f52a 100644 --- a/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/SetupRejectionTests.java +++ b/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/SetupRejectionTests.java @@ -76,7 +76,7 @@ void rejectSetupTcp( StepVerifier.create(clientRequester.onClose()).expectComplete().verify(Duration.ofSeconds(5)); - StepVerifier.create(serverRequester.flatMap(socket -> socket.onClose())) + StepVerifier.create(serverRequester.flatMap(Channel::onClose)) .expectComplete() .verify(Duration.ofSeconds(5)); diff --git a/today-remoting/src/main/java/infra/remoting/Channel.java b/today-remoting/src/main/java/infra/remoting/Channel.java index 6cd33ba..583c54b 100644 --- a/today-remoting/src/main/java/infra/remoting/Channel.java +++ b/today-remoting/src/main/java/infra/remoting/Channel.java @@ -17,17 +17,83 @@ package infra.remoting; +import org.reactivestreams.Publisher; + +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + /** * A contract providing different interaction models for protocol. * * @author 海子 Yang */ -public interface Channel extends Availability, ChannelHandler { +public interface Channel extends Availability, Closeable { + + /** + * Fire and Forget interaction model of protocol. + * + * @param payload Request payload. + * @return {@code Publisher} that completes when the passed {@code payload} is successfully + * handled, otherwise errors. + */ + default Mono fireAndForget(Payload payload) { + return ChannelAdapter.fireAndForget(payload); + } + + /** + * Request-Response interaction model of protocol. + * + * @param payload Request payload. + * @return {@code Publisher} containing at most a single {@code Payload} representing the + * response. + */ + default Mono requestResponse(Payload payload) { + return ChannelAdapter.requestResponse(payload); + } + + /** + * Request-Stream interaction model of protocol. + * + * @param payload Request payload. + * @return {@code Publisher} containing the stream of {@code Payload}s representing the response. + */ + default Flux requestStream(Payload payload) { + return ChannelAdapter.requestStream(payload); + } + + /** + * Request-Channel interaction model of protocol. + * + * @param payloads Stream of request payloads. + * @return Stream of response payloads. + */ + default Flux requestChannel(Publisher payloads) { + return ChannelAdapter.requestChannel(payloads); + } + + /** + * Metadata-Push interaction model of protocol. + * + * @param payload Request payloads. + * @return {@code Publisher} that completes when the passed {@code payload} is successfully + * handled, otherwise errors. + */ + default Mono metadataPush(Payload payload) { + return ChannelAdapter.metadataPush(payload); + } @Override default double availability() { return isDisposed() ? 0.0 : 1.0; } + @Override + default void dispose() { + } + + @Override + default Mono onClose() { + return Mono.never(); + } } diff --git a/today-remoting/src/main/java/infra/remoting/ChannelAcceptor.java b/today-remoting/src/main/java/infra/remoting/ChannelAcceptor.java index 1e84806..308b4ee 100644 --- a/today-remoting/src/main/java/infra/remoting/ChannelAcceptor.java +++ b/today-remoting/src/main/java/infra/remoting/ChannelAcceptor.java @@ -38,9 +38,9 @@ public interface ChannelAcceptor { * * @param setup the {@code setup} received from a client in a server scenario, or in a client * scenario this is the setup about to be sent to the server. - * @param channel socket for sending requests to the remote peer. + * @param channel channel for sending requests to the remote peer. * @return {@code Channel} to accept requests with. - * @throws SetupException If the acceptor needs to reject the setup of this socket. + * @throws SetupException If the acceptor needs to reject the setup of this channel. */ Mono accept(ConnectionSetupPayload setup, Channel channel); diff --git a/today-remoting/src/main/java/infra/remoting/ChannelHandler.java b/today-remoting/src/main/java/infra/remoting/ChannelHandler.java deleted file mode 100644 index e2d4980..0000000 --- a/today-remoting/src/main/java/infra/remoting/ChannelHandler.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright 2021 - 2024 the original author or authors. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] - */ - -package infra.remoting; - -import org.reactivestreams.Publisher; - -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; - -/** - * A contract providing different interaction models for protocol. - * - * @author 海子 Yang - * @since 1.0 2025/8/11 17:51 - */ -public interface ChannelHandler extends Closeable { - - /** - * Fire and Forget interaction model of protocol. - * - * @param payload Request payload. - * @return {@code Publisher} that completes when the passed {@code payload} is successfully - * handled, otherwise errors. - */ - default Mono fireAndForget(Payload payload) { - return ChannelAdapter.fireAndForget(payload); - } - - /** - * Request-Response interaction model of protocol. - * - * @param payload Request payload. - * @return {@code Publisher} containing at most a single {@code Payload} representing the - * response. - */ - default Mono requestResponse(Payload payload) { - return ChannelAdapter.requestResponse(payload); - } - - /** - * Request-Stream interaction model of protocol. - * - * @param payload Request payload. - * @return {@code Publisher} containing the stream of {@code Payload}s representing the response. - */ - default Flux requestStream(Payload payload) { - return ChannelAdapter.requestStream(payload); - } - - /** - * Request-Channel interaction model of protocol. - * - * @param payloads Stream of request payloads. - * @return Stream of response payloads. - */ - default Flux requestChannel(Publisher payloads) { - return ChannelAdapter.requestChannel(payloads); - } - - /** - * Metadata-Push interaction model of protocol. - * - * @param payload Request payloads. - * @return {@code Publisher} that completes when the passed {@code payload} is successfully - * handled, otherwise errors. - */ - default Mono metadataPush(Payload payload) { - return ChannelAdapter.metadataPush(payload); - } - - @Override - default void dispose() { - } - - @Override - default Mono onClose() { - return Mono.never(); - } - -} diff --git a/today-remoting/src/main/java/infra/remoting/core/RemotingServer.java b/today-remoting/src/main/java/infra/remoting/core/RemotingServer.java index 0ed2186..aca5fbc 100644 --- a/today-remoting/src/main/java/infra/remoting/core/RemotingServer.java +++ b/today-remoting/src/main/java/infra/remoting/core/RemotingServer.java @@ -400,8 +400,7 @@ private Mono acceptSetup(ServerSetup serverSetup, ByteBuf setupFrame, Conn return interceptors .decorateAcceptor(acceptor) .accept(setupPayload, wrappedChannelRequester) - .onErrorResume(err -> Mono.fromRunnable(() -> serverSetup.sendError( - wrappedConnection, rejectedSetupError(err))) + .onErrorResume(err -> Mono.fromRunnable(() -> serverSetup.sendError(wrappedConnection, rejectedSetupError(err))) .then(wrappedConnection.onClose()) .then(Mono.error(err))) .doOnNext(channelHandler -> { diff --git a/today-remoting/src/main/java/infra/remoting/core/RequesterChannel.java b/today-remoting/src/main/java/infra/remoting/core/RequesterChannel.java index c0ee76c..540d68d 100644 --- a/today-remoting/src/main/java/infra/remoting/core/RequesterChannel.java +++ b/today-remoting/src/main/java/infra/remoting/core/RequesterChannel.java @@ -230,7 +230,7 @@ private void handleStreamZero(FrameType type, ByteBuf frame) { } break; default: - // Ignore unknown frames. Throwing an error will close the socket. + // Ignore unknown frames. Throwing an error will close the channel. if (LOGGER.isInfoEnabled()) { LOGGER.info("Requester received unsupported frame on stream 0: {}", frame.toString()); } diff --git a/today-remoting/src/main/java/infra/remoting/lb/ChannelPool.java b/today-remoting/src/main/java/infra/remoting/lb/ChannelPool.java index ccff6e1..d87adaf 100644 --- a/today-remoting/src/main/java/infra/remoting/lb/ChannelPool.java +++ b/today-remoting/src/main/java/infra/remoting/lb/ChannelPool.java @@ -81,13 +81,13 @@ public Mono onClose() { protected void doOnDispose() { Operators.terminate(S, this); - Channel[] activeSockets = ACTIVE_CHANNELS.getAndSet(this, TERMINATED); - for (Channel channel : activeSockets) { + Channel[] activeChannels = ACTIVE_CHANNELS.getAndSet(this, TERMINATED); + for (Channel channel : activeChannels) { channel.dispose(); } - if (activeSockets.length > 0) { - Mono.whenDelayError(Arrays.stream(activeSockets).map(Channel::onClose).collect(Collectors.toList())) + if (activeChannels.length > 0) { + Mono.whenDelayError(Arrays.stream(activeChannels).map(Channel::onClose).collect(Collectors.toList())) .subscribe(null, onAllClosedSink::tryEmitError, onAllClosedSink::tryEmitEmpty); } else { @@ -111,9 +111,9 @@ public void onNext(List targets) { // This operation should happen less frequently than calls to select() (which are per request) // and therefore it is acceptable somewhat less efficient. - PooledChannel[] previouslyActiveSockets; - PooledChannel[] inactiveSockets; - PooledChannel[] socketsToUse; + PooledChannel[] previouslyActiveChannels; + PooledChannel[] inactiveChannels; + PooledChannel[] channelsToUse; for (; ; ) { HashMap channelSuppliersCopy = new HashMap<>(targets.size()); @@ -123,32 +123,32 @@ public void onNext(List targets) { } // Intersect current and new list of targets and find the ones to keep vs dispose - previouslyActiveSockets = this.activeChannels; - inactiveSockets = new PooledChannel[previouslyActiveSockets.length]; - PooledChannel[] nextActiveSockets = - new PooledChannel[previouslyActiveSockets.length + channelSuppliersCopy.size()]; - int activeSocketsPosition = 0; - int inactiveSocketsPosition = 0; - for (PooledChannel channel : previouslyActiveSockets) { + previouslyActiveChannels = this.activeChannels; + inactiveChannels = new PooledChannel[previouslyActiveChannels.length]; + PooledChannel[] nextActiveChannels = + new PooledChannel[previouslyActiveChannels.length + channelSuppliersCopy.size()]; + int activeChannelsPosition = 0; + int inactiveChannelsPosition = 0; + for (PooledChannel channel : previouslyActiveChannels) { Integer index = channelSuppliersCopy.remove(channel.target()); if (index == null) { // if one of the active channels is not included, we remove it and put in the // pending removal if (!channel.isDisposed()) { - inactiveSockets[inactiveSocketsPosition++] = channel; + inactiveChannels[inactiveChannelsPosition++] = channel; // TODO: provide a meaningful algo for keeping removed channel in the list - // nextActiveSockets[position++] = channel; + // nextActiveChannels[position++] = channel; } } else { if (!channel.isDisposed()) { // keep old Channel instance - nextActiveSockets[activeSocketsPosition++] = channel; + nextActiveChannels[activeChannelsPosition++] = channel; } else { // put newly create Channel instance LoadBalanceTarget target = targets.get(index); - nextActiveSockets[activeSocketsPosition++] = + nextActiveChannels[activeChannelsPosition++] = new PooledChannel(this, this.connector.connect(target.getTransport()), target); } } @@ -156,32 +156,32 @@ public void onNext(List targets) { // The remainder are the brand new targets for (LoadBalanceTarget target : channelSuppliersCopy.keySet()) { - nextActiveSockets[activeSocketsPosition++] = + nextActiveChannels[activeChannelsPosition++] = new PooledChannel(this, this.connector.connect(target.getTransport()), target); } - if (activeSocketsPosition == 0) { - socketsToUse = EMPTY; + if (activeChannelsPosition == 0) { + channelsToUse = EMPTY; } else { - socketsToUse = Arrays.copyOf(nextActiveSockets, activeSocketsPosition); + channelsToUse = Arrays.copyOf(nextActiveChannels, activeChannelsPosition); } - if (ACTIVE_CHANNELS.compareAndSet(this, previouslyActiveSockets, socketsToUse)) { + if (ACTIVE_CHANNELS.compareAndSet(this, previouslyActiveChannels, channelsToUse)) { break; } } - for (PooledChannel inactiveSocket : inactiveSockets) { - if (inactiveSocket == null) { + for (PooledChannel inactiveChannel : inactiveChannels) { + if (inactiveChannel == null) { break; } - inactiveSocket.dispose(); + inactiveChannel.dispose(); } if (isPending()) { // notifies that upstream is resolved - if (socketsToUse != EMPTY) { + if (channelsToUse != EMPTY) { //noinspection ConstantConditions complete(this); } @@ -217,7 +217,7 @@ public Channel select() { invalidate(); // check since it is possible that between doSelect() and invalidate() we might - // have received new sockets + // have received new channels selected = doSelect(); if (selected != null) { return selected; @@ -231,13 +231,13 @@ public Channel select() { @Nullable public Channel doSelect() { - PooledChannel[] sockets = this.activeChannels; + PooledChannel[] channels = this.activeChannels; - if (sockets == EMPTY || sockets == TERMINATED) { + if (channels == EMPTY || channels == TERMINATED) { return null; } - return this.loadbalanceStrategy.select(WrappingList.wrap(sockets)); + return this.loadbalanceStrategy.select(WrappingList.wrap(channels)); } static class DeferredResolutionChannel implements Channel { @@ -397,50 +397,50 @@ static final class WrappingList implements List { static final ThreadLocal INSTANCE = ThreadLocal.withInitial(WrappingList::new); - private PooledChannel[] activeSockets; + private PooledChannel[] activeChannels; - static List wrap(PooledChannel[] activeSockets) { - final WrappingList sockets = INSTANCE.get(); - sockets.activeSockets = activeSockets; - return sockets; + static List wrap(PooledChannel[] activeChannels) { + final WrappingList channels = INSTANCE.get(); + channels.activeChannels = activeChannels; + return channels; } @Override public Channel get(int index) { - final PooledChannel socket = activeSockets[index]; + final PooledChannel channel = activeChannels[index]; - Channel realValue = socket.value; + Channel realValue = channel.value; if (realValue != null) { return realValue; } - realValue = socket.valueIfResolved(); + realValue = channel.valueIfResolved(); if (realValue != null) { return realValue; } - return socket; + return channel; } @Override public int size() { - return activeSockets.length; + return activeChannels.length; } @Override public boolean isEmpty() { - return activeSockets.length == 0; + return activeChannels.length == 0; } @Override public Object[] toArray() { - return activeSockets; + return activeChannels; } @Override @SuppressWarnings("unchecked") public T[] toArray(T[] a) { - return (T[]) activeSockets; + return (T[]) activeChannels; } @Override diff --git a/today-remoting/src/main/java/infra/remoting/lb/PooledChannel.java b/today-remoting/src/main/java/infra/remoting/lb/PooledChannel.java index 53cea0d..867f287 100644 --- a/today-remoting/src/main/java/infra/remoting/lb/PooledChannel.java +++ b/today-remoting/src/main/java/infra/remoting/lb/PooledChannel.java @@ -131,12 +131,12 @@ void doCleanup(Throwable t) { final ChannelPool parent = this.parent; for (; ; ) { - final PooledChannel[] sockets = parent.activeChannels; - final int activeSocketsCount = sockets.length; + final PooledChannel[] channels = parent.activeChannels; + final int activeChannelsCount = channels.length; int index = -1; - for (int i = 0; i < activeSocketsCount; i++) { - if (sockets[i] == this) { + for (int i = 0; i < activeChannelsCount; i++) { + if (channels[i] == this) { index = i; break; } @@ -146,24 +146,24 @@ void doCleanup(Throwable t) { break; } - final PooledChannel[] newSockets; - if (activeSocketsCount == 1) { - newSockets = ChannelPool.EMPTY; + final PooledChannel[] newChannels; + if (activeChannelsCount == 1) { + newChannels = ChannelPool.EMPTY; } else { - final int lastIndex = activeSocketsCount - 1; + final int lastIndex = activeChannelsCount - 1; - newSockets = new PooledChannel[lastIndex]; + newChannels = new PooledChannel[lastIndex]; if (index != 0) { - System.arraycopy(sockets, 0, newSockets, 0, index); + System.arraycopy(channels, 0, newChannels, 0, index); } if (index != lastIndex) { - System.arraycopy(sockets, index + 1, newSockets, index, lastIndex - index); + System.arraycopy(channels, index + 1, newChannels, index, lastIndex - index); } } - if (ChannelPool.ACTIVE_CHANNELS.compareAndSet(parent, sockets, newSockets)) { + if (ChannelPool.ACTIVE_CHANNELS.compareAndSet(parent, channels, newChannels)) { break; } } @@ -230,8 +230,8 @@ public Mono onClose() { @Override public double availability() { - final Channel socket = valueIfResolved(); - return socket != null ? socket.availability() : 0.0d; + final Channel channel = valueIfResolved(); + return channel != null ? channel.availability() : 0.0d; } static final class MonoInner extends MonoDeferredResolution { diff --git a/today-remoting/src/main/java/infra/remoting/plugins/ChannelAcceptorDecorator.java b/today-remoting/src/main/java/infra/remoting/plugins/ChannelAcceptorDecorator.java index cbbfb92..23e82b7 100644 --- a/today-remoting/src/main/java/infra/remoting/plugins/ChannelAcceptorDecorator.java +++ b/today-remoting/src/main/java/infra/remoting/plugins/ChannelAcceptorDecorator.java @@ -21,7 +21,7 @@ /** * Contract to decorate a {@link ChannelAcceptor}, providing access to connection {@code setup} - * information and the ability to also decorate the sockets for requesting and responding. + * information and the ability to also decorate the channels for requesting and responding. * *

      This could be used as an alternative to registering an individual "requester" {@code * ChannelInterceptor} and "responder" {@code ChannelInterceptor}. diff --git a/today-remoting/src/main/java/infra/remoting/plugins/ChannelDecorator.java b/today-remoting/src/main/java/infra/remoting/plugins/ChannelDecorator.java index e870ee1..f2249ec 100644 --- a/today-remoting/src/main/java/infra/remoting/plugins/ChannelDecorator.java +++ b/today-remoting/src/main/java/infra/remoting/plugins/ChannelDecorator.java @@ -28,6 +28,9 @@ @FunctionalInterface public interface ChannelDecorator { + /** + * Decorate Channel + */ Channel decorate(Channel channel); } diff --git a/today-remoting/src/main/java/infra/remoting/plugins/RateLimitDecorator.java b/today-remoting/src/main/java/infra/remoting/plugins/RateLimitDecorator.java index cd28cee..ee57119 100644 --- a/today-remoting/src/main/java/infra/remoting/plugins/RateLimitDecorator.java +++ b/today-remoting/src/main/java/infra/remoting/plugins/RateLimitDecorator.java @@ -56,8 +56,8 @@ private RateLimitDecorator(int highTide, int lowTide, boolean requesterProxy) { } @Override - public Channel decorate(Channel socket) { - return requesterProxy ? new RequesterChannel(socket) : new ResponderChannel(socket); + public Channel decorate(Channel channel) { + return requesterProxy ? new RequesterChannel(channel) : new ResponderChannel(channel); } /** diff --git a/today-remoting/src/test/java/infra/remoting/examples/tcp/channel/ChannelEchoClient.java b/today-remoting/src/test/java/infra/remoting/examples/tcp/channel/ChannelEchoClient.java index 3dad7cd..8a8b6a0 100644 --- a/today-remoting/src/test/java/infra/remoting/examples/tcp/channel/ChannelEchoClient.java +++ b/today-remoting/src/test/java/infra/remoting/examples/tcp/channel/ChannelEchoClient.java @@ -47,16 +47,16 @@ public static void main(String[] args) { RemotingServer.create(echoAcceptor).bindNow(TcpServerTransport.create("localhost", 7000)); - Channel socket = + Channel channel = ChannelConnector.connectWith(TcpClientTransport.create("localhost", 7000)).block(); - socket + channel .requestChannel( Flux.interval(Duration.ofMillis(1000)).map(i -> DefaultPayload.create("Hello"))) .map(Payload::getDataUtf8) .doOnNext(logger::debug) .take(10) - .doFinally(signalType -> socket.dispose()) + .doFinally(signalType -> channel.dispose()) .then() .block(); } diff --git a/today-remoting/src/test/java/infra/remoting/examples/tcp/plugins/LimitRateInterceptorExample.java b/today-remoting/src/test/java/infra/remoting/examples/tcp/plugins/LimitRateInterceptorExample.java index 1ab1b78..3092118 100644 --- a/today-remoting/src/test/java/infra/remoting/examples/tcp/plugins/LimitRateInterceptorExample.java +++ b/today-remoting/src/test/java/infra/remoting/examples/tcp/plugins/LimitRateInterceptorExample.java @@ -60,7 +60,7 @@ public Flux requestChannel(Publisher payloads) { .interceptors(registry -> registry.forResponder(RateLimitDecorator.forResponder(64))) .bindNow(TcpServerTransport.create("localhost", 7000)); - Channel socket = + Channel channel = ChannelConnector.create() .interceptors(registry -> registry.forRequester(RateLimitDecorator.forRequester(64))) .connect(TcpClientTransport.create("localhost", 7000)) @@ -69,7 +69,7 @@ public Flux requestChannel(Publisher payloads) { logger.debug( "\n\nStart of requestStream interaction\n" + "----------------------------------\n"); - socket + channel .requestStream(DefaultPayload.create("Hello")) .doOnRequest(e -> logger.debug("Client sends requestN(" + e + ")")) .map(Payload::getDataUtf8) @@ -81,7 +81,7 @@ public Flux requestChannel(Publisher payloads) { logger.debug( "\n\nStart of requestChannel interaction\n" + "-----------------------------------\n"); - socket + channel .requestChannel( Flux.generate( () -> 1L, @@ -95,7 +95,7 @@ public Flux requestChannel(Publisher payloads) { .doOnNext(logger::debug) .take(10) .then() - .doFinally(signalType -> socket.dispose()) + .doFinally(signalType -> channel.dispose()) .then() .block(); } diff --git a/today-remoting/src/test/java/infra/remoting/examples/tcp/requestresponse/HelloWorldClient.java b/today-remoting/src/test/java/infra/remoting/examples/tcp/requestresponse/HelloWorldClient.java index e9bb75f..e775a44 100644 --- a/today-remoting/src/test/java/infra/remoting/examples/tcp/requestresponse/HelloWorldClient.java +++ b/today-remoting/src/test/java/infra/remoting/examples/tcp/requestresponse/HelloWorldClient.java @@ -53,11 +53,11 @@ public Mono requestResponse(Payload p) { RemotingServer.create(ChannelAcceptor.with(channel)) .bindNow(TcpServerTransport.create("localhost", 7000)); - Channel socket = + Channel channel1 = ChannelConnector.connectWith(TcpClientTransport.create("localhost", 7000)).block(); for (int i = 0; i < 3; i++) { - socket + channel1 .requestResponse(DefaultPayload.create("Hello")) .map(Payload::getDataUtf8) .onErrorReturn("error") @@ -65,6 +65,6 @@ public Mono requestResponse(Payload p) { .block(); } - socket.dispose(); + channel1.dispose(); } } diff --git a/today-remoting/src/test/java/infra/remoting/examples/tcp/stream/ClientStreamingToServer.java b/today-remoting/src/test/java/infra/remoting/examples/tcp/stream/ClientStreamingToServer.java index 30f68b5..2fa29d6 100644 --- a/today-remoting/src/test/java/infra/remoting/examples/tcp/stream/ClientStreamingToServer.java +++ b/today-remoting/src/test/java/infra/remoting/examples/tcp/stream/ClientStreamingToServer.java @@ -43,20 +43,20 @@ public static void main(String[] args) throws InterruptedException { .map(aLong -> DefaultPayload.create("Interval: " + aLong)))) .bindNow(TcpServerTransport.create("localhost", 7000)); - Channel socket = + Channel channel = ChannelConnector.create() .setupPayload(DefaultPayload.create("test", "test")) .connect(TcpClientTransport.create("localhost", 7000)) .block(); final Payload payload = DefaultPayload.create("Hello"); - socket + channel .requestStream(payload) .map(Payload::getDataUtf8) .doOnNext(logger::debug) .take(10) .then() - .doFinally(signalType -> socket.dispose()) + .doFinally(signalType -> channel.dispose()) .then() .block(); From a3317365c230cc7860dc2ae8d40a769954f8cc0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Tue, 12 Aug 2025 22:21:53 +0800 Subject: [PATCH 040/104] :art: --- .../netty/server/CloseableChannel.java | 2 +- .../transport/tcp/TCPServerTransport.java | 2 +- .../transport/websocket/CloseableChannel.java | 2 +- .../java/infra/remoting/AbortedException.java | 60 ----- .../java/infra/remoting/util/FutureMono.java | 214 ------------------ .../service/MethodServiceInvocation.java | 4 +- .../cloud/service/ServiceMethodInvoker.java | 67 ++++-- 7 files changed, 59 insertions(+), 292 deletions(-) delete mode 100644 today-remoting/src/main/java/infra/remoting/AbortedException.java delete mode 100644 today-remoting/src/main/java/infra/remoting/util/FutureMono.java diff --git a/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/server/CloseableChannel.java b/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/server/CloseableChannel.java index a3a7311..7bf2cd4 100644 --- a/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/server/CloseableChannel.java +++ b/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/server/CloseableChannel.java @@ -20,8 +20,8 @@ import java.net.InetSocketAddress; import java.util.Objects; +import infra.core.FutureMono; import infra.remoting.Closeable; -import infra.remoting.util.FutureMono; import io.netty.channel.Channel; import reactor.core.publisher.Mono; import reactor.netty.DisposableChannel; diff --git a/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/tcp/TCPServerTransport.java b/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/tcp/TCPServerTransport.java index 3a398f8..a9d159a 100644 --- a/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/tcp/TCPServerTransport.java +++ b/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/tcp/TCPServerTransport.java @@ -21,6 +21,7 @@ import java.net.InetSocketAddress; import java.util.concurrent.TimeUnit; +import infra.core.FutureMono; import infra.lang.Assert; import infra.lang.Nullable; import infra.logging.Logger; @@ -28,7 +29,6 @@ import infra.remoting.transport.ConnectionAcceptor; import infra.remoting.transport.ServerTransport; import infra.remoting.transport.netty.server.CloseableChannel; -import infra.remoting.util.FutureMono; import infra.util.ClassUtils; import infra.util.concurrent.Future; import io.netty.bootstrap.ServerBootstrap; diff --git a/today-remoting-transport-websocket/src/main/java/infra/remoting/transport/websocket/CloseableChannel.java b/today-remoting-transport-websocket/src/main/java/infra/remoting/transport/websocket/CloseableChannel.java index 8c66b8a..c2c0e29 100644 --- a/today-remoting-transport-websocket/src/main/java/infra/remoting/transport/websocket/CloseableChannel.java +++ b/today-remoting-transport-websocket/src/main/java/infra/remoting/transport/websocket/CloseableChannel.java @@ -20,8 +20,8 @@ import java.net.InetSocketAddress; import java.util.Objects; +import infra.core.FutureMono; import infra.remoting.Closeable; -import infra.remoting.util.FutureMono; import io.netty.channel.Channel; import reactor.core.publisher.Mono; import reactor.netty.DisposableChannel; diff --git a/today-remoting/src/main/java/infra/remoting/AbortedException.java b/today-remoting/src/main/java/infra/remoting/AbortedException.java deleted file mode 100644 index 27a93a0..0000000 --- a/today-remoting/src/main/java/infra/remoting/AbortedException.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright 2021 - 2024 the original author or authors. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] - */ -package infra.remoting; - -import java.io.IOException; -import java.io.Serial; -import java.net.SocketException; - -/** - * An exception marking prematurely or unexpectedly closed inbound. - */ -public class AbortedException extends RuntimeException { - - @Serial - private static final long serialVersionUID = 6091789064032301718L; - - static final String CONNECTION_CLOSED_BEFORE_SEND = "Connection has been closed BEFORE send operation"; - - public AbortedException(String message) { - super(message); - } - - public AbortedException(Throwable throwable) { - super(throwable); - } - - /** - * Return true if connection has been simply aborted on a tcp level by verifying if - * the given inbound error. - * - * @param err an inbound exception - * @return true if connection has been simply aborted on a tcp level - */ - public static boolean isConnectionReset(Throwable err) { - return (err instanceof AbortedException && CONNECTION_CLOSED_BEFORE_SEND.equals(err.getMessage())) || - (err instanceof IOException && (err.getMessage() == null || err.getMessage() - .contains("Broken pipe") || - err.getMessage().contains("Connection reset by peer"))) || - (err instanceof SocketException && err.getMessage() != null && err.getMessage().contains("Connection reset by peer")); - } - - public static AbortedException beforeSend() { - return new AbortedException(CONNECTION_CLOSED_BEFORE_SEND); - } - -} diff --git a/today-remoting/src/main/java/infra/remoting/util/FutureMono.java b/today-remoting/src/main/java/infra/remoting/util/FutureMono.java deleted file mode 100644 index f077a45..0000000 --- a/today-remoting/src/main/java/infra/remoting/util/FutureMono.java +++ /dev/null @@ -1,214 +0,0 @@ -/* - * Copyright 2021 - 2024 the original author or authors. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] - */ - -package infra.remoting.util; - -import org.reactivestreams.Subscriber; -import org.reactivestreams.Subscription; - -import java.nio.channels.ClosedChannelException; -import java.util.Objects; -import java.util.function.Supplier; - -import infra.remoting.AbortedException; -import infra.util.concurrent.Future; -import infra.util.concurrent.FutureListener; -import reactor.core.CoreSubscriber; -import reactor.core.publisher.Mono; -import reactor.core.publisher.Operators; -import reactor.util.context.Context; - -/** - * @author 海子 Yang - * @since 1.0 2025/8/3 11:34 - */ -public abstract class FutureMono extends Mono { - - /** - * Convert a {@link Future} into {@link Mono}. {@link Mono#subscribe(Subscriber)} - * will bridge to {@link Future#onCompleted(FutureListener)}. - * - * @param future the future to convert from - * @param the future type - * @return A {@link Mono} forwarding {@link Future} success or failure - */ - public static > Mono of(F future) { - Objects.requireNonNull(future, "future"); - if (future.isDone()) { - if (!future.isSuccess()) { - return Mono.error(FutureSubscription.wrapError(future.getCause())); - } - return Mono.empty(); - } - return new ImmediateFutureMono<>(future); - } - - /** - * Convert a supplied {@link Future} for each subscriber into {@link Mono}. - * {@link Mono#subscribe(Subscriber)} - * will bridge to {@link Future#onCompleted(FutureListener)}. - * - * @param deferredFuture the future to evaluate and convert from - * @param the future type - * @return A {@link Mono} forwarding {@link Future} success or failure - */ - public static > Mono deferFuture(Supplier deferredFuture) { - return new DeferredFutureMono<>(deferredFuture); - } - - static final class ImmediateFutureMono> extends FutureMono { - - final F future; - - ImmediateFutureMono(F future) { - this.future = Objects.requireNonNull(future, "future"); - } - - @Override - public void subscribe(final CoreSubscriber s) { - doSubscribe(s, future); - } - } - - static final class DeferredFutureMono> extends FutureMono { - - final Supplier deferredFuture; - - DeferredFutureMono(Supplier deferredFuture) { - this.deferredFuture = Objects.requireNonNull(deferredFuture, "deferredFuture"); - } - - @Override - public void subscribe(CoreSubscriber s) { - F f; - try { - f = deferredFuture.get(); - } - catch (Throwable t) { - Operators.error(s, t); - return; - } - - if (f == null) { - Operators.error(s, - Operators.onOperatorError(new NullPointerException( - "Deferred supplied null"), s.currentContext())); - return; - } - - doSubscribe(s, f); - } - } - - @SuppressWarnings("FutureReturnValueIgnored") - static > void doSubscribe(CoreSubscriber s, F future) { - if (future.isDone()) { - if (future.isSuccess()) { - Operators.complete(s); - } - else { - Operators.error(s, FutureSubscription.wrapError(future.getCause())); - } - return; - } - - FutureSubscription fs = new FutureSubscription<>(future, s); - // propagate subscription before adding listener to avoid any race between finishing future and onSubscribe - // is called - s.onSubscribe(fs); - - // check if subscription was not cancelled immediately. - if (fs.cancelled) { - // if so do nothing anymore - return; - } - - // add listener to the future to propagate on complete when future is done - // onCompleted likely to be thread safe method - future.onCompleted(fs); - - // check once again if is cancelled to see if we need to removeListener in case onCompleted racing with - // subscription.cancel (which should remove listener) - if (fs.cancelled) { - // Returned value is deliberately ignored - future.cancel(); - } - } - - static final class FutureSubscription> - implements FutureListener, Subscription, Supplier { - - final CoreSubscriber s; - - final F future; - - boolean cancelled; - - FutureSubscription(F future, CoreSubscriber s) { - this.s = s; - this.future = future; - } - - @Override - public void request(long n) { - //noop - } - - @Override - public Context get() { - return s.currentContext(); - } - - @Override - @SuppressWarnings("FutureReturnValueIgnored") - public void cancel() { - // cancel is not thread safe since we assume that removeListener is thread-safe. That said if we have - // concurrent onCompleted and removeListener and if onCompleted is after removeListener, the other Thread - // after execution onCompleted should see changes happened before removeListener. Thus, it should see - // cancelled flag set to true and should cleanup added handler - this.cancelled = true; - future.cancel(); - } - - @Override - public void operationComplete(F future) { - if (cancelled) { - // Returned value is deliberately ignored - return; - } - if (future.isSuccess()) { - T now = future.getNow(); - if (now != null) { - s.onNext(now); - } - s.onComplete(); - } - else { - s.onError(wrapError(future.getCause())); - } - } - - private static Throwable wrapError(Throwable error) { - if (error instanceof ClosedChannelException) { - return new AbortedException(error); - } - else { - return error; - } - } - } -} diff --git a/today-service-client/src/main/java/infra/cloud/service/MethodServiceInvocation.java b/today-service-client/src/main/java/infra/cloud/service/MethodServiceInvocation.java index faa7ae4..d08d533 100644 --- a/today-service-client/src/main/java/infra/cloud/service/MethodServiceInvocation.java +++ b/today-service-client/src/main/java/infra/cloud/service/MethodServiceInvocation.java @@ -48,10 +48,10 @@ public InvocationResult proceed() throws Throwable { return interceptors[currentIndex++].intercept(this); } - return invokeRemoting(args); + return invokeRemoting(); } - protected abstract InvocationResult invokeRemoting(Object[] args); + protected abstract InvocationResult invokeRemoting(); @Override public ServiceInterfaceMethod getServiceMethod() { diff --git a/today-service-client/src/main/java/infra/cloud/service/ServiceMethodInvoker.java b/today-service-client/src/main/java/infra/cloud/service/ServiceMethodInvoker.java index c1efc23..550591a 100644 --- a/today-service-client/src/main/java/infra/cloud/service/ServiceMethodInvoker.java +++ b/today-service-client/src/main/java/infra/cloud/service/ServiceMethodInvoker.java @@ -18,14 +18,19 @@ package infra.cloud.service; import org.reactivestreams.Publisher; +import org.reactivestreams.Subscriber; +import org.reactivestreams.Subscription; +import infra.core.ReactiveAdapterRegistry; import infra.lang.Nullable; import infra.remoting.Payload; import infra.remoting.RemotingOperations; import infra.util.concurrent.Future; +import infra.util.concurrent.FutureListener; import infra.util.concurrent.Promise; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; +import reactor.core.publisher.Operators; /** * Service Method Invoker @@ -61,27 +66,27 @@ public MethodServiceInvocation0(ServiceInterfaceMethod serviceMethod, Object[] a } @Override - protected InvocationResult invokeRemoting(Object[] args) { + protected InvocationResult invokeRemoting() { RemotingOperations operations = remotingOperationsProvider.getRemotingOperations(getServiceMethod()); Publisher publisher = switch (getType()) { - case FIRE_AND_FORGET -> operations.fireAndForget(createMonoPayload(args)).cast(Payload.class); - case REQUEST_RESPONSE -> operations.requestResponse(createMonoPayload(args)); - case RESPONSE_STREAMING -> operations.requestStream(createMonoPayload(args)); - case DUPLEX_STREAMING -> operations.requestChannel(createChannelPayload(args)); + case FIRE_AND_FORGET -> operations.fireAndForget(createMonoPayload()).cast(Payload.class); + case REQUEST_RESPONSE -> operations.requestResponse(createMonoPayload()); + case RESPONSE_STREAMING -> operations.requestStream(createMonoPayload()); + case DUPLEX_STREAMING -> operations.requestChannel(createChannelPayload()); }; - return new InvocationResult0(null, getType(), publisher); + return new InvocationResult0(getType(), publisher); } - private Mono createMonoPayload(Object[] args) { + private Mono createMonoPayload() { return null; } @SuppressWarnings("unchecked") - private Publisher createChannelPayload(Object[] args) { - Flux flux = (Flux) args[0]; + private Publisher createChannelPayload() { + Flux flux = (Flux) getArguments()[0]; return null; } @@ -92,10 +97,10 @@ private Object deserialize(Payload payload) { return null; } - class InvocationResult0 extends AbstractInvocationResult { + class InvocationResult0 extends AbstractInvocationResult implements Subscriber, FutureListener> { @Nullable - private final Throwable throwable; + private Throwable throwable; private final InvocationType invocationType; @@ -103,10 +108,14 @@ class InvocationResult0 extends AbstractInvocationResult { private final Promise resultPromise = Future.forPromise(); - public InvocationResult0(@Nullable Throwable throwable, InvocationType invocationType, Publisher publisher) { - this.throwable = throwable; + @Nullable + private Subscription payloadSubscription; + + public InvocationResult0(InvocationType invocationType, Publisher publisher) { this.invocationType = invocationType; this.publisher = publisher; + publisher.subscribe(this); + resultPromise.onCompleted(this); } @Override @@ -138,6 +147,7 @@ public Future future() { @Override public Publisher publisher() { + ReactiveAdapterRegistry sharedInstance = ReactiveAdapterRegistry.getSharedInstance(); return switch (getType()) { case FIRE_AND_FORGET -> Mono.from(publisher); case REQUEST_RESPONSE -> Mono.from(publisher).map(ServiceMethodInvoker.this::deserialize); @@ -145,6 +155,37 @@ public Publisher publisher() { }; } + @Override + public void onSubscribe(Subscription s) { + if (Operators.validate(payloadSubscription, s)) { + this.payloadSubscription = s; + s.request(Long.MAX_VALUE); + } + } + + @Override + public void onNext(Payload payload) { + + } + + @Override + public void onError(Throwable t) { + + } + + @Override + public void onComplete() { + + } + + @Override + public void operationComplete(Future completed) { + if (completed.isCancelled()) { + if (payloadSubscription != null) { + payloadSubscription.cancel(); + } + } + } } } From d5bfb4f38475791b5660bebf2eedb6b9e00f2e1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Fri, 15 Aug 2025 19:42:24 +0800 Subject: [PATCH 041/104] :art: --- .../remoting/core/DefaultRemotingClient.java | 12 +++------ .../infra/remoting/core/ReconnectMono.java | 13 ++++------ .../remoting/core/ResolvingOperator.java | 26 +++++++++---------- .../resume/InMemoryResumableFramesStore.java | 3 ++- 4 files changed, 24 insertions(+), 30 deletions(-) diff --git a/today-remoting/src/main/java/infra/remoting/core/DefaultRemotingClient.java b/today-remoting/src/main/java/infra/remoting/core/DefaultRemotingClient.java index bb7d9ab..10dbed8 100644 --- a/today-remoting/src/main/java/infra/remoting/core/DefaultRemotingClient.java +++ b/today-remoting/src/main/java/infra/remoting/core/DefaultRemotingClient.java @@ -78,7 +78,7 @@ class DefaultRemotingClient extends ResolvingOperator implements CoreSu } private Mono unwrapReconnectMono(Mono source) { - return source instanceof ReconnectMono ? ((ReconnectMono) source).getSource() : source; + return source instanceof ReconnectMono ? ((ReconnectMono) source).source : source; } @Override @@ -405,7 +405,7 @@ static final class FlattingInner extends DeferredResolution { @Override @SuppressWarnings({ "unchecked", "rawtypes" }) - public void accept(Channel channel, Throwable t) { + public void accept(Channel channel, @Nullable Throwable t) { if (isCancelled()) { return; } @@ -494,7 +494,7 @@ static final class RequestChannelInner extends DeferredResolution source; if (interactionType == FrameType.REQUEST_CHANNEL) { - source = channel.requestChannel(upstream); + channel.requestChannel(upstream).subscribe(this); } else { onError(new IllegalStateException("Should never happen")); - return; } - - source.subscribe(this); } } diff --git a/today-remoting/src/main/java/infra/remoting/core/ReconnectMono.java b/today-remoting/src/main/java/infra/remoting/core/ReconnectMono.java index fe9eda5..4c8a9b5 100644 --- a/today-remoting/src/main/java/infra/remoting/core/ReconnectMono.java +++ b/today-remoting/src/main/java/infra/remoting/core/ReconnectMono.java @@ -36,14 +36,13 @@ final class ReconnectMono extends Mono implements Invalidatable, Disposable, Scannable { - final Mono source; + public final Mono source; + final BiConsumer onValueReceived; final Consumer onValueExpired; final ResolvingInner resolvingInner; - ReconnectMono( - Mono source, - Consumer onValueExpired, + ReconnectMono(Mono source, Consumer onValueExpired, BiConsumer onValueReceived) { this.source = source; this.onValueExpired = onValueExpired; @@ -51,10 +50,7 @@ final class ReconnectMono extends Mono implements Invalidatable, Disposabl this.resolvingInner = new ResolvingInner<>(this); } - public Mono getSource() { - return source; - } - + @Nullable @Override public Object scanUnsafe(Attr key) { if (key == Attr.PARENT) @@ -269,6 +265,7 @@ protected void doSubscribe() { this.parent.source.subscribe(this.mainSubscriber); } + @Nullable @Override public Object scanUnsafe(Attr key) { if (key == Attr.PARENT) diff --git a/today-remoting/src/main/java/infra/remoting/core/ResolvingOperator.java b/today-remoting/src/main/java/infra/remoting/core/ResolvingOperator.java index fba2b49..b67ec21 100644 --- a/today-remoting/src/main/java/infra/remoting/core/ResolvingOperator.java +++ b/today-remoting/src/main/java/infra/remoting/core/ResolvingOperator.java @@ -76,7 +76,7 @@ public ResolvingOperator() { @Override public final void dispose() { - this.terminate(ON_DISPOSE); + terminate(ON_DISPOSE); } @Override @@ -100,7 +100,7 @@ public final T valueIfResolved() { final void observe(BiConsumer actual) { for (; ; ) { - final int state = this.add(actual); + final int state = add(actual); T value = this.value; @@ -160,7 +160,7 @@ public T block(@Nullable Duration timeout) { // connect once if (subscribers == EMPTY_UNSUBSCRIBED && SUBSCRIBERS.compareAndSet(this, EMPTY_UNSUBSCRIBED, EMPTY_SUBSCRIBED)) { - this.doSubscribe(); + doSubscribe(); } long delay; @@ -196,7 +196,7 @@ public T block(@Nullable Duration timeout) { // connect again since invalidate() has happened in between if (subscribers == EMPTY_UNSUBSCRIBED && SUBSCRIBERS.compareAndSet(this, EMPTY_UNSUBSCRIBED, EMPTY_SUBSCRIBED)) { - this.doSubscribe(); + doSubscribe(); } Thread.sleep(1); @@ -225,9 +225,9 @@ final void terminate(Throwable t) { return; } - this.doOnDispose(); + doOnDispose(); - this.doFinally(); + doFinally(); for (BiConsumer consumer : subscribers) { consumer.accept(null, t); @@ -237,7 +237,7 @@ final void terminate(Throwable t) { final void complete(T value) { BiConsumer[] subscribers = this.subscribers; if (subscribers == TERMINATED) { - this.doOnValueExpired(value); + doOnValueExpired(value); return; } @@ -252,12 +252,12 @@ final void complete(T value) { subscribers = this.subscribers; if (subscribers == TERMINATED) { - this.doFinally(); + doFinally(); return; } } - this.doOnValueResolved(value); + doOnValueResolved(value); for (BiConsumer consumer : subscribers) { consumer.accept(value, null); @@ -280,7 +280,7 @@ final void doFinally() { value = this.value; if (value != null && isDisposed()) { this.value = null; - this.doOnValueExpired(value); + doOnValueExpired(value); return; } @@ -307,7 +307,7 @@ final void invalidate() { final T value = this.value; if (value != null) { this.value = null; - this.doOnValueExpired(value); + doOnValueExpired(value); } int m = 1; @@ -352,7 +352,7 @@ public final boolean connect() { } if (SUBSCRIBERS.compareAndSet(this, a, EMPTY_SUBSCRIBED)) { - this.doSubscribe(); + doSubscribe(); return true; } } @@ -378,7 +378,7 @@ final int add(BiConsumer ps) { if (SUBSCRIBERS.compareAndSet(this, a, b)) { if (a == EMPTY_UNSUBSCRIBED) { - this.doSubscribe(); + doSubscribe(); } return ADDED_STATE; } diff --git a/today-remoting/src/main/java/infra/remoting/resume/InMemoryResumableFramesStore.java b/today-remoting/src/main/java/infra/remoting/resume/InMemoryResumableFramesStore.java index 601b057..507fd6c 100644 --- a/today-remoting/src/main/java/infra/remoting/resume/InMemoryResumableFramesStore.java +++ b/today-remoting/src/main/java/infra/remoting/resume/InMemoryResumableFramesStore.java @@ -464,7 +464,8 @@ void handleResumableFrame(ByteBuf frame) { } @Override - public void request(long n) { } + public void request(long n) { + } @Override public void cancel() { From 6b74d0713dd7c90ad639ac863fa60028402b17c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Sun, 17 Aug 2025 22:28:14 +0800 Subject: [PATCH 042/104] =?UTF-8?q?:sparkles:=20=E5=BA=8F=E5=88=97?= =?UTF-8?q?=E5=8C=96=20API=20=E5=87=86=E5=A4=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- settings.gradle | 1 + today-cloud-core/build.gradle | 4 - .../core/serialize/JdkSerialization.java | 46 - .../cloud/core/serialize/Serialization.java | 67 - today-service-api/build.gradle | 4 +- .../infra/cloud/serialize/ByteBufInput.java | 155 -- .../infra/cloud/serialize/ByteBufOutput.java | 138 -- .../cloud/serialize/DefaultByteBufInput.java | 114 ++ .../cloud/serialize/DefaultByteBufOutput.java | 88 + .../ProtobufArgumentSerialization.java | 17 +- .../serialize/ReturnValueSerialization.java | 13 +- .../serialize/RpcArgumentSerialization.java | 5 +- .../serialize/RpcRequestSerialization.java | 3 +- .../serialize/RpcResponseSerialization.java | 7 +- .../SimpleValueArgumentSerialization.java | 5 +- .../serialize/ThrowableSerialization.java | 3 +- .../value/FuncValueSerialization.java | 4 +- .../serialize/value/ValueSerialization.java | 4 +- .../infra/cloud/service/InvocationResult.java | 4 + .../infra/cloud/service/InvocationType.java | 4 +- .../service/AbstractInvocationResult.java | 7 +- .../cloud/service/ClientInterceptor.java | 4 +- ...faultServiceInterfaceMetadataProvider.java | 6 +- .../cloud/service/DuplexStreamingResult.java | 77 + .../cloud/service/FireAndForgetResult.java | 77 + .../cloud/service/RequestResponseResult.java | 80 + .../service/ResponseStreamingResult.java | 77 + .../cloud/service/ServiceMethodInvoker.java | 86 +- .../cloud/service/TracingInterceptor.java | 46 + today-service-provider/build.gradle | 3 - .../provider/RpcRequestDeserializer.java | 4 +- today-service-serialization/build.gradle | 13 + .../infra/cloud}/serialize/Deserializer.java | 20 +- .../java/infra/cloud/serialize/Input.java | 272 +++ .../java/infra/cloud/serialize/Message.java | 60 + .../java/infra/cloud/serialize/Output.java | 209 +++ .../infra/cloud/serialize/Serialization.java | 26 + .../serialize/SerializationException.java | 32 + .../infra/cloud}/serialize/Serializer.java | 19 +- .../serialize/format/ExtensionTypeHeader.java | 83 + .../serialize/format/MessageBufferPacker.java | 124 ++ .../cloud/serialize/format/MessageFormat.java | 164 ++ .../format/MessageFormatException.java | 34 + .../MessageInsufficientBufferException.java | 29 + .../MessageIntegerOverflowException.java | 48 + .../MessageNeverUsedFormatException.java | 31 + .../cloud/serialize/format/MessagePack.java | 700 +++++++ .../format/MessagePackException.java | 32 + .../cloud/serialize/format/MessagePacker.java | 1093 +++++++++++ .../format/MessageSizeException.java | 40 + .../format/MessageStringCodingException.java | 35 + .../format/MessageTypeCastException.java | 26 + .../format/MessageTypeException.java | 29 +- .../serialize/format/MessageUnpacker.java | 1639 +++++++++++++++++ .../format/buffer/ArrayBufferInput.java | 79 + .../format/buffer/ArrayBufferOutput.java | 161 ++ .../format/buffer/ByteBufferInput.java | 63 + .../format/buffer/ChannelBufferInput.java | 73 + .../format/buffer/ChannelBufferOutput.java | 93 + .../format/buffer/DirectBufferAccess.java | 175 ++ .../format/buffer/InputStreamBufferInput.java | 83 + .../format/buffer/MessageBuffer.java | 574 ++++++ .../format/buffer/MessageBufferBE.java | 98 + .../format/buffer/MessageBufferInput.java | 60 + .../format/buffer/MessageBufferOutput.java | 82 + .../format/buffer/MessageBufferU.java | 244 +++ .../buffer/OutputStreamBufferOutput.java | 86 + .../cloud/serialize/format/package-info.java | 26 + .../serialize/format/value/ArrayValue.java | 58 + .../serialize/format/value/BinaryValue.java | 29 + .../serialize/format/value/BooleanValue.java | 31 + .../format/value/ExtensionValue.java | 33 + .../serialize/format/value/FloatValue.java | 29 + .../format/value/ImmutableArrayValue.java | 41 + .../format/value/ImmutableBinaryValue.java | 29 + .../format/value/ImmutableBooleanValue.java | 27 + .../format/value/ImmutableExtensionValue.java | 27 + .../format/value/ImmutableFloatValue.java | 29 + .../format/value/ImmutableIntegerValue.java | 27 + .../format/value/ImmutableMapValue.java | 27 + .../format/value/ImmutableNilValue.java | 25 + .../format/value/ImmutableNumberValue.java | 28 + .../format/value/ImmutableRawValue.java | 30 + .../format/value/ImmutableStringValue.java | 28 + .../format/value/ImmutableTimestampValue.java | 27 + .../format/value/ImmutableValue.java | 54 + .../serialize/format/value/IntegerValue.java | 91 + .../serialize/format/value/MapValue.java | 56 + .../serialize/format/value/NilValue.java | 25 + .../serialize/format/value/NumberValue.java | 66 + .../serialize/format/value/RawValue.java | 64 + .../serialize/format/value/StringValue.java | 31 + .../format/value/TimestampValue.java | 34 + .../cloud/serialize/format/value/Value.java | 332 ++++ .../serialize/format/value/ValueFactory.java | 275 +++ .../serialize/format/value/ValueType.java | 99 + .../serialize/format/value/Variable.java | 1164 ++++++++++++ .../value/impl/AbstractImmutableRawValue.java | 175 ++ .../value/impl/AbstractImmutableValue.java | 156 ++ .../value/impl/ImmutableArrayValueImpl.java | 240 +++ .../impl/ImmutableBigIntegerValueImpl.java | 233 +++ .../value/impl/ImmutableBinaryValueImpl.java | 90 + .../value/impl/ImmutableBooleanValueImpl.java | 108 ++ .../value/impl/ImmutableDoubleValueImpl.java | 141 ++ .../impl/ImmutableExtensionValueImpl.java | 128 ++ .../value/impl/ImmutableLongValueImpl.java | 212 +++ .../value/impl/ImmutableMapValueImpl.java | 331 ++++ .../value/impl/ImmutableNilValueImpl.java | 92 + .../value/impl/ImmutableStringValueImpl.java | 94 + .../impl/ImmutableTimestampValueImpl.java | 182 ++ .../infra/cloud/serialize/MessageTests.java | 81 + 111 files changed, 12347 insertions(+), 540 deletions(-) delete mode 100644 today-cloud-core/src/main/java/infra/cloud/core/serialize/JdkSerialization.java delete mode 100644 today-cloud-core/src/main/java/infra/cloud/core/serialize/Serialization.java delete mode 100644 today-service-api/src/main/java/infra/cloud/serialize/ByteBufInput.java delete mode 100644 today-service-api/src/main/java/infra/cloud/serialize/ByteBufOutput.java create mode 100644 today-service-api/src/main/java/infra/cloud/serialize/DefaultByteBufInput.java create mode 100644 today-service-api/src/main/java/infra/cloud/serialize/DefaultByteBufOutput.java create mode 100644 today-service-client/src/main/java/infra/cloud/service/DuplexStreamingResult.java create mode 100644 today-service-client/src/main/java/infra/cloud/service/FireAndForgetResult.java create mode 100644 today-service-client/src/main/java/infra/cloud/service/RequestResponseResult.java create mode 100644 today-service-client/src/main/java/infra/cloud/service/ResponseStreamingResult.java create mode 100644 today-service-client/src/test/java/infra/cloud/service/TracingInterceptor.java create mode 100644 today-service-serialization/build.gradle rename {today-cloud-core/src/main/java/infra/cloud/core => today-service-serialization/src/main/java/infra/cloud}/serialize/Deserializer.java (59%) create mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/Input.java create mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/Message.java create mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/Output.java create mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/Serialization.java create mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/SerializationException.java rename {today-cloud-core/src/main/java/infra/cloud/core => today-service-serialization/src/main/java/infra/cloud}/serialize/Serializer.java (63%) create mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/ExtensionTypeHeader.java create mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageBufferPacker.java create mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageFormat.java create mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageFormatException.java create mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageInsufficientBufferException.java create mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageIntegerOverflowException.java create mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageNeverUsedFormatException.java create mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/MessagePack.java create mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/MessagePackException.java create mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/MessagePacker.java create mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageSizeException.java create mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageStringCodingException.java create mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageTypeCastException.java rename today-cloud-core/src/main/java/infra/cloud/core/serialize/DeserializeFailedException.java => today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageTypeException.java (57%) create mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageUnpacker.java create mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/ArrayBufferInput.java create mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/ArrayBufferOutput.java create mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/ByteBufferInput.java create mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/ChannelBufferInput.java create mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/ChannelBufferOutput.java create mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/DirectBufferAccess.java create mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/InputStreamBufferInput.java create mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/MessageBuffer.java create mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/MessageBufferBE.java create mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/MessageBufferInput.java create mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/MessageBufferOutput.java create mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/MessageBufferU.java create mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/OutputStreamBufferOutput.java create mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/package-info.java create mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ArrayValue.java create mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/value/BinaryValue.java create mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/value/BooleanValue.java create mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ExtensionValue.java create mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/value/FloatValue.java create mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableArrayValue.java create mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableBinaryValue.java create mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableBooleanValue.java create mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableExtensionValue.java create mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableFloatValue.java create mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableIntegerValue.java create mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableMapValue.java create mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableNilValue.java create mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableNumberValue.java create mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableRawValue.java create mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableStringValue.java create mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableTimestampValue.java create mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableValue.java create mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/value/IntegerValue.java create mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/value/MapValue.java create mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/value/NilValue.java create mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/value/NumberValue.java create mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/value/RawValue.java create mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/value/StringValue.java create mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/value/TimestampValue.java create mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/value/Value.java create mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ValueFactory.java create mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ValueType.java create mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/value/Variable.java create mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/AbstractImmutableRawValue.java create mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/AbstractImmutableValue.java create mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableArrayValueImpl.java create mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableBigIntegerValueImpl.java create mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableBinaryValueImpl.java create mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableBooleanValueImpl.java create mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableDoubleValueImpl.java create mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableExtensionValueImpl.java create mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableLongValueImpl.java create mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableMapValueImpl.java create mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableNilValueImpl.java create mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableStringValueImpl.java create mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableTimestampValueImpl.java create mode 100644 today-service-serialization/src/test/java/infra/cloud/serialize/MessageTests.java diff --git a/settings.gradle b/settings.gradle index 8e2fcb1..c852c63 100644 --- a/settings.gradle +++ b/settings.gradle @@ -35,6 +35,7 @@ include 'today-service-api' include 'today-service-client' include 'today-service-provider' include 'today-service-registry' +include 'today-service-serialization' include 'today-service-registry-simple-api' include 'today-service-registry-simple-client' include 'today-service-registry-simple-server' diff --git a/today-cloud-core/build.gradle b/today-cloud-core/build.gradle index c252acf..9497de9 100644 --- a/today-cloud-core/build.gradle +++ b/today-cloud-core/build.gradle @@ -6,9 +6,5 @@ dependencies { implementation 'cn.taketoday:today-context' -// implementation 'org.msgpack:msgpack-core:0.9.8' - implementation 'io.protostuff:protostuff-core:1.7.4' - implementation 'io.protostuff:protostuff-runtime:1.7.4' - annotationProcessor 'cn.taketoday:infra-configuration-processor' } \ No newline at end of file diff --git a/today-cloud-core/src/main/java/infra/cloud/core/serialize/JdkSerialization.java b/today-cloud-core/src/main/java/infra/cloud/core/serialize/JdkSerialization.java deleted file mode 100644 index bffb97c..0000000 --- a/today-cloud-core/src/main/java/infra/cloud/core/serialize/JdkSerialization.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2021 - 2024 the original author or authors. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] - */ - -package infra.cloud.core.serialize; - -import java.io.IOException; -import java.io.InputStream; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.io.OutputStream; - -/** - * Jdk Serialization - * - * @author TODAY 2021/7/9 21:25 - */ -public class JdkSerialization extends Serialization { - - @Override - public void serialize(final Object object, final OutputStream output) throws IOException { - try (ObjectOutputStream oos = new ObjectOutputStream(output)) { - oos.writeObject(object); - } - } - - @Override - protected final Object deserializeInternal(final InputStream inputStream) throws IOException, ClassNotFoundException { - try (final ObjectInputStream objectInput = new ObjectInputStream(inputStream)) { - return objectInput.readObject(); - } - } -} diff --git a/today-cloud-core/src/main/java/infra/cloud/core/serialize/Serialization.java b/today-cloud-core/src/main/java/infra/cloud/core/serialize/Serialization.java deleted file mode 100644 index 942c7f6..0000000 --- a/today-cloud-core/src/main/java/infra/cloud/core/serialize/Serialization.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright 2021 - 2024 the original author or authors. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] - */ - -package infra.cloud.core.serialize; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; - -/** - * For streaming an object to an OutputStream and - * for converting from data in an InputStream to an Object - * - * @author TODAY 2021/7/8 23:04 - */ -@Deprecated -public abstract class Serialization implements Serializer, Deserializer { - - /** - * Write an object of type T to the given OutputStream. - *

      Note: Implementations should not close the given OutputStream - * (or any decorators of that OutputStream) but rather leave this up - * to the caller. - * - * @param object the object to serialize - * @param output the output stream - * @throws IOException in case of errors writing to the stream - */ - @Override - public abstract void serialize(Object object, OutputStream output) throws IOException; - - /** - * Read (assemble) an object of type T from the given InputStream. - *

      Note: Implementations should not close the given InputStream - * (or any decorators of that InputStream) but rather leave this up - * to the caller. - * - * @param inputStream the input stream - * @return the deserialized object - * @throws IOException in case of errors reading from the stream - * @throws ClassNotFoundException if target type not in classpath - */ - @Override - @SuppressWarnings("unchecked") - public T deserialize(InputStream inputStream) throws IOException, ClassNotFoundException { - return (T) deserializeInternal(inputStream); - } - - protected Object deserializeInternal(InputStream inputStream) throws IOException, ClassNotFoundException { - throw new UnsupportedOperationException(); - } - -} diff --git a/today-service-api/build.gradle b/today-service-api/build.gradle index 20694b9..0a791a3 100644 --- a/today-service-api/build.gradle +++ b/today-service-api/build.gradle @@ -4,13 +4,11 @@ description = "TODAY Service API" dependencies { api project(":today-remoting") api project(":today-cloud-core") + api project(":today-service-serialization") implementation 'cn.taketoday:today-beans' implementation 'cn.taketoday:today-context' - implementation 'io.protostuff:protostuff-core:1.7.4' - implementation 'io.protostuff:protostuff-runtime:1.7.4' - optional "com.google.protobuf:protobuf-java" testImplementation project(":today-cloud-samples:demo-tests:demo-user-api") diff --git a/today-service-api/src/main/java/infra/cloud/serialize/ByteBufInput.java b/today-service-api/src/main/java/infra/cloud/serialize/ByteBufInput.java deleted file mode 100644 index 142fa92..0000000 --- a/today-service-api/src/main/java/infra/cloud/serialize/ByteBufInput.java +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Copyright 2021 - 2024 the original author or authors. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] - */ - -package infra.cloud.serialize; - -import java.io.IOException; -import java.nio.ByteBuffer; - -import io.netty.buffer.ByteBuf; -import io.protostuff.ByteString; -import io.protostuff.Input; -import io.protostuff.Output; -import io.protostuff.Schema; - -/** - * @author 海子 Yang - * @since 1.0 2024/12/20 21:35 - */ -public class ByteBufInput implements Input { - - private final ByteBuf buffer; - - public ByteBufInput(ByteBuf buffer) { - this.buffer = buffer; - } - - @Override - public void handleUnknownField(int fieldNumber, Schema schema) throws IOException { - - } - - @Override - public int readFieldNumber(Schema schema) throws IOException { - return 0; - } - - @Override - public int readInt32() throws IOException { - return 0; - } - - @Override - public int readUInt32() throws IOException { - return 0; - } - - @Override - public int readSInt32() throws IOException { - return 0; - } - - @Override - public int readFixed32() throws IOException { - return 0; - } - - @Override - public int readSFixed32() throws IOException { - return 0; - } - - @Override - public long readInt64() throws IOException { - return 0; - } - - @Override - public long readUInt64() throws IOException { - return 0; - } - - @Override - public long readSInt64() throws IOException { - return 0; - } - - @Override - public long readFixed64() throws IOException { - return 0; - } - - @Override - public long readSFixed64() throws IOException { - return 0; - } - - @Override - public float readFloat() throws IOException { - return 0; - } - - @Override - public double readDouble() throws IOException { - return 0; - } - - @Override - public boolean readBool() throws IOException { - return false; - } - - @Override - public int readEnum() throws IOException { - return 0; - } - - @Override - public String readString() throws IOException { - return ""; - } - - @Override - public ByteString readBytes() throws IOException { - return null; - } - - @Override - public void readBytes(ByteBuffer bb) throws IOException { - - } - - @Override - public byte[] readByteArray() throws IOException { - return new byte[0]; - } - - @Override - public ByteBuffer readByteBuffer() throws IOException { - return null; - } - - @Override - public T mergeObject(T value, Schema schema) throws IOException { - return null; - } - - @Override - public void transferByteRangeTo(Output output, boolean utf8String, int fieldNumber, boolean repeated) throws IOException { - - } -} diff --git a/today-service-api/src/main/java/infra/cloud/serialize/ByteBufOutput.java b/today-service-api/src/main/java/infra/cloud/serialize/ByteBufOutput.java deleted file mode 100644 index b73bb5b..0000000 --- a/today-service-api/src/main/java/infra/cloud/serialize/ByteBufOutput.java +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright 2021 - 2024 the original author or authors. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] - */ - -package infra.cloud.serialize; - -import java.io.IOException; -import java.nio.ByteBuffer; - -import io.netty.buffer.ByteBuf; -import io.protostuff.ByteString; -import io.protostuff.Output; -import io.protostuff.Schema; - -/** - * @author 海子 Yang - * @since 1.0 2024/12/20 21:28 - */ -public class ByteBufOutput implements Output { - private final ByteBuf buffer; - - public ByteBufOutput(ByteBuf buffer) { - this.buffer = buffer; - } - - @Override - public void writeInt32(int fieldNumber, int value, boolean repeated) throws IOException { - - } - - @Override - public void writeUInt32(int fieldNumber, int value, boolean repeated) throws IOException { - - } - - @Override - public void writeSInt32(int fieldNumber, int value, boolean repeated) throws IOException { - - } - - @Override - public void writeFixed32(int fieldNumber, int value, boolean repeated) throws IOException { - - } - - @Override - public void writeSFixed32(int fieldNumber, int value, boolean repeated) throws IOException { - - } - - @Override - public void writeInt64(int fieldNumber, long value, boolean repeated) throws IOException { - - } - - @Override - public void writeUInt64(int fieldNumber, long value, boolean repeated) throws IOException { - - } - - @Override - public void writeSInt64(int fieldNumber, long value, boolean repeated) throws IOException { - - } - - @Override - public void writeFixed64(int fieldNumber, long value, boolean repeated) throws IOException { - - } - - @Override - public void writeSFixed64(int fieldNumber, long value, boolean repeated) throws IOException { - - } - - @Override - public void writeFloat(int fieldNumber, float value, boolean repeated) throws IOException { - - } - - @Override - public void writeDouble(int fieldNumber, double value, boolean repeated) throws IOException { - - } - - @Override - public void writeBool(int fieldNumber, boolean value, boolean repeated) throws IOException { - - } - - @Override - public void writeEnum(int fieldNumber, int value, boolean repeated) throws IOException { - - } - - @Override - public void writeString(int fieldNumber, CharSequence value, boolean repeated) throws IOException { - - } - - @Override - public void writeBytes(int fieldNumber, ByteString value, boolean repeated) throws IOException { - - } - - @Override - public void writeByteArray(int fieldNumber, byte[] value, boolean repeated) throws IOException { - - } - - @Override - public void writeByteRange(boolean utf8String, int fieldNumber, byte[] value, int offset, int length, boolean repeated) throws IOException { - - } - - @Override - public void writeObject(int fieldNumber, T value, Schema schema, boolean repeated) throws IOException { - - } - - @Override - public void writeBytes(int fieldNumber, ByteBuffer value, boolean repeated) throws IOException { - - } -} diff --git a/today-service-api/src/main/java/infra/cloud/serialize/DefaultByteBufInput.java b/today-service-api/src/main/java/infra/cloud/serialize/DefaultByteBufInput.java new file mode 100644 index 0000000..97b9ffa --- /dev/null +++ b/today-service-api/src/main/java/infra/cloud/serialize/DefaultByteBufInput.java @@ -0,0 +1,114 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.serialize; + +import java.nio.charset.StandardCharsets; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; + +/** + * @author 海子 Yang + * @since 1.0 2024/12/20 21:35 + */ +public class DefaultByteBufInput implements Input { + + private final ByteBuf buffer; + + public DefaultByteBufInput(ByteBuf buffer) { + this.buffer = buffer; + } + + @Override + public void read(byte[] b) { + buffer.readBytes(b); + } + + @Override + public byte[] read() { + return ByteBufUtil.getBytes(buffer); + } + + @Override + public void read(byte[] b, int off, int len) { + buffer.readBytes(b, off, len); + } + + @Override + public int skipBytes(int n) { + int start = buffer.readerIndex(); + buffer.skipBytes(n); + return start - buffer.readerIndex(); + } + + @Override + public boolean readBoolean() { + return buffer.readBoolean(); + } + + @Override + public byte readByte() { + return buffer.readByte(); + } + + @Override + public int readUnsignedByte() { + return buffer.readUnsignedByte(); + } + + @Override + public short readShort() { + return buffer.readShort(); + } + + @Override + public int readUnsignedShort() { + return buffer.readUnsignedShort(); + } + + @Override + public char readChar() { + return buffer.readChar(); + } + + @Override + public int readInt() { + return buffer.readInt(); + } + + @Override + public long readLong() { + return buffer.readLong(); + } + + @Override + public float readFloat() { + return buffer.readFloat(); + } + + @Override + public double readDouble() { + return buffer.readDouble(); + } + + @Override + public String readString() { + return buffer.readString(readUnsignedShort(), StandardCharsets.UTF_8); + } + +} diff --git a/today-service-api/src/main/java/infra/cloud/serialize/DefaultByteBufOutput.java b/today-service-api/src/main/java/infra/cloud/serialize/DefaultByteBufOutput.java new file mode 100644 index 0000000..8fb7476 --- /dev/null +++ b/today-service-api/src/main/java/infra/cloud/serialize/DefaultByteBufOutput.java @@ -0,0 +1,88 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.serialize; + +import java.nio.charset.StandardCharsets; + +import io.netty.buffer.ByteBuf; + +/** + * @author 海子 Yang + * @since 1.0 2024/12/20 21:28 + */ +public class DefaultByteBufOutput implements Output { + + private final ByteBuf buffer; + + public DefaultByteBufOutput(ByteBuf buffer) { + this.buffer = buffer; + } + + @Override + public void write(byte b) { + buffer.writeByte(b); + } + + @Override + public void write(byte[] b) { + buffer.writeBytes(b); + } + + @Override + public void write(byte[] b, int off, int len) { + buffer.writeBytes(b, off, len); + } + + @Override + public void write(boolean v) { + buffer.writeBoolean(v); + } + + @Override + public void write(short v) { + buffer.writeShort(v); + } + + @Override + public void write(int v) { + buffer.writeInt(v); + } + + @Override + public void write(long v) { + buffer.writeLong(v); + } + + @Override + public void write(float v) { + buffer.writeFloat(v); + } + + @Override + public void write(double v) { + buffer.writeDouble(v); + } + + @Override + public void write(String s) { + int length = s.length(); + buffer.writeShort(length); + buffer.writeCharSequence(s, StandardCharsets.UTF_8); + } + +} diff --git a/today-service-api/src/main/java/infra/cloud/serialize/ProtobufArgumentSerialization.java b/today-service-api/src/main/java/infra/cloud/serialize/ProtobufArgumentSerialization.java index 8e00a7f..d6cb505 100644 --- a/today-service-api/src/main/java/infra/cloud/serialize/ProtobufArgumentSerialization.java +++ b/today-service-api/src/main/java/infra/cloud/serialize/ProtobufArgumentSerialization.java @@ -24,13 +24,10 @@ import java.lang.reflect.Method; import infra.cloud.RpcMethod; -import infra.cloud.core.serialize.DeserializeFailedException; import infra.core.MethodParameter; import infra.lang.Nullable; import infra.util.ConcurrentReferenceHashMap; import io.netty.buffer.ByteBuf; -import io.protostuff.Input; -import io.protostuff.Output; /** * Serialization for protobuf @@ -53,7 +50,7 @@ public void serialize(MethodParameter parameter, @Nullable Message value, ByteBu } @Override - public Message deserialize(MethodParameter parameter, ByteBuf payload, Input input) throws DeserializeFailedException { + public Message deserialize(MethodParameter parameter, ByteBuf payload, Input input) throws SerializationException { Class parameterType = parameter.getParameterType(); Message.Builder messageBuilder = getMessageBuilder(parameterType); @@ -75,7 +72,7 @@ private Message.Builder getMessageBuilder(Class clazz) { return (Message.Builder) method.invoke(clazz); } catch (Exception ex) { - throw new DeserializeFailedException( + throw new SerializationException( "Invalid Protobuf Message type: no invocable newBuilder() method on " + clazz, ex); } } @@ -90,20 +87,20 @@ public boolean supportsArgument(RpcMethod method) { } @Override - public void serialize(RpcMethod method, Message value, ByteBuf payload, Output output) throws IOException { - + public void serialize(RpcMethod method, Message value, ByteBuf payload, Output output) { + output.write(value.toByteArray()); } @Override - public Message deserialize(RpcMethod method, ByteBuf payload, Input input) throws DeserializeFailedException { + public Message deserialize(RpcMethod method, ByteBuf payload, Input input) throws SerializationException { Class parameterType = method.getReturnType().getParameterType(); Message.Builder messageBuilder = getMessageBuilder(parameterType); try { - return messageBuilder.mergeFrom(payload.array()).build(); + return messageBuilder.mergeFrom(input.read()).build(); } catch (InvalidProtocolBufferException e) { - throw new DeserializeFailedException(e); + throw new SerializationException("Invalid protocol buffer", e); } } diff --git a/today-service-api/src/main/java/infra/cloud/serialize/ReturnValueSerialization.java b/today-service-api/src/main/java/infra/cloud/serialize/ReturnValueSerialization.java index 4046971..c936550 100644 --- a/today-service-api/src/main/java/infra/cloud/serialize/ReturnValueSerialization.java +++ b/today-service-api/src/main/java/infra/cloud/serialize/ReturnValueSerialization.java @@ -17,13 +17,8 @@ package infra.cloud.serialize; -import java.io.IOException; - import infra.cloud.RpcMethod; -import infra.cloud.core.serialize.DeserializeFailedException; import io.netty.buffer.ByteBuf; -import io.protostuff.Input; -import io.protostuff.Output; /** * @author 海子 Yang @@ -39,8 +34,10 @@ public interface ReturnValueSerialization { */ boolean supportsArgument(RpcMethod method); - void serialize(RpcMethod method, T returnValue, ByteBuf payload, Output output) throws IOException; - - T deserialize(RpcMethod method, ByteBuf payload, Input input) throws DeserializeFailedException; + void serialize(RpcMethod method, T returnValue, ByteBuf payload, Output output) + throws SerializationException; + + T deserialize(RpcMethod method, ByteBuf payload, Input input) + throws SerializationException; } diff --git a/today-service-api/src/main/java/infra/cloud/serialize/RpcArgumentSerialization.java b/today-service-api/src/main/java/infra/cloud/serialize/RpcArgumentSerialization.java index 255ee64..f109c87 100644 --- a/today-service-api/src/main/java/infra/cloud/serialize/RpcArgumentSerialization.java +++ b/today-service-api/src/main/java/infra/cloud/serialize/RpcArgumentSerialization.java @@ -19,12 +19,9 @@ import java.io.IOException; -import infra.cloud.core.serialize.DeserializeFailedException; import infra.core.MethodParameter; import infra.lang.Nullable; import io.netty.buffer.ByteBuf; -import io.protostuff.Input; -import io.protostuff.Output; /** * @author 海子 Yang @@ -43,6 +40,6 @@ public interface RpcArgumentSerialization { void serialize(MethodParameter parameter, @Nullable T value, ByteBuf payload, Output output) throws IOException; @Nullable - T deserialize(MethodParameter parameter, ByteBuf payload, Input input) throws DeserializeFailedException; + T deserialize(MethodParameter parameter, ByteBuf payload, Input input) throws SerializationException; } diff --git a/today-service-api/src/main/java/infra/cloud/serialize/RpcRequestSerialization.java b/today-service-api/src/main/java/infra/cloud/serialize/RpcRequestSerialization.java index ea50662..c2642ef 100644 --- a/today-service-api/src/main/java/infra/cloud/serialize/RpcRequestSerialization.java +++ b/today-service-api/src/main/java/infra/cloud/serialize/RpcRequestSerialization.java @@ -25,7 +25,6 @@ import infra.cloud.RpcRequest; import infra.core.MethodParameter; import io.netty.buffer.ByteBuf; -import io.protostuff.Output; /** * @author 海子 Yang @@ -56,7 +55,7 @@ public void serialize(RpcRequest request, ByteBuf payload) throws IOException { int idx = 0; Object[] arguments = request.getArguments(); - Output output = new ByteBufOutput(payload); + Output output = new DefaultByteBufOutput(payload); beforeSerializeArguments(output, arguments); for (MethodParameter parameter : rpcMethod.getParameters()) { var serialization = findArgumentSerialization(parameter); diff --git a/today-service-api/src/main/java/infra/cloud/serialize/RpcResponseSerialization.java b/today-service-api/src/main/java/infra/cloud/serialize/RpcResponseSerialization.java index 10bcd35..802ec19 100644 --- a/today-service-api/src/main/java/infra/cloud/serialize/RpcResponseSerialization.java +++ b/today-service-api/src/main/java/infra/cloud/serialize/RpcResponseSerialization.java @@ -23,7 +23,6 @@ import infra.cloud.RpcMethod; import infra.cloud.RpcRequest; import infra.cloud.RpcResponse; -import infra.cloud.core.serialize.DeserializeFailedException; import io.netty.buffer.ByteBuf; /** @@ -55,11 +54,11 @@ public void serialize(RpcResponse response, ByteBuf payload) throws IOException var serialization = findSerialization(rpcMethod); Object result = response.getResult(); - serialization.serialize(rpcMethod, result, payload, new ByteBufOutput(payload)); + serialization.serialize(rpcMethod, result, payload, new DefaultByteBufOutput(payload)); } } - public RpcResponse deserialize(RpcRequest rpcRequest, ByteBuf body) throws DeserializeFailedException { + public RpcResponse deserialize(RpcRequest rpcRequest, ByteBuf body) throws SerializationException { RpcMethod rpcMethod = rpcRequest.getRpcMethod(); RpcResponse response = new RpcResponse(); response.setRpcMethod(rpcMethod); @@ -70,7 +69,7 @@ public RpcResponse deserialize(RpcRequest rpcRequest, ByteBuf body) throws Deser } else { var serialization = findSerialization(rpcMethod); - Object result = serialization.deserialize(rpcMethod, body, new ByteBufInput(body)); + Object result = serialization.deserialize(rpcMethod, body, new DefaultByteBufInput(body)); response.setResult(result); } return response; diff --git a/today-service-api/src/main/java/infra/cloud/serialize/SimpleValueArgumentSerialization.java b/today-service-api/src/main/java/infra/cloud/serialize/SimpleValueArgumentSerialization.java index 2f2c253..622b09d 100644 --- a/today-service-api/src/main/java/infra/cloud/serialize/SimpleValueArgumentSerialization.java +++ b/today-service-api/src/main/java/infra/cloud/serialize/SimpleValueArgumentSerialization.java @@ -22,13 +22,10 @@ import java.util.Map; import infra.beans.BeanUtils; -import infra.cloud.core.serialize.DeserializeFailedException; import infra.cloud.serialize.value.ValueSerialization; import infra.core.MethodParameter; import infra.lang.Nullable; import io.netty.buffer.ByteBuf; -import io.protostuff.Input; -import io.protostuff.Output; import static infra.cloud.serialize.value.ValueSerialization.map; @@ -69,7 +66,7 @@ public void serialize(MethodParameter parameter, @Nullable Object value, ByteBuf @Nullable @Override - public Object deserialize(MethodParameter parameter, ByteBuf payload, Input input) throws DeserializeFailedException { + public Object deserialize(MethodParameter parameter, ByteBuf payload, Input input) throws SerializationException { boolean isNull = payload.readBoolean(); if (isNull) { return null; diff --git a/today-service-api/src/main/java/infra/cloud/serialize/ThrowableSerialization.java b/today-service-api/src/main/java/infra/cloud/serialize/ThrowableSerialization.java index 3925bf0..5bf0e81 100644 --- a/today-service-api/src/main/java/infra/cloud/serialize/ThrowableSerialization.java +++ b/today-service-api/src/main/java/infra/cloud/serialize/ThrowableSerialization.java @@ -19,7 +19,6 @@ import java.io.IOException; -import infra.cloud.core.serialize.DeserializeFailedException; import io.netty.buffer.ByteBuf; /** @@ -32,7 +31,7 @@ public void serialize(Throwable throwable, ByteBuf payload) throws IOException { } - public Throwable deserialize(ByteBuf body) throws DeserializeFailedException { + public Throwable deserialize(ByteBuf body) throws SerializationException { return null; } diff --git a/today-service-api/src/main/java/infra/cloud/serialize/value/FuncValueSerialization.java b/today-service-api/src/main/java/infra/cloud/serialize/value/FuncValueSerialization.java index e76a579..5cdbb09 100644 --- a/today-service-api/src/main/java/infra/cloud/serialize/value/FuncValueSerialization.java +++ b/today-service-api/src/main/java/infra/cloud/serialize/value/FuncValueSerialization.java @@ -21,7 +21,7 @@ import java.util.function.BiConsumer; import java.util.function.Function; -import infra.cloud.core.serialize.DeserializeFailedException; +import infra.cloud.serialize.SerializationException; import infra.core.MethodParameter; import io.netty.buffer.ByteBuf; @@ -46,7 +46,7 @@ public void serialize(MethodParameter parameter, T value, ByteBuf payload) throw } @Override - public T deserialize(MethodParameter parameter, ByteBuf payload) throws DeserializeFailedException { + public T deserialize(MethodParameter parameter, ByteBuf payload) throws SerializationException { return reader.apply(payload); } diff --git a/today-service-api/src/main/java/infra/cloud/serialize/value/ValueSerialization.java b/today-service-api/src/main/java/infra/cloud/serialize/value/ValueSerialization.java index 11d156e..17feb1f 100644 --- a/today-service-api/src/main/java/infra/cloud/serialize/value/ValueSerialization.java +++ b/today-service-api/src/main/java/infra/cloud/serialize/value/ValueSerialization.java @@ -21,7 +21,7 @@ import java.util.function.BiConsumer; import java.util.function.Function; -import infra.cloud.core.serialize.DeserializeFailedException; +import infra.cloud.serialize.SerializationException; import infra.core.MethodParameter; import infra.lang.Assert; import io.netty.buffer.ByteBuf; @@ -34,7 +34,7 @@ public interface ValueSerialization { void serialize(MethodParameter parameter, T value, ByteBuf payload) throws IOException; - T deserialize(MethodParameter parameter, ByteBuf payload) throws DeserializeFailedException; + T deserialize(MethodParameter parameter, ByteBuf payload) throws SerializationException; static ValueSerialization map(Function reader, BiConsumer writer) { Assert.notNull(reader, "reader Function is required"); diff --git a/today-service-api/src/main/java/infra/cloud/service/InvocationResult.java b/today-service-api/src/main/java/infra/cloud/service/InvocationResult.java index e1a2f78..ce90d2e 100644 --- a/today-service-api/src/main/java/infra/cloud/service/InvocationResult.java +++ b/today-service-api/src/main/java/infra/cloud/service/InvocationResult.java @@ -45,6 +45,10 @@ default boolean isRequestResponse() { return getType() == InvocationType.REQUEST_RESPONSE; } + default boolean isStreaming() { + return !getType().serverSendsOneMessage(); + } + /** * Only for {@link InvocationType#REQUEST_RESPONSE} * diff --git a/today-service-api/src/main/java/infra/cloud/service/InvocationType.java b/today-service-api/src/main/java/infra/cloud/service/InvocationType.java index 9593148..0adead5 100644 --- a/today-service-api/src/main/java/infra/cloud/service/InvocationType.java +++ b/today-service-api/src/main/java/infra/cloud/service/InvocationType.java @@ -44,7 +44,7 @@ public enum InvocationType { DUPLEX_STREAMING; /** - * Returns {@code true} for {@code UNARY} and {@code RESPONSE_STREAMING}, which do not permit the + * Returns {@code true} for {@code REQUEST_RESPONSE} and {@code RESPONSE_STREAMING}, which do not permit the * client to stream. */ public final boolean clientSendsOneMessage() { @@ -52,7 +52,7 @@ public final boolean clientSendsOneMessage() { } /** - * Returns {@code true} for {@code UNARY} and {@code CLIENT_STREAMING}, which do not permit the + * Returns {@code true} for {@code REQUEST_RESPONSE}, which do not permit the * server to stream. */ public final boolean serverSendsOneMessage() { diff --git a/today-service-client/src/main/java/infra/cloud/service/AbstractInvocationResult.java b/today-service-client/src/main/java/infra/cloud/service/AbstractInvocationResult.java index c67af07..7092f17 100644 --- a/today-service-client/src/main/java/infra/cloud/service/AbstractInvocationResult.java +++ b/today-service-client/src/main/java/infra/cloud/service/AbstractInvocationResult.java @@ -18,11 +18,16 @@ package infra.cloud.service; import infra.core.AttributeAccessorSupport; +import infra.remoting.Payload; /** * @author 海子 Yang * @since 1.0 2025/8/9 16:17 */ -public abstract class AbstractInvocationResult extends AttributeAccessorSupport implements InvocationResult { +abstract class AbstractInvocationResult extends AttributeAccessorSupport implements InvocationResult { + + protected final Object deserialize(Payload payload) { + return null; + } } diff --git a/today-service-client/src/main/java/infra/cloud/service/ClientInterceptor.java b/today-service-client/src/main/java/infra/cloud/service/ClientInterceptor.java index c870ae9..61b16ef 100644 --- a/today-service-client/src/main/java/infra/cloud/service/ClientInterceptor.java +++ b/today-service-client/src/main/java/infra/cloud/service/ClientInterceptor.java @@ -27,8 +27,8 @@ * interceptor (traces all the calls on the intercepted method(s)): * *

      {@code
      - * class TracingInterceptor implements ServiceInterceptor {
      - *    public Object intercept(ServiceInvocation i) throws Throwable {
      + * class TracingInterceptor implements ClientInterceptor {
      + *    public InvocationResult intercept(ServiceInvocation i) throws Throwable {
        *         System.out.println("before service " + i + " with args " + i.getArguments());
        *         Object ret = i.proceed();
        *         System.out.println("after service " + i + " returns " + ret);
      diff --git a/today-service-client/src/main/java/infra/cloud/service/DefaultServiceInterfaceMetadataProvider.java b/today-service-client/src/main/java/infra/cloud/service/DefaultServiceInterfaceMetadataProvider.java
      index 85dfe49..b2ce2bf 100644
      --- a/today-service-client/src/main/java/infra/cloud/service/DefaultServiceInterfaceMetadataProvider.java
      +++ b/today-service-client/src/main/java/infra/cloud/service/DefaultServiceInterfaceMetadataProvider.java
      @@ -110,8 +110,8 @@ public InvocationType getInvocationType(ServiceInterfaceMethod method) {
           }
       
           @Override
      -    public Object resolve(ServiceInterfaceMethod method, InvocationResult result) throws Throwable {
      -      return Mono.fromFuture(result.future().completable());
      +    public Mono resolve(ServiceInterfaceMethod method, InvocationResult result) throws Throwable {
      +      return Mono.from(result.publisher());
           }
       
           @Override
      @@ -137,7 +137,7 @@ public InvocationType getInvocationType(ServiceInterfaceMethod method) {
           }
       
           @Override
      -    public Object resolve(ServiceInterfaceMethod method, InvocationResult result) throws Throwable {
      +    public Flux resolve(ServiceInterfaceMethod method, InvocationResult result) throws Throwable {
             return Flux.from(result.publisher());
           }
       
      diff --git a/today-service-client/src/main/java/infra/cloud/service/DuplexStreamingResult.java b/today-service-client/src/main/java/infra/cloud/service/DuplexStreamingResult.java
      new file mode 100644
      index 0000000..c1cfae4
      --- /dev/null
      +++ b/today-service-client/src/main/java/infra/cloud/service/DuplexStreamingResult.java
      @@ -0,0 +1,77 @@
      +/*
      + * Copyright 2021 - 2024 the original author or authors.
      + *
      + * This program is free software: you can redistribute it and/or modify
      + * it under the terms of the GNU General Public License as published by
      + * the Free Software Foundation, either version 3 of the License, or
      + * (at your option) any later version.
      + *
      + * This program is distributed in the hope that it will be useful,
      + * but WITHOUT ANY WARRANTY; without even the implied warranty of
      + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      + * GNU General Public License for more details.
      + *
      + * You should have received a copy of the GNU General Public License
      + * along with this program.  If not, see [http://www.gnu.org/licenses/]
      + */
      +
      +package infra.cloud.service;
      +
      +import org.reactivestreams.Publisher;
      +
      +import infra.remoting.Payload;
      +import infra.util.concurrent.Future;
      +import reactor.core.publisher.Flux;
      +
      +/**
      + * @author 海子 Yang
      + * @since 1.0 2025/8/15 20:35
      + */
      +class DuplexStreamingResult extends AbstractInvocationResult {
      +
      +  private final Flux payloadFlux;
      +
      +  public DuplexStreamingResult(Flux payloadFlux) {
      +    this.payloadFlux = payloadFlux;
      +  }
      +
      +  @Override
      +  public Object getValue() {
      +    return null;
      +  }
      +
      +  @Override
      +  public boolean isFailed() {
      +    return false;
      +  }
      +
      +  @Override
      +  public Throwable getException() {
      +    return null;
      +  }
      +
      +  @Override
      +  public InvocationType getType() {
      +    return InvocationType.DUPLEX_STREAMING;
      +  }
      +
      +  @Override
      +  public boolean isRequestResponse() {
      +    return false;
      +  }
      +
      +  @Override
      +  public boolean isStreaming() {
      +    return true;
      +  }
      +
      +  @Override
      +  public Future future() {
      +    return null;
      +  }
      +
      +  @Override
      +  public Publisher publisher() {
      +    return null;
      +  }
      +}
      diff --git a/today-service-client/src/main/java/infra/cloud/service/FireAndForgetResult.java b/today-service-client/src/main/java/infra/cloud/service/FireAndForgetResult.java
      new file mode 100644
      index 0000000..662103d
      --- /dev/null
      +++ b/today-service-client/src/main/java/infra/cloud/service/FireAndForgetResult.java
      @@ -0,0 +1,77 @@
      +/*
      + * Copyright 2021 - 2024 the original author or authors.
      + *
      + * This program is free software: you can redistribute it and/or modify
      + * it under the terms of the GNU General Public License as published by
      + * the Free Software Foundation, either version 3 of the License, or
      + * (at your option) any later version.
      + *
      + * This program is distributed in the hope that it will be useful,
      + * but WITHOUT ANY WARRANTY; without even the implied warranty of
      + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      + * GNU General Public License for more details.
      + *
      + * You should have received a copy of the GNU General Public License
      + * along with this program.  If not, see [http://www.gnu.org/licenses/]
      + */
      +
      +package infra.cloud.service;
      +
      +import org.reactivestreams.Publisher;
      +
      +import infra.util.concurrent.Future;
      +import reactor.core.publisher.Mono;
      +
      +/**
      + * @author 海子 Yang
      + * @since 1.0 2025/8/15 20:36
      + */
      +class FireAndForgetResult extends AbstractInvocationResult {
      +
      +  private final Mono fireAndForgetMono;
      +
      +  public FireAndForgetResult(Mono fireAndForgetMono) {
      +    this.fireAndForgetMono = fireAndForgetMono;
      +  }
      +
      +  @Override
      +  public Object getValue() {
      +    return null;
      +  }
      +
      +  @Override
      +  public boolean isFailed() {
      +    return false;
      +  }
      +
      +  @Override
      +  public Throwable getException() {
      +    return null;
      +  }
      +
      +  @Override
      +  public InvocationType getType() {
      +    return InvocationType.FIRE_AND_FORGET;
      +  }
      +
      +  @Override
      +  public boolean isRequestResponse() {
      +    return false;
      +  }
      +
      +  @Override
      +  public boolean isStreaming() {
      +    return false;
      +  }
      +
      +  @Override
      +  public Future future() {
      +    return null;
      +  }
      +
      +  @Override
      +  public Publisher publisher() {
      +    return fireAndForgetMono;
      +  }
      +
      +}
      diff --git a/today-service-client/src/main/java/infra/cloud/service/RequestResponseResult.java b/today-service-client/src/main/java/infra/cloud/service/RequestResponseResult.java
      new file mode 100644
      index 0000000..346be66
      --- /dev/null
      +++ b/today-service-client/src/main/java/infra/cloud/service/RequestResponseResult.java
      @@ -0,0 +1,80 @@
      +/*
      + * Copyright 2021 - 2024 the original author or authors.
      + *
      + * This program is free software: you can redistribute it and/or modify
      + * it under the terms of the GNU General Public License as published by
      + * the Free Software Foundation, either version 3 of the License, or
      + * (at your option) any later version.
      + *
      + * This program is distributed in the hope that it will be useful,
      + * but WITHOUT ANY WARRANTY; without even the implied warranty of
      + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      + * GNU General Public License for more details.
      + *
      + * You should have received a copy of the GNU General Public License
      + * along with this program.  If not, see [http://www.gnu.org/licenses/]
      + */
      +
      +package infra.cloud.service;
      +
      +import org.reactivestreams.Publisher;
      +
      +import infra.lang.Nullable;
      +import infra.remoting.Payload;
      +import infra.util.concurrent.Future;
      +import reactor.core.publisher.Mono;
      +
      +/**
      + * @author 海子 Yang
      + * @since 1.0 2025/8/15 19:55
      + */
      +class RequestResponseResult extends AbstractInvocationResult {
      +
      +  private final Mono payloadMono;
      +
      +  RequestResponseResult(Mono payloadMono) {
      +    this.payloadMono = payloadMono;
      +  }
      +
      +  @Nullable
      +  @Override
      +  public Object getValue() {
      +    return payloadMono.map(this::deserialize).block();
      +  }
      +
      +  @Override
      +  public boolean isFailed() {
      +    return false;
      +  }
      +
      +  @Override
      +  public Throwable getException() {
      +    return null;
      +  }
      +
      +  @Override
      +  public InvocationType getType() {
      +    return InvocationType.REQUEST_RESPONSE;
      +  }
      +
      +  @Override
      +  public boolean isRequestResponse() {
      +    return true;
      +  }
      +
      +  @Override
      +  public boolean isStreaming() {
      +    return false;
      +  }
      +
      +  @Override
      +  public Future future() {
      +    return null;
      +  }
      +
      +  @Override
      +  public Publisher publisher() {
      +    return null;
      +  }
      +
      +}
      diff --git a/today-service-client/src/main/java/infra/cloud/service/ResponseStreamingResult.java b/today-service-client/src/main/java/infra/cloud/service/ResponseStreamingResult.java
      new file mode 100644
      index 0000000..b9dcb8b
      --- /dev/null
      +++ b/today-service-client/src/main/java/infra/cloud/service/ResponseStreamingResult.java
      @@ -0,0 +1,77 @@
      +/*
      + * Copyright 2021 - 2024 the original author or authors.
      + *
      + * This program is free software: you can redistribute it and/or modify
      + * it under the terms of the GNU General Public License as published by
      + * the Free Software Foundation, either version 3 of the License, or
      + * (at your option) any later version.
      + *
      + * This program is distributed in the hope that it will be useful,
      + * but WITHOUT ANY WARRANTY; without even the implied warranty of
      + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      + * GNU General Public License for more details.
      + *
      + * You should have received a copy of the GNU General Public License
      + * along with this program.  If not, see [http://www.gnu.org/licenses/]
      + */
      +
      +package infra.cloud.service;
      +
      +import org.reactivestreams.Publisher;
      +
      +import infra.remoting.Payload;
      +import infra.util.concurrent.Future;
      +import reactor.core.publisher.Flux;
      +
      +/**
      + * @author 海子 Yang
      + * @since 1.0 2025/8/15 20:34
      + */
      +class ResponseStreamingResult extends AbstractInvocationResult {
      +
      +  private final Flux payloadFlux;
      +
      +  public ResponseStreamingResult(Flux payloadFlux) {
      +    this.payloadFlux = payloadFlux;
      +  }
      +
      +  @Override
      +  public Object getValue() {
      +    return null;
      +  }
      +
      +  @Override
      +  public boolean isFailed() {
      +    return false;
      +  }
      +
      +  @Override
      +  public Throwable getException() {
      +    return null;
      +  }
      +
      +  @Override
      +  public InvocationType getType() {
      +    return InvocationType.RESPONSE_STREAMING;
      +  }
      +
      +  @Override
      +  public boolean isRequestResponse() {
      +    return false;
      +  }
      +
      +  @Override
      +  public boolean isStreaming() {
      +    return true;
      +  }
      +
      +  @Override
      +  public Future future() {
      +    return null;
      +  }
      +
      +  @Override
      +  public Publisher publisher() {
      +    return null;
      +  }
      +}
      diff --git a/today-service-client/src/main/java/infra/cloud/service/ServiceMethodInvoker.java b/today-service-client/src/main/java/infra/cloud/service/ServiceMethodInvoker.java
      index 550591a..57a87e3 100644
      --- a/today-service-client/src/main/java/infra/cloud/service/ServiceMethodInvoker.java
      +++ b/today-service-client/src/main/java/infra/cloud/service/ServiceMethodInvoker.java
      @@ -21,7 +21,7 @@
       import org.reactivestreams.Subscriber;
       import org.reactivestreams.Subscription;
       
      -import infra.core.ReactiveAdapterRegistry;
      +import infra.cloud.serialize.RpcRequestSerialization;
       import infra.lang.Nullable;
       import infra.remoting.Payload;
       import infra.remoting.RemotingOperations;
      @@ -45,6 +45,8 @@ public class ServiceMethodInvoker implements ServiceInvoker {
       
         private final ServiceInterfaceMetadata metadata;
       
      +  private RpcRequestSerialization requestSerialization;
      +
         ServiceMethodInvoker(ServiceInterfaceMetadata metadata,
                 ClientInterceptor[] interceptors, RemotingOperationsProvider remotingOperationsProvider) {
           this.metadata = metadata;
      @@ -68,15 +70,12 @@ public MethodServiceInvocation0(ServiceInterfaceMethod serviceMethod, Object[] a
           @Override
           protected InvocationResult invokeRemoting() {
             RemotingOperations operations = remotingOperationsProvider.getRemotingOperations(getServiceMethod());
      -
      -      Publisher publisher = switch (getType()) {
      -        case FIRE_AND_FORGET -> operations.fireAndForget(createMonoPayload()).cast(Payload.class);
      -        case REQUEST_RESPONSE -> operations.requestResponse(createMonoPayload());
      -        case RESPONSE_STREAMING -> operations.requestStream(createMonoPayload());
      -        case DUPLEX_STREAMING -> operations.requestChannel(createChannelPayload());
      +      return switch (getType()) {
      +        case FIRE_AND_FORGET -> new FireAndForgetResult(operations.fireAndForget(createMonoPayload()));
      +        case REQUEST_RESPONSE -> new RequestResponseResult(operations.requestResponse(createMonoPayload()));
      +        case RESPONSE_STREAMING -> new ResponseStreamingResult(operations.requestStream(createMonoPayload()));
      +        case DUPLEX_STREAMING -> new DuplexStreamingResult(operations.requestChannel(createChannelPayload()));
             };
      -
      -      return new InvocationResult0(getType(), publisher);
           }
       
           private Mono createMonoPayload() {
      @@ -97,27 +96,30 @@ private Object deserialize(Payload payload) {
           return null;
         }
       
      -  class InvocationResult0 extends AbstractInvocationResult implements Subscriber, FutureListener> {
      +  class InvocationResult0 extends AbstractInvocationResult implements Publisher,
      +          Subscriber, FutureListener>, Subscription {
       
           @Nullable
           private Throwable throwable;
       
           private final InvocationType invocationType;
       
      -    private final Publisher publisher;
      +    private final Publisher payloadPublisher;
       
      -    private final Promise resultPromise = Future.forPromise();
      +    @Nullable
      +    private Promise resultPromise;
       
           @Nullable
           private Subscription payloadSubscription;
       
      +    private Subscriber downstream;
      +
           public InvocationResult0(InvocationType invocationType, Publisher publisher) {
             this.invocationType = invocationType;
      -      this.publisher = publisher;
      -      publisher.subscribe(this);
      -      resultPromise.onCompleted(this);
      +      this.payloadPublisher = publisher;
           }
       
      +    @Nullable
           @Override
           public Object getValue() {
             return future().join();
      @@ -141,41 +143,73 @@ public InvocationType getType() {
       
           @Override
           public Future future() {
      -      // TODO
      +      if (resultPromise == null) {
      +        resultPromise = Future.forPromise();
      +      }
             return resultPromise;
           }
       
           @Override
           public Publisher publisher() {
      -      ReactiveAdapterRegistry sharedInstance = ReactiveAdapterRegistry.getSharedInstance();
      -      return switch (getType()) {
      -        case FIRE_AND_FORGET -> Mono.from(publisher);
      -        case REQUEST_RESPONSE -> Mono.from(publisher).map(ServiceMethodInvoker.this::deserialize);
      -        case RESPONSE_STREAMING, DUPLEX_STREAMING -> Flux.from(publisher).map(ServiceMethodInvoker.this::deserialize);
      -      };
      +      return this;
      +    }
      +
      +    @Override
      +    public void subscribe(Subscriber downstream) {
      +      this.downstream = downstream;
      +      downstream.onSubscribe(this);
      +      payloadPublisher.subscribe(this);
      +      if (resultPromise != null) {
      +        resultPromise.onCompleted(this);
      +      }
      +    }
      +
      +    @Override
      +    public void request(long n) {
      +      if (Operators.validate(n) && payloadSubscription != null) {
      +        payloadSubscription.request(n);
      +      }
      +    }
      +
      +    @Override
      +    public void cancel() {
      +      if (payloadSubscription != null) {
      +        payloadSubscription.cancel();
      +        payloadSubscription = null;
      +      }
      +
      +      if (resultPromise != null) {
      +        resultPromise.cancel();
      +      }
           }
       
           @Override
           public void onSubscribe(Subscription s) {
             if (Operators.validate(payloadSubscription, s)) {
               this.payloadSubscription = s;
      -        s.request(Long.MAX_VALUE);
             }
           }
       
           @Override
           public void onNext(Payload payload) {
      -
      +      Object result = deserialize(payload);
      +      downstream.onNext(result);
      +      if (resultPromise != null) {
      +        resultPromise.trySuccess(result);
      +      }
           }
       
           @Override
           public void onError(Throwable t) {
      -
      +      downstream.onError(t);
           }
       
           @Override
           public void onComplete() {
      -
      +      downstream.onComplete();
      +      if (resultPromise != null && !resultPromise.isDone()) {
      +        resultPromise.trySuccess(null);
      +      }
           }
       
           @Override
      diff --git a/today-service-client/src/test/java/infra/cloud/service/TracingInterceptor.java b/today-service-client/src/test/java/infra/cloud/service/TracingInterceptor.java
      new file mode 100644
      index 0000000..d33222d
      --- /dev/null
      +++ b/today-service-client/src/test/java/infra/cloud/service/TracingInterceptor.java
      @@ -0,0 +1,46 @@
      +/*
      + * Copyright 2021 - 2024 the original author or authors.
      + *
      + * This program is free software: you can redistribute it and/or modify
      + * it under the terms of the GNU General Public License as published by
      + * the Free Software Foundation, either version 3 of the License, or
      + * (at your option) any later version.
      + *
      + * This program is distributed in the hope that it will be useful,
      + * but WITHOUT ANY WARRANTY; without even the implied warranty of
      + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      + * GNU General Public License for more details.
      + *
      + * You should have received a copy of the GNU General Public License
      + * along with this program.  If not, see [http://www.gnu.org/licenses/]
      + */
      +
      +package infra.cloud.service;
      +
      +import java.util.Arrays;
      +
      +/**
      + * @author 海子 Yang
      + * @since 1.0 2025/8/13 16:56
      + */
      +class TracingInterceptor implements ClientInterceptor {
      +
      +  @Override
      +  public InvocationResult intercept(ServiceInvocation invocation) throws Throwable {
      +    System.out.printf("before service %s with args %s%n", invocation, Arrays.toString(invocation.getArguments()));
      +    InvocationResult result = invocation.proceed();
      +
      +    if (result.isRequestResponse()) {
      +      result.future().onCompleted(future -> {
      +        if (future.isSuccess()) {
      +          System.out.printf("after service %s returns %s%n", invocation, future.getNow());
      +        }
      +        else {
      +          System.out.printf("service %s failed %s%n", invocation, future.getCause());
      +        }
      +      });
      +    }
      +    return result;
      +  }
      +
      +}
      diff --git a/today-service-provider/build.gradle b/today-service-provider/build.gradle
      index 361be72..c31a9ef 100644
      --- a/today-service-provider/build.gradle
      +++ b/today-service-provider/build.gradle
      @@ -31,9 +31,6 @@ dependencies {
         optional 'io.netty:netty-handler'
         optional 'io.netty:netty-transport-classes-epoll'
       
      -  implementation 'io.protostuff:protostuff-core:1.7.4'
      -  implementation 'io.protostuff:protostuff-runtime:1.7.4'
      -
       }
       
       // --add-opens=java.base/java.nio=ALL-UNNAMED
      diff --git a/today-service-provider/src/main/java/infra/cloud/provider/RpcRequestDeserializer.java b/today-service-provider/src/main/java/infra/cloud/provider/RpcRequestDeserializer.java
      index c4c1c2b..f27cfe0 100644
      --- a/today-service-provider/src/main/java/infra/cloud/provider/RpcRequestDeserializer.java
      +++ b/today-service-provider/src/main/java/infra/cloud/provider/RpcRequestDeserializer.java
      @@ -24,8 +24,8 @@
       import java.util.Objects;
       
       import infra.cloud.RpcRequest;
      -import infra.cloud.core.serialize.DeserializeFailedException;
       import infra.cloud.serialize.RpcArgumentSerialization;
      +import infra.cloud.serialize.SerializationException;
       import infra.lang.Nullable;
       import infra.reflect.MethodInvoker;
       import infra.util.ClassUtils;
      @@ -48,7 +48,7 @@ public RpcRequestDeserializer(List argumentSerializati
           this.argumentSerializations = argumentSerializations;
         }
       
      -  public RpcRequest deserialize(ByteBuf payload) throws DeserializeFailedException {
      +  public RpcRequest deserialize(ByteBuf payload) throws SerializationException {
           RpcRequest rpcRequest = new RpcRequest();
       //    ByteBufInput input = new ByteBufInput(payload);
       
      diff --git a/today-service-serialization/build.gradle b/today-service-serialization/build.gradle
      new file mode 100644
      index 0000000..b7382ea
      --- /dev/null
      +++ b/today-service-serialization/build.gradle
      @@ -0,0 +1,13 @@
      +description = "TODAY Service serialization API and default format based on msgpack specification"
      +
      +dependencies {
      +  api "cn.taketoday:today-core"
      +
      +}
      +
      +compileJava {
      +  options.compilerArgs += [
      +      "--add-exports=java.base/sun.nio.ch=ALL-UNNAMED"
      +  ]
      +}
      +
      diff --git a/today-cloud-core/src/main/java/infra/cloud/core/serialize/Deserializer.java b/today-service-serialization/src/main/java/infra/cloud/serialize/Deserializer.java
      similarity index 59%
      rename from today-cloud-core/src/main/java/infra/cloud/core/serialize/Deserializer.java
      rename to today-service-serialization/src/main/java/infra/cloud/serialize/Deserializer.java
      index 192c41f..4a83e70 100644
      --- a/today-cloud-core/src/main/java/infra/cloud/core/serialize/Deserializer.java
      +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/Deserializer.java
      @@ -15,32 +15,22 @@
        * along with this program.  If not, see [http://www.gnu.org/licenses/]
        */
       
      -package infra.cloud.core.serialize;
      +package infra.cloud.serialize;
       
       import java.io.IOException;
      -import java.io.InputStream;
       
       /**
      - * A strategy interface for converting from data in an InputStream to an Object.
      + * A strategy interface for converting from data in an Input to an Object.
        *
      - * @author TODAY 2021/7/8 22:53
      - * @author Gary Russell
      - * @author Mark Fisher
      + * @author 海子 Yang
      + * @since 1.0 2025/8/16 16:59
        */
      -@Deprecated
      -@FunctionalInterface
       public interface Deserializer {
       
         /**
      -   * Read (assemble) an object of type T from the given InputStream.
      -   * 

      Note: Implementations should not close the given InputStream - * (or any decorators of that InputStream) but rather leave this up - * to the caller. - * - * @param inputStream the input stream * @return the deserialized object * @throws IOException in case of errors reading from the stream */ - Object deserialize(InputStream inputStream) throws IOException, ClassNotFoundException; + Object read(Input input) throws IOException; } diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/Input.java b/today-service-serialization/src/main/java/infra/cloud/serialize/Input.java new file mode 100644 index 0000000..fbdf33f --- /dev/null +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/Input.java @@ -0,0 +1,272 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.serialize; + +/** + * An Input lets an application read primitive data types and objects from a source of data. + * + * @author 海子 Yang + * @see java.io.DataInput + * @since 1.0 2025/8/16 16:59 + */ +public interface Input { + + /** + * Reads some bytes from an input + * stream and stores them into the buffer + * array {@code b}. The number of bytes + * read is equal + * to the length of {@code b}. + * + * @param b the buffer into which the data is read. + * @throws NullPointerException if {@code b} is {@code null}. + */ + void read(byte[] b) throws SerializationException; + + /** + * Reads {@code len} bytes from an input. + * + * @param b the buffer into which the data is read. + * @param off an int specifying the offset in the data array {@code b}. + * @param len an int specifying the number of bytes to read. + * @throws NullPointerException if {@code b} is {@code null}. + * @throws IndexOutOfBoundsException if {@code off} is negative, + * {@code len} is negative, or {@code len} is greater than + * {@code b.length - off}. + */ + void read(byte[] b, int off, int len) throws SerializationException; + + byte[] read(); + + default void read(Message message) throws SerializationException { + message.readFrom(this); + } + + /** + * Makes an attempt to skip over + * {@code n} bytes + * of data from the input + * stream, discarding the skipped bytes. However, + * it may skip + * over some smaller number of + * bytes, possibly zero. This may result from + * any of a + * number of conditions; reaching + * end of file before {@code n} bytes + * have been skipped is + * only one possibility. + * This method never throws an {@code EOFException}. + * The actual + * number of bytes skipped is returned. + * + * @param n the number of bytes to be skipped. + * @return the number of bytes actually skipped. + * @throws SerializationException if an I/O error occurs. + */ + int skipBytes(int n) throws SerializationException; + + /** + * Reads one input byte and returns + * {@code true} if that byte is nonzero, + * {@code false} if that byte is zero. + * This method is suitable for reading + * the byte written by the {@code writeBoolean} + * method of interface {@code Input}. + * + * @return the {@code boolean} value read. + * @throws SerializationException if an I/O error occurs. + */ + boolean readBoolean() throws SerializationException; + + /** + * Reads and returns one input byte. + * The byte is treated as a signed value in + * the range {@code -128} through {@code 127}, + * inclusive. + * This method is suitable for + * reading the byte written by the {@code writeByte} + * method of interface {@code Input}. + * + * @return the 8-bit value read. + * @throws SerializationException if an I/O error occurs. + */ + byte readByte() throws SerializationException; + + /** + * Reads one input byte, zero-extends + * it to type {@code int}, and returns + * the result, which is therefore in the range + * {@code 0} + * through {@code 255}. + * This method is suitable for reading + * the byte written by the {@code writeByte} + * method of interface {@code Input} + * if the argument to {@code writeByte} + * was intended to be a value in the range + * {@code 0} through {@code 255}. + * + * @return the unsigned 8-bit value read. + * @throws SerializationException if an I/O error occurs. + */ + int readUnsignedByte() throws SerializationException; + + /** + * Reads two input bytes and returns + * a {@code short} value. Let {@code a} + * be the first byte read and {@code b} + * be the second byte. The value + * returned + * is: + *

      {@code (short)((a << 8) | (b & 0xff))
      +   * }
      + * This method + * is suitable for reading the bytes written + * by the {@code writeShort} method of + * interface {@code Input}. + * + * @return the 16-bit value read. + * @throws SerializationException if an I/O error occurs. + */ + short readShort() throws SerializationException; + + /** + * Reads two input bytes and returns + * an {@code int} value in the range {@code 0} + * through {@code 65535}. Let {@code a} + * be the first byte read and + * {@code b} + * be the second byte. The value returned is: + *
      {@code (((a & 0xff) << 8) | (b & 0xff))
      +   * }
      + * This method is suitable for reading the bytes + * written by the {@code writeShort} method + * of interface {@code Input} if + * the argument to {@code writeShort} + * was intended to be a value in the range + * {@code 0} through {@code 65535}. + * + * @return the unsigned 16-bit value read. + * @throws SerializationException if an I/O error occurs. + */ + int readUnsignedShort() throws SerializationException; + + /** + * Reads two input bytes and returns a {@code char} value. + * Let {@code a} + * be the first byte read and {@code b} + * be the second byte. The value + * returned is: + *
      {@code (char)((a << 8) | (b & 0xff))
      +   * }
      + * This method + * is suitable for reading bytes written by + * the {@code writeChar} method of interface + * {@code Input}. + * + * @return the {@code char} value read. + * @throws SerializationException if an I/O error occurs. + */ + char readChar() throws SerializationException; + + /** + * Reads four input bytes and returns an + * {@code int} value. Let {@code a-d} + * be the first through fourth bytes read. The value returned is: + *
      {@code
      +   * (((a & 0xff) << 24) | ((b & 0xff) << 16) |
      +   *  ((c & 0xff) <<  8) | (d & 0xff))
      +   * }
      + * This method is suitable + * for reading bytes written by the {@code writeInt} + * method of interface {@code Input}. + * + * @return the {@code int} value read. + * @throws SerializationException if an I/O error occurs. + */ + int readInt() throws SerializationException; + + /** + * Reads eight input bytes and returns + * a {@code long} value. Let {@code a-h} + * be the first through eighth bytes read. + * The value returned is: + *
      {@code
      +   * (((long)(a & 0xff) << 56) |
      +   *  ((long)(b & 0xff) << 48) |
      +   *  ((long)(c & 0xff) << 40) |
      +   *  ((long)(d & 0xff) << 32) |
      +   *  ((long)(e & 0xff) << 24) |
      +   *  ((long)(f & 0xff) << 16) |
      +   *  ((long)(g & 0xff) <<  8) |
      +   *  ((long)(h & 0xff)))
      +   * }
      + *

      + * This method is suitable + * for reading bytes written by the {@code writeLong} + * method of interface {@code Input}. + * + * @return the {@code long} value read. + * @throws SerializationException if an I/O error occurs. + */ + long readLong() throws SerializationException; + + /** + * Reads four input bytes and returns + * a {@code float} value. It does this + * by first constructing an {@code int} + * value in exactly the manner + * of the {@code readInt} + * method, then converting this {@code int} + * value to a {@code float} in + * exactly the manner of the method {@code Float.intBitsToFloat}. + * This method is suitable for reading + * bytes written by the {@code writeFloat} + * method of interface {@code Input}. + * + * @return the {@code float} value read. + * @throws SerializationException if an I/O error occurs. + */ + float readFloat() throws SerializationException; + + /** + * Reads eight input bytes and returns + * a {@code double} value. It does this + * by first constructing a {@code long} + * value in exactly the manner + * of the {@code readLong} + * method, then converting this {@code long} + * value to a {@code double} in exactly + * the manner of the method {@code Double.longBitsToDouble}. + * This method is suitable for reading + * bytes written by the {@code writeDouble} + * method of interface {@code Input}. + * + * @return the {@code double} value read. + * @throws SerializationException if an I/O error occurs. + */ + double readDouble() throws SerializationException; + + /** + * Reads a {@link String} field value. + * + * @return a string. + * @throws SerializationException if an I/O error occurs. + */ + String readString() throws SerializationException; + +} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/Message.java b/today-service-serialization/src/main/java/infra/cloud/serialize/Message.java new file mode 100644 index 0000000..035e82b --- /dev/null +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/Message.java @@ -0,0 +1,60 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.serialize; + +/** + * Only the identity of the class of a Message instance is + * written in the serialization stream, and it is the responsibility + * of the class to save and restore the contents of its instances. + *

      + * The writeTo and readFrom methods of the Message + * interface are implemented by a class to give the class complete + * control over the format and contents of the stream for an object + * and its supertypes. + * + * @author 海子 Yang + * @see java.io.Serializable + * @see java.io.Externalizable + * @since 1.0 2025/8/16 23:42 + */ +public interface Message { + + /** + * The object implements the writeTo method to save its contents + * by calling the methods of {@link Output} for its primitive values or + * calling the write method of Output for objects, strings, + * and arrays. + * + * @param output the stream to write the object to + * @throws SerializationException Serialization occur + */ + void writeTo(Output output); + + /** + * The object implements the readFrom method to restore its + * contents by calling the methods of {@link Input} for primitive + * types and read for objects, strings and arrays. The + * readFrom method must read the values in the same sequence + * and with the same types as were written by writeTo. + * + * @param input the source to read data from in order to restore the object + * @throws SerializationException Serialization occur + */ + void readFrom(Input input); + +} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/Output.java b/today-service-serialization/src/main/java/infra/cloud/serialize/Output.java new file mode 100644 index 0000000..37972fa --- /dev/null +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/Output.java @@ -0,0 +1,209 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.serialize; + +/** + * @author 海子 Yang + * @see java.io.DataOutput + * @since 1.0 2025/8/16 16:58 + */ +public interface Output { + + /** + * Writes to the output stream the eight + * low-order bits of the argument {@code b}. + * The 24 high-order bits of {@code b} + * are ignored. + * + * @param b the byte to be written. + * @throws SerializationException if an I/O error occurs. + */ + void write(byte b) throws SerializationException; + + /** + * Writes to the output stream all the bytes in array {@code b}. + * If {@code b} is {@code null}, + * a {@code NullPointerException} is thrown. + * If {@code b.length} is zero, then + * no bytes are written. Otherwise, the byte + * {@code b[0]} is written first, then + * {@code b[1]}, and so on; the last byte + * written is {@code b[b.length-1]}. + * + * @param b the data. + * @throws SerializationException if an I/O error occurs. + */ + void write(byte[] b) throws SerializationException; + + /** + * Writes {@code len} bytes from array + * {@code b}, in order, to + * the output stream. If {@code b} + * is {@code null}, a {@code NullPointerException} + * is thrown. If {@code off} is negative, + * or {@code len} is negative, or {@code off+len} + * is greater than the length of the array + * {@code b}, then an {@code IndexOutOfBoundsException} + * is thrown. If {@code len} is zero, + * then no bytes are written. Otherwise, the + * byte {@code b[off]} is written first, + * then {@code b[off+1]}, and so on; the + * last byte written is {@code b[off+len-1]}. + * + * @param b the data. + * @param off the start offset in the data. + * @param len the number of bytes to write. + * @throws SerializationException if an I/O error occurs. + */ + void write(byte[] b, int off, int len) throws SerializationException; + + /** + * Writes a {@code boolean} value to this output stream. + * If the argument {@code v} + * is {@code true}, the value {@code (byte)1} + * is written; if {@code v} is {@code false}, + * the value {@code (byte)0} is written. + * The byte written by this method may + * be read by the {@code readBoolean} + * method of interface {@code DataInput}, + * which will then return a {@code boolean} + * equal to {@code v}. + * + * @param v the boolean to be written. + * @throws SerializationException if an I/O error occurs. + */ + void write(boolean v) throws SerializationException; + + /** + * Writes two bytes to the output + * stream to represent the value of the argument. + * The byte values to be written, in the order + * shown, are: + *

      {@code
      +   * (byte)(0xff & (v >> 8))
      +   * (byte)(0xff & v)
      +   * }

      + * The bytes written by this method may be + * read by the {@code readShort} method + * of interface {@code DataInput}, which + * will then return a {@code short} equal + * to {@code (short)v}. + * + * @param v the {@code short} value to be written. + * @throws SerializationException if an I/O error occurs. + */ + void write(short v) throws SerializationException; + + /** + * Writes an {@code int} value, which is + * comprised of four bytes, to the output stream. + * The byte values to be written, in the order + * shown, are: + *

      {@code
      +   * (byte)(0xff & (v >> 24))
      +   * (byte)(0xff & (v >> 16))
      +   * (byte)(0xff & (v >>  8))
      +   * (byte)(0xff & v)
      +   * }

      + * The bytes written by this method may be read + * by the {@code readInt} method of interface + * {@code DataInput}, which will then + * return an {@code int} equal to {@code v}. + * + * @param v the {@code int} value to be written. + * @throws SerializationException if an I/O error occurs. + */ + void write(int v) throws SerializationException; + + /** + * Writes a {@code long} value, which is + * comprised of eight bytes, to the output stream. + * The byte values to be written, in the order + * shown, are: + *

      {@code
      +   * (byte)(0xff & (v >> 56))
      +   * (byte)(0xff & (v >> 48))
      +   * (byte)(0xff & (v >> 40))
      +   * (byte)(0xff & (v >> 32))
      +   * (byte)(0xff & (v >> 24))
      +   * (byte)(0xff & (v >> 16))
      +   * (byte)(0xff & (v >>  8))
      +   * (byte)(0xff & v)
      +   * }

      + * The bytes written by this method may be + * read by the {@code readLong} method + * of interface {@code DataInput}, which + * will then return a {@code long} equal + * to {@code v}. + * + * @param v the {@code long} value to be written. + * @throws SerializationException if an I/O error occurs. + */ + void write(long v) throws SerializationException; + + /** + * Writes a {@code float} value, + * which is comprised of four bytes, to the output stream. + * It does this as if it first converts this + * {@code float} value to an {@code int} + * in exactly the manner of the {@code Float.floatToIntBits} + * method and then writes the {@code int} + * value in exactly the manner of the {@code writeInt} + * method. The bytes written by this method + * may be read by the {@code readFloat} + * method of interface {@code DataInput}, + * which will then return a {@code float} + * equal to {@code v}. + * + * @param v the {@code float} value to be written. + * @throws SerializationException if an I/O error occurs. + */ + void write(float v) throws SerializationException; + + /** + * Writes a {@code double} value, + * which is comprised of eight bytes, to the output stream. + * It does this as if it first converts this + * {@code double} value to a {@code long} + * in exactly the manner of the {@code Double.doubleToLongBits} + * method and then writes the {@code long} + * value in exactly the manner of the {@code writeLong} + * method. The bytes written by this method + * may be read by the {@code readDouble} + * method of interface {@code DataInput}, + * which will then return a {@code double} + * equal to {@code v}. + * + * @param v the {@code double} value to be written. + * @throws SerializationException if an I/O error occurs. + */ + void write(double v) throws SerializationException; + + /** + * Writes string + * + * @param s the string value to be written. + * @throws SerializationException if an I/O error occurs. + */ + void write(String s) throws SerializationException; + + default void write(Message message) throws SerializationException { + message.writeTo(this); + } + +} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/Serialization.java b/today-service-serialization/src/main/java/infra/cloud/serialize/Serialization.java new file mode 100644 index 0000000..d741da5 --- /dev/null +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/Serialization.java @@ -0,0 +1,26 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.serialize; + +/** + * @author 海子 Yang + * @since 1.0 2025/8/16 16:57 + */ +public interface Serialization extends Deserializer, Serializer { + +} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/SerializationException.java b/today-service-serialization/src/main/java/infra/cloud/serialize/SerializationException.java new file mode 100644 index 0000000..156a67b --- /dev/null +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/SerializationException.java @@ -0,0 +1,32 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.serialize; + +import infra.lang.Nullable; + +/** + * @author 海子 Yang + * @since 1.0 2025/8/16 17:04 + */ +public class SerializationException extends RuntimeException { + + public SerializationException(@Nullable String message, @Nullable Throwable cause) { + super(message, cause); + } + +} diff --git a/today-cloud-core/src/main/java/infra/cloud/core/serialize/Serializer.java b/today-service-serialization/src/main/java/infra/cloud/serialize/Serializer.java similarity index 63% rename from today-cloud-core/src/main/java/infra/cloud/core/serialize/Serializer.java rename to today-service-serialization/src/main/java/infra/cloud/serialize/Serializer.java index b4324be..3779555 100644 --- a/today-cloud-core/src/main/java/infra/cloud/core/serialize/Serializer.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/Serializer.java @@ -15,32 +15,23 @@ * along with this program. If not, see [http://www.gnu.org/licenses/] */ -package infra.cloud.core.serialize; +package infra.cloud.serialize; import java.io.IOException; -import java.io.OutputStream; /** - * A strategy interface for streaming an object to an OutputStream. - * - * @author Gary Russell - * @author Mark Fisher - * @author TODAY 2021/7/8 22:52 + * @author 海子 Yang + * @since 1.0 2025/8/16 16:57 */ -@Deprecated -@FunctionalInterface public interface Serializer { /** - * Write an object of type T to the given OutputStream. - *

      Note: Implementations should not close the given OutputStream - * (or any decorators of that OutputStream) but rather leave this up - * to the caller. + * Write an object to the given Output. * * @param object the object to serialize * @param output the output stream * @throws IOException in case of errors writing to the stream */ - void serialize(Object object, OutputStream output) throws IOException; + void write(Object object, Output output) throws IOException; } diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/ExtensionTypeHeader.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/ExtensionTypeHeader.java new file mode 100644 index 0000000..23af74e --- /dev/null +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/ExtensionTypeHeader.java @@ -0,0 +1,83 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.serialize.format; + +import infra.lang.Assert; + +/** + * Header of the Extension types + */ +public class ExtensionTypeHeader { + private final byte type; + private final int length; + + /** + * Create an extension type header + * Example: + *

      +   * {@code
      +   * ...
      +   * ExtensionTypeHeader header = new ExtensionTypeHeader(checkedCastToByte(0x01), 32);
      +   * ...
      +   * }
      +   * 
      + * + * @param type extension type (byte). You can check the valid byte range with {@link #checkedCastToByte(int)} method. + * @param length extension type data length + */ + public ExtensionTypeHeader(byte type, int length) { + Assert.isTrue(length >= 0, "length must be >= 0"); + this.type = type; + this.length = length; + } + + public static byte checkedCastToByte(int code) { + Assert.isTrue(Byte.MIN_VALUE <= code && code <= Byte.MAX_VALUE, "Extension type code must be within the range of byte"); + return (byte) code; + } + + public byte getType() { + return type; + } + + public boolean isTimestampType() { + return type == MessagePack.Code.EXT_TIMESTAMP; + } + + public int getLength() { + return length; + } + + @Override + public int hashCode() { + return (type + 31) * 31 + length; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof ExtensionTypeHeader other) { + return this.type == other.type && this.length == other.length; + } + return false; + } + + @Override + public String toString() { + return String.format("ExtensionTypeHeader(type:%d, length:%,d)", type, length); + } +} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageBufferPacker.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageBufferPacker.java new file mode 100644 index 0000000..97eb415 --- /dev/null +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageBufferPacker.java @@ -0,0 +1,124 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.serialize.format; + +import java.io.IOException; +import java.util.List; + +import infra.cloud.serialize.format.buffer.ArrayBufferOutput; +import infra.cloud.serialize.format.buffer.MessageBuffer; +import infra.cloud.serialize.format.buffer.MessageBufferOutput; + +/** + * MessagePacker that is useful to produce byte array output. + *

      + * This class allocates a new buffer instead of resizing the buffer when data doesn't fit in the initial capacity. + * This is faster than ByteArrayOutputStream especially when size of written bytes is large because resizing a buffer + * usually needs to copy contents of the buffer. + */ +public class MessageBufferPacker extends MessagePacker { + + protected MessageBufferPacker(MessagePack.PackerConfig config) { + this(new ArrayBufferOutput(config.getBufferSize()), config); + } + + protected MessageBufferPacker(ArrayBufferOutput out, MessagePack.PackerConfig config) { + super(out, config); + } + + public MessageBufferOutput reset(MessageBufferOutput out) throws IOException { + if (!(out instanceof ArrayBufferOutput)) { + throw new IllegalArgumentException("MessageBufferPacker accepts only ArrayBufferOutput"); + } + return super.reset(out); + } + + private ArrayBufferOutput getArrayBufferOut() { + return (ArrayBufferOutput) out; + } + + @Override + public void clear() { + super.clear(); + getArrayBufferOut().clear(); + } + + /** + * Gets copy of the written data as a byte array. + *

      + * If your application needs better performance and smaller memory consumption, you may prefer + * {@link #toMessageBuffer()} or {@link #toBufferList()} to avoid copying. + * + * @return the byte array + */ + public byte[] toByteArray() { + try { + flush(); + } + catch (IOException ex) { + // IOException must not happen because underlying ArrayBufferOutput never throws IOException + throw new RuntimeException(ex); + } + return getArrayBufferOut().toByteArray(); + } + + /** + * Gets the written data as a MessageBuffer. + *

      + * Unlike {@link #toByteArray()}, this method omits copy of the contents if size of the written data is smaller + * than a single buffer capacity. + * + * @return the MessageBuffer instance + */ + public MessageBuffer toMessageBuffer() { + try { + flush(); + } + catch (IOException ex) { + // IOException must not happen because underlying ArrayBufferOutput never throws IOException + throw new RuntimeException(ex); + } + return getArrayBufferOut().toMessageBuffer(); + } + + /** + * Returns the written data as a list of MessageBuffer. + *

      + * Unlike {@link #toByteArray()} or {@link #toMessageBuffer()}, this is the fastest method that doesn't + * copy contents in any cases. + * + * @return the list of MessageBuffer instances + */ + public List toBufferList() { + try { + flush(); + } + catch (IOException ex) { + // IOException must not happen because underlying ArrayBufferOutput never throws IOException + throw new RuntimeException(ex); + } + return getArrayBufferOut().toBufferList(); + } + + /** + * @return the size of the buffer in use + */ + public int getBufferSize() { + return getArrayBufferOut().getSize(); + } +} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageFormat.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageFormat.java new file mode 100644 index 0000000..fd25c00 --- /dev/null +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageFormat.java @@ -0,0 +1,164 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.serialize.format; + +import infra.cloud.serialize.format.MessagePack.Code; +import infra.cloud.serialize.format.value.ValueType; +import infra.lang.VisibleForTesting; + +/** + * Describes the list of the message format types defined in the MessagePack specification. + */ +public enum MessageFormat { + // INT7 + POS_FIX_INT(ValueType.INTEGER), + // MAP4 + FIX_MAP(ValueType.MAP), + // ARRAY4 + FIX_ARRAY(ValueType.ARRAY), + // STR5 + FIX_STR(ValueType.STRING), + NIL(ValueType.NIL), + NEVER_USED(null), + BOOLEAN(ValueType.BOOLEAN), + BIN8(ValueType.BINARY), + BIN16(ValueType.BINARY), + BIN32(ValueType.BINARY), + EXT8(ValueType.EXTENSION), + EXT16(ValueType.EXTENSION), + EXT32(ValueType.EXTENSION), + FLOAT32(ValueType.FLOAT), + FLOAT64(ValueType.FLOAT), + UINT8(ValueType.INTEGER), + UINT16(ValueType.INTEGER), + UINT32(ValueType.INTEGER), + UINT64(ValueType.INTEGER), + + INT8(ValueType.INTEGER), + INT16(ValueType.INTEGER), + INT32(ValueType.INTEGER), + INT64(ValueType.INTEGER), + FIX_EXT1(ValueType.EXTENSION), + FIX_EXT2(ValueType.EXTENSION), + FIX_EXT4(ValueType.EXTENSION), + FIX_EXT8(ValueType.EXTENSION), + FIX_EXT16(ValueType.EXTENSION), + STR8(ValueType.STRING), + STR16(ValueType.STRING), + STR32(ValueType.STRING), + ARRAY16(ValueType.ARRAY), + ARRAY32(ValueType.ARRAY), + MAP16(ValueType.MAP), + MAP32(ValueType.MAP), + NEG_FIX_INT(ValueType.INTEGER); + + private static final MessageFormat[] formatTable = new MessageFormat[256]; + + private final ValueType valueType; + + MessageFormat(ValueType valueType) { + this.valueType = valueType; + } + + /** + * Retruns the ValueType corresponding to this MessageFormat + * + * @return value type + * @throws MessageFormatException if this == NEVER_USED type + */ + public ValueType getValueType() throws MessageFormatException { + if (this == NEVER_USED) { + throw new MessageFormatException("Cannot convert NEVER_USED to ValueType"); + } + return valueType; + } + + static { + // Preparing a look up table for converting byte values into MessageFormat types + for (int b = 0; b <= 0xFF; ++b) { + MessageFormat mf = toMessageFormat((byte) b); + formatTable[b] = mf; + } + } + + /** + * Returns a MessageFormat type of the specified byte value + * + * @param b MessageFormat of the given byte + */ + public static MessageFormat valueOf(final byte b) { + return formatTable[b & 0xFF]; + } + + /** + * Converting a byte value into MessageFormat. For faster performance, use {@link #valueOf} + * + * @param b MessageFormat of the given byte + */ + @VisibleForTesting + static MessageFormat toMessageFormat(final byte b) { + if (Code.isPosFixInt(b)) { + return POS_FIX_INT; + } + if (Code.isNegFixInt(b)) { + return NEG_FIX_INT; + } + if (Code.isFixStr(b)) { + return FIX_STR; + } + if (Code.isFixedArray(b)) { + return FIX_ARRAY; + } + if (Code.isFixedMap(b)) { + return FIX_MAP; + } + return switch (b) { + case Code.NIL -> NIL; + case Code.FALSE, Code.TRUE -> BOOLEAN; + case Code.BIN8 -> BIN8; + case Code.BIN16 -> BIN16; + case Code.BIN32 -> BIN32; + case Code.EXT8 -> EXT8; + case Code.EXT16 -> EXT16; + case Code.EXT32 -> EXT32; + case Code.FLOAT32 -> FLOAT32; + case Code.FLOAT64 -> FLOAT64; + case Code.UINT8 -> UINT8; + case Code.UINT16 -> UINT16; + case Code.UINT32 -> UINT32; + case Code.UINT64 -> UINT64; + case Code.INT8 -> INT8; + case Code.INT16 -> INT16; + case Code.INT32 -> INT32; + case Code.INT64 -> INT64; + case Code.FIXEXT1 -> FIX_EXT1; + case Code.FIXEXT2 -> FIX_EXT2; + case Code.FIXEXT4 -> FIX_EXT4; + case Code.FIXEXT8 -> FIX_EXT8; + case Code.FIXEXT16 -> FIX_EXT16; + case Code.STR8 -> STR8; + case Code.STR16 -> STR16; + case Code.STR32 -> STR32; + case Code.ARRAY16 -> ARRAY16; + case Code.ARRAY32 -> ARRAY32; + case Code.MAP16 -> MAP16; + case Code.MAP32 -> MAP32; + default -> NEVER_USED; + }; + } +} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageFormatException.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageFormatException.java new file mode 100644 index 0000000..d16b996 --- /dev/null +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageFormatException.java @@ -0,0 +1,34 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.serialize.format; + +import infra.lang.Nullable; + +/** + * Thrown when the input message pack format is invalid + */ +public class MessageFormatException extends MessagePackException { + + public MessageFormatException(@Nullable String message) { + this(message, null); + } + + public MessageFormatException(@Nullable String message, @Nullable Throwable cause) { + super(message, cause); + } +} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageInsufficientBufferException.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageInsufficientBufferException.java new file mode 100644 index 0000000..601cc31 --- /dev/null +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageInsufficientBufferException.java @@ -0,0 +1,29 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.serialize.format; + +/** + * Exception that indicates end of input. + */ +public class MessageInsufficientBufferException extends MessagePackException { + + public MessageInsufficientBufferException() { + super(null, null); + } + +} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageIntegerOverflowException.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageIntegerOverflowException.java new file mode 100644 index 0000000..2f3a618 --- /dev/null +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageIntegerOverflowException.java @@ -0,0 +1,48 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.serialize.format; + +import java.math.BigInteger; + +/** + * This error is thrown when the user tries to read an integer value + * using a smaller types. For example, calling MessageUnpacker.unpackInt() for an integer value + * that is larger than Integer.MAX_VALUE will cause this exception. + */ +public class MessageIntegerOverflowException extends MessageTypeException { + + private final BigInteger bigInteger; + + public MessageIntegerOverflowException(BigInteger bigInteger) { + super(null, null); + this.bigInteger = bigInteger; + } + + public MessageIntegerOverflowException(long value) { + this(BigInteger.valueOf(value)); + } + + public BigInteger getBigInteger() { + return bigInteger; + } + + @Override + public String getMessage() { + return bigInteger.toString(); + } +} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageNeverUsedFormatException.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageNeverUsedFormatException.java new file mode 100644 index 0000000..def13b5 --- /dev/null +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageNeverUsedFormatException.java @@ -0,0 +1,31 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.serialize.format; + +import infra.lang.Nullable; + +/** + * Thrown when the input message pack format is invalid + */ +public class MessageNeverUsedFormatException extends MessageFormatException { + + public MessageNeverUsedFormatException(@Nullable String message) { + super(message, null); + } + +} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessagePack.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessagePack.java new file mode 100644 index 0000000..f127a17 --- /dev/null +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessagePack.java @@ -0,0 +1,700 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.serialize.format; + +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.ByteBuffer; +import java.nio.channels.ReadableByteChannel; +import java.nio.channels.WritableByteChannel; +import java.nio.charset.Charset; +import java.nio.charset.CodingErrorAction; +import java.nio.charset.StandardCharsets; + +import infra.cloud.serialize.format.buffer.ArrayBufferInput; +import infra.cloud.serialize.format.buffer.ByteBufferInput; +import infra.cloud.serialize.format.buffer.ChannelBufferInput; +import infra.cloud.serialize.format.buffer.ChannelBufferOutput; +import infra.cloud.serialize.format.buffer.InputStreamBufferInput; +import infra.cloud.serialize.format.buffer.MessageBufferInput; +import infra.cloud.serialize.format.buffer.MessageBufferOutput; +import infra.cloud.serialize.format.buffer.OutputStreamBufferOutput; + +/** + * Convenience class to build packer and unpacker classes. + *

      + * You can select an appropriate factory method as following. + * + *

      + * Deserializing objects from binary: + * + * + * + * + * + * + * + * + *
      Input typeFactory methodReturn type
      byte[]{@link #newUnpacker(byte[], int, int)}{@link MessageUnpacker}
      ByteBuffer{@link #newUnpacker(ByteBuffer)}{@link MessageUnpacker}
      InputStream{@link #newUnpacker(InputStream)}{@link MessageUnpacker}
      ReadableByteChannel{@link #newUnpacker(ReadableByteChannel)}{@link MessageUnpacker}
      {@link MessageBufferInput}{@link #newUnpacker(MessageBufferInput)}{@link MessageUnpacker}
      + * + *

      + * Serializing objects into binary: + * + * + * + * + * + * + * + *
      Output typeFactory methodReturn type
      byte[]{@link #newBufferPacker()}{@link MessageBufferPacker}
      OutputStream{@link #newPacker(OutputStream)}{@link MessagePacker}
      WritableByteChannel{@link #newPacker(WritableByteChannel)}{@link MessagePacker}
      {@link MessageBufferOutput}{@link #newPacker(MessageBufferOutput)}{@link MessagePacker}
      + */ +public class MessagePack { + + /** + * Applications should use java.nio.charset.StandardCharsets.UTF_8 instead since Java 7. + */ + public static final Charset UTF8 = StandardCharsets.UTF_8; + + /** + * Configuration of a {@link MessagePacker} used by {@link #newPacker(MessageBufferOutput)} and {@link #newBufferPacker()} methods. + */ + public static final PackerConfig DEFAULT_PACKER_CONFIG = new PackerConfig(); + + /** + * Configuration of a {@link MessageUnpacker} used by {@link #newUnpacker(MessageBufferInput)} methods. + */ + public static final UnpackerConfig DEFAULT_UNPACKER_CONFIG = new UnpackerConfig(); + + /** + * The prefix code set of MessagePack format. See also https://github.com/msgpack/msgpack/blob/master/spec.md for details. + */ + public static final class Code { + public static boolean isFixInt(byte b) { + int v = b & 0xFF; + return v <= 0x7f || v >= 0xe0; + } + + public static boolean isPosFixInt(byte b) { + return (b & POSFIXINT_MASK) == 0; + } + + public static boolean isNegFixInt(byte b) { + return (b & NEGFIXINT_PREFIX) == NEGFIXINT_PREFIX; + } + + public static boolean isFixStr(byte b) { + return (b & (byte) 0xe0) == Code.FIXSTR_PREFIX; + } + + public static boolean isFixedArray(byte b) { + return (b & (byte) 0xf0) == Code.FIXARRAY_PREFIX; + } + + public static boolean isFixedMap(byte b) { + return (b & (byte) 0xf0) == Code.FIXMAP_PREFIX; + } + + public static boolean isFixedRaw(byte b) { + return (b & (byte) 0xe0) == Code.FIXSTR_PREFIX; + } + + public static final byte POSFIXINT_MASK = (byte) 0x80; + + public static final byte FIXMAP_PREFIX = (byte) 0x80; + public static final byte FIXARRAY_PREFIX = (byte) 0x90; + public static final byte FIXSTR_PREFIX = (byte) 0xa0; + + public static final byte NIL = (byte) 0xc0; + public static final byte NEVER_USED = (byte) 0xc1; + public static final byte FALSE = (byte) 0xc2; + public static final byte TRUE = (byte) 0xc3; + public static final byte BIN8 = (byte) 0xc4; + public static final byte BIN16 = (byte) 0xc5; + public static final byte BIN32 = (byte) 0xc6; + public static final byte EXT8 = (byte) 0xc7; + public static final byte EXT16 = (byte) 0xc8; + public static final byte EXT32 = (byte) 0xc9; + public static final byte FLOAT32 = (byte) 0xca; + public static final byte FLOAT64 = (byte) 0xcb; + public static final byte UINT8 = (byte) 0xcc; + public static final byte UINT16 = (byte) 0xcd; + public static final byte UINT32 = (byte) 0xce; + public static final byte UINT64 = (byte) 0xcf; + + public static final byte INT8 = (byte) 0xd0; + public static final byte INT16 = (byte) 0xd1; + public static final byte INT32 = (byte) 0xd2; + public static final byte INT64 = (byte) 0xd3; + + public static final byte FIXEXT1 = (byte) 0xd4; + public static final byte FIXEXT2 = (byte) 0xd5; + public static final byte FIXEXT4 = (byte) 0xd6; + public static final byte FIXEXT8 = (byte) 0xd7; + public static final byte FIXEXT16 = (byte) 0xd8; + + public static final byte STR8 = (byte) 0xd9; + public static final byte STR16 = (byte) 0xda; + public static final byte STR32 = (byte) 0xdb; + + public static final byte ARRAY16 = (byte) 0xdc; + public static final byte ARRAY32 = (byte) 0xdd; + + public static final byte MAP16 = (byte) 0xde; + public static final byte MAP32 = (byte) 0xdf; + + public static final byte NEGFIXINT_PREFIX = (byte) 0xe0; + + public static final byte EXT_TIMESTAMP = (byte) -1; + } + + private MessagePack() { + // Prohibit instantiation of this class + } + + /** + * Creates a packer that serializes objects into the specified output. + *

      + * {@link MessageBufferOutput} is an interface that lets applications customize memory + * allocation of internal buffer of {@link MessagePacker}. You may prefer {@link #newBufferPacker()}, + * {@link #newPacker(OutputStream)}, or {@link #newPacker(WritableByteChannel)} methods instead. + *

      + * This method is equivalent to DEFAULT_PACKER_CONFIG.newPacker(out). + * + * @param out A MessageBufferOutput that allocates buffer chunks and receives the buffer chunks with packed data filled in them + * @return A new MessagePacker instance + */ + public static MessagePacker newPacker(MessageBufferOutput out) { + return DEFAULT_PACKER_CONFIG.newPacker(out); + } + + /** + * Creates a packer that serializes objects into the specified output stream. + *

      + * Note that you don't have to wrap OutputStream in BufferedOutputStream because MessagePacker has buffering + * internally. + *

      + * This method is equivalent to DEFAULT_PACKER_CONFIG.newPacker(out). + * + * @param out The output stream that receives sequence of bytes + * @return A new MessagePacker instance + */ + public static MessagePacker newPacker(OutputStream out) { + return DEFAULT_PACKER_CONFIG.newPacker(out); + } + + /** + * Creates a packer that serializes objects into the specified writable channel. + *

      + * This method is equivalent to DEFAULT_PACKER_CONFIG.newPacker(channel). + * + * @param channel The output channel that receives sequence of bytes + * @return A new MessagePacker instance + */ + public static MessagePacker newPacker(WritableByteChannel channel) { + return DEFAULT_PACKER_CONFIG.newPacker(channel); + } + + /** + * Creates a packer that serializes objects into byte arrays. + *

      + * This method provides an optimized implementation of newDefaultBufferPacker(new ByteArrayOutputStream()). + *

      + * This method is equivalent to DEFAULT_PACKER_CONFIG.newBufferPacker(). + * + * @return A new MessageBufferPacker instance + */ + public static MessageBufferPacker newBufferPacker() { + return DEFAULT_PACKER_CONFIG.newBufferPacker(); + } + + /** + * Creates an unpacker that deserializes objects from a specified input. + *

      + * {@link MessageBufferInput} is an interface that lets applications customize memory + * allocation of internal buffer of {@link MessageUnpacker}. You may prefer + * {@link #newUnpacker(InputStream)}, {@link #newUnpacker(ReadableByteChannel)}, + * {@link #newUnpacker(byte[], int, int)}, or {@link #newUnpacker(ByteBuffer)} methods instead. + *

      + * This method is equivalent to DEFAULT_UNPACKER_CONFIG.newDefaultUnpacker(in). + * + * @param in The input stream that provides sequence of buffer chunks and optionally reuses them when MessageUnpacker consumed one completely + * @return A new MessageUnpacker instance + */ + public static MessageUnpacker newUnpacker(MessageBufferInput in) { + return DEFAULT_UNPACKER_CONFIG.newUnpacker(in); + } + + /** + * Creates an unpacker that deserializes objects from a specified input stream. + *

      + * Note that you don't have to wrap InputStream in BufferedInputStream because MessageUnpacker has buffering + * internally. + *

      + * This method is equivalent to DEFAULT_UNPACKER_CONFIG.newDefaultUnpacker(in). + * + * @param in The input stream that provides sequence of bytes + * @return A new MessageUnpacker instance + */ + public static MessageUnpacker newUnpacker(InputStream in) { + return DEFAULT_UNPACKER_CONFIG.newUnpacker(in); + } + + /** + * Creates an unpacker that deserializes objects from a specified readable channel. + *

      + * This method is equivalent to DEFAULT_UNPACKER_CONFIG.newDefaultUnpacker(in). + * + * @param channel The input channel that provides sequence of bytes + * @return A new MessageUnpacker instance + */ + public static MessageUnpacker newUnpacker(ReadableByteChannel channel) { + return DEFAULT_UNPACKER_CONFIG.newUnpacker(channel); + } + + /** + * Creates an unpacker that deserializes objects from a specified byte array. + *

      + * This method provides an optimized implementation of newDefaultUnpacker(new ByteArrayInputStream(contents)). + *

      + * This method is equivalent to DEFAULT_UNPACKER_CONFIG.newDefaultUnpacker(contents). + * + * @param contents The byte array that contains packed objects in MessagePack format + * @return A new MessageUnpacker instance that will never throw IOException + */ + public static MessageUnpacker newUnpacker(byte[] contents) { + return DEFAULT_UNPACKER_CONFIG.newUnpacker(contents); + } + + /** + * Creates an unpacker that deserializes objects from subarray of a specified byte array. + *

      + * This method provides an optimized implementation of newDefaultUnpacker(new ByteArrayInputStream(contents, offset, length)). + *

      + * This method is equivalent to DEFAULT_UNPACKER_CONFIG.newDefaultUnpacker(contents). + * + * @param contents The byte array that contains packed objects + * @param offset The index of the first byte + * @param length The number of bytes + * @return A new MessageUnpacker instance that will never throw IOException + */ + public static MessageUnpacker newUnpacker(byte[] contents, int offset, int length) { + return DEFAULT_UNPACKER_CONFIG.newUnpacker(contents, offset, length); + } + + /** + * Creates an unpacker that deserializes objects from a specified ByteBuffer. + *

      + * Note that the returned unpacker reads data from the current position of the ByteBuffer until its limit. + * However, its position does not change when unpacker reads data. You may use + * {@link MessageUnpacker#getTotalReadBytes()} to get actual amount of bytes used in ByteBuffer. + *

      + * This method supports both non-direct buffer and direct buffer. + * + * @param contents The byte buffer that contains packed objects + * @return A new MessageUnpacker instance that will never throw IOException + */ + public static MessageUnpacker newUnpacker(ByteBuffer contents) { + return DEFAULT_UNPACKER_CONFIG.newUnpacker(contents); + } + + /** + * MessagePacker configuration. + */ + public static class PackerConfig implements Cloneable { + + private int smallStringOptimizationThreshold = 512; + + private int bufferFlushThreshold = 8192; + + private int bufferSize = 8192; + + private boolean str8FormatSupport = true; + + public PackerConfig() { + } + + private PackerConfig(PackerConfig copy) { + this.smallStringOptimizationThreshold = copy.smallStringOptimizationThreshold; + this.bufferFlushThreshold = copy.bufferFlushThreshold; + this.bufferSize = copy.bufferSize; + this.str8FormatSupport = copy.str8FormatSupport; + } + + @Override + public PackerConfig clone() { + return new PackerConfig(this); + } + + @Override + public int hashCode() { + int result = smallStringOptimizationThreshold; + result = 31 * result + bufferFlushThreshold; + result = 31 * result + bufferSize; + result = 31 * result + (str8FormatSupport ? 1 : 0); + return result; + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof PackerConfig o)) { + return false; + } + return this.smallStringOptimizationThreshold == o.smallStringOptimizationThreshold + && this.bufferFlushThreshold == o.bufferFlushThreshold + && this.bufferSize == o.bufferSize + && this.str8FormatSupport == o.str8FormatSupport; + } + + /** + * Creates a packer that serializes objects into the specified output. + *

      + * {@link MessageBufferOutput} is an interface that lets applications customize memory + * allocation of internal buffer of {@link MessagePacker}. + * + * @param out A MessageBufferOutput that allocates buffer chunks and receives the buffer chunks with packed data filled in them + * @return A new MessagePacker instance + */ + public MessagePacker newPacker(MessageBufferOutput out) { + return new MessagePacker(out, this); + } + + /** + * Creates a packer that serializes objects into the specified output stream. + *

      + * Note that you don't have to wrap OutputStream in BufferedOutputStream because MessagePacker has buffering + * internally. + * + * @param out The output stream that receives sequence of bytes + * @return A new MessagePacker instance + */ + public MessagePacker newPacker(OutputStream out) { + return newPacker(new OutputStreamBufferOutput(out, bufferSize)); + } + + /** + * Creates a packer that serializes objects into the specified writable channel. + * + * @param channel The output channel that receives sequence of bytes + * @return A new MessagePacker instance + */ + public MessagePacker newPacker(WritableByteChannel channel) { + return newPacker(new ChannelBufferOutput(channel, bufferSize)); + } + + /** + * Creates a packer that serializes objects into byte arrays. + *

      + * This method provides an optimized implementation of newDefaultBufferPacker(new ByteArrayOutputStream()). + * + * @return A new MessageBufferPacker instance + */ + public MessageBufferPacker newBufferPacker() { + return new MessageBufferPacker(this); + } + + /** + * Use String.getBytes() for converting Java Strings that are shorter than this threshold. + * Note that this parameter is subject to change. + */ + public PackerConfig withSmallStringOptimizationThreshold(int length) { + PackerConfig copy = clone(); + copy.smallStringOptimizationThreshold = length; + return copy; + } + + public int getSmallStringOptimizationThreshold() { + return smallStringOptimizationThreshold; + } + + /** + * When the next payload size exceeds this threshold, MessagePacker will call + * {@link MessageBufferOutput#flush()} before writing more data (default: 8192). + */ + public PackerConfig withBufferFlushThreshold(int bytes) { + PackerConfig copy = clone(); + copy.bufferFlushThreshold = bytes; + return copy; + } + + public int getBufferFlushThreshold() { + return bufferFlushThreshold; + } + + /** + * When a packer is created with {@link #newPacker(OutputStream)} or {@link #newPacker(WritableByteChannel)}, the stream will be + * buffered with this size of buffer (default: 8192). + */ + public PackerConfig withBufferSize(int bytes) { + PackerConfig copy = clone(); + copy.bufferSize = bytes; + return copy; + } + + public int getBufferSize() { + return bufferSize; + } + + /** + * Disable str8 format when needed backward compatibility between + * different msgpack serializer versions. + * default true (str8 supported enabled) + */ + public PackerConfig withStr8FormatSupport(boolean str8FormatSupport) { + PackerConfig copy = clone(); + copy.str8FormatSupport = str8FormatSupport; + return copy; + } + + public boolean isStr8FormatSupport() { + return str8FormatSupport; + } + } + + /** + * MessageUnpacker configuration. + */ + public static class UnpackerConfig implements Cloneable { + + private boolean allowReadingStringAsBinary = true; + + private boolean allowReadingBinaryAsString = true; + + private CodingErrorAction actionOnMalformedString = CodingErrorAction.REPLACE; + + private CodingErrorAction actionOnUnmappableString = CodingErrorAction.REPLACE; + + private int stringSizeLimit = Integer.MAX_VALUE; + + private int bufferSize = 8192; + + private int stringDecoderBufferSize = 8192; + + public UnpackerConfig() { + } + + private UnpackerConfig(UnpackerConfig copy) { + this.allowReadingStringAsBinary = copy.allowReadingStringAsBinary; + this.allowReadingBinaryAsString = copy.allowReadingBinaryAsString; + this.actionOnMalformedString = copy.actionOnMalformedString; + this.actionOnUnmappableString = copy.actionOnUnmappableString; + this.stringDecoderBufferSize = copy.stringDecoderBufferSize; + this.stringSizeLimit = copy.stringSizeLimit; + this.bufferSize = copy.bufferSize; + } + + @Override + public UnpackerConfig clone() { + return new UnpackerConfig(this); + } + + @Override + public int hashCode() { + int result = (allowReadingStringAsBinary ? 1 : 0); + result = 31 * result + (allowReadingBinaryAsString ? 1 : 0); + result = 31 * result + (actionOnMalformedString != null ? actionOnMalformedString.hashCode() : 0); + result = 31 * result + (actionOnUnmappableString != null ? actionOnUnmappableString.hashCode() : 0); + result = 31 * result + stringSizeLimit; + result = 31 * result + bufferSize; + result = 31 * result + stringDecoderBufferSize; + return result; + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof UnpackerConfig o)) { + return false; + } + return this.allowReadingStringAsBinary == o.allowReadingStringAsBinary + && this.allowReadingBinaryAsString == o.allowReadingBinaryAsString + && this.actionOnMalformedString == o.actionOnMalformedString + && this.actionOnUnmappableString == o.actionOnUnmappableString + && this.stringSizeLimit == o.stringSizeLimit + && this.stringDecoderBufferSize == o.stringDecoderBufferSize + && this.bufferSize == o.bufferSize; + } + + /** + * Creates an unpacker that deserializes objects from a specified input. + *

      + * {@link MessageBufferInput} is an interface that lets applications customize memory + * allocation of internal buffer of {@link MessageUnpacker}. + * + * @param in The input stream that provides sequence of buffer chunks and optionally reuses them when MessageUnpacker consumed one completely + * @return A new MessageUnpacker instance + */ + public MessageUnpacker newUnpacker(MessageBufferInput in) { + return new MessageUnpacker(in, this); + } + + /** + * Creates an unpacker that deserializes objects from a specified input stream. + *

      + * Note that you don't have to wrap InputStream in BufferedInputStream because MessageUnpacker has buffering + * internally. + * + * @param in The input stream that provides sequence of bytes + * @return A new MessageUnpacker instance + */ + public MessageUnpacker newUnpacker(InputStream in) { + return newUnpacker(new InputStreamBufferInput(in, bufferSize)); + } + + /** + * Creates an unpacker that deserializes objects from a specified readable channel. + * + * @param channel The input channel that provides sequence of bytes + * @return A new MessageUnpacker instance + */ + public MessageUnpacker newUnpacker(ReadableByteChannel channel) { + return newUnpacker(new ChannelBufferInput(channel, bufferSize)); + } + + /** + * Creates an unpacker that deserializes objects from a specified byte array. + *

      + * This method provides an optimized implementation of newDefaultUnpacker(new ByteArrayInputStream(contents)). + * + * @param contents The byte array that contains packed objects in MessagePack format + * @return A new MessageUnpacker instance that will never throw IOException + */ + public MessageUnpacker newUnpacker(byte[] contents) { + return newUnpacker(new ArrayBufferInput(contents)); + } + + /** + * Creates an unpacker that deserializes objects from subarray of a specified byte array. + *

      + * This method provides an optimized implementation of newDefaultUnpacker(new ByteArrayInputStream(contents, offset, length)). + * + * @param contents The byte array that contains packed objects + * @param offset The index of the first byte + * @param length The number of bytes + * @return A new MessageUnpacker instance that will never throw IOException + */ + public MessageUnpacker newUnpacker(byte[] contents, int offset, int length) { + return newUnpacker(new ArrayBufferInput(contents, offset, length)); + } + + /** + * Creates an unpacker that deserializes objects from a specified ByteBuffer. + *

      + * Note that the returned unpacker reads data from the current position of the ByteBuffer until its limit. + * However, its position does not change when unpacker reads data. You may use + * {@link MessageUnpacker#getTotalReadBytes()} to get actual amount of bytes used in ByteBuffer. + * + * @param contents The byte buffer that contains packed objects + * @return A new MessageUnpacker instance that will never throw IOException + */ + public MessageUnpacker newUnpacker(ByteBuffer contents) { + return newUnpacker(new ByteBufferInput(contents)); + } + + /** + * Allows unpackBinaryHeader to read str format family (default: true) + */ + public UnpackerConfig withAllowReadingStringAsBinary(boolean enable) { + UnpackerConfig copy = clone(); + copy.allowReadingStringAsBinary = enable; + return copy; + } + + public boolean getAllowReadingStringAsBinary() { + return allowReadingStringAsBinary; + } + + /** + * Allows unpackString and unpackRawStringHeader and unpackString to read bin format family (default: true) + */ + public UnpackerConfig withAllowReadingBinaryAsString(boolean enable) { + UnpackerConfig copy = clone(); + copy.allowReadingBinaryAsString = enable; + return copy; + } + + public boolean getAllowReadingBinaryAsString() { + return allowReadingBinaryAsString; + } + + /** + * Sets action when encountered a malformed input (default: REPLACE) + */ + public UnpackerConfig withActionOnMalformedString(CodingErrorAction action) { + UnpackerConfig copy = clone(); + copy.actionOnMalformedString = action; + return copy; + } + + public CodingErrorAction getActionOnMalformedString() { + return actionOnMalformedString; + } + + /** + * Sets action when an unmappable character is found (default: REPLACE) + */ + public UnpackerConfig withActionOnUnmappableString(CodingErrorAction action) { + UnpackerConfig copy = clone(); + copy.actionOnUnmappableString = action; + return copy; + } + + public CodingErrorAction getActionOnUnmappableString() { + return actionOnUnmappableString; + } + + /** + * unpackString size limit (default: Integer.MAX_VALUE). + */ + public UnpackerConfig withStringSizeLimit(int bytes) { + UnpackerConfig copy = clone(); + copy.stringSizeLimit = bytes; + return copy; + } + + public int getStringSizeLimit() { + return stringSizeLimit; + } + + /** + * + */ + public UnpackerConfig withStringDecoderBufferSize(int bytes) { + UnpackerConfig copy = clone(); + copy.stringDecoderBufferSize = bytes; + return copy; + } + + public int getStringDecoderBufferSize() { + return stringDecoderBufferSize; + } + + /** + * When a packer is created with newUnpacker(OutputStream) or newUnpacker(WritableByteChannel), the stream will be + * buffered with this size of buffer (default: 8192). + */ + public UnpackerConfig withBufferSize(int bytes) { + UnpackerConfig copy = clone(); + copy.bufferSize = bytes; + return copy; + } + + public int getBufferSize() { + return bufferSize; + } + } + +} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessagePackException.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessagePackException.java new file mode 100644 index 0000000..9cbab7c --- /dev/null +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessagePackException.java @@ -0,0 +1,32 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.serialize.format; + +import infra.cloud.serialize.SerializationException; +import infra.lang.Nullable; + +/** + * A base class of all the message pack exceptions. + */ +public class MessagePackException extends SerializationException { + + public MessagePackException(@Nullable String message, @Nullable Throwable cause) { + super(message, cause); + } + +} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessagePacker.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessagePacker.java new file mode 100644 index 0000000..f8a1c78 --- /dev/null +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessagePacker.java @@ -0,0 +1,1093 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.serialize.format; + +import java.io.Closeable; +import java.io.Flushable; +import java.io.IOException; +import java.math.BigInteger; +import java.nio.ByteBuffer; +import java.nio.CharBuffer; +import java.nio.charset.CharacterCodingException; +import java.nio.charset.CharsetEncoder; +import java.nio.charset.CoderResult; +import java.nio.charset.CodingErrorAction; +import java.time.Instant; +import java.util.Objects; + +import infra.cloud.serialize.format.buffer.ChannelBufferOutput; +import infra.cloud.serialize.format.buffer.MessageBuffer; +import infra.cloud.serialize.format.buffer.MessageBufferOutput; +import infra.cloud.serialize.format.buffer.OutputStreamBufferOutput; +import infra.cloud.serialize.format.value.Value; +import infra.lang.Nullable; + +import static infra.cloud.serialize.format.MessagePack.Code.ARRAY16; +import static infra.cloud.serialize.format.MessagePack.Code.ARRAY32; +import static infra.cloud.serialize.format.MessagePack.Code.BIN16; +import static infra.cloud.serialize.format.MessagePack.Code.BIN32; +import static infra.cloud.serialize.format.MessagePack.Code.BIN8; +import static infra.cloud.serialize.format.MessagePack.Code.EXT16; +import static infra.cloud.serialize.format.MessagePack.Code.EXT32; +import static infra.cloud.serialize.format.MessagePack.Code.EXT8; +import static infra.cloud.serialize.format.MessagePack.Code.EXT_TIMESTAMP; +import static infra.cloud.serialize.format.MessagePack.Code.FALSE; +import static infra.cloud.serialize.format.MessagePack.Code.FIXARRAY_PREFIX; +import static infra.cloud.serialize.format.MessagePack.Code.FIXEXT1; +import static infra.cloud.serialize.format.MessagePack.Code.FIXEXT16; +import static infra.cloud.serialize.format.MessagePack.Code.FIXEXT2; +import static infra.cloud.serialize.format.MessagePack.Code.FIXEXT4; +import static infra.cloud.serialize.format.MessagePack.Code.FIXEXT8; +import static infra.cloud.serialize.format.MessagePack.Code.FIXMAP_PREFIX; +import static infra.cloud.serialize.format.MessagePack.Code.FIXSTR_PREFIX; +import static infra.cloud.serialize.format.MessagePack.Code.FLOAT32; +import static infra.cloud.serialize.format.MessagePack.Code.FLOAT64; +import static infra.cloud.serialize.format.MessagePack.Code.INT16; +import static infra.cloud.serialize.format.MessagePack.Code.INT32; +import static infra.cloud.serialize.format.MessagePack.Code.INT64; +import static infra.cloud.serialize.format.MessagePack.Code.INT8; +import static infra.cloud.serialize.format.MessagePack.Code.MAP16; +import static infra.cloud.serialize.format.MessagePack.Code.MAP32; +import static infra.cloud.serialize.format.MessagePack.Code.NIL; +import static infra.cloud.serialize.format.MessagePack.Code.STR16; +import static infra.cloud.serialize.format.MessagePack.Code.STR32; +import static infra.cloud.serialize.format.MessagePack.Code.STR8; +import static infra.cloud.serialize.format.MessagePack.Code.TRUE; +import static infra.cloud.serialize.format.MessagePack.Code.UINT16; +import static infra.cloud.serialize.format.MessagePack.Code.UINT32; +import static infra.cloud.serialize.format.MessagePack.Code.UINT64; +import static infra.cloud.serialize.format.MessagePack.Code.UINT8; + +/** + * MessagePack serializer that converts objects into binary. + * You can use factory methods of {@link MessagePack} class or {@link MessagePack.PackerConfig} class to create + * an instance. + *

      + * This class provides following primitive methods to write MessagePack values. These primitive methods write + * short bytes (1 to 7 bytes) to the internal buffer at once. There are also some utility methods for convenience. + *

      + * Primitive methods: + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
      Java typePacker methodMessagePack type
      null{@link #packNil()}Nil
      boolean{@link #packBoolean(boolean)}Boolean
      byte{@link #packByte(byte)}Integer
      short{@link #packShort(short)}Integer
      int{@link #packInt(int)}Integer
      long{@link #packLong(long)}Integer
      BigInteger{@link #packBigInteger(BigInteger)}Integer
      float{@link #packFloat(float)}Float
      double{@link #packDouble(double)}Float
      byte[]{@link #packBinaryHeader(int)}Binary
      String{@link #packRawStringHeader(int)}String
      List{@link #packArrayHeader(int)}Array
      Map{@link #packMapHeader(int)}Map
      custom user type{@link #packExtensionTypeHeader(byte, int)}Extension
      + * + *

      + * Utility methods: + * + * + * + * + * + *
      Java typePacker methodMessagePack type
      String{@link #packString(String)}String
      {@link Value}{@link #packValue(Value)}
      + * + *

      + * To write a byte array, first you call {@link #packBinaryHeader} method with length of the byte array. Then, + * you call {@link #writePayload(byte[], int, int)} or {@link #addPayload(byte[], int, int)} method to write the + * contents. + * + *

      + * To write a List, Collection or array, first you call {@link #packArrayHeader(int)} method with the number of + * elements. Then, you call packer methods for each element. + * iteration. + * + *

      + * To write a Map, first you call {@link #packMapHeader(int)} method with size of the map. Then, for each pair, + * you call packer methods for key first, and then value. You will call packer methods twice as many time as the + * size of the map. + * + *

      + * Note that packXxxHeader methods don't validate number of elements. You must call packer methods for correct + * number of times to produce valid MessagePack data. + * + *

      + * When IOException is thrown, primitive methods guarantee that all data is written to the internal buffer or no data + * is written. This is convenient behavior when you use a non-blocking output channel that may not be writable + * immediately. + */ +public class MessagePacker implements Closeable, Flushable { + + private final int smallStringOptimizationThreshold; + + private final int bufferFlushThreshold; + + private final boolean str8FormatSupport; + + /** + * Current internal buffer. + */ + protected MessageBufferOutput out; + + @Nullable + private MessageBuffer buffer; + + private int position; + + /** + * Total written byte size + */ + private long totalFlushBytes; + + /** + * String encoder + */ + @Nullable + private CharsetEncoder encoder; + + /** + * Create an MessagePacker that outputs the packed data to the given {@link MessageBufferOutput}. + * This method is available for subclasses to override. Use MessagePack.PackerConfig.newPacker method to instantiate this implementation. + * + * @param out MessageBufferOutput. Use {@link OutputStreamBufferOutput}, {@link ChannelBufferOutput} or + * your own implementation of {@link MessageBufferOutput} interface. + */ + protected MessagePacker(MessageBufferOutput out, MessagePack.PackerConfig config) { + this.out = Objects.requireNonNull(out, "MessageBufferOutput is null"); + this.smallStringOptimizationThreshold = config.getSmallStringOptimizationThreshold(); + this.bufferFlushThreshold = config.getBufferFlushThreshold(); + this.str8FormatSupport = config.isStr8FormatSupport(); + this.position = 0; + this.totalFlushBytes = 0; + } + + /** + * Replaces underlying output. + *

      + * This method flushes current internal buffer to the output, swaps it with the new given output, then returns + * the old output. + * + *

      + * This method doesn't close the old output. + * + * @param out new output + * @return the old output + * @throws IOException when underlying output throws IOException + * @throws NullPointerException the given output is null + */ + public MessageBufferOutput reset(MessageBufferOutput out) throws IOException { + // Validate the argument + MessageBufferOutput newOut = Objects.requireNonNull(out, "MessageBufferOutput is null"); + + // Flush before reset + flush(); + MessageBufferOutput old = this.out; + this.out = newOut; + + // Reset totalFlushBytes + this.totalFlushBytes = 0; + + return old; + } + + /** + * Returns total number of written bytes. + *

      + * This method returns total of amount of data flushed to the underlying output plus size of current + * internal buffer. + * + *

      + * Calling {@link #reset(MessageBufferOutput)} resets this number to 0. + */ + public long getTotalWrittenBytes() { + return totalFlushBytes + position; + } + + /** + * Clears the written data. + */ + public void clear() { + position = 0; + } + + /** + * Flushes internal buffer to the underlying output. + *

      + * This method also calls flush method of the underlying output after writing internal buffer. + */ + @Override + public void flush() throws IOException { + if (position > 0) { + flushBuffer(); + } + out.flush(); + } + + /** + * Closes underlying output. + *

      + * This method flushes internal buffer before closing. + */ + @Override + public void close() throws IOException { + try { + flush(); + } + finally { + out.close(); + } + } + + private void flushBuffer() throws IOException { + out.writeBuffer(position); + buffer = null; + totalFlushBytes += position; + position = 0; + } + + private MessageBuffer ensureCapacity(int minimumSize) throws IOException { + if (buffer == null) { + buffer = out.next(minimumSize); + } + else if (position + minimumSize >= buffer.size()) { + flushBuffer(); + buffer = out.next(minimumSize); + } + return buffer; + } + + private void writeByte(byte b) throws IOException { + ensureCapacity(1).putByte(position++, b); + } + + private void writeByteAndByte(byte b, byte v) throws IOException { + MessageBuffer buffer = ensureCapacity(2); + buffer.putByte(position++, b); + buffer.putByte(position++, v); + } + + private void writeByteAndShort(byte b, short v) throws IOException { + MessageBuffer buffer = ensureCapacity(3); + buffer.putByte(position++, b); + buffer.putShort(position, v); + position += 2; + } + + private void writeByteAndInt(byte b, int v) throws IOException { + MessageBuffer buffer = ensureCapacity(5); + buffer.putByte(position++, b); + buffer.putInt(position, v); + position += 4; + } + + private void writeByteAndFloat(byte b, float v) throws IOException { + MessageBuffer buffer = ensureCapacity(5); + buffer.putByte(position++, b); + buffer.putFloat(position, v); + position += 4; + } + + private void writeByteAndDouble(byte b, double v) throws IOException { + MessageBuffer buffer = ensureCapacity(9); + buffer.putByte(position++, b); + buffer.putDouble(position, v); + position += 8; + } + + private void writeByteAndLong(byte b, long v) throws IOException { + MessageBuffer buffer = ensureCapacity(9); + buffer.putByte(position++, b); + buffer.putLong(position, v); + position += 8; + } + + /** + * Writes a Nil value. + *

      + * This method writes a nil byte. + * + * @return this + * @throws IOException when underlying output throws IOException + */ + public MessagePacker packNil() throws IOException { + writeByte(NIL); + return this; + } + + /** + * Writes a Boolean value. + *

      + * This method writes a true byte or a false byte. + * + * @return this + * @throws IOException when underlying output throws IOException + */ + public MessagePacker packBoolean(boolean b) throws IOException { + writeByte(b ? TRUE : FALSE); + return this; + } + + /** + * Writes an Integer value. + * + *

      + * This method writes an integer using the smallest format from the int format family. + * + * @param b the integer to be written + * @return this + * @throws IOException when underlying output throws IOException + */ + public MessagePacker packByte(byte b) throws IOException { + if (b < -(1 << 5)) { + writeByteAndByte(INT8, b); + } + else { + writeByte(b); + } + return this; + } + + /** + * Writes an Integer value. + * + *

      + * This method writes an integer using the smallest format from the int format family. + * + * @param v the integer to be written + * @return this + * @throws IOException when underlying output throws IOException + */ + public MessagePacker packShort(short v) throws IOException { + if (v < -(1 << 5)) { + if (v < -(1 << 7)) { + writeByteAndShort(INT16, v); + } + else { + writeByteAndByte(INT8, (byte) v); + } + } + else if (v < (1 << 7)) { + writeByte((byte) v); + } + else { + if (v < (1 << 8)) { + writeByteAndByte(UINT8, (byte) v); + } + else { + writeByteAndShort(UINT16, v); + } + } + return this; + } + + /** + * Writes an Integer value. + * + *

      + * This method writes an integer using the smallest format from the int format family. + * + * @param r the integer to be written + * @return this + * @throws IOException when underlying output throws IOException + */ + public MessagePacker packInt(int r) throws IOException { + if (r < -(1 << 5)) { + if (r < -(1 << 15)) { + writeByteAndInt(INT32, r); + } + else if (r < -(1 << 7)) { + writeByteAndShort(INT16, (short) r); + } + else { + writeByteAndByte(INT8, (byte) r); + } + } + else if (r < (1 << 7)) { + writeByte((byte) r); + } + else { + if (r < (1 << 8)) { + writeByteAndByte(UINT8, (byte) r); + } + else if (r < (1 << 16)) { + writeByteAndShort(UINT16, (short) r); + } + else { + // unsigned 32 + writeByteAndInt(UINT32, r); + } + } + return this; + } + + /** + * Writes an Integer value. + * + *

      + * This method writes an integer using the smallest format from the int format family. + * + * @param v the integer to be written + * @return this + * @throws IOException when underlying output throws IOException + */ + public MessagePacker packLong(long v) throws IOException { + if (v < -(1L << 5)) { + if (v < -(1L << 15)) { + if (v < -(1L << 31)) { + writeByteAndLong(INT64, v); + } + else { + writeByteAndInt(INT32, (int) v); + } + } + else { + if (v < -(1 << 7)) { + writeByteAndShort(INT16, (short) v); + } + else { + writeByteAndByte(INT8, (byte) v); + } + } + } + else if (v < (1 << 7)) { + // fixnum + writeByte((byte) v); + } + else { + if (v < (1L << 16)) { + if (v < (1 << 8)) { + writeByteAndByte(UINT8, (byte) v); + } + else { + writeByteAndShort(UINT16, (short) v); + } + } + else { + if (v < (1L << 32)) { + writeByteAndInt(UINT32, (int) v); + } + else { + writeByteAndLong(UINT64, v); + } + } + } + return this; + } + + /** + * Writes an Integer value. + * + *

      + * This method writes an integer using the smallest format from the int format family. + * + * @param bi the integer to be written + * @return this + * @throws IOException when underlying output throws IOException + */ + public MessagePacker packBigInteger(BigInteger bi) throws IOException { + if (bi.bitLength() <= 63) { + packLong(bi.longValue()); + } + else if (bi.bitLength() == 64 && bi.signum() == 1) { + writeByteAndLong(UINT64, bi.longValue()); + } + else { + throw new IllegalArgumentException("MessagePack cannot serialize BigInteger larger than 2^64-1"); + } + return this; + } + + /** + * Writes a Float value. + * + *

      + * This method writes a float value using float format family. + * + * @param v the value to be written + * @return this + * @throws IOException when underlying output throws IOException + */ + public MessagePacker packFloat(float v) throws IOException { + writeByteAndFloat(FLOAT32, v); + return this; + } + + /** + * Writes a Float value. + * + *

      + * This method writes a float value using float format family. + * + * @param v the value to be written + * @return this + * @throws IOException when underlying output throws IOException + */ + public MessagePacker packDouble(double v) throws IOException { + writeByteAndDouble(FLOAT64, v); + return this; + } + + private void packStringWithGetBytes(String s) throws IOException { + // JVM performs various optimizations (memory allocation, reusing encoder etc.) when String.getBytes is used + byte[] bytes = s.getBytes(MessagePack.UTF8); + // Write the length and payload of small string to the buffer so that it avoids an extra flush of buffer + packRawStringHeader(bytes.length); + addPayload(bytes); + } + + private void prepareEncoder() { + if (encoder == null) { + this.encoder = MessagePack.UTF8.newEncoder() + .onMalformedInput(CodingErrorAction.REPLACE) + .onUnmappableCharacter(CodingErrorAction.REPLACE); + } + encoder.reset(); + } + + private int encodeStringToBufferAt(MessageBuffer buffer, int pos, String s) { + prepareEncoder(); + ByteBuffer bb = buffer.sliceAsByteBuffer(pos, buffer.size() - pos); + int startPosition = bb.position(); + CharBuffer in = CharBuffer.wrap(s); + CoderResult cr = encoder.encode(in, bb, true); + if (cr.isError()) { + try { + cr.throwException(); + } + catch (CharacterCodingException e) { + throw new MessageStringCodingException(e); + } + } + if (!cr.isUnderflow() || cr.isOverflow()) { + // Underflow should be on to ensure all of the input string is encoded + return -1; + } + // NOTE: This flush method does nothing if we use UTF8 encoder, but other general encoders require this + cr = encoder.flush(bb); + if (!cr.isUnderflow()) { + return -1; + } + return bb.position() - startPosition; + } + + private static final int UTF_8_MAX_CHAR_SIZE = 6; + + /** + * Writes a String vlaue in UTF-8 encoding. + * + *

      + * This method writes a UTF-8 string using the smallest format from the str format family by default. If {@link MessagePack.PackerConfig#withStr8FormatSupport(boolean)} is set to false, smallest format from the str format family excepting str8 format. + * + * @param s the string to be written + * @return this + * @throws IOException when underlying output throws IOException + */ + public MessagePacker packString(String s) throws IOException { + if (s.isEmpty()) { + packRawStringHeader(0); + return this; + } + else if (s.length() < smallStringOptimizationThreshold) { + // Using String.getBytes is generally faster for small strings. + // Also, when running on a platform that has a corrupted CharsetEncoder (i.e. Android 4.x), avoid using it. + packStringWithGetBytes(s); + return this; + } + else if (s.length() < (1 << 8)) { + // ensure capacity for 2-byte raw string header + the maximum string size (+ 1 byte for falback code) + MessageBuffer buffer = ensureCapacity(2 + s.length() * UTF_8_MAX_CHAR_SIZE + 1); + // keep 2-byte header region and write raw string + int written = encodeStringToBufferAt(buffer, position + 2, s); + if (written >= 0) { + if (str8FormatSupport && written < (1 << 8)) { + buffer.putByte(position++, STR8); + buffer.putByte(position++, (byte) written); + position += written; + } + else { + if (written >= (1 << 16)) { + // this must not happen because s.length() is less than 2^8 and (2^8) * UTF_8_MAX_CHAR_SIZE is less than 2^16 + throw new IllegalArgumentException("Unexpected UTF-8 encoder state"); + } + // move 1 byte backward to expand 3-byte header region to 3 bytes + buffer.putMessageBuffer(position + 3, buffer, position + 2, written); + // write 3-byte header + buffer.putByte(position++, STR16); + buffer.putShort(position, (short) written); + position += 2; + position += written; + } + return this; + } + } + else if (s.length() < (1 << 16)) { + // ensure capacity for 3-byte raw string header + the maximum string size (+ 2 bytes for fallback code) + MessageBuffer buffer = ensureCapacity(3 + s.length() * UTF_8_MAX_CHAR_SIZE + 2); + // keep 3-byte header region and write raw string + int written = encodeStringToBufferAt(buffer, position + 3, s); + if (written >= 0) { + if (written < (1 << 16)) { + buffer.putByte(position++, STR16); + buffer.putShort(position, (short) written); + position += 2; + position += written; + } + else { + // move 2 bytes backward to expand 3-byte header region to 5 bytes + buffer.putMessageBuffer(position + 5, buffer, position + 3, written); + // write 3-byte header header + buffer.putByte(position++, STR32); + buffer.putInt(position, written); + position += 4; + position += written; + } + return this; + } + } + + // Here doesn't use above optimized code for s.length() < (1 << 32) so that + // ensureCapacity is not called with an integer larger than (3 + ((1 << 16) * UTF_8_MAX_CHAR_SIZE) + 2). + // This makes it sure that MessageBufferOutput.next won't be called a size larger than + // 384KB, which is OK size to keep in memory. + + // fallback + packStringWithGetBytes(s); + return this; + } + + /** + * Writes a Timestamp value. + * + *

      + * This method writes a timestamp value using timestamp format family. + * + * @param instant the timestamp to be written + * @return this packer + * @throws IOException when underlying output throws IOException + */ + public MessagePacker packTimestamp(Instant instant) throws IOException { + return packTimestamp(instant.getEpochSecond(), instant.getNano()); + } + + /** + * Writes a Timesamp value using a millisecond value (e.g., System.currentTimeMillis()) + * + * @param millis the millisecond value + * @return this packer + * @throws IOException when underlying output throws IOException + */ + public MessagePacker packTimestamp(long millis) throws IOException { + return packTimestamp(Instant.ofEpochMilli(millis)); + } + + private static final long NANOS_PER_SECOND = 1000000000L; + + /** + * Writes a Timestamp value. + * + *

      + * This method writes a timestamp value using timestamp format family. + * + * @param epochSecond the number of seconds from 1970-01-01T00:00:00Z + * @param nanoAdjustment the nanosecond adjustment to the number of seconds, positive or negative + * @return this + * @throws IOException when underlying output throws IOException + * @throws ArithmeticException when epochSecond plus nanoAdjustment in seconds exceeds the range of long + */ + public MessagePacker packTimestamp(long epochSecond, int nanoAdjustment) throws IOException, ArithmeticException { + long sec = Math.addExact(epochSecond, Math.floorDiv(nanoAdjustment, NANOS_PER_SECOND)); + long nsec = Math.floorMod((long) nanoAdjustment, NANOS_PER_SECOND); + + if (sec >>> 34 == 0) { + // sec can be serialized in 34 bits. + long data64 = (nsec << 34) | sec; + if ((data64 & 0xffffffff00000000L) == 0L) { + // sec can be serialized in 32 bits and nsec is 0. + // use timestamp 32 + writeTimestamp32((int) sec); + } + else { + // sec exceeded 32 bits or nsec is not 0. + // use timestamp 64 + writeTimestamp64(data64); + } + } + else { + // use timestamp 96 format + writeTimestamp96(sec, (int) nsec); + } + return this; + } + + private void writeTimestamp32(int sec) throws IOException { + // timestamp 32 in fixext 4 + MessageBuffer buffer = ensureCapacity(6); + buffer.putByte(position++, FIXEXT4); + buffer.putByte(position++, EXT_TIMESTAMP); + buffer.putInt(position, sec); + position += 4; + } + + private void writeTimestamp64(long data64) throws IOException { + // timestamp 64 in fixext 8 + MessageBuffer buffer = ensureCapacity(10); + buffer.putByte(position++, FIXEXT8); + buffer.putByte(position++, EXT_TIMESTAMP); + buffer.putLong(position, data64); + position += 8; + } + + private void writeTimestamp96(long sec, int nsec) throws IOException { + // timestamp 96 in ext 8 + MessageBuffer buffer = ensureCapacity(15); + buffer.putByte(position++, EXT8); + buffer.putByte(position++, (byte) 12); // length of nsec and sec + buffer.putByte(position++, EXT_TIMESTAMP); + buffer.putInt(position, nsec); + position += 4; + buffer.putLong(position, sec); + position += 8; + } + + /** + * Writes header of an Array value. + *

      + * You will call other packer methods for each element after this method call. + *

      + * You don't have to call anything at the end of iteration. + * + * @param arraySize number of elements to be written + * @return this + * @throws IOException when underlying output throws IOException + */ + public MessagePacker packArrayHeader(int arraySize) throws IOException { + if (arraySize < 0) { + throw new IllegalArgumentException("array size must be >= 0"); + } + + if (arraySize < (1 << 4)) { + writeByte((byte) (FIXARRAY_PREFIX | arraySize)); + } + else if (arraySize < (1 << 16)) { + writeByteAndShort(ARRAY16, (short) arraySize); + } + else { + writeByteAndInt(ARRAY32, arraySize); + } + return this; + } + + /** + * Writes header of a Map value. + *

      + * After this method call, for each key-value pair, you will call packer methods for key first, and then value. + * You will call packer methods twice as many time as the size of the map. + *

      + * You don't have to call anything at the end of iteration. + * + * @param mapSize number of pairs to be written + * @return this + * @throws IOException when underlying output throws IOException + */ + public MessagePacker packMapHeader(int mapSize) throws IOException { + if (mapSize < 0) { + throw new IllegalArgumentException("map size must be >= 0"); + } + + if (mapSize < (1 << 4)) { + writeByte((byte) (FIXMAP_PREFIX | mapSize)); + } + else if (mapSize < (1 << 16)) { + writeByteAndShort(MAP16, (short) mapSize); + } + else { + writeByteAndInt(MAP32, mapSize); + } + return this; + } + + /** + * Writes a dynamically typed value. + * + * @param v the value to be written + * @return this + * @throws IOException when underlying output throws IOException + */ + public MessagePacker packValue(Value v) throws IOException { + v.writeTo(this); + return this; + } + + /** + * Writes header of an Extension value. + *

      + * You MUST call {@link #writePayload(byte[])} or {@link #addPayload(byte[])} method to write body binary. + * + * @param extType the extension type tag to be written + * @param payloadLen number of bytes of a payload binary to be written + * @return this + * @throws IOException when underlying output throws IOException + */ + public MessagePacker packExtensionTypeHeader(byte extType, int payloadLen) throws IOException { + if (payloadLen < (1 << 8)) { + if (payloadLen > 0 && (payloadLen & (payloadLen - 1)) == 0) { // check whether dataLen == 2^x + if (payloadLen == 1) { + writeByteAndByte(FIXEXT1, extType); + } + else if (payloadLen == 2) { + writeByteAndByte(FIXEXT2, extType); + } + else if (payloadLen == 4) { + writeByteAndByte(FIXEXT4, extType); + } + else if (payloadLen == 8) { + writeByteAndByte(FIXEXT8, extType); + } + else if (payloadLen == 16) { + writeByteAndByte(FIXEXT16, extType); + } + else { + writeByteAndByte(EXT8, (byte) payloadLen); + writeByte(extType); + } + } + else { + writeByteAndByte(EXT8, (byte) payloadLen); + writeByte(extType); + } + } + else if (payloadLen < (1 << 16)) { + writeByteAndShort(EXT16, (short) payloadLen); + writeByte(extType); + } + else { + writeByteAndInt(EXT32, payloadLen); + writeByte(extType); + + // TODO support dataLen > 2^31 - 1 + } + return this; + } + + /** + * Writes header of a Binary value. + *

      + * You MUST call {@link #writePayload(byte[])} or {@link #addPayload(byte[])} method to write body binary. + * + * @param len number of bytes of a binary to be written + * @return this + * @throws IOException when underlying output throws IOException + */ + public MessagePacker packBinaryHeader(int len) throws IOException { + if (len < (1 << 8)) { + writeByteAndByte(BIN8, (byte) len); + } + else if (len < (1 << 16)) { + writeByteAndShort(BIN16, (short) len); + } + else { + writeByteAndInt(BIN32, len); + } + return this; + } + + /** + * Writes header of a String value. + *

      + * Length must be number of bytes of a string in UTF-8 encoding. + *

      + * You MUST call {@link #writePayload(byte[])} or {@link #addPayload(byte[])} method to write body of the + * UTF-8 encoded string. + * + * @param len number of bytes of a UTF-8 string to be written + * @return this + * @throws IOException when underlying output throws IOException + */ + public MessagePacker packRawStringHeader(int len) throws IOException { + if (len < (1 << 5)) { + writeByte((byte) (FIXSTR_PREFIX | len)); + } + else if (str8FormatSupport && len < (1 << 8)) { + writeByteAndByte(STR8, (byte) len); + } + else if (len < (1 << 16)) { + writeByteAndShort(STR16, (short) len); + } + else { + writeByteAndInt(STR32, len); + } + return this; + } + + /** + * Writes a byte array to the output. + *

      + * This method is used with {@link #packRawStringHeader(int)} or {@link #packBinaryHeader(int)} methods. + *

      + * Unlike {@link #writePayload(byte[])} method, this method does not make a defensive copy of the given byte + * array, even if it is shorter than {@link MessagePack.PackerConfig#withBufferFlushThreshold(int)}. This is + * faster than {@link #writePayload(byte[])} method but caller must not modify the byte array after calling + * this method. + * + * @param data the data to add + * @return this + * @throws IOException when underlying output throws IOException + * @see #writePayload(byte[]) + */ + public MessagePacker packBinary(@Nullable byte[] data) throws IOException { + if (data == null || data.length == 0) { + return packBinaryHeader(0); + } + return packBinaryHeader(data.length) + .addPayload(data); + } + + /** + * Writes a byte array to the output. + *

      + * This method is used with {@link #packRawStringHeader(int)} or {@link #packBinaryHeader(int)} methods. + * + * @param src the data to add + * @return this + * @throws IOException when underlying output throws IOException + */ + public MessagePacker writePayload(byte[] src) throws IOException { + return writePayload(src, 0, src.length); + } + + /** + * Writes a byte array to the output. + *

      + * This method is used with {@link #packRawStringHeader(int)} or {@link #packBinaryHeader(int)} methods. + * + * @param src the data to add + * @param off the start offset in the data + * @param len the number of bytes to add + * @return this + * @throws IOException when underlying output throws IOException + */ + public MessagePacker writePayload(byte[] src, int off, int len) throws IOException { + if (buffer == null || buffer.size() - position < len || len > bufferFlushThreshold) { + flush(); // call flush before write + // Directly write payload to the output without using the buffer + out.write(src, off, len); + totalFlushBytes += len; + } + else { + buffer.putBytes(position, src, off, len); + position += len; + } + return this; + } + + /** + * Writes a byte array to the output. + *

      + * This method is used with {@link #packRawStringHeader(int)} or {@link #packBinaryHeader(int)} methods. + *

      + * Unlike {@link #writePayload(byte[])} method, this method does not make a defensive copy of the given byte + * array, even if it is shorter than {@link MessagePack.PackerConfig#withBufferFlushThreshold(int)}. This is + * faster than {@link #writePayload(byte[])} method but caller must not modify the byte array after calling + * this method. + * + * @param src the data to add + * @return this + * @throws IOException when underlying output throws IOException + * @see #writePayload(byte[]) + */ + public MessagePacker addPayload(byte[] src) throws IOException { + return addPayload(src, 0, src.length); + } + + /** + * Writes a byte array to the output. + *

      + * This method is used with {@link #packRawStringHeader(int)} or {@link #packBinaryHeader(int)} methods. + *

      + * Unlike {@link #writePayload(byte[], int, int)} method, this method does not make a defensive copy of the + * given byte array, even if it is shorter than {@link MessagePack.PackerConfig#withBufferFlushThreshold(int)}. + * This is faster than {@link #writePayload(byte[])} method but caller must not modify the byte array after + * calling this method. + * + * @param src the data to add + * @param off the start offset in the data + * @param len the number of bytes to add + * @return this + * @throws IOException when underlying output throws IOException + * @see #writePayload(byte[], int, int) + */ + public MessagePacker addPayload(byte[] src, int off, int len) throws IOException { + if (buffer == null || buffer.size() - position < len || len > bufferFlushThreshold) { + flush(); // call flush before add + // Directly add the payload without using the buffer + out.add(src, off, len); + totalFlushBytes += len; + } + else { + buffer.putBytes(position, src, off, len); + position += len; + } + return this; + } + + // + + public MessagePacker write(boolean val) throws IOException { + return packBoolean(val); + } + + public MessagePacker write(byte val) throws IOException { + return packByte(val); + } + + public MessagePacker write(short val) throws IOException { + return packShort(val); + } + + public MessagePacker write(int val) throws IOException { + return packInt(val); + } + + public MessagePacker write(long val) throws IOException { + return packLong(val); + } + + public MessagePacker write(float val) throws IOException { + return packFloat(val); + } + + public MessagePacker write(double val) throws IOException { + return packDouble(val); + } + + public MessagePacker write(@Nullable byte[] bytes) throws IOException { + return packBinary(bytes); + } + + public MessagePacker write(String s) throws IOException { + return packString(s); + } + + public MessagePacker write(Instant instant) throws IOException { + return packTimestamp(instant); + } + +} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageSizeException.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageSizeException.java new file mode 100644 index 0000000..f6d1888 --- /dev/null +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageSizeException.java @@ -0,0 +1,40 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.serialize.format; + +/** + * Thrown to indicate too large message size (e.g, larger than 2^31-1). + */ +public class MessageSizeException extends MessagePackException { + + private final long size; + + public MessageSizeException(long size) { + super(null, null); + this.size = size; + } + + public MessageSizeException(String message, long size) { + super(message, null); + this.size = size; + } + + public long getSize() { + return size; + } +} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageStringCodingException.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageStringCodingException.java new file mode 100644 index 0000000..2b390a1 --- /dev/null +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageStringCodingException.java @@ -0,0 +1,35 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.serialize.format; + +import java.nio.charset.CharacterCodingException; + +/** + * Thrown to indicate an error when encoding/decoding a String value + */ +public class MessageStringCodingException extends MessagePackException { + + public MessageStringCodingException(CharacterCodingException cause) { + super(null, cause); + } + + @Override + public CharacterCodingException getCause() { + return (CharacterCodingException) super.getCause(); + } +} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageTypeCastException.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageTypeCastException.java new file mode 100644 index 0000000..2d87a81 --- /dev/null +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageTypeCastException.java @@ -0,0 +1,26 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.serialize.format; + +public class MessageTypeCastException extends MessageTypeException { + + public MessageTypeCastException() { + super(null, null); + } + +} diff --git a/today-cloud-core/src/main/java/infra/cloud/core/serialize/DeserializeFailedException.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageTypeException.java similarity index 57% rename from today-cloud-core/src/main/java/infra/cloud/core/serialize/DeserializeFailedException.java rename to today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageTypeException.java index 14e647d..51a9802 100644 --- a/today-cloud-core/src/main/java/infra/cloud/core/serialize/DeserializeFailedException.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageTypeException.java @@ -15,34 +15,21 @@ * along with this program. If not, see [http://www.gnu.org/licenses/] */ -package infra.cloud.core.serialize; +package infra.cloud.serialize.format; -import java.io.Serial; - -import infra.cloud.RemotingException; +import infra.lang.Nullable; /** - * Deserialize Failed - * - * @author TODAY 2021/7/11 23:54 + * Thrown when a type mismatch error occurs */ -public class DeserializeFailedException extends RemotingException { - @Serial - private static final long serialVersionUID = 1L; - - public DeserializeFailedException() { - super(); - } +public class MessageTypeException extends MessagePackException { - public DeserializeFailedException(String message) { - super(message); + public MessageTypeException(@Nullable String message) { + super(message, null); } - public DeserializeFailedException(Throwable cause) { - super(cause); - } - - public DeserializeFailedException(String message, Throwable cause) { + public MessageTypeException(@Nullable String message, @Nullable Throwable cause) { super(message, cause); } + } diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageUnpacker.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageUnpacker.java new file mode 100644 index 0000000..ed4f815 --- /dev/null +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageUnpacker.java @@ -0,0 +1,1639 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.serialize.format; + +import java.io.Closeable; +import java.io.IOException; +import java.math.BigInteger; +import java.nio.ByteBuffer; +import java.nio.CharBuffer; +import java.nio.charset.CharacterCodingException; +import java.nio.charset.CharsetDecoder; +import java.nio.charset.CoderResult; +import java.nio.charset.CodingErrorAction; +import java.time.Instant; +import java.util.Objects; + +import infra.cloud.serialize.format.MessagePack.Code; +import infra.cloud.serialize.format.buffer.MessageBuffer; +import infra.cloud.serialize.format.buffer.MessageBufferInput; +import infra.cloud.serialize.format.value.ImmutableValue; +import infra.cloud.serialize.format.value.Value; +import infra.cloud.serialize.format.value.ValueFactory; +import infra.cloud.serialize.format.value.Variable; + +import static infra.cloud.serialize.format.MessagePack.Code.EXT_TIMESTAMP; + +/** + * MessagePack deserializer that converts binary into objects. + * You can use factory methods of {@link MessagePack} class or {@link MessagePack.UnpackerConfig} class to create + * an instance. + * To read values as statically-typed Java objects, there are two typical use cases. + *

      + * One use case is to read objects as {@link Value} using {@link #unpackValue} method. A {@link Value} object + * contains type of the deserialized value as well as the value itself so that you can inspect type of the + * deserialized values later. You can repeat {@link #unpackValue} until {@link #hasNext()} method returns false so + * that you can deserialize sequence of MessagePack values. + *

      + * The other use case is to use {@link #getNextFormat()} and {@link MessageFormat#getValueType()} methods followed + * by unpackXxx methods corresponding to returned type. Following code snipet is a typical application code: + *

      
      + *     MessageUnpacker unpacker = MessagePack.newDefaultUnpacker(...);
      + *     while(unpacker.hasNext()) {
      + *         MessageFormat format = unpacker.getNextFormat();
      + *         ValueType type = format.getValueType();
      + *         int length;
      + *         ExtensionTypeHeader extension;
      + *         switch(type) {
      + *             case NIL:
      + *                 unpacker.unpackNil();
      + *                 break;
      + *             case BOOLEAN:
      + *                 unpacker.unpackBoolean();
      + *                 break;
      + *             case INTEGER:
      + *                 switch (format) {
      + *                 case UINT64:
      + *                     unpacker.unpackBigInteger();
      + *                     break;
      + *                 case INT64:
      + *                 case UINT32:
      + *                     unpacker.unpackLong();
      + *                     break;
      + *                 default:
      + *                     unpacker.unpackInt();
      + *                     break;
      + *                 }
      + *                 break;
      + *             case FLOAT:
      + *                 unpacker.unpackDouble();
      + *                 break;
      + *             case STRING:
      + *                 unpacker.unpackString();
      + *                 break;
      + *             case BINARY:
      + *                 length = unpacker.unpackBinaryHeader();
      + *                 unpacker.readPayload(new byte[length]);
      + *                 break;
      + *             case ARRAY:
      + *                 length = unpacker.unpackArrayHeader();
      + *                 for (int i = 0; i < length; i++) {
      + *                     readRecursively(unpacker);
      + *                 }
      + *                 break;
      + *             case MAP:
      + *                 length = unpacker.unpackMapHeader();
      + *                 for (int i = 0; i < length; i++) {
      + *                     readRecursively(unpacker);  // key
      + *                     readRecursively(unpacker);  // value
      + *                 }
      + *                 break;
      + *             case EXTENSION:
      + *                 extension = unpacker.unpackExtensionTypeHeader();
      + *                 unpacker.readPayload(new byte[extension.getLength()]);
      + *                 break;
      + *             }
      + *         }
      + *     }
      + *
      + * 

      + * Following methods correspond to the MessagePack types: + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
      MessagePack typeUnpacker methodJava type
      Nil{@link #unpackNil()}null
      Boolean{@link #unpackBoolean()}boolean
      Integer{@link #unpackByte()}byte
      Integer{@link #unpackShort()}short
      Integer{@link #unpackInt()}int
      Integer{@link #unpackLong()}long
      Integer{@link #unpackBigInteger()}BigInteger
      Float{@link #unpackFloat()}float
      Float{@link #unpackDouble()}double
      Binary{@link #unpackBinaryHeader()}byte array
      String{@link #unpackRawStringHeader()}String
      String{@link #unpackString()}String
      Array{@link #unpackArrayHeader()}Array
      Map{@link #unpackMapHeader()}Map
      Extension{@link #unpackExtensionTypeHeader()}{@link ExtensionTypeHeader}
      + * + *

      + * To read a byte array, first call {@link #unpackBinaryHeader} method to get length of the byte array. Then, + * call {@link #readPayload(int)} or {@link #readPayloadAsReference(int)} method to read the the contents. + * + *

      + * To read an Array type, first call {@link #unpackArrayHeader()} method to get number of elements. Then, + * call unpacker methods for each element. + * + *

      + * To read a Map, first call {@link #unpackMapHeader()} method to get number of pairs of the map. Then, + * for each pair, call unpacker methods for key first, and then value. will call unpacker methods twice + * as many time as the returned count. + */ +public class MessageUnpacker implements Closeable { + + private static final MessageBuffer EMPTY_BUFFER = MessageBuffer.wrap(new byte[0]); + + private final boolean allowReadingStringAsBinary; + private final boolean allowReadingBinaryAsString; + private final CodingErrorAction actionOnMalformedString; + private final CodingErrorAction actionOnUnmappableString; + private final int stringSizeLimit; + private final int stringDecoderBufferSize; + + private MessageBufferInput in; + + /** + * Points to the current buffer to read + */ + private MessageBuffer buffer = EMPTY_BUFFER; + + /** + * Cursor position in the current buffer + */ + private int position; + + /** + * Total read byte size + */ + private int totalReadBytes; + + /** + * An extra buffer for reading a small number value across the input buffer boundary. + * At most 8-byte buffer (for readLong used by uint 64 and UTF-8 character decoding) is required. + */ + private final MessageBuffer numberBuffer = MessageBuffer.allocate(8); + + /** + * After calling prepareNumberBuffer(), the caller should use this variable to read from the returned MessageBuffer. + */ + private int nextReadPosition; + + /** + * For decoding String in unpackString. + */ + private StringBuilder decodeStringBuffer; + + /** + * For decoding String in unpackString. + */ + private CharsetDecoder decoder; + + /** + * Buffer for decoding strings + */ + private CharBuffer decodeBuffer; + + /** + * Create an MessageUnpacker that reads data from the given MessageBufferInput. + * This method is available for subclasses to override. Use MessagePack.UnpackerConfig.newUnpacker method to instantiate this implementation. + */ + protected MessageUnpacker(MessageBufferInput in, MessagePack.UnpackerConfig config) { + this.in = Objects.requireNonNull(in, "MessageBufferInput is null"); + this.allowReadingStringAsBinary = config.getAllowReadingStringAsBinary(); + this.allowReadingBinaryAsString = config.getAllowReadingBinaryAsString(); + this.actionOnMalformedString = config.getActionOnMalformedString(); + this.actionOnUnmappableString = config.getActionOnUnmappableString(); + this.stringSizeLimit = config.getStringSizeLimit(); + this.stringDecoderBufferSize = config.getStringDecoderBufferSize(); + } + + /** + * Replaces underlying input. + *

      + * This method clears internal buffer, swaps the underlying input with the new given input, then returns + * the old input. + * + *

      + * This method doesn't close the old input. + * + * @param in new input + * @return the old input + * @throws IOException never happens unless a subclass overrides this method + * @throws NullPointerException the given input is null + */ + public MessageBufferInput reset(MessageBufferInput in) throws IOException { + MessageBufferInput newIn = Objects.requireNonNull(in, "MessageBufferInput is null"); + + // Reset the internal states + MessageBufferInput old = this.in; + this.in = newIn; + this.buffer = EMPTY_BUFFER; + this.position = 0; + this.totalReadBytes = 0; + // No need to initialize the already allocated string decoder here since we can reuse it. + + return old; + } + + /** + * Returns total number of read bytes. + *

      + * This method returns total of amount of data consumed from the underlying input minus size of data + * remained still unused in the current internal buffer. + * + *

      + * Calling {@link #reset(MessageBufferInput)} resets this number to 0. + */ + public int getTotalReadBytes() { + return totalReadBytes + position; + } + + /** + * Get the next buffer without changing the position + */ + private MessageBuffer getNextBuffer() throws IOException { + MessageBuffer next = in.next(); + if (next == null) { + throw new MessageInsufficientBufferException(); + } + assert (buffer != null); + totalReadBytes += buffer.size(); + return next; + } + + private void nextBuffer() throws IOException { + buffer = getNextBuffer(); + position = 0; + } + + /** + * Returns a short size buffer (upto 8 bytes) to read a number value + * + * @throws MessageInsufficientBufferException If no more buffer can be acquired from the input source for reading the specified data length + */ + private MessageBuffer prepareNumberBuffer(int readLength) throws IOException { + int remaining = buffer.size() - position; + if (remaining >= readLength) { + // When the data is contained inside the default buffer + nextReadPosition = position; + position += readLength; // here assumes following buffer.getXxx never throws exception + return buffer; // Return the default buffer + } + else { + // When the default buffer doesn't contain the whole length, + // fill the temporary buffer from the current data fragment and + // next fragment(s). + + int off = 0; + if (remaining > 0) { + numberBuffer.putMessageBuffer(0, buffer, position, remaining); + readLength -= remaining; + off += remaining; + } + + while (true) { + nextBuffer(); + int nextSize = buffer.size(); + if (nextSize >= readLength) { + numberBuffer.putMessageBuffer(off, buffer, 0, readLength); + position = readLength; + break; + } + else { + numberBuffer.putMessageBuffer(off, buffer, 0, nextSize); + readLength -= nextSize; + off += nextSize; + } + } + + nextReadPosition = 0; + return numberBuffer; + } + } + + private static int utf8MultibyteCharacterSize(byte firstByte) { + return Integer.numberOfLeadingZeros(~(firstByte & 0xff) << 24); + } + + /** + * Returns true if this unpacker has more elements. + * When this returns true, subsequent call to {@link #getNextFormat()} returns an + * MessageFormat instance. If false, next {@link #getNextFormat()} call will throw an MessageInsufficientBufferException. + * + * @return true if this unpacker has more elements to read + */ + public boolean hasNext() throws IOException { + return ensureBuffer(); + } + + private boolean ensureBuffer() throws IOException { + while (buffer.size() <= position) { + MessageBuffer next = in.next(); + if (next == null) { + return false; + } + totalReadBytes += buffer.size(); + buffer = next; + position = 0; + } + return true; + } + + /** + * Returns format of the next value. + * + *

      + * Note that this method doesn't consume data from the internal buffer unlike the other unpack methods. + * Calling this method twice will return the same value. + * + *

      + * To not throw {@link MessageInsufficientBufferException}, this method should be called only when + * {@link #hasNext()} returns true. + * + * @return the next MessageFormat + * @throws IOException when underlying input throws IOException + * @throws MessageInsufficientBufferException when the end of file reached, i.e. {@link #hasNext()} == false. + */ + public MessageFormat getNextFormat() throws IOException { + // makes sure that buffer has at least 1 byte + if (!ensureBuffer()) { + throw new MessageInsufficientBufferException(); + } + byte b = buffer.getByte(position); + return MessageFormat.valueOf(b); + } + + /** + * Read a byte value at the cursor and proceed the cursor. + */ + private byte readInt8() throws IOException { + if (buffer.size() > position) { + byte b = buffer.getByte(position); + position++; + return b; + } + else { + nextBuffer(); + if (buffer.size() > 0) { + byte b = buffer.getByte(0); + position = 1; + return b; + } + return readInt8(); + } + } + + private short readInt16() throws IOException { + MessageBuffer numberBuffer = prepareNumberBuffer(2); + return numberBuffer.getShort(nextReadPosition); + } + + private int readInt32() throws IOException { + MessageBuffer numberBuffer = prepareNumberBuffer(4); + return numberBuffer.getInt(nextReadPosition); + } + + private long readInt64() throws IOException { + MessageBuffer numberBuffer = prepareNumberBuffer(8); + return numberBuffer.getLong(nextReadPosition); + } + + private float readFloat32() throws IOException { + MessageBuffer numberBuffer = prepareNumberBuffer(4); + return numberBuffer.getFloat(nextReadPosition); + } + + private double readFloat64() throws IOException { + MessageBuffer numberBuffer = prepareNumberBuffer(8); + return numberBuffer.getDouble(nextReadPosition); + } + + /** + * Skip the next value, then move the cursor at the end of the value + */ + public void skipValue() throws IOException { + skipValue(1); + } + + /** + * Skip next values, then move the cursor at the end of the value + * + * @param count number of values to skip + */ + public void skipValue(int count) throws IOException { + while (count > 0) { + byte b = readInt8(); + MessageFormat f = MessageFormat.valueOf(b); + switch (f) { + case POS_FIX_INT: + case NEG_FIX_INT: + case BOOLEAN: + case NIL: + break; + case FIX_MAP: { + int mapLen = b & 0x0f; + count += mapLen * 2; + break; + } + case FIX_ARRAY: { + int arrayLen = b & 0x0f; + count += arrayLen; + break; + } + case FIX_STR: { + int strLen = b & 0x1f; + skipPayload(strLen); + break; + } + case INT8: + case UINT8: + skipPayload(1); + break; + case INT16: + case UINT16: + skipPayload(2); + break; + case INT32: + case UINT32: + case FLOAT32: + skipPayload(4); + break; + case INT64: + case UINT64: + case FLOAT64: + skipPayload(8); + break; + case BIN8: + case STR8: + skipPayload(readNextLength8()); + break; + case BIN16: + case STR16: + skipPayload(readNextLength16()); + break; + case BIN32: + case STR32: + skipPayload(readNextLength32()); + break; + case FIX_EXT1: + skipPayload(2); + break; + case FIX_EXT2: + skipPayload(3); + break; + case FIX_EXT4: + skipPayload(5); + break; + case FIX_EXT8: + skipPayload(9); + break; + case FIX_EXT16: + skipPayload(17); + break; + case EXT8: + skipPayload(readNextLength8() + 1); + break; + case EXT16: + skipPayload(readNextLength16() + 1); + break; + case EXT32: + int extLen = readNextLength32(); + // Skip the first ext type header (1-byte) first in case ext length is Integer.MAX_VALUE + skipPayload(1); + skipPayload(extLen); + break; + case ARRAY16: + count += readNextLength16(); + break; + case ARRAY32: + count += readNextLength32(); + break; + case MAP16: + count += readNextLength16() * 2; + break; + case MAP32: + count += readNextLength32() * 2; // TODO check int overflow + break; + case NEVER_USED: + throw new MessageNeverUsedFormatException("Encountered 0xC1 \"NEVER_USED\" byte"); + } + + count--; + } + } + + /** + * Create an exception for the case when an unexpected byte value is read + */ + private static MessagePackException unexpected(String expected, byte b) { + MessageFormat format = MessageFormat.valueOf(b); + if (format == MessageFormat.NEVER_USED) { + return new MessageNeverUsedFormatException(String.format("Expected %s, but encountered 0xC1 \"NEVER_USED\" byte", expected)); + } + else { + String name = format.getValueType().name(); + String typeName = name.charAt(0) + name.substring(1).toLowerCase(); + return new MessageTypeException(String.format("Expected %s, but got %s (%02x)", expected, typeName, b)); + } + } + + private static MessagePackException unexpectedExtension(String expected, int expectedType, int actualType) { + return new MessageTypeException(String.format("Expected extension type %s (%d), but got extension type %d", + expected, expectedType, actualType)); + } + + public ImmutableValue unpackValue() throws IOException { + MessageFormat mf = getNextFormat(); + switch (mf.getValueType()) { + case NIL: + readInt8(); + return ValueFactory.newNil(); + case BOOLEAN: + return ValueFactory.newBoolean(unpackBoolean()); + case INTEGER: + if (mf == MessageFormat.UINT64) { + return ValueFactory.newInteger(unpackBigInteger()); + } + else { + return ValueFactory.newInteger(unpackLong()); + } + case FLOAT: + return ValueFactory.newFloat(unpackDouble()); + case STRING: { + int length = unpackRawStringHeader(); + if (length > stringSizeLimit) { + throw new MessageSizeException(String.format("cannot unpack a String of size larger than %,d: %,d", stringSizeLimit, length), length); + } + return ValueFactory.newString(readPayload(length), true); + } + case BINARY: { + int length = unpackBinaryHeader(); + return ValueFactory.newBinary(readPayload(length), true); + } + case ARRAY: { + int size = unpackArrayHeader(); + Value[] array = new Value[size]; + for (int i = 0; i < size; i++) { + array[i] = unpackValue(); + } + return ValueFactory.newArray(array, true); + } + case MAP: { + int size = unpackMapHeader(); + Value[] kvs = new Value[size * 2]; + for (int i = 0; i < size * 2; ) { + kvs[i] = unpackValue(); + i++; + kvs[i] = unpackValue(); + i++; + } + return ValueFactory.newMap(kvs, true); + } + case EXTENSION: { + ExtensionTypeHeader extHeader = unpackExtensionTypeHeader(); + if (extHeader.getType() == EXT_TIMESTAMP) { + return ValueFactory.newTimestamp(unpackTimestamp(extHeader)); + } + return ValueFactory.newExtension(extHeader.getType(), readPayload(extHeader.getLength())); + } + default: + throw new MessageNeverUsedFormatException("Unknown value type"); + } + } + + public Variable unpackValue(Variable var) throws IOException { + MessageFormat mf = getNextFormat(); + switch (mf.getValueType()) { + case NIL: + readInt8(); + var.setNilValue(); + return var; + case BOOLEAN: + var.setBooleanValue(unpackBoolean()); + return var; + case INTEGER: + if (mf == MessageFormat.UINT64) { + var.setIntegerValue(unpackBigInteger()); + return var; + } + var.setIntegerValue(unpackLong()); + return var; + case FLOAT: + var.setFloatValue(unpackDouble()); + return var; + case STRING: { + int length = unpackRawStringHeader(); + if (length > stringSizeLimit) { + throw new MessageSizeException(String.format("cannot unpack a String of size larger than %,d: %,d", stringSizeLimit, length), length); + } + var.setStringValue(readPayload(length)); + return var; + } + case BINARY: { + int length = unpackBinaryHeader(); + var.setBinaryValue(readPayload(length)); + return var; + } + case ARRAY: { + int size = unpackArrayHeader(); + Value[] kvs = new Value[size]; + for (int i = 0; i < size; i++) { + kvs[i] = unpackValue(); + } + var.setArrayValue(kvs); + return var; + } + case MAP: { + int size = unpackMapHeader(); + Value[] kvs = new Value[size * 2]; + for (int i = 0; i < size * 2; ) { + kvs[i] = unpackValue(); + i++; + kvs[i] = unpackValue(); + i++; + } + var.setMapValue(kvs); + return var; + } + case EXTENSION: { + ExtensionTypeHeader extHeader = unpackExtensionTypeHeader(); + if (extHeader.getType() == EXT_TIMESTAMP) { + var.setTimestampValue(unpackTimestamp(extHeader)); + } + else { + var.setExtensionValue(extHeader.getType(), readPayload(extHeader.getLength())); + } + return var; + } + default: + throw new MessageFormatException("Unknown value type"); + } + } + + /** + * Reads a Nil byte. + * + * @throws MessageTypeException when value is not MessagePack Nil type + * @throws IOException when underlying input throws IOException + */ + public void unpackNil() throws IOException { + byte b = readInt8(); + if (b == Code.NIL) { + return; + } + throw unexpected("Nil", b); + } + + /** + * Peeks a Nil byte and reads it if next byte is a nil value. + *

      + * The difference from {@link #unpackNil()} is that unpackNil throws an exception if the next byte is not nil value + * while this tryUnpackNil method returns false without changing position. + * + * @return true if a nil value is read + * @throws MessageInsufficientBufferException when the end of file reached + * @throws IOException when underlying input throws IOException + */ + public boolean tryUnpackNil() throws IOException { + // makes sure that buffer has at least 1 byte + if (!ensureBuffer()) { + throw new MessageInsufficientBufferException(); + } + byte b = buffer.getByte(position); + if (b == Code.NIL) { + readInt8(); + return true; + } + return false; + } + + /** + * Reads true or false. + * + * @return the read value + * @throws MessageTypeException when value is not MessagePack Boolean type + * @throws IOException when underlying input throws IOException + */ + public boolean unpackBoolean() throws IOException { + byte b = readInt8(); + if (b == Code.FALSE) { + return false; + } + else if (b == Code.TRUE) { + return true; + } + throw unexpected("boolean", b); + } + + /** + * Reads a byte. + *

      + * This method throws {@link MessageIntegerOverflowException} if the value doesn't fit in the range of byte. This may happen when {@link #getNextFormat()} returns UINT8, INT16, or larger integer formats. + * + * @return the read value + * @throws MessageIntegerOverflowException when value doesn't fit in the range of byte + * @throws MessageTypeException when value is not MessagePack Integer type + * @throws IOException when underlying input throws IOException + */ + public byte unpackByte() throws IOException { + byte b = readInt8(); + if (Code.isFixInt(b)) { + return b; + } + switch (b) { + case Code.UINT8: // unsigned int 8 + byte u8 = readInt8(); + if (u8 < (byte) 0) { + throw overflowU8(u8); + } + return u8; + case Code.UINT16: // unsigned int 16 + short u16 = readInt16(); + if (u16 < 0 || u16 > Byte.MAX_VALUE) { + throw overflowU16(u16); + } + return (byte) u16; + case Code.UINT32: // unsigned int 32 + int u32 = readInt32(); + if (u32 < 0 || u32 > Byte.MAX_VALUE) { + throw overflowU32(u32); + } + return (byte) u32; + case Code.UINT64: // unsigned int 64 + long u64 = readInt64(); + if (u64 < 0L || u64 > Byte.MAX_VALUE) { + throw overflowU64(u64); + } + return (byte) u64; + case Code.INT8: // signed int 8 + return readInt8(); + case Code.INT16: // signed int 16 + short i16 = readInt16(); + if (i16 < Byte.MIN_VALUE || i16 > Byte.MAX_VALUE) { + throw overflowI16(i16); + } + return (byte) i16; + case Code.INT32: // signed int 32 + int i32 = readInt32(); + if (i32 < Byte.MIN_VALUE || i32 > Byte.MAX_VALUE) { + throw overflowI32(i32); + } + return (byte) i32; + case Code.INT64: // signed int 64 + long i64 = readInt64(); + if (i64 < Byte.MIN_VALUE || i64 > Byte.MAX_VALUE) { + throw overflowI64(i64); + } + return (byte) i64; + } + throw unexpected("Integer", b); + } + + /** + * Reads a short. + *

      + * This method throws {@link MessageIntegerOverflowException} if the value + * doesn't fit in the range of short. This may happen when {@link #getNextFormat()} + * returns UINT16, INT32, or larger integer formats. + * + * @return the read value + * @throws MessageIntegerOverflowException when value doesn't fit in the range of short + * @throws MessageTypeException when value is not MessagePack Integer type + * @throws IOException when underlying input throws IOException + */ + public short unpackShort() throws IOException { + byte b = readInt8(); + if (Code.isFixInt(b)) { + return b; + } + switch (b) { + case Code.UINT8: // unsigned int 8 + byte u8 = readInt8(); + return (short) (u8 & 0xff); + case Code.UINT16: // unsigned int 16 + short u16 = readInt16(); + if (u16 < (short) 0) { + throw overflowU16(u16); + } + return u16; + case Code.UINT32: // unsigned int 32 + int u32 = readInt32(); + if (u32 < 0 || u32 > Short.MAX_VALUE) { + throw overflowU32(u32); + } + return (short) u32; + case Code.UINT64: // unsigned int 64 + long u64 = readInt64(); + if (u64 < 0L || u64 > Short.MAX_VALUE) { + throw overflowU64(u64); + } + return (short) u64; + case Code.INT8: // signed int 8 + return readInt8(); + case Code.INT16: // signed int 16 + return readInt16(); + case Code.INT32: // signed int 32 + int i32 = readInt32(); + if (i32 < Short.MIN_VALUE || i32 > Short.MAX_VALUE) { + throw overflowI32(i32); + } + return (short) i32; + case Code.INT64: // signed int 64 + long i64 = readInt64(); + if (i64 < Short.MIN_VALUE || i64 > Short.MAX_VALUE) { + throw overflowI64(i64); + } + return (short) i64; + } + throw unexpected("Integer", b); + } + + /** + * Reads a int. + *

      + * This method throws {@link MessageIntegerOverflowException} if the value + * doesn't fit in the range of int. This may happen when {@link #getNextFormat()} + * returns UINT32, INT64, or larger integer formats. + * + * @return the read value + * @throws MessageIntegerOverflowException when value doesn't fit in the range of int + * @throws MessageTypeException when value is not MessagePack Integer type + * @throws IOException when underlying input throws IOException + */ + public int unpackInt() throws IOException { + byte b = readInt8(); + if (Code.isFixInt(b)) { + return b; + } + switch (b) { + case Code.UINT8: // unsigned int 8 + byte u8 = readInt8(); + return u8 & 0xff; + case Code.UINT16: // unsigned int 16 + short u16 = readInt16(); + return u16 & 0xffff; + case Code.UINT32: // unsigned int 32 + int u32 = readInt32(); + if (u32 < 0) { + throw overflowU32(u32); + } + return u32; + case Code.UINT64: // unsigned int 64 + long u64 = readInt64(); + if (u64 < 0L || u64 > (long) Integer.MAX_VALUE) { + throw overflowU64(u64); + } + return (int) u64; + case Code.INT8: // signed int 8 + return readInt8(); + case Code.INT16: // signed int 16 + return readInt16(); + case Code.INT32: // signed int 32 + return readInt32(); + case Code.INT64: // signed int 64 + long i64 = readInt64(); + if (i64 < (long) Integer.MIN_VALUE || i64 > (long) Integer.MAX_VALUE) { + throw overflowI64(i64); + } + return (int) i64; + } + throw unexpected("Integer", b); + } + + /** + * Reads a long. + *

      + * This method throws {@link MessageIntegerOverflowException} if the value doesn't + * fit in the range of long. This may happen when {@link #getNextFormat()} returns UINT64. + * + * @return the read value + * @throws MessageIntegerOverflowException when value doesn't fit in the range of long + * @throws MessageTypeException when value is not MessagePack Integer type + * @throws IOException when underlying input throws IOException + */ + public long unpackLong() throws IOException { + byte b = readInt8(); + if (Code.isFixInt(b)) { + return b; + } + switch (b) { + case Code.UINT8: // unsigned int 8 + byte u8 = readInt8(); + return u8 & 0xff; + case Code.UINT16: // unsigned int 16 + short u16 = readInt16(); + return u16 & 0xffff; + case Code.UINT32: // unsigned int 32 + int u32 = readInt32(); + if (u32 < 0) { + return (long) (u32 & 0x7fffffff) + 0x80000000L; + } + else { + return u32; + } + case Code.UINT64: // unsigned int 64 + long u64 = readInt64(); + if (u64 < 0L) { + throw overflowU64(u64); + } + return u64; + case Code.INT8: // signed int 8 + return readInt8(); + case Code.INT16: // signed int 16 + return readInt16(); + case Code.INT32: // signed int 32 + return readInt32(); + case Code.INT64: // signed int 64 + return readInt64(); + } + throw unexpected("Integer", b); + } + + /** + * Reads a BigInteger. + * + * @return the read value + * @throws MessageTypeException when value is not MessagePack Integer type + * @throws IOException when underlying input throws IOException + */ + public BigInteger unpackBigInteger() throws IOException { + byte b = readInt8(); + if (Code.isFixInt(b)) { + return BigInteger.valueOf(b); + } + switch (b) { + case Code.UINT8: // unsigned int 8 + byte u8 = readInt8(); + return BigInteger.valueOf(u8 & 0xff); + case Code.UINT16: // unsigned int 16 + short u16 = readInt16(); + return BigInteger.valueOf(u16 & 0xffff); + case Code.UINT32: // unsigned int 32 + int u32 = readInt32(); + if (u32 < 0) { + return BigInteger.valueOf((long) (u32 & 0x7fffffff) + 0x80000000L); + } + else { + return BigInteger.valueOf(u32); + } + case Code.UINT64: // unsigned int 64 + long u64 = readInt64(); + if (u64 < 0L) { + return BigInteger.valueOf(u64 + Long.MAX_VALUE + 1L).setBit(63); + } + else { + return BigInteger.valueOf(u64); + } + case Code.INT8: // signed int 8 + byte i8 = readInt8(); + return BigInteger.valueOf(i8); + case Code.INT16: // signed int 16 + short i16 = readInt16(); + return BigInteger.valueOf(i16); + case Code.INT32: // signed int 32 + int i32 = readInt32(); + return BigInteger.valueOf(i32); + case Code.INT64: // signed int 64 + long i64 = readInt64(); + return BigInteger.valueOf(i64); + } + throw unexpected("Integer", b); + } + + /** + * Reads a float. + *

      + * This method rounds value to the range of float when precision of the read + * value is larger than the range of float. This may happen when {@link #getNextFormat()} returns FLOAT64. + * + * @return the read value + * @throws MessageTypeException when value is not MessagePack Float type + * @throws IOException when underlying input throws IOException + */ + public float unpackFloat() throws IOException { + byte b = readInt8(); + return switch (b) { + case Code.FLOAT32 -> readFloat32(); + case Code.FLOAT64 -> { + double dv = readFloat64(); + yield (float) dv; + } + default -> throw unexpected("Float", b); + }; + } + + /** + * Reads a double. + * + * @return the read value + * @throws MessageTypeException when value is not MessagePack Float type + * @throws IOException when underlying input throws IOException + */ + public double unpackDouble() throws IOException { + byte b = readInt8(); + return switch (b) { + case Code.FLOAT32 -> readFloat32(); + case Code.FLOAT64 -> readFloat64(); + default -> throw unexpected("Float", b); + }; + } + + private static final String EMPTY_STRING = ""; + + private void resetDecoder() { + if (decoder == null) { + decodeBuffer = CharBuffer.allocate(stringDecoderBufferSize); + decoder = MessagePack.UTF8.newDecoder() + .onMalformedInput(actionOnMalformedString) + .onUnmappableCharacter(actionOnUnmappableString); + } + else { + decoder.reset(); + } + if (decodeStringBuffer == null) { + decodeStringBuffer = new StringBuilder(); + } + else { + decodeStringBuffer.setLength(0); + } + } + + public String unpackString() throws IOException { + int len = unpackRawStringHeader(); + if (len == 0) { + return EMPTY_STRING; + } + if (len > stringSizeLimit) { + throw new MessageSizeException(String.format("cannot unpack a String of size larger than %,d: %,d", stringSizeLimit, len), len); + } + + resetDecoder(); // should be invoked only once per value + + if (buffer.size() - position >= len) { + return decodeStringFastPath(len); + } + + try { + int rawRemaining = len; + while (rawRemaining > 0) { + int bufferRemaining = buffer.size() - position; + if (bufferRemaining >= rawRemaining) { + decodeStringBuffer.append(decodeStringFastPath(rawRemaining)); + break; + } + else if (bufferRemaining == 0) { + nextBuffer(); + } + else { + ByteBuffer bb = buffer.sliceAsByteBuffer(position, bufferRemaining); + int bbStartPosition = bb.position(); + decodeBuffer.clear(); + + CoderResult cr = decoder.decode(bb, decodeBuffer, false); + int readLen = bb.position() - bbStartPosition; + position += readLen; + rawRemaining -= readLen; + decodeStringBuffer.append(decodeBuffer.flip()); + + if (cr.isError()) { + handleCoderError(cr); + } + if (cr.isUnderflow() && readLen < bufferRemaining) { + // handle incomplete multibyte character + int incompleteMultiBytes = utf8MultibyteCharacterSize(buffer.getByte(position)); + ByteBuffer multiByteBuffer = ByteBuffer.allocate(incompleteMultiBytes); + buffer.getBytes(position, buffer.size() - position, multiByteBuffer); + + // read until multiByteBuffer is filled + while (true) { + nextBuffer(); + + int more = multiByteBuffer.remaining(); + if (buffer.size() >= more) { + buffer.getBytes(0, more, multiByteBuffer); + position = more; + break; + } + else { + buffer.getBytes(0, buffer.size(), multiByteBuffer); + position = buffer.size(); + } + } + multiByteBuffer.position(0); + decodeBuffer.clear(); + cr = decoder.decode(multiByteBuffer, decodeBuffer, false); + if (cr.isError()) { + handleCoderError(cr); + } + if (cr.isOverflow() || (cr.isUnderflow() && multiByteBuffer.position() < multiByteBuffer.limit())) { + // isOverflow or isOverflow must not happen. if happened, throw exception + try { + cr.throwException(); + throw new MessageFormatException("Unexpected UTF-8 multibyte sequence"); + } + catch (Exception ex) { + throw new MessageFormatException("Unexpected UTF-8 multibyte sequence", ex); + } + } + rawRemaining -= multiByteBuffer.limit(); + decodeStringBuffer.append(decodeBuffer.flip()); + } + } + } + return decodeStringBuffer.toString(); + } + catch (CharacterCodingException e) { + throw new MessageStringCodingException(e); + } + } + + private void handleCoderError(CoderResult cr) throws CharacterCodingException { + if ((cr.isMalformed() && actionOnMalformedString == CodingErrorAction.REPORT) || + (cr.isUnmappable() && actionOnUnmappableString == CodingErrorAction.REPORT)) { + cr.throwException(); + } + } + + private String decodeStringFastPath(int length) { + if (actionOnMalformedString == CodingErrorAction.REPLACE && + actionOnUnmappableString == CodingErrorAction.REPLACE && + buffer.hasArray()) { + String s = new String(buffer.array(), buffer.arrayOffset() + position, length, MessagePack.UTF8); + position += length; + return s; + } + else { + ByteBuffer bb = buffer.sliceAsByteBuffer(position, length); + CharBuffer cb; + try { + cb = decoder.decode(bb); + } + catch (CharacterCodingException e) { + throw new MessageStringCodingException(e); + } + position += length; + return cb.toString(); + } + } + + public Instant unpackTimestamp() throws IOException { + ExtensionTypeHeader ext = unpackExtensionTypeHeader(); + return unpackTimestamp(ext); + } + + /** + * Unpack timestamp that can be used after reading the extension type header with unpackExtensionTypeHeader. + */ + public Instant unpackTimestamp(ExtensionTypeHeader ext) throws IOException { + if (ext.getType() != EXT_TIMESTAMP) { + throw unexpectedExtension("Timestamp", EXT_TIMESTAMP, ext.getType()); + } + switch (ext.getLength()) { + case 4: { + // Need to convert Java's int (int32) to uint32 + long u32 = readInt32() & 0xffffffffL; + return Instant.ofEpochSecond(u32); + } + case 8: { + long data64 = readInt64(); + int nsec = (int) (data64 >>> 34); + long sec = data64 & 0x00000003ffffffffL; + return Instant.ofEpochSecond(sec, nsec); + } + case 12: { + // Need to convert Java's int (int32) to uint32 + long nsecU32 = readInt32() & 0xffffffffL; + long sec = readInt64(); + return Instant.ofEpochSecond(sec, nsecU32); + } + default: + throw new MessageFormatException(String.format("Timestamp extension type (%d) expects 4, 8, or 12 bytes of payload but got %d bytes", + EXT_TIMESTAMP, ext.getLength())); + } + } + + /** + * Reads header of an array. + * + *

      + * This method returns number of elements to be read. After this method call, you call unpacker methods for + * each element. You don't have to call anything at the end of iteration. + * + * @return the size of the array to be read + * @throws MessageTypeException when value is not MessagePack Array type + * @throws MessageSizeException when size of the array is larger than 2^31 - 1 + * @throws IOException when underlying input throws IOException + */ + public int unpackArrayHeader() throws IOException { + byte b = readInt8(); + if (Code.isFixedArray(b)) { // fixarray + return b & 0x0f; + } + return switch (b) { + // array 16 + case Code.ARRAY16 -> readNextLength16(); + // array 32 + case Code.ARRAY32 -> readNextLength32(); + default -> throw unexpected("Array", b); + }; + } + + /** + * Reads header of a map. + * + *

      + * This method returns number of pairs to be read. After this method call, for each pair, you call unpacker + * methods for key first, and then value. You will call unpacker methods twice as many time as the returned + * count. You don't have to call anything at the end of iteration. + * + * @return the size of the map to be read + * @throws MessageTypeException when value is not MessagePack Map type + * @throws MessageSizeException when size of the map is larger than 2^31 - 1 + * @throws IOException when underlying input throws IOException + */ + public int unpackMapHeader() throws IOException { + byte b = readInt8(); + if (Code.isFixedMap(b)) { // fixmap + return b & 0x0f; + } + return switch (b) { + case Code.MAP16 -> readNextLength16();// map 16 + case Code.MAP32 -> readNextLength32();// map 32 + default -> throw unexpected("Map", b); + }; + } + + public ExtensionTypeHeader unpackExtensionTypeHeader() throws IOException { + byte b = readInt8(); + switch (b) { + case Code.FIXEXT1: { + byte type = readInt8(); + return new ExtensionTypeHeader(type, 1); + } + case Code.FIXEXT2: { + byte type = readInt8(); + return new ExtensionTypeHeader(type, 2); + } + case Code.FIXEXT4: { + byte type = readInt8(); + return new ExtensionTypeHeader(type, 4); + } + case Code.FIXEXT8: { + byte type = readInt8(); + return new ExtensionTypeHeader(type, 8); + } + case Code.FIXEXT16: { + byte type = readInt8(); + return new ExtensionTypeHeader(type, 16); + } + case Code.EXT8: { + MessageBuffer numberBuffer = prepareNumberBuffer(2); + int u8 = numberBuffer.getByte(nextReadPosition); + int length = u8 & 0xff; + byte type = numberBuffer.getByte(nextReadPosition + 1); + return new ExtensionTypeHeader(type, length); + } + case Code.EXT16: { + MessageBuffer numberBuffer = prepareNumberBuffer(3); + int u16 = numberBuffer.getShort(nextReadPosition); + int length = u16 & 0xffff; + byte type = numberBuffer.getByte(nextReadPosition + 2); + return new ExtensionTypeHeader(type, length); + } + case Code.EXT32: { + MessageBuffer numberBuffer = prepareNumberBuffer(5); + int length = numberBuffer.getInt(nextReadPosition); + if (length < 0) { + throw overflowU32Size(length); + } + byte type = numberBuffer.getByte(nextReadPosition + 4); + return new ExtensionTypeHeader(type, length); + } + } + + throw unexpected("Ext", b); + } + + private int tryReadStringHeader(byte b) throws IOException { + return switch (b) { + case Code.STR8 -> readNextLength8(); // str 8 + case Code.STR16 -> readNextLength16(); // str 16 + case Code.STR32 -> readNextLength32(); // str 32 + default -> -1; + }; + } + + private int tryReadBinaryHeader(byte b) throws IOException { + return switch (b) { + case Code.BIN8 -> readNextLength8(); // bin 8 + case Code.BIN16 -> readNextLength16(); // bin 16 + case Code.BIN32 -> readNextLength32(); // bin 32 + default -> -1; + }; + } + + public int unpackRawStringHeader() throws IOException { + byte b = readInt8(); + if (Code.isFixedRaw(b)) { // FixRaw + return b & 0x1f; + } + int len = tryReadStringHeader(b); + if (len >= 0) { + return len; + } + + if (allowReadingBinaryAsString) { + len = tryReadBinaryHeader(b); + if (len >= 0) { + return len; + } + } + throw unexpected("String", b); + } + + /** + * Reads header of a binary. + * + *

      + * This method returns number of bytes to be read. After this method call, you call a readPayload method such as + * {@link #readPayload(int)} with the returned count. + * + *

      + * You can divide readPayload method into multiple calls. In this case, you must repeat readPayload methods + * until total amount of bytes becomes equal to the returned count. + * + * @return the size of the map to be read + * @throws MessageTypeException when value is not MessagePack Map type + * @throws MessageSizeException when size of the map is larger than 2^31 - 1 + * @throws IOException when underlying input throws IOException + */ + public int unpackBinaryHeader() throws IOException { + byte b = readInt8(); + if (Code.isFixedRaw(b)) { // FixRaw + return b & 0x1f; + } + int len = tryReadBinaryHeader(b); + if (len >= 0) { + return len; + } + + if (allowReadingStringAsBinary) { + len = tryReadStringHeader(b); + if (len >= 0) { + return len; + } + } + throw unexpected("Binary", b); + } + + /** + * Reads payload bytes of binary, extension, or raw string types. + *

      + * This consumes specified amount of bytes into the specified byte array. + * + * @throws IOException when underlying input throws IOException + */ + public byte[] unpackBinary() throws IOException { + int size = unpackBinaryHeader(); + return readPayload(size); + } + + /** + * Skip reading the specified number of bytes. Use this method only if you know skipping data is safe. + * For simply skipping the next value, use {@link #skipValue()}. + */ + private void skipPayload(int numBytes) throws IOException { + if (numBytes < 0) { + throw new IllegalArgumentException("payload size must be >= 0: " + numBytes); + } + while (true) { + int bufferRemaining = buffer.size() - position; + if (bufferRemaining >= numBytes) { + position += numBytes; + return; + } + else { + position += bufferRemaining; + numBytes -= bufferRemaining; + } + nextBuffer(); + } + } + + /** + * Reads payload bytes of binary, extension, or raw string types. + * + *

      + * This consumes bytes, copies them to the specified buffer, and moves forward position of the byte buffer + * until ByteBuffer.remaining() returns 0. + * + * @param dst the byte buffer into which the data is read + * @throws IOException when underlying input throws IOException + */ + public void readPayload(ByteBuffer dst) throws IOException { + while (true) { + int dstRemaining = dst.remaining(); + int bufferRemaining = buffer.size() - position; + if (bufferRemaining >= dstRemaining) { + buffer.getBytes(position, dstRemaining, dst); + position += dstRemaining; + return; + } + buffer.getBytes(position, bufferRemaining, dst); + position += bufferRemaining; + + nextBuffer(); + } + } + + /** + * Reads payload bytes of binary, extension, or raw string types. + * + *

      + * This consumes bytes, copies them to the specified buffer + * This is usually faster than readPayload(ByteBuffer) by using unsafe.copyMemory + * + * @param dst the Message buffer into which the data is read + * @param off the offset in the Message buffer + * @param len the number of bytes to read + * @throws IOException when underlying input throws IOException + */ + public void readPayload(MessageBuffer dst, int off, int len) throws IOException { + while (true) { + int bufferRemaining = buffer.size() - position; + if (bufferRemaining >= len) { + dst.putMessageBuffer(off, buffer, position, len); + position += len; + return; + } + dst.putMessageBuffer(off, buffer, position, bufferRemaining); + off += bufferRemaining; + len -= bufferRemaining; + position += bufferRemaining; + + nextBuffer(); + } + } + + /** + * Reads payload bytes of binary, extension, or raw string types. + *

      + * This consumes specified amount of bytes into the specified byte array. + * + *

      + * This method is equivalent to readPayload(dst, 0, dst.length). + * + * @param dst the byte array into which the data is read + * @throws IOException when underlying input throws IOException + */ + public void readPayload(byte[] dst) throws IOException { + readPayload(dst, 0, dst.length); + } + + /** + * Reads payload bytes of binary, extension, or raw string types. + *

      + * This method allocates a new byte array and consumes specified amount of bytes into the byte array. + * + *

      + * This method is equivalent to readPayload(new byte[length]). + * + * @param length number of bytes to be read + * @return the new byte array + * @throws IOException when underlying input throws IOException + */ + public byte[] readPayload(int length) throws IOException { + byte[] newArray = new byte[length]; + readPayload(newArray); + return newArray; + } + + /** + * Reads payload bytes of binary, extension, or raw string types. + *

      + * This consumes specified amount of bytes into the specified byte array. + * + * @param dst the byte array into which the data is read + * @param off the offset in the dst array + * @param len the number of bytes to read + * @throws IOException when underlying input throws IOException + */ + public void readPayload(byte[] dst, int off, int len) throws IOException { + while (true) { + int bufferRemaining = buffer.size() - position; + if (bufferRemaining >= len) { + buffer.getBytes(position, dst, off, len); + position += len; + return; + } + buffer.getBytes(position, dst, off, bufferRemaining); + off += bufferRemaining; + len -= bufferRemaining; + position += bufferRemaining; + + nextBuffer(); + } + } + + /** + * Reads payload bytes of binary, extension, or raw string types as a reference to internal buffer. + *

      + * Note: This methods may return raw memory region, access to which has no strict boundary checks. + * To use this method safely, you need to understand the internal buffer handling of msgpack-java. + * + *

      + * This consumes specified amount of bytes and returns its reference or copy. This method tries to + * return reference as much as possible because it is faster. However, it may copy data to a newly + * allocated buffer if reference is not applicable. + * + * @param length number of bytes to be read + * @throws IOException when underlying input throws IOException + */ + public MessageBuffer readPayloadAsReference(int length) throws IOException { + int bufferRemaining = buffer.size() - position; + if (bufferRemaining >= length) { + MessageBuffer slice = buffer.slice(position, length); + position += length; + return slice; + } + MessageBuffer dst = MessageBuffer.allocate(length); + readPayload(dst, 0, length); + return dst; + } + + private int readNextLength8() throws IOException { + byte u8 = readInt8(); + return u8 & 0xff; + } + + private int readNextLength16() throws IOException { + short u16 = readInt16(); + return u16 & 0xffff; + } + + private int readNextLength32() throws IOException { + int u32 = readInt32(); + if (u32 < 0) { + throw overflowU32Size(u32); + } + return u32; + } + + /** + * Closes underlying input. + */ + @Override + public void close() throws IOException { + totalReadBytes += position; + buffer = EMPTY_BUFFER; + position = 0; + in.close(); + } + + private static MessageIntegerOverflowException overflowU8(byte u8) { + BigInteger bi = BigInteger.valueOf(u8 & 0xff); + return new MessageIntegerOverflowException(bi); + } + + private static MessageIntegerOverflowException overflowU16(short u16) { + BigInteger bi = BigInteger.valueOf(u16 & 0xffff); + return new MessageIntegerOverflowException(bi); + } + + private static MessageIntegerOverflowException overflowU32(int u32) { + BigInteger bi = BigInteger.valueOf((long) (u32 & 0x7fffffff) + 0x80000000L); + return new MessageIntegerOverflowException(bi); + } + + private static MessageIntegerOverflowException overflowU64(long u64) { + BigInteger bi = BigInteger.valueOf(u64 + Long.MAX_VALUE + 1L).setBit(63); + return new MessageIntegerOverflowException(bi); + } + + private static MessageIntegerOverflowException overflowI16(short i16) { + BigInteger bi = BigInteger.valueOf(i16); + return new MessageIntegerOverflowException(bi); + } + + private static MessageIntegerOverflowException overflowI32(int i32) { + BigInteger bi = BigInteger.valueOf(i32); + return new MessageIntegerOverflowException(bi); + } + + private static MessageIntegerOverflowException overflowI64(long i64) { + BigInteger bi = BigInteger.valueOf(i64); + return new MessageIntegerOverflowException(bi); + } + + private static MessageSizeException overflowU32Size(int u32) { + long lv = (long) (u32 & 0x7fffffff) + 0x80000000L; + return new MessageSizeException(lv); + } +} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/ArrayBufferInput.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/ArrayBufferInput.java new file mode 100644 index 0000000..c7314a6 --- /dev/null +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/ArrayBufferInput.java @@ -0,0 +1,79 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.serialize.format.buffer; + +import java.util.Objects; + +/** + * MessageBufferInput adapter for byte arrays + */ +public class ArrayBufferInput implements MessageBufferInput { + + private MessageBuffer buffer; + + private boolean isEmpty; + + public ArrayBufferInput(MessageBuffer buf) { + this.buffer = buf; + this.isEmpty = buf == null; + } + + public ArrayBufferInput(byte[] arr) { + this(arr, 0, arr.length); + } + + public ArrayBufferInput(byte[] arr, int offset, int length) { + this(MessageBuffer.wrap(Objects.requireNonNull(arr, "input array is null"), offset, length)); + } + + /** + * Reset buffer. This method returns the old buffer. + * + * @param buf new buffer. This can be null to make this input empty. + * @return the old buffer. + */ + public MessageBuffer reset(MessageBuffer buf) { + MessageBuffer old = this.buffer; + this.buffer = buf; + this.isEmpty = buf == null; + return old; + } + + public void reset(byte[] arr) { + reset(MessageBuffer.wrap(Objects.requireNonNull(arr, "input array is null"))); + } + + public void reset(byte[] arr, int offset, int len) { + reset(MessageBuffer.wrap(Objects.requireNonNull(arr, "input array is null"), offset, len)); + } + + @Override + public MessageBuffer next() { + if (isEmpty) { + return null; + } + isEmpty = true; + return buffer; + } + + @Override + public void close() { + buffer = null; + isEmpty = true; + } +} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/ArrayBufferOutput.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/ArrayBufferOutput.java new file mode 100644 index 0000000..c5830de --- /dev/null +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/ArrayBufferOutput.java @@ -0,0 +1,161 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.serialize.format.buffer; + +import java.util.ArrayList; +import java.util.List; + +/** + * MessageBufferOutput adapter that writes data into a list of byte arrays. + *

      + * This class allocates a new buffer instead of resizing the buffer when data doesn't fit in the initial capacity. + * This is faster than ByteArrayOutputStream especially when size of written bytes is large because resizing a buffer + * usually needs to copy contents of the buffer. + */ +public class ArrayBufferOutput implements MessageBufferOutput { + + private final ArrayList list; + + private final int bufferSize; + + private MessageBuffer lastBuffer; + + public ArrayBufferOutput() { + this(8192); + } + + public ArrayBufferOutput(int bufferSize) { + this.bufferSize = bufferSize; + this.list = new ArrayList<>(); + } + + /** + * Gets the size of the written data. + * + * @return number of bytes + */ + public int getSize() { + int size = 0; + for (MessageBuffer buffer : list) { + size += buffer.size(); + } + return size; + } + + /** + * Gets a copy of the written data as a byte array. + *

      + * If your application needs better performance and smaller memory consumption, you may prefer + * {@link #toMessageBuffer()} or {@link #toBufferList()} to avoid copying. + * + * @return the byte array + */ + public byte[] toByteArray() { + byte[] data = new byte[getSize()]; + int off = 0; + for (MessageBuffer buffer : list) { + buffer.getBytes(0, data, off, buffer.size()); + off += buffer.size(); + } + return data; + } + + /** + * Gets the written data as a MessageBuffer. + *

      + * Unlike {@link #toByteArray()}, this method omits copy of the contents if size of the written data is smaller + * than a single buffer capacity. + * + * @return the MessageBuffer instance + */ + public MessageBuffer toMessageBuffer() { + if (list.size() == 1) { + return list.get(0); + } + else if (list.isEmpty()) { + return MessageBuffer.allocate(0); + } + else { + return MessageBuffer.wrap(toByteArray()); + } + } + + /** + * Returns the written data as a list of MessageBuffer. + *

      + * Unlike {@link #toByteArray()} or {@link #toMessageBuffer()}, this is the fastest method that doesn't + * copy contents in any cases. + * + * @return the list of MessageBuffer instances + */ + public List toBufferList() { + return new ArrayList<>(list); + } + + /** + * Clears the written data. + */ + public void clear() { + list.clear(); + } + + @Override + public MessageBuffer next(int minimumSize) { + if (lastBuffer != null && lastBuffer.size() > minimumSize) { + return lastBuffer; + } + else { + int size = Math.max(bufferSize, minimumSize); + MessageBuffer buffer = MessageBuffer.allocate(size); + lastBuffer = buffer; + return buffer; + } + } + + @Override + public void writeBuffer(int length) { + list.add(lastBuffer.slice(0, length)); + if (lastBuffer.size() - length > bufferSize / 4) { + lastBuffer = lastBuffer.slice(length, lastBuffer.size() - length); + } + else { + lastBuffer = null; + } + } + + @Override + public void write(byte[] buffer, int offset, int length) { + MessageBuffer copy = MessageBuffer.allocate(length); + copy.putBytes(0, buffer, offset, length); + list.add(copy); + } + + @Override + public void add(byte[] buffer, int offset, int length) { + MessageBuffer wrapped = MessageBuffer.wrap(buffer, offset, length); + list.add(wrapped); + } + + @Override + public void close() { + } + + @Override + public void flush() { + } +} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/ByteBufferInput.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/ByteBufferInput.java new file mode 100644 index 0000000..06d06c2 --- /dev/null +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/ByteBufferInput.java @@ -0,0 +1,63 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.serialize.format.buffer; + +import java.nio.ByteBuffer; +import java.util.Objects; + +/** + * {@link MessageBufferInput} adapter for {@link ByteBuffer} + */ +public class ByteBufferInput + implements MessageBufferInput { + private ByteBuffer input; + private boolean isRead = false; + + public ByteBufferInput(ByteBuffer input) { + this.input = Objects.requireNonNull(input, "input ByteBuffer is null").slice(); + } + + /** + * Reset buffer. + * + * @param input new buffer + * @return the old buffer + */ + public ByteBuffer reset(ByteBuffer input) { + ByteBuffer old = this.input; + this.input = Objects.requireNonNull(input, "input ByteBuffer is null").slice(); + isRead = false; + return old; + } + + @Override + public MessageBuffer next() { + if (isRead) { + return null; + } + + MessageBuffer b = MessageBuffer.wrap(input); + isRead = true; + return b; + } + + @Override + public void close() { + // Nothing to do + } +} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/ChannelBufferInput.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/ChannelBufferInput.java new file mode 100644 index 0000000..d83f929 --- /dev/null +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/ChannelBufferInput.java @@ -0,0 +1,73 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.serialize.format.buffer; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.channels.ReadableByteChannel; +import java.util.Objects; + +import infra.lang.Assert; + +/** + * {@link MessageBufferInput} adapter for {@link ReadableByteChannel} + */ +public class ChannelBufferInput implements MessageBufferInput { + + private ReadableByteChannel channel; + + private final MessageBuffer buffer; + + public ChannelBufferInput(ReadableByteChannel channel) { + this(channel, 8192); + } + + public ChannelBufferInput(ReadableByteChannel channel, int bufferSize) { + this.channel = Objects.requireNonNull(channel, "input channel is null"); + Assert.isTrue(bufferSize > 0, () -> "buffer size must be > 0: " + bufferSize); + this.buffer = MessageBuffer.allocate(bufferSize); + } + + /** + * Reset channel. This method doesn't close the old resource. + * + * @param channel new channel + * @return the old resource + */ + public ReadableByteChannel reset(ReadableByteChannel channel) throws IOException { + ReadableByteChannel old = this.channel; + this.channel = channel; + return old; + } + + @Override + public MessageBuffer next() throws IOException { + ByteBuffer b = buffer.sliceAsByteBuffer(); + int ret = channel.read(b); + if (ret == -1) { + return null; + } + b.flip(); + return buffer.slice(0, b.limit()); + } + + @Override + public void close() throws IOException { + channel.close(); + } +} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/ChannelBufferOutput.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/ChannelBufferOutput.java new file mode 100644 index 0000000..77e0d29 --- /dev/null +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/ChannelBufferOutput.java @@ -0,0 +1,93 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.serialize.format.buffer; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.channels.WritableByteChannel; +import java.util.Objects; + +/** + * {@link MessageBufferOutput} adapter for {@link WritableByteChannel} + */ +public class ChannelBufferOutput implements MessageBufferOutput { + + private WritableByteChannel channel; + + private MessageBuffer buffer; + + public ChannelBufferOutput(WritableByteChannel channel) { + this(channel, 8192); + } + + public ChannelBufferOutput(WritableByteChannel channel, int bufferSize) { + this.channel = Objects.requireNonNull(channel, "output channel is null"); + this.buffer = MessageBuffer.allocate(bufferSize); + } + + /** + * Reset channel. This method doesn't close the old channel. + * + * @param channel new channel + * @return the old channel + */ + public WritableByteChannel reset(WritableByteChannel channel) { + WritableByteChannel old = this.channel; + this.channel = channel; + return old; + } + + @Override + public MessageBuffer next(int minimumSize) throws IOException { + if (buffer.size() < minimumSize) { + buffer = MessageBuffer.allocate(minimumSize); + } + return buffer; + } + + @Override + public void writeBuffer(int length) throws IOException { + ByteBuffer bb = buffer.sliceAsByteBuffer(0, length); + while (bb.hasRemaining()) { + channel.write(bb); + } + } + + @Override + public void write(byte[] buffer, int offset, int length) throws IOException { + ByteBuffer bb = ByteBuffer.wrap(buffer, offset, length); + while (bb.hasRemaining()) { + channel.write(bb); + } + } + + @Override + public void add(byte[] buffer, int offset, int length) throws IOException { + write(buffer, offset, length); + } + + @Override + public void close() throws IOException { + channel.close(); + } + + @Override + public void flush() { + } + +} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/DirectBufferAccess.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/DirectBufferAccess.java new file mode 100644 index 0000000..b9953a2 --- /dev/null +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/DirectBufferAccess.java @@ -0,0 +1,175 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.serialize.format.buffer; + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.nio.Buffer; +import java.nio.ByteBuffer; + +import sun.misc.Unsafe; +import sun.nio.ch.DirectBuffer; + +/** + * Wraps the difference of access methods to DirectBuffers between Android and others. + */ +class DirectBufferAccess { + + private DirectBufferAccess() { + } + + enum DirectBufferConstructorType { + ARGS_LONG_LONG, + ARGS_LONG_INT_REF, + ARGS_LONG_INT, + ARGS_INT_INT, + ARGS_MB_INT_INT + } + + // For Java >=9, invokes a jdk.internal.ref.Cleaner + static Method mInvokeCleaner; + + // TODO We should use MethodHandle for efficiency, but it is not available in JDK6 + static Constructor byteBufferConstructor; + static Class directByteBufferClass; + static DirectBufferConstructorType directBufferConstructorType; + static Method memoryBlockWrapFromJni; + + static { + try { + final ByteBuffer direct = ByteBuffer.allocateDirect(1); + // Find the hidden constructor for DirectByteBuffer + directByteBufferClass = direct.getClass(); + Constructor directByteBufferConstructor = null; + DirectBufferConstructorType constructorType = null; + Method mbWrap = null; + try { + // JDK21 DirectByteBuffer(long, long) + directByteBufferConstructor = directByteBufferClass.getDeclaredConstructor(long.class, long.class); + constructorType = DirectBufferConstructorType.ARGS_LONG_LONG; + } + catch (NoSuchMethodException e00) { + try { + // TODO We should use MethodHandle for Java7, which can avoid the cost of boxing with JIT optimization + directByteBufferConstructor = directByteBufferClass.getDeclaredConstructor(long.class, int.class, Object.class); + constructorType = DirectBufferConstructorType.ARGS_LONG_INT_REF; + } + catch (NoSuchMethodException e0) { + try { + // https://android.googlesource.com/platform/libcore/+/master/luni/src/main/java/java/nio/DirectByteBuffer.java + // DirectByteBuffer(long address, int capacity) + directByteBufferConstructor = directByteBufferClass.getDeclaredConstructor(long.class, int.class); + constructorType = DirectBufferConstructorType.ARGS_LONG_INT; + } + catch (NoSuchMethodException e1) { + try { + directByteBufferConstructor = directByteBufferClass.getDeclaredConstructor(int.class, int.class); + constructorType = DirectBufferConstructorType.ARGS_INT_INT; + } + catch (NoSuchMethodException e2) { + Class aClass = Class.forName("java.nio.MemoryBlock"); + mbWrap = aClass.getDeclaredMethod("wrapFromJni", int.class, long.class); + mbWrap.setAccessible(true); + directByteBufferConstructor = directByteBufferClass.getDeclaredConstructor(aClass, int.class, int.class); + constructorType = DirectBufferConstructorType.ARGS_MB_INT_INT; + } + } + } + } + + byteBufferConstructor = directByteBufferConstructor; + directBufferConstructorType = constructorType; + memoryBlockWrapFromJni = mbWrap; + + if (byteBufferConstructor == null) { + throw new RuntimeException("Constructor of DirectByteBuffer is not found"); + } + + try { + byteBufferConstructor.setAccessible(true); + } + catch (RuntimeException e) { + // This is a Java9+ exception, so we need to detect it without importing it for Java8 support + if ("java.lang.reflect.InaccessibleObjectException".equals(e.getClass().getName())) { + byteBufferConstructor = null; + } + else { + throw e; + } + } + + setupCleanerJava9(direct); + } + catch (Exception e) { + throw new RuntimeException(e); + } + } + + private static void setupCleanerJava9(final ByteBuffer direct) { + Object obj = getInvokeCleanerMethod(direct); + if (obj instanceof Throwable) { + throw new RuntimeException((Throwable) obj); + } + mInvokeCleaner = (Method) obj; + } + + /** + * Checks if we have a usable {@link Unsafe#invokeCleaner}. + * + * @param direct a direct buffer + * @return the method or an error + */ + private static Object getInvokeCleanerMethod(ByteBuffer direct) { + try { + // See https://bugs.openjdk.java.net/browse/JDK-8171377 + Method m = MessageBuffer.unsafe.getClass().getDeclaredMethod( + "invokeCleaner", ByteBuffer.class); + m.invoke(MessageBuffer.unsafe, direct); + return m; + } + catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) { + return e; + } + } + + static long getAddress(Buffer buffer) { + return ((DirectBuffer) buffer).address(); + } + + static ByteBuffer newByteBuffer(long address, int index, int length, ByteBuffer reference) { + if (byteBufferConstructor == null) { + throw new IllegalStateException("Can't create a new DirectByteBuffer. In JDK17+, two JVM options needs to be set: " + + "--add-opens=java.base/java.nio=ALL-UNNAMED and --add-opens=java.base/sun.nio.ch=ALL-UNNAMED"); + } + try { + return switch (directBufferConstructorType) { + case ARGS_LONG_LONG -> (ByteBuffer) byteBufferConstructor.newInstance(address + index, (long) length); + case ARGS_LONG_INT_REF -> (ByteBuffer) byteBufferConstructor.newInstance(address + index, length, reference); + case ARGS_LONG_INT -> (ByteBuffer) byteBufferConstructor.newInstance(address + index, length); + case ARGS_INT_INT -> (ByteBuffer) byteBufferConstructor.newInstance((int) address + index, length); + case ARGS_MB_INT_INT -> (ByteBuffer) byteBufferConstructor.newInstance( + memoryBlockWrapFromJni.invoke(null, address + index, length), length, 0); + }; + } + catch (Throwable e) { + // Convert checked exception to unchecked exception + throw new RuntimeException(e); + } + } +} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/InputStreamBufferInput.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/InputStreamBufferInput.java new file mode 100644 index 0000000..eb4d84b --- /dev/null +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/InputStreamBufferInput.java @@ -0,0 +1,83 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.serialize.format.buffer; + +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.channels.FileChannel; +import java.util.Objects; + +import infra.lang.Assert; + +/** + * {@link MessageBufferInput} adapter for {@link InputStream} + */ +public class InputStreamBufferInput implements MessageBufferInput { + + private InputStream in; + + private final byte[] buffer; + + public static MessageBufferInput newBufferInput(InputStream in) { + Assert.notNull(in, "InputStream is null"); + if (in instanceof FileInputStream) { + FileChannel channel = ((FileInputStream) in).getChannel(); + if (channel != null) { + return new ChannelBufferInput(channel); + } + } + return new InputStreamBufferInput(in); + } + + public InputStreamBufferInput(InputStream in) { + this(in, 8192); + } + + public InputStreamBufferInput(InputStream in, int bufferSize) { + this.in = Objects.requireNonNull(in, "input is null"); + this.buffer = new byte[bufferSize]; + } + + /** + * Reset Stream. This method doesn't close the old resource. + * + * @param in new stream + * @return the old resource + */ + public InputStream reset(InputStream in) throws IOException { + InputStream old = this.in; + this.in = in; + return old; + } + + @Override + public MessageBuffer next() throws IOException { + int readLen = in.read(buffer); + if (readLen == -1) { + return null; + } + return MessageBuffer.wrap(buffer, 0, readLen); + } + + @Override + public void close() + throws IOException { + in.close(); + } +} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/MessageBuffer.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/MessageBuffer.java new file mode 100644 index 0000000..c57ad83 --- /dev/null +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/MessageBuffer.java @@ -0,0 +1,574 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.serialize.format.buffer; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.nio.BufferOverflowException; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.util.Objects; + +import infra.lang.Assert; +import sun.misc.Unsafe; + +/** + * MessageBuffer class is an abstraction of memory with fast methods to serialize and deserialize primitive values + * to/from the memory. All MessageBuffer implementations ensure short/int/float/long/double values are written in + * big-endian order. + *

      + * Applications can allocate a new buffer using {@link #allocate(int)} method, or wrap an byte array or ByteBuffer + * using {@link #wrap(byte[], int, int)} methods. {@link #wrap(ByteBuffer)} method supports both direct buffers and + * array-backed buffers. + *

      + * MessageBuffer class itself is optimized for little-endian CPU archtectures so that JVM (HotSpot) can take advantage + * of the fastest JIT format which skips TypeProfile checking. To ensure this performance, applications must not import + * unnecessary classes such as MessagePackBE. On big-endian CPU archtectures, it automatically uses a subclass that + * includes TypeProfile overhead but still faster than stndard ByteBuffer class. On JVMs older than Java 7 and JVMs + * without Unsafe API (such as Android), implementation falls back to an universal implementation that uses ByteBuffer + * internally. + */ +public class MessageBuffer { + + static final boolean isUniversalBuffer; + + static final Unsafe unsafe; + + static final int javaVersion = getJavaVersion(); + + /** + * Reference to MessageBuffer Constructors + */ + private static final Constructor mbArrConstructor; + private static final Constructor mbBBConstructor; + + /** + * The offset from the object memory header to its byte array data + */ + static final int ARRAY_BYTE_BASE_OFFSET; + + private static final String UNIVERSAL_MESSAGE_BUFFER = "infra.cloud.serialize.format.buffer.MessageBufferU"; + private static final String BIGENDIAN_MESSAGE_BUFFER = "infra.cloud.serialize.format.buffer.MessageBufferBE"; + private static final String DEFAULT_MESSAGE_BUFFER = "infra.cloud.serialize.format.buffer.MessageBuffer"; + + static { + boolean useUniversalBuffer = false; + Unsafe unsafeInstance = null; + int arrayByteBaseOffset = 16; + + try { + boolean hasUnsafe = false; + try { + hasUnsafe = Class.forName("sun.misc.Unsafe") != null; + } + catch (Exception ignored) { + } + + // Detect android VM + boolean isAndroid = System.getProperty("java.runtime.name", "").toLowerCase().contains("android"); + + // Is Google App Engine? + boolean isGAE = System.getProperty("com.google.appengine.runtime.version") != null; + + // For Java6, android and JVM that has no Unsafe class, use Universal MessageBuffer (based on ByteBuffer). + useUniversalBuffer = + Boolean.parseBoolean(System.getProperty("msgpack.universal-buffer", "false")) + || isAndroid + || isGAE + || javaVersion < 7 + || !hasUnsafe; + + if (!useUniversalBuffer) { + // Fetch theUnsafe object for Oracle and OpenJDK + Field field = Unsafe.class.getDeclaredField("theUnsafe"); + field.setAccessible(true); + unsafeInstance = (Unsafe) field.get(null); + if (unsafeInstance == null) { + throw new RuntimeException("Unsafe is unavailable"); + } + arrayByteBaseOffset = unsafeInstance.arrayBaseOffset(byte[].class); + int arrayByteIndexScale = unsafeInstance.arrayIndexScale(byte[].class); + + // Make sure the VM thinks bytes are only one byte wide + if (arrayByteIndexScale != 1) { + throw new IllegalStateException("Byte array index scale must be 1, but is " + arrayByteIndexScale); + } + } + } + catch (Exception e) { + e.printStackTrace(System.err); + // Use MessageBufferU + useUniversalBuffer = true; + } + finally { + // Initialize the static fields + unsafe = unsafeInstance; + ARRAY_BYTE_BASE_OFFSET = arrayByteBaseOffset; + + // Switch MessageBuffer implementation according to the environment + isUniversalBuffer = useUniversalBuffer; + String bufferClsName; + if (isUniversalBuffer) { + bufferClsName = UNIVERSAL_MESSAGE_BUFFER; + } + else { + // Check the endian of this CPU + boolean isLittleEndian = ByteOrder.nativeOrder() == ByteOrder.LITTLE_ENDIAN; + bufferClsName = isLittleEndian ? DEFAULT_MESSAGE_BUFFER : BIGENDIAN_MESSAGE_BUFFER; + } + + if (DEFAULT_MESSAGE_BUFFER.equals(bufferClsName)) { + // No need to use reflection here, we're not using a MessageBuffer subclass. + mbArrConstructor = null; + mbBBConstructor = null; + } + else { + try { + // We need to use reflection here to find MessageBuffer implementation classes because + // importing these classes creates TypeProfile and adds some overhead to method calls. + + // MessageBufferX (default, BE or U) class + Class bufferCls = Class.forName(bufferClsName); + + // MessageBufferX(byte[]) constructor + Constructor mbArrCstr = bufferCls.getDeclaredConstructor(byte[].class, int.class, int.class); + mbArrCstr.setAccessible(true); + mbArrConstructor = mbArrCstr; + + // MessageBufferX(ByteBuffer) constructor + Constructor mbBBCstr = bufferCls.getDeclaredConstructor(ByteBuffer.class); + mbBBCstr.setAccessible(true); + mbBBConstructor = mbBBCstr; + } + catch (Exception e) { + e.printStackTrace(System.err); + throw new RuntimeException(e); // No more fallback exists if MessageBuffer constructors are inaccessible + } + } + } + } + + private static int getJavaVersion() { + String javaVersion = System.getProperty("java.specification.version", ""); + int dotPos = javaVersion.indexOf('.'); + if (dotPos != -1) { + try { + int major = Integer.parseInt(javaVersion.substring(0, dotPos)); + int minor = Integer.parseInt(javaVersion.substring(dotPos + 1)); + return major > 1 ? major : minor; + } + catch (NumberFormatException e) { + e.printStackTrace(System.err); + } + } + else { + try { + return Integer.parseInt(javaVersion); + } + catch (NumberFormatException e) { + e.printStackTrace(System.err); + } + } + return 6; + } + + /** + * Base object for resolving the relative address of the raw byte array. + * If base == null, the address value is a raw memory address + */ + protected final Object base; + + /** + * Head address of the underlying memory. If base is null, the address is a direct memory address, and if not, + * it is the relative address within an array object (base) + */ + protected final long address; + + /** + * Size of the underlying memory + */ + protected final int size; + + /** + * Reference is used to hold a reference to an object that holds the underlying memory so that it cannot be + * released by the garbage collector. + */ + protected final ByteBuffer reference; + + /** + * Allocates a new MessageBuffer backed by a byte array. + * + * @throws IllegalArgumentException If the capacity is a negative integer + */ + public static MessageBuffer allocate(int size) { + if (size < 0) { + throw new IllegalArgumentException("size must not be negative"); + } + return wrap(new byte[size]); + } + + /** + * Wraps a byte array into a MessageBuffer. + *

      + * The new MessageBuffer will be backed by the given byte array. + * Modifications to the new MessageBuffer will cause the byte array to be modified and vice versa. + *

      + * The new buffer's size will be array.length. hasArray() will return true. + * + * @param array the byte array that will gack this MessageBuffer + * @return a new MessageBuffer that wraps the given byte array + */ + public static MessageBuffer wrap(byte[] array) { + return newMessageBuffer(array, 0, array.length); + } + + /** + * Wraps a byte array into a MessageBuffer. + *

      + * The new MessageBuffer will be backed by the given byte array. + * Modifications to the new MessageBuffer will cause the byte array to be modified and vice versa. + *

      + * The new buffer's size will be length. hasArray() will return true. + * + * @param array the byte array that will gack this MessageBuffer + * @param offset The offset of the subarray to be used; must be non-negative and no larger than array.length + * @param length The length of the subarray to be used; must be non-negative and no larger than array.length - offset + * @return a new MessageBuffer that wraps the given byte array + */ + public static MessageBuffer wrap(byte[] array, int offset, int length) { + return newMessageBuffer(array, offset, length); + } + + /** + * Wraps a ByteBuffer into a MessageBuffer. + *

      + * The new MessageBuffer will be backed by the given byte buffer. Modifications to the new MessageBuffer will cause the byte buffer to be modified and vice versa. However, change of position, limit, or mark of given byte buffer doesn't affect MessageBuffer. + *

      + * The new buffer's size will be bb.remaining(). hasArray() will return the same result with bb.hasArray(). + * + * @param bb the byte buffer that will gack this MessageBuffer + * @return a new MessageBuffer that wraps the given byte array + * @throws IllegalArgumentException given byte buffer returns false both from hasArray() and isDirect() + * @throws UnsupportedOperationException given byte buffer is a direct buffer and this platform doesn't support Unsafe API + */ + public static MessageBuffer wrap(ByteBuffer bb) { + return newMessageBuffer(bb); + } + + /** + * Creates a new MessageBuffer instance backed by a java heap array + */ + private static MessageBuffer newMessageBuffer(byte[] arr, int off, int len) { + Objects.requireNonNull(arr); + if (mbArrConstructor != null) { + return newInstance(mbArrConstructor, arr, off, len); + } + return new MessageBuffer(arr, off, len); + } + + /** + * Creates a new MessageBuffer instance backed by ByteBuffer + */ + private static MessageBuffer newMessageBuffer(ByteBuffer bb) { + Objects.requireNonNull(bb); + if (mbBBConstructor != null) { + return newInstance(mbBBConstructor, bb); + } + return new MessageBuffer(bb); + } + + /** + * Creates a new MessageBuffer instance + * + * @param constructor A MessageBuffer constructor + * @return new MessageBuffer instance + */ + private static MessageBuffer newInstance(Constructor constructor, Object... args) { + try { + // We need to use reflection to create MessageBuffer instances in order to prevent TypeProfile generation for getInt method. TypeProfile will be + // generated to resolve one of the method references when two or more classes overrides the method. + return (MessageBuffer) constructor.newInstance(args); + } + catch (InstantiationException e) { + // should never happen + throw new IllegalStateException(e); + } + catch (IllegalAccessException e) { + // should never happen unless security manager restricts this reflection + throw new IllegalStateException(e); + } + catch (InvocationTargetException e) { + if (e.getCause() instanceof RuntimeException) { + // underlying constructor may throw RuntimeException + throw (RuntimeException) e.getCause(); + } + else if (e.getCause() instanceof Error) { + throw (Error) e.getCause(); + } + // should never happen + throw new IllegalStateException(e.getCause()); + } + } + + /** + * Create a MessageBuffer instance from an java heap array + */ + MessageBuffer(byte[] arr, int offset, int length) { + this.base = arr; // non-null is already checked at newMessageBuffer + this.address = ARRAY_BYTE_BASE_OFFSET + offset; + this.size = length; + this.reference = null; + } + + /** + * Create a MessageBuffer instance from a given ByteBuffer instance + */ + MessageBuffer(ByteBuffer bb) { + if (bb.isDirect()) { + if (isUniversalBuffer) { + // MessageBufferU overrides almost all methods, only field 'size' is used. + this.base = null; + this.address = 0; + this.size = bb.remaining(); + this.reference = null; + return; + } + // Direct buffer or off-heap memory + this.base = null; + this.address = DirectBufferAccess.getAddress(bb) + bb.position(); + this.size = bb.remaining(); + this.reference = bb; + } + else if (bb.hasArray()) { + this.base = bb.array(); + this.address = ARRAY_BYTE_BASE_OFFSET + bb.arrayOffset() + bb.position(); + this.size = bb.remaining(); + this.reference = null; + } + else { + throw new IllegalArgumentException("Only the array-backed ByteBuffer or DirectBuffer is supported"); + } + } + + protected MessageBuffer(Object base, long address, int length) { + this.base = base; + this.address = address; + this.size = length; + this.reference = null; + } + + /** + * Gets the size of the buffer. + *

      + * MessageBuffer doesn't have limit unlike ByteBuffer. Instead, you can use {@link #slice(int, int)} to get a + * part of the buffer. + * + * @return number of bytes + */ + public int size() { + return size; + } + + public MessageBuffer slice(int offset, int length) { + // TODO ensure deleting this slice does not collapse this MessageBuffer + if (offset == 0 && length == size()) { + return this; + } + else { + Assert.isTrue(offset + length <= size(), "offset must <= size - length"); + return new MessageBuffer(base, address + offset, length); + } + } + + public byte getByte(int index) { + return unsafe.getByte(base, address + index); + } + + public boolean getBoolean(int index) { + return unsafe.getBoolean(base, address + index); + } + + public short getShort(int index) { + short v = unsafe.getShort(base, address + index); + return Short.reverseBytes(v); + } + + /** + * Read a big-endian int value at the specified index + */ + public int getInt(int index) { + // Reading little-endian value + int i = unsafe.getInt(base, address + index); + // Reversing the endian + return Integer.reverseBytes(i); + } + + public float getFloat(int index) { + return Float.intBitsToFloat(getInt(index)); + } + + public long getLong(int index) { + long l = unsafe.getLong(base, address + index); + return Long.reverseBytes(l); + } + + public double getDouble(int index) { + return Double.longBitsToDouble(getLong(index)); + } + + public void getBytes(int index, byte[] dst, int dstOffset, int length) { + unsafe.copyMemory(base, address + index, dst, ARRAY_BYTE_BASE_OFFSET + dstOffset, length); + } + + public void getBytes(int index, int len, ByteBuffer dst) { + if (dst.remaining() < len) { + throw new BufferOverflowException(); + } + ByteBuffer src = sliceAsByteBuffer(index, len); + dst.put(src); + } + + public void putByte(int index, byte v) { + unsafe.putByte(base, address + index, v); + } + + public void putBoolean(int index, boolean v) { + unsafe.putBoolean(base, address + index, v); + } + + public void putShort(int index, short v) { + v = Short.reverseBytes(v); + unsafe.putShort(base, address + index, v); + } + + /** + * Write a big-endian integer value to the memory + */ + public void putInt(int index, int v) { + // Reversing the endian + v = Integer.reverseBytes(v); + unsafe.putInt(base, address + index, v); + } + + public void putFloat(int index, float v) { + putInt(index, Float.floatToRawIntBits(v)); + } + + public void putLong(int index, long l) { + // Reversing the endian + l = Long.reverseBytes(l); + unsafe.putLong(base, address + index, l); + } + + public void putDouble(int index, double v) { + putLong(index, Double.doubleToRawLongBits(v)); + } + + public void putBytes(int index, byte[] src, int srcOffset, int length) { + unsafe.copyMemory(src, ARRAY_BYTE_BASE_OFFSET + srcOffset, base, address + index, length); + } + + public void putByteBuffer(int index, ByteBuffer src, int len) { + assert (len <= src.remaining()); + assert (!isUniversalBuffer); + + if (src.isDirect()) { + unsafe.copyMemory(null, DirectBufferAccess.getAddress(src) + src.position(), base, address + index, len); + src.position(src.position() + len); + } + else if (src.hasArray()) { + byte[] srcArray = src.array(); + unsafe.copyMemory(srcArray, ARRAY_BYTE_BASE_OFFSET + src.position(), base, address + index, len); + src.position(src.position() + len); + } + else { + if (hasArray()) { + src.get((byte[]) base, index, len); + } + else { + for (int i = 0; i < len; ++i) { + unsafe.putByte(base, address + index, src.get()); + } + } + } + } + + public void putMessageBuffer(int index, MessageBuffer src, int srcOffset, int len) { + unsafe.copyMemory(src.base, src.address + srcOffset, base, address + index, len); + } + + /** + * Create a ByteBuffer view of the range [index, index+length) of this memory + */ + public ByteBuffer sliceAsByteBuffer(int index, int length) { + if (hasArray()) { + return ByteBuffer.wrap((byte[]) base, (int) ((address - ARRAY_BYTE_BASE_OFFSET) + index), length); + } + else { + assert (!isUniversalBuffer); + return DirectBufferAccess.newByteBuffer(address, index, length, reference); + } + } + + /** + * Get a ByteBuffer view of this buffer + */ + public ByteBuffer sliceAsByteBuffer() { + return sliceAsByteBuffer(0, size()); + } + + public boolean hasArray() { + return base != null; + } + + /** + * Get a copy of this buffer + */ + public byte[] toByteArray() { + byte[] b = new byte[size()]; + unsafe.copyMemory(base, address, b, ARRAY_BYTE_BASE_OFFSET, size()); + return b; + } + + public byte[] array() { + return (byte[]) base; + } + + public int arrayOffset() { + return (int) address - ARRAY_BYTE_BASE_OFFSET; + } + + /** + * Copy this buffer contents to another MessageBuffer + */ + public void copyTo(int index, MessageBuffer dst, int offset, int length) { + unsafe.copyMemory(base, address + index, dst.base, dst.address + offset, length); + } + + public String toHexString(int offset, int length) { + StringBuilder s = new StringBuilder(); + for (int i = offset; i < length; ++i) { + if (i != offset) { + s.append(" "); + } + s.append(String.format("%02x", getByte(i))); + } + return s.toString(); + } +} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/MessageBufferBE.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/MessageBufferBE.java new file mode 100644 index 0000000..1464edf --- /dev/null +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/MessageBufferBE.java @@ -0,0 +1,98 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.serialize.format.buffer; + +import java.nio.ByteBuffer; + +import infra.lang.Assert; + +/** + * MessageBufferBE is a {@link MessageBuffer} implementation tailored to big-endian machines. + * The specification of Message Pack demands writing short/int/float/long/double values in the big-endian format. + * In the big-endian machine, we do not need to swap the byte order. + */ +public class MessageBufferBE extends MessageBuffer { + + MessageBufferBE(byte[] arr, int offset, int length) { + super(arr, offset, length); + } + + MessageBufferBE(ByteBuffer bb) { + super(bb); + } + + private MessageBufferBE(Object base, long address, int length) { + super(base, address, length); + } + + @Override + public MessageBufferBE slice(int offset, int length) { + if (offset == 0 && length == size()) { + return this; + } + else { + Assert.isTrue(offset + length <= size(), "offset must <= size - length"); + return new MessageBufferBE(base, address + offset, length); + } + } + + @Override + public short getShort(int index) { + return unsafe.getShort(base, address + index); + } + + @Override + public int getInt(int index) { + // We can simply return the integer value as big-endian value + return unsafe.getInt(base, address + index); + } + + public long getLong(int index) { + return unsafe.getLong(base, address + index); + } + + @Override + public float getFloat(int index) { + return unsafe.getFloat(base, address + index); + } + + @Override + public double getDouble(int index) { + return unsafe.getDouble(base, address + index); + } + + @Override + public void putShort(int index, short v) { + unsafe.putShort(base, address + index, v); + } + + @Override + public void putInt(int index, int v) { + unsafe.putInt(base, address + index, v); + } + + @Override + public void putLong(int index, long v) { + unsafe.putLong(base, address + index, v); + } + + @Override + public void putDouble(int index, double v) { + unsafe.putDouble(base, address + index, v); + } +} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/MessageBufferInput.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/MessageBufferInput.java new file mode 100644 index 0000000..36ed055 --- /dev/null +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/MessageBufferInput.java @@ -0,0 +1,60 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.serialize.format.buffer; + +import java.io.Closeable; +import java.io.IOException; + +import infra.lang.Nullable; + +/** + * Provides a sequence of MessageBuffer instances. + *

      + * A MessageBufferInput implementation has control of lifecycle + * of the memory so that it can reuse previously allocated memory, + * use memory pools, or use memory-mapped files. + */ +public interface MessageBufferInput extends Closeable { + + /** + * Returns a next buffer to read. + *

      + * This method should return a MessageBuffer instance that has data filled in. When this method is called twice, + * the previously returned buffer is no longer used. Thus, implementation of this method can safely discard it. + * This is useful when it uses a memory pool. + * + * @return the next MessageBuffer, or return null if no more buffer is available. + * @throws IOException when IO error occurred when reading the data + */ + @Nullable + MessageBuffer next() throws IOException; + + /** + * Closes the input. + *

      + * When this method is called, the buffer previously returned from {@link #next()} method is no longer used. + * Thus, implementation of this method can safely discard it. + *

      + * If the input is already closed then invoking this method has no effect. + * + * @throws IOException when IO error occurred when closing the data source + */ + @Override + void close() throws IOException; + +} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/MessageBufferOutput.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/MessageBufferOutput.java new file mode 100644 index 0000000..26557c7 --- /dev/null +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/MessageBufferOutput.java @@ -0,0 +1,82 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.serialize.format.buffer; + +import java.io.Closeable; +import java.io.Flushable; +import java.io.IOException; + +/** + * Provides a buffered output stream that writes sequence of MessageBuffer instances. + *

      + * A MessageBufferOutput implementation has total control of the buffer memory so that it can reuse buffer memory, + * use buffer pools, or use memory-mapped files. + */ +public interface MessageBufferOutput extends Closeable, Flushable { + + /** + * Allocates the next buffer to write. + *

      + * This method should return a MessageBuffer instance that has specified size of capacity at least. + *

      + * When this method is called twice, the previously returned buffer is no longer used. This method may be called + * twice without call of {@link #writeBuffer(int)} in between. In this case, the buffer should be + * discarded without flushing it to the output. + * + * @param minimumSize the mimium required buffer size to allocate + * @return the MessageBuffer instance with at least minimumSize bytes of capacity + */ + MessageBuffer next(int minimumSize) throws IOException; + + /** + * Writes the previously allocated buffer. + *

      + * This method should write the buffer previously returned from {@link #next(int)} method until specified number of + * bytes. Once the buffer is written, the buffer is no longer used. + *

      + * This method is not always called for each {@link #next(int)} call. In this case, the buffer should be discarded + * without flushing it to the output when the next {@link #next(int)} is called. + * + * @param length the number of bytes to write + */ + void writeBuffer(int length) throws IOException; + + /** + * Writes an external payload data. + * This method should follow semantics of OutputStream. + * + * @param buffer the data to write + * @param offset the start offset in the data + * @param length the number of bytes to write + */ + void write(byte[] buffer, int offset, int length) throws IOException; + + /** + * Writes an external payload data. + *

      + * Unlike {@link #write(byte[], int, int)} method, the buffer is given - this MessageBufferOutput implementation + * gets ownership of the buffer and may modify contents of the buffer. Contents of this buffer won't be modified + * by the caller. + * + * @param buffer the data to add + * @param offset the start offset in the data + * @param length the number of bytes to add + */ + void add(byte[] buffer, int offset, int length) throws IOException; + +} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/MessageBufferU.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/MessageBufferU.java new file mode 100644 index 0000000..b3a02ca --- /dev/null +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/MessageBufferU.java @@ -0,0 +1,244 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.serialize.format.buffer; + +import java.nio.ByteBuffer; + +import infra.lang.Assert; + +/** + * Universal MessageBuffer implementation supporting Java6 and Android. + * This buffer always uses ByteBuffer-based memory access + */ +public class MessageBufferU extends MessageBuffer { + + private final ByteBuffer wrap; + + MessageBufferU(byte[] arr, int offset, int length) { + super(arr, offset, length); + this.wrap = ByteBuffer.wrap(arr, offset, length).slice(); + } + + MessageBufferU(ByteBuffer bb) { + super(bb); + this.wrap = bb.slice(); + } + + private MessageBufferU(Object base, long address, int length, ByteBuffer wrap) { + super(base, address, length); + this.wrap = wrap; + } + + @Override + public MessageBufferU slice(int offset, int length) { + if (offset == 0 && length == size()) { + return this; + } + else { + Assert.isTrue(offset + length <= size(), "offset must <= size - length"); + try { + wrap.position(offset); + wrap.limit(offset + length); + return new MessageBufferU(base, address + offset, length, wrap.slice()); + } + finally { + resetBufferPosition(); + } + } + } + + private void resetBufferPosition() { + wrap.position(0); + wrap.limit(size); + } + + @Override + public byte getByte(int index) { + return wrap.get(index); + } + + @Override + public boolean getBoolean(int index) { + return wrap.get(index) != 0; + } + + @Override + public short getShort(int index) { + return wrap.getShort(index); + } + + @Override + public int getInt(int index) { + return wrap.getInt(index); + } + + @Override + public float getFloat(int index) { + return wrap.getFloat(index); + } + + @Override + public long getLong(int index) { + return wrap.getLong(index); + } + + @Override + public double getDouble(int index) { + return wrap.getDouble(index); + } + + @Override + public void getBytes(int index, int len, ByteBuffer dst) { + try { + wrap.position(index); + wrap.limit(index + len); + dst.put(wrap); + } + finally { + resetBufferPosition(); + } + } + + @Override + public void putByte(int index, byte v) { + wrap.put(index, v); + } + + @Override + public void putBoolean(int index, boolean v) { + wrap.put(index, v ? (byte) 1 : (byte) 0); + } + + @Override + public void putShort(int index, short v) { + wrap.putShort(index, v); + } + + @Override + public void putInt(int index, int v) { + wrap.putInt(index, v); + } + + @Override + public void putFloat(int index, float v) { + wrap.putFloat(index, v); + } + + @Override + public void putLong(int index, long l) { + wrap.putLong(index, l); + } + + @Override + public void putDouble(int index, double v) { + wrap.putDouble(index, v); + } + + @Override + public ByteBuffer sliceAsByteBuffer(int index, int length) { + try { + wrap.position(index); + wrap.limit(index + length); + return wrap.slice(); + } + finally { + resetBufferPosition(); + } + } + + @Override + public ByteBuffer sliceAsByteBuffer() { + return sliceAsByteBuffer(0, size); + } + + @Override + public void getBytes(int index, byte[] dst, int dstOffset, int length) { + try { + wrap.position(index); + wrap.get(dst, dstOffset, length); + } + finally { + resetBufferPosition(); + } + } + + @Override + public void putByteBuffer(int index, ByteBuffer src, int len) { + assert (len <= src.remaining()); + + if (src.hasArray()) { + putBytes(index, src.array(), src.position() + src.arrayOffset(), len); + src.position(src.position() + len); + } + else { + int prevSrcLimit = src.limit(); + try { + src.limit(src.position() + len); + wrap.position(index); + wrap.put(src); + } + finally { + src.limit(prevSrcLimit); + } + } + } + + @Override + public void putBytes(int index, byte[] src, int srcOffset, int length) { + try { + wrap.position(index); + wrap.put(src, srcOffset, length); + } + finally { + resetBufferPosition(); + } + } + + @Override + public void copyTo(int index, MessageBuffer dst, int offset, int length) { + try { + wrap.position(index); + dst.putByteBuffer(offset, wrap, length); + } + finally { + resetBufferPosition(); + } + } + + @Override + public void putMessageBuffer(int index, MessageBuffer src, int srcOffset, int len) { + putByteBuffer(index, src.sliceAsByteBuffer(srcOffset, len), len); + } + + @Override + public byte[] toByteArray() { + byte[] b = new byte[size()]; + getBytes(0, b, 0, b.length); + return b; + } + + @Override + public boolean hasArray() { + return !wrap.isDirect(); + } + + @Override + public byte[] array() { + return hasArray() ? wrap.array() : null; + } +} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/OutputStreamBufferOutput.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/OutputStreamBufferOutput.java new file mode 100644 index 0000000..73491bf --- /dev/null +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/OutputStreamBufferOutput.java @@ -0,0 +1,86 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.serialize.format.buffer; + +import java.io.IOException; +import java.io.OutputStream; +import java.util.Objects; + +/** + * MessageBufferOutput adapter for {@link OutputStream}. + */ +public class OutputStreamBufferOutput implements MessageBufferOutput { + + private OutputStream out; + + private MessageBuffer buffer; + + public OutputStreamBufferOutput(OutputStream out) { + this(out, 8192); + } + + public OutputStreamBufferOutput(OutputStream out, int bufferSize) { + this.out = Objects.requireNonNull(out, "output is null"); + this.buffer = MessageBuffer.allocate(bufferSize); + } + + /** + * Reset Stream. This method doesn't close the old stream. + * + * @param out new stream + * @return the old stream + */ + public OutputStream reset(OutputStream out) { + OutputStream old = this.out; + this.out = out; + return old; + } + + @Override + public MessageBuffer next(int minimumSize) throws IOException { + if (buffer.size() < minimumSize) { + buffer = MessageBuffer.allocate(minimumSize); + } + return buffer; + } + + @Override + public void writeBuffer(int length) throws IOException { + write(buffer.array(), buffer.arrayOffset(), length); + } + + @Override + public void write(byte[] buffer, int offset, int length) throws IOException { + out.write(buffer, offset, length); + } + + @Override + public void add(byte[] buffer, int offset, int length) throws IOException { + write(buffer, offset, length); + } + + @Override + public void close() throws IOException { + out.close(); + } + + @Override + public void flush() throws IOException { + out.flush(); + } +} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/package-info.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/package-info.java new file mode 100644 index 0000000..91f9755 --- /dev/null +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/package-info.java @@ -0,0 +1,26 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +/** + * msgpack specification implementation + */ +@NonNullFields +@NonNullApi +package infra.cloud.serialize.format; + +import infra.lang.NonNullApi; +import infra.lang.NonNullFields; \ No newline at end of file diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ArrayValue.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ArrayValue.java new file mode 100644 index 0000000..6eb813a --- /dev/null +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ArrayValue.java @@ -0,0 +1,58 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.serialize.format.value; + +import java.util.Iterator; +import java.util.List; + +/** + * Representation of MessagePack's Array type. + *

      + * MessagePack's Array type can represent sequence of values. + */ +public interface ArrayValue extends Value, Iterable { + + /** + * Returns number of elements in this array. + */ + int size(); + + /** + * Returns the element at the specified position in this array. + * + * @throws IndexOutOfBoundsException If the index is out of range + * (index < 0 || index >= size()) + */ + Value get(int index); + + /** + * Returns the element at the specified position in this array. + * This method returns an ImmutableNilValue if the index is out of range. + */ + Value getOrNilValue(int index); + + /** + * Returns an iterator over elements. + */ + Iterator iterator(); + + /** + * Returns the value as {@code List}. + */ + List list(); +} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/BinaryValue.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/BinaryValue.java new file mode 100644 index 0000000..28ebd75 --- /dev/null +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/BinaryValue.java @@ -0,0 +1,29 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.serialize.format.value; + +/** + * Representation of MessagePack's Binary type. + * + * MessagePack's Binary type can represent a byte array at most 264-1 bytes. + * + * @see RawValue + */ +public interface BinaryValue + extends RawValue { +} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/BooleanValue.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/BooleanValue.java new file mode 100644 index 0000000..a588f4d --- /dev/null +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/BooleanValue.java @@ -0,0 +1,31 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.serialize.format.value; + +/** + * Representation MessagePack's Boolean type. + * + * MessagePack's Boolean type can represent {@code true} or {@code false}. + */ +public interface BooleanValue + extends Value { + /** + * Returns the value as a {@code boolean}. + */ + boolean getBoolean(); +} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ExtensionValue.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ExtensionValue.java new file mode 100644 index 0000000..7bca8b5 --- /dev/null +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ExtensionValue.java @@ -0,0 +1,33 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.serialize.format.value; + +/** + * Representation of MessagePack's Extension type. + * + * MessagePack's Extension type can represent represents a tuple of type information and a byte array where type information is an + * integer whose meaning is defined by applications. + * + * As the type information, applications can use 0 to 127 as the application-specific types. -1 to -128 is reserved for MessagePack's future extension. + */ +public interface ExtensionValue + extends Value { + byte getType(); + + byte[] getData(); +} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/FloatValue.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/FloatValue.java new file mode 100644 index 0000000..d7d6922 --- /dev/null +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/FloatValue.java @@ -0,0 +1,29 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.serialize.format.value; + +/** + * Representation of MessagePack's Float type. + *

      + * MessagePack's Float type can represent IEEE 754 double precision floating point numbers including NaN and infinity. This is same with Java's {@code double} type. + * + * @see NumberValue + */ +public interface FloatValue extends NumberValue { + +} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableArrayValue.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableArrayValue.java new file mode 100644 index 0000000..83c9156 --- /dev/null +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableArrayValue.java @@ -0,0 +1,41 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.serialize.format.value; + +import java.util.Iterator; +import java.util.List; + +/** + * Immutable representation of MessagePack's Array type. + * + * MessagePack's Array type can represent sequence of values. + */ +public interface ImmutableArrayValue + extends ArrayValue, ImmutableValue { + /** + * Returns an iterator over elements. + * Returned Iterator does not support {@code remove()} method since the value is immutable. + */ + Iterator iterator(); + + /** + * Returns the value as {@code List}. + * Returned List is immutable. It does not support {@code put()}, {@code clear()}, or other methods that modify the value. + */ + List list(); +} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableBinaryValue.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableBinaryValue.java new file mode 100644 index 0000000..1a7c1ad --- /dev/null +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableBinaryValue.java @@ -0,0 +1,29 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.serialize.format.value; + +/** + * Immutable representation of MessagePack's Binary type. + * + * MessagePack's Binary type can represent a byte array at most 264-1 bytes. + * + * @see ImmutableRawValue + */ +public interface ImmutableBinaryValue + extends BinaryValue, ImmutableRawValue { +} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableBooleanValue.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableBooleanValue.java new file mode 100644 index 0000000..48ea26e --- /dev/null +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableBooleanValue.java @@ -0,0 +1,27 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.serialize.format.value; + +/** + * Immutable representation of MessagePack's Boolean type. + * + * MessagePack's Boolean type can represent {@code true} or {@code false}. + */ +public interface ImmutableBooleanValue + extends BooleanValue, ImmutableValue { +} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableExtensionValue.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableExtensionValue.java new file mode 100644 index 0000000..6caa006 --- /dev/null +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableExtensionValue.java @@ -0,0 +1,27 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.serialize.format.value; + +/** + * Immutable representation of MessagePack's Extension type. + * + * @see ExtensionValue + */ +public interface ImmutableExtensionValue + extends ExtensionValue, ImmutableValue { +} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableFloatValue.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableFloatValue.java new file mode 100644 index 0000000..f216837 --- /dev/null +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableFloatValue.java @@ -0,0 +1,29 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.serialize.format.value; + +/** + * Immutable representation of MessagePack's Float type. + * + * MessagePack's Float type can represent IEEE 754 double precision floating point numbers including NaN and infinity. This is same with Java's {@code double} type. + * + * @see ImmutableNumberValue + */ +public interface ImmutableFloatValue + extends FloatValue, ImmutableNumberValue { +} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableIntegerValue.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableIntegerValue.java new file mode 100644 index 0000000..ded546a --- /dev/null +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableIntegerValue.java @@ -0,0 +1,27 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.serialize.format.value; + +/** + * Immutable representation of MessagePack's Integer type. + * + * MessagePack's Integer type can represent from -263 to 264-1. + */ +public interface ImmutableIntegerValue + extends IntegerValue, ImmutableNumberValue { +} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableMapValue.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableMapValue.java new file mode 100644 index 0000000..2177a1e --- /dev/null +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableMapValue.java @@ -0,0 +1,27 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.serialize.format.value; + +/** + * Immutable representation of MessagePack's Map type. + * + * MessagePack's Map type can represent sequence of key-value pairs. + */ +public interface ImmutableMapValue + extends MapValue, ImmutableValue { +} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableNilValue.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableNilValue.java new file mode 100644 index 0000000..642d11e --- /dev/null +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableNilValue.java @@ -0,0 +1,25 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.serialize.format.value; + +/** + * Immutable representation of MessagePack's Nil type. + */ +public interface ImmutableNilValue extends NilValue, ImmutableValue { + +} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableNumberValue.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableNumberValue.java new file mode 100644 index 0000000..0508517 --- /dev/null +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableNumberValue.java @@ -0,0 +1,28 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.serialize.format.value; + +/** + * Immutable base interface of {@link ImmutableIntegerValue} and {@link ImmutableFloatValue} interfaces. To extract primitive type values, call toXXX methods, which may lose some information by rounding or truncation. + * + * @see ImmutableIntegerValue + * @see ImmutableFloatValue + */ +public interface ImmutableNumberValue + extends NumberValue, ImmutableValue { +} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableRawValue.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableRawValue.java new file mode 100644 index 0000000..1a00b74 --- /dev/null +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableRawValue.java @@ -0,0 +1,30 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.serialize.format.value; + +/** + * Immutable base interface of {@link ImmutableStringValue} and {@link ImmutableBinaryValue} interfaces. + *

      + * MessagePack's Raw type can represent a byte array at most 264-1 bytes. + * + * @see ImmutableStringValue + * @see ImmutableBinaryValue + */ +public interface ImmutableRawValue + extends RawValue, ImmutableValue { +} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableStringValue.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableStringValue.java new file mode 100644 index 0000000..6abced0 --- /dev/null +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableStringValue.java @@ -0,0 +1,28 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.serialize.format.value; + +/** + * Immutable representation of MessagePack's String type. + * + * @see StringValue + * @see ImmutableRawValue + */ +public interface ImmutableStringValue + extends StringValue, ImmutableRawValue { +} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableTimestampValue.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableTimestampValue.java new file mode 100644 index 0000000..eb5702f --- /dev/null +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableTimestampValue.java @@ -0,0 +1,27 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.serialize.format.value; + +/** + * Immutable representation of MessagePack's Timestamp type. + * + * @see TimestampValue + */ +public interface ImmutableTimestampValue + extends TimestampValue, ImmutableValue { +} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableValue.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableValue.java new file mode 100644 index 0000000..2c6de33 --- /dev/null +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableValue.java @@ -0,0 +1,54 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.serialize.format.value; + +/** + * Immutable declaration of {@link Value} interface. + */ +public interface ImmutableValue extends Value { + + @Override + ImmutableNilValue asNilValue(); + + @Override + ImmutableBooleanValue asBooleanValue(); + + @Override + ImmutableIntegerValue asIntegerValue(); + + @Override + ImmutableFloatValue asFloatValue(); + + @Override + ImmutableArrayValue asArrayValue(); + + @Override + ImmutableMapValue asMapValue(); + + @Override + ImmutableRawValue asRawValue(); + + @Override + ImmutableBinaryValue asBinaryValue(); + + @Override + ImmutableStringValue asStringValue(); + + @Override + ImmutableTimestampValue asTimestampValue(); +} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/IntegerValue.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/IntegerValue.java new file mode 100644 index 0000000..57a1bc8 --- /dev/null +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/IntegerValue.java @@ -0,0 +1,91 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.serialize.format.value; + +import java.math.BigInteger; + +import infra.cloud.serialize.format.MessageFormat; +import infra.cloud.serialize.format.MessageIntegerOverflowException; + +/** + * Representation of MessagePack's Integer type. + * + * MessagePack's Integer type can represent from -263 to 264-1. + */ +public interface IntegerValue + extends NumberValue { + /** + * Returns true if the value is in the range of [-27 to 27-1]. + */ + boolean isInByteRange(); + + /** + * Returns true if the value is in the range of [-215 to 215-1] + */ + boolean isInShortRange(); + + /** + * Returns true if the value is in the range of [-231 to 231-1] + */ + boolean isInIntRange(); + + /** + * Returns true if the value is in the range of [-263 to 263-1] + */ + boolean isInLongRange(); + + /** + * Returns the most succinct MessageFormat type to represent this integer value. + * + * @return the smallest integer type of MessageFormat that is big enough to store the value. + */ + MessageFormat mostSuccinctMessageFormat(); + + /** + * Returns the value as a {@code byte}, otherwise throws an exception. + * + * @throws MessageIntegerOverflowException If the value does not fit in the range of {@code byte} type. + */ + byte asByte(); + + /** + * Returns the value as a {@code short}, otherwise throws an exception. + * + * @throws MessageIntegerOverflowException If the value does not fit in the range of {@code short} type. + */ + short asShort(); + + /** + * Returns the value as an {@code int}, otherwise throws an exception. + * + * @throws MessageIntegerOverflowException If the value does not fit in the range of {@code int} type. + */ + int asInt(); + + /** + * Returns the value as a {@code long}, otherwise throws an exception. + * + * @throws MessageIntegerOverflowException If the value does not fit in the range of {@code long} type. + */ + long asLong(); + + /** + * Returns the value as a {@code BigInteger}. + */ + BigInteger asBigInteger(); +} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/MapValue.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/MapValue.java new file mode 100644 index 0000000..05818fa --- /dev/null +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/MapValue.java @@ -0,0 +1,56 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.serialize.format.value; + +import java.util.Collection; +import java.util.Map; +import java.util.Set; + +/** + * Representation of MessagePack's Map type. + *

      + * MessagePack's Map type can represent sequence of key-value pairs. + */ +public interface MapValue extends Value { + + /** + * Returns number of key-value pairs in this array. + */ + int size(); + + Set keySet(); + + Set> entrySet(); + + Collection values(); + + /** + * Returns the value as {@code Map}. + */ + Map map(); + + /** + * Returns the key-value pairs as an array of {@code Value}. + *

      + * Odd elements are keys. Next element of an odd element is a value corresponding to the key. + *

      + * For example, if this value represents {"k1": "v1", "k2": "v2"}, this method returns ["k1", "v1", "k2", "v2"]. + */ + Value[] getKeyValueArray(); + +} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/NilValue.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/NilValue.java new file mode 100644 index 0000000..2fcad8c --- /dev/null +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/NilValue.java @@ -0,0 +1,25 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.serialize.format.value; + +/** + * Representation of MessagePack's Nil type. + */ +public interface NilValue extends Value { + +} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/NumberValue.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/NumberValue.java new file mode 100644 index 0000000..75eabe1 --- /dev/null +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/NumberValue.java @@ -0,0 +1,66 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.serialize.format.value; + +import java.math.BigInteger; + +/** + * Base interface of {@link IntegerValue} and {@link FloatValue} interfaces. To extract primitive type values, call toXXX methods, which may lose some information by rounding or truncation. + * + * @see IntegerValue + * @see FloatValue + */ +public interface NumberValue extends Value { + + /** + * Represent this value as a byte value, which may involve rounding or truncation of the original value. + * the value. + */ + byte toByte(); + + /** + * Represent this value as a short value, which may involve rounding or truncation of the original value. + */ + short toShort(); + + /** + * Represent this value as an int value, which may involve rounding or truncation of the original value. + * value. + */ + int toInt(); + + /** + * Represent this value as a long value, which may involve rounding or truncation of the original value. + */ + long toLong(); + + /** + * Represent this value as a BigInteger, which may involve rounding or truncation of the original value. + */ + BigInteger toBigInteger(); + + /** + * Represent this value as a 32-bit float value, which may involve rounding or truncation of the original value. + */ + float toFloat(); + + /** + * Represent this value as a 64-bit double value, which may involve rounding or truncation of the original value. + */ + double toDouble(); +} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/RawValue.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/RawValue.java new file mode 100644 index 0000000..589a0fc --- /dev/null +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/RawValue.java @@ -0,0 +1,64 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.serialize.format.value; + +import java.nio.ByteBuffer; + +import infra.cloud.serialize.format.MessageStringCodingException; + +/** + * Base interface of {@link StringValue} and {@link BinaryValue} interfaces. + *

      + * MessagePack's Raw type can represent a byte array at most 264-1 bytes. + * + * @see StringValue + * @see BinaryValue + */ +public interface RawValue + extends Value { + /** + * Returns the value as {@code byte[]}. + * + * This method copies the byte array. + */ + byte[] asByteArray(); + + /** + * Returns the value as {@code ByteBuffer}. + * + * Returned ByteBuffer is read-only. See also {@link ByteBuffer#asReadOnlyBuffer()}. + * This method doesn't copy the byte array as much as possible. + */ + ByteBuffer asByteBuffer(); + + /** + * Returns the value as {@code String}. + * + * This method throws an exception if the value includes invalid UTF-8 byte sequence. + * + * @throws MessageStringCodingException If this value includes invalid UTF-8 byte sequence. + */ + String asString(); + + /** + * Returns the value as {@code String}. + * + * This method replaces an invalid UTF-8 byte sequence with U+FFFD replacement character. + */ + String toString(); +} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/StringValue.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/StringValue.java new file mode 100644 index 0000000..3d535ed --- /dev/null +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/StringValue.java @@ -0,0 +1,31 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.serialize.format.value; + +/** + * Representation of MessagePack's String type. + * + * MessagePack's String type can represent a UTF-8 string at most 264-1 bytes. + * + * Note that the value could include invalid byte sequences. {@code asString()} method throws {@code MessageTypeStringCodingException} if the value includes invalid byte sequence. {@code toJson()} method replaces an invalid byte sequence with U+FFFD replacement character. + * + * @see RawValue + */ +public interface StringValue + extends RawValue { +} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/TimestampValue.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/TimestampValue.java new file mode 100644 index 0000000..fd753b3 --- /dev/null +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/TimestampValue.java @@ -0,0 +1,34 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.serialize.format.value; + +import java.time.Instant; + +/** + * Value representation of MessagePack's Timestamp type. + */ +public interface TimestampValue + extends ExtensionValue { + long getEpochSecond(); + + int getNano(); + + long toEpochMillis(); + + Instant toInstant(); +} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/Value.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/Value.java new file mode 100644 index 0000000..68f1cc9 --- /dev/null +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/Value.java @@ -0,0 +1,332 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.serialize.format.value; + +import java.io.IOException; + +import infra.cloud.serialize.format.MessagePacker; +import infra.cloud.serialize.format.MessageTypeCastException; + +/** + * Value stores a value and its type in MessagePack type system. + * + *

      Type conversion

      + *

      + * You can check type first using isXxx() methods or {@link #getValueType()} method, then convert the value to a + * subtype using asXxx() methods. You can also call asXxx() methods directly and catch + * {@link MessageTypeCastException}. + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
      MessagePack typeCheck methodConvert methodValue type
      Nil{@link #isNilValue()}{@link #asNumberValue()}{@link NilValue}
      Boolean{@link #isBooleanValue()}{@link #asBooleanValue()}{@link BooleanValue}
      Integer or Float{@link #isNumberValue()}{@link #asNumberValue()}{@link NumberValue}
      Integer{@link #isIntegerValue()}{@link #asIntegerValue()}{@link IntegerValue}
      Float{@link #isFloatValue()}{@link #asFloatValue()}{@link FloatValue}
      String or Binary{@link #isRawValue()}{@link #asRawValue()}{@link RawValue}
      String{@link #isStringValue()}{@link #asStringValue()}{@link StringValue}
      Binary{@link #isBinaryValue()}{@link #asBinaryValue()}{@link BinaryValue}
      Array{@link #isArrayValue()}{@link #asArrayValue()}{@link ArrayValue}
      Map{@link #isMapValue()}{@link #asMapValue()}{@link MapValue}
      Extension{@link #isExtensionValue()}{@link #asExtensionValue()}{@link ExtensionValue}
      + * + *

      Immutable interface

      + *

      + * Value interface is the base interface of all Value interfaces. Immutable subtypes are useful so that you can + * declare that a (final) field or elements of a container object are immutable. Method arguments should be a + * regular Value interface generally. + *

      + * You can use {@link #immutableValue()} method to get immutable subtypes. + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
      MessagePack typeSubtype methodImmutable value type
      any types{@link Value}.{@link Value#immutableValue()}{@link ImmutableValue}
      Nil{@link NilValue}.{@link NilValue#immutableValue()}{@link ImmutableNilValue}
      Boolean{@link BooleanValue}.{@link BooleanValue#immutableValue()}{@link ImmutableBooleanValue}
      Integer{@link IntegerValue}.{@link IntegerValue#immutableValue()}{@link ImmutableIntegerValue}
      Float{@link FloatValue}.{@link FloatValue#immutableValue()}{@link ImmutableFloatValue}
      Integer or Float{@link NumberValue}.{@link NumberValue#immutableValue()}{@link ImmutableNumberValue}
      String or Binary{@link RawValue}.{@link RawValue#immutableValue()}{@link ImmutableRawValue}
      String{@link StringValue}.{@link StringValue#immutableValue()}{@link ImmutableStringValue}
      Binary{@link BinaryValue}.{@link BinaryValue#immutableValue()}{@link ImmutableBinaryValue}
      Array{@link ArrayValue}.{@link ArrayValue#immutableValue()}{@link ImmutableArrayValue}
      Map{@link MapValue}.{@link MapValue#immutableValue()}{@link ImmutableMapValue}
      Extension{@link ExtensionValue}.{@link ExtensionValue#immutableValue()}{@link ImmutableExtensionValue}
      + * + *

      Converting to JSON

      + *

      + * {@link #toJson()} method returns JSON representation of a Value. See its documents for details. + *

      + * toString() also returns a string representation of a Value that is similar to JSON. However, unlike toJson() method, + * toString() may return a special format that is not be compatible with JSON when JSON doesn't support the type such + * as ExtensionValue. + */ +public interface Value { + + /** + * Returns type of this value. + *

      + * Note that you can't use instanceof to check type of a value because type of a mutable value is variable. + */ + ValueType getValueType(); + + /** + * Returns immutable copy of this value. + *

      + * This method simply returns this without copying the value if this value is already immutable. + */ + ImmutableValue immutableValue(); + + /** + * Returns true if type of this value is Nil. + *

      + * If this method returns true, {@code asNilValue} never throws exceptions. + * Note that you can't use instanceof or cast ((NilValue) thisValue) to check type of a value because type of a mutable value is variable. + */ + boolean isNilValue(); + + /** + * Returns true if type of this value is Boolean. + *

      + * If this method returns true, {@code asBooleanValue} never throws exceptions. + * Note that you can't use instanceof or cast ((BooleanValue) thisValue) to check type of a value because type of a mutable value is variable. + */ + boolean isBooleanValue(); + + /** + * Returns true if type of this value is Integer or Float. + *

      + * If this method returns true, {@code asNumberValue} never throws exceptions. + * Note that you can't use instanceof or cast ((NumberValue) thisValue) to check type of a value because type of a mutable value is variable. + */ + boolean isNumberValue(); + + /** + * Returns true if type of this value is Integer. + *

      + * If this method returns true, {@code asIntegerValue} never throws exceptions. + * Note that you can't use instanceof or cast ((IntegerValue) thisValue) to check type of a value because type of a mutable value is variable. + */ + boolean isIntegerValue(); + + /** + * Returns true if type of this value is Float. + *

      + * If this method returns true, {@code asFloatValue} never throws exceptions. + * Note that you can't use instanceof or cast ((FloatValue) thisValue) to check type of a value because type of a mutable value is variable. + */ + boolean isFloatValue(); + + /** + * Returns true if type of this value is String or Binary. + *

      + * If this method returns true, {@code asRawValue} never throws exceptions. + * Note that you can't use instanceof or cast ((RawValue) thisValue) to check type of a value because type of a mutable value is variable. + */ + boolean isRawValue(); + + /** + * Returns true if type of this value is Binary. + *

      + * If this method returns true, {@code asBinaryValue} never throws exceptions. + * Note that you can't use instanceof or cast ((BinaryValue) thisValue) to check type of a value because type of a mutable value is variable. + */ + boolean isBinaryValue(); + + /** + * Returns true if type of this value is String. + *

      + * If this method returns true, {@code asStringValue} never throws exceptions. + * Note that you can't use instanceof or cast ((StringValue) thisValue) to check type of a value because type of a mutable value is variable. + */ + boolean isStringValue(); + + /** + * Returns true if type of this value is Array. + *

      + * If this method returns true, {@code asArrayValue} never throws exceptions. + * Note that you can't use instanceof or cast ((ArrayValue) thisValue) to check type of a value because type of a mutable value is variable. + */ + boolean isArrayValue(); + + /** + * Returns true if type of this value is Map. + *

      + * If this method returns true, {@code asMapValue} never throws exceptions. + * Note that you can't use instanceof or cast ((MapValue) thisValue) to check type of a value because type of a mutable value is variable. + */ + boolean isMapValue(); + + /** + * Returns true if type of this an Extension. + *

      + * If this method returns true, {@code asExtensionValue} never throws exceptions. + * Note that you can't use instanceof or cast ((ExtensionValue) thisValue) to check type of a value because + * type of a mutable value is variable. + */ + boolean isExtensionValue(); + + /** + * Returns true if the type of this value is Timestamp. + *

      + * If this method returns true, {@code asTimestamp} never throws exceptions. + * Note that you can't use instanceof or cast ((MapValue) thisValue) to check type of a value because type of a mutable value is variable. + */ + boolean isTimestampValue(); + + /** + * Returns the value as {@code NilValue}. Otherwise throws {@code MessageTypeCastException}. + *

      + * Note that you can't use instanceof or cast ((NilValue) thisValue) to check type of a value because type of a mutable value is variable. + * + * @throws MessageTypeCastException If type of this value is not Nil. + */ + NilValue asNilValue(); + + /** + * Returns the value as {@code BooleanValue}. Otherwise throws {@code MessageTypeCastException}. + *

      + * Note that you can't use instanceof or cast ((BooleanValue) thisValue) to check type of a value because type of a mutable value is variable. + * + * @throws MessageTypeCastException If type of this value is not Boolean. + */ + BooleanValue asBooleanValue(); + + /** + * Returns the value as {@code NumberValue}. Otherwise throws {@code MessageTypeCastException}. + *

      + * Note that you can't use instanceof or cast ((NumberValue) thisValue) to check type of a value because type of a mutable value is variable. + * + * @throws MessageTypeCastException If type of this value is not Integer or Float. + */ + NumberValue asNumberValue(); + + /** + * Returns the value as {@code IntegerValue}. Otherwise throws {@code MessageTypeCastException}. + *

      + * Note that you can't use instanceof or cast ((IntegerValue) thisValue) to check type of a value because type of a mutable value is variable. + * + * @throws MessageTypeCastException If type of this value is not Integer. + */ + IntegerValue asIntegerValue(); + + /** + * Returns the value as {@code FloatValue}. Otherwise throws {@code MessageTypeCastException}. + *

      + * Note that you can't use instanceof or cast ((FloatValue) thisValue) to check type of a value because type of a mutable value is variable. + * + * @throws MessageTypeCastException If type of this value is not Float. + */ + FloatValue asFloatValue(); + + /** + * Returns the value as {@code RawValue}. Otherwise throws {@code MessageTypeCastException}. + *

      + * Note that you can't use instanceof or cast ((RawValue) thisValue) to check type of a value because type of a mutable value is variable. + * + * @throws MessageTypeCastException If type of this value is not Binary or String. + */ + RawValue asRawValue(); + + /** + * Returns the value as {@code BinaryValue}. Otherwise throws {@code MessageTypeCastException}. + *

      + * Note that you can't use instanceof or cast ((BinaryValue) thisValue) to check type of a value because type of a mutable value is variable. + * + * @throws MessageTypeCastException If type of this value is not Binary. + */ + BinaryValue asBinaryValue(); + + /** + * Returns the value as {@code StringValue}. Otherwise throws {@code MessageTypeCastException}. + *

      + * Note that you can't use instanceof or cast ((StringValue) thisValue) to check type of a value because type of a mutable value is variable. + * + * @throws MessageTypeCastException If type of this value is not String. + */ + StringValue asStringValue(); + + /** + * Returns the value as {@code ArrayValue}. Otherwise throws {@code MessageTypeCastException}. + *

      + * Note that you can't use instanceof or cast ((ArrayValue) thisValue) to check type of a value because type of a mutable value is variable. + * + * @throws MessageTypeCastException If type of this value is not Array. + */ + ArrayValue asArrayValue(); + + /** + * Returns the value as {@code MapValue}. Otherwise throws {@code MessageTypeCastException}. + *

      + * Note that you can't use instanceof or cast ((MapValue) thisValue) to check type of a value because type of a mutable value is variable. + * + * @throws MessageTypeCastException If type of this value is not Map. + */ + MapValue asMapValue(); + + /** + * Returns the value as {@code ExtensionValue}. Otherwise throws {@code MessageTypeCastException}. + *

      + * Note that you can't use instanceof or cast ((ExtensionValue) thisValue) to check type of a value + * because type of a mutable value is variable. + * + * @throws MessageTypeCastException If type of this value is not an Extension. + */ + ExtensionValue asExtensionValue(); + + /** + * Returns the value as {@code TimestampValue}. Otherwise throws {@code MessageTypeCastException}. + *

      + * Note that you can't use instanceof or cast ((TimestampValue) thisValue) to check type of a value because type of a mutable value is variable. + * + * @throws MessageTypeCastException If type of this value is not Map. + */ + TimestampValue asTimestampValue(); + + /** + * Serializes the value using the specified {@code MessagePacker} + * + * @see MessagePacker + */ + void writeTo(MessagePacker pk) throws IOException; + + /** + * Compares this value to the specified object. + *

      + * This method returns {@code true} if type and value are equivalent. + * If this value is {@code MapValue} or {@code ArrayValue}, this method check equivalence of elements recursively. + */ + boolean equals(Object obj); + + /** + * Returns json representation of this Value. + *

      + * Following behavior is not configurable at this release and they might be changed at future releases: + * + *

        + *
      • if a key of MapValue is not string, the key is converted to a string using toString method.
      • + *
      • NaN and Infinity of DoubleValue are converted to null.
      • + *
      • ExtensionValue is converted to a 2-element array where first element is a number and second element is the data encoded in hex.
      • + *
      • BinaryValue is converted to a string using UTF-8 encoding. Invalid byte sequence is replaced with U+FFFD replacement character.
      • + *
      • Invalid UTF-8 byte sequences in StringValue is replaced with U+FFFD replacement character
      • + *
          + */ + String toJson(); +} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ValueFactory.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ValueFactory.java new file mode 100644 index 0000000..85f8992 --- /dev/null +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ValueFactory.java @@ -0,0 +1,275 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.serialize.format.value; + +import java.math.BigInteger; +import java.time.Instant; +import java.util.AbstractMap; +import java.util.Arrays; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import infra.cloud.serialize.format.value.impl.ImmutableArrayValueImpl; +import infra.cloud.serialize.format.value.impl.ImmutableBigIntegerValueImpl; +import infra.cloud.serialize.format.value.impl.ImmutableBinaryValueImpl; +import infra.cloud.serialize.format.value.impl.ImmutableBooleanValueImpl; +import infra.cloud.serialize.format.value.impl.ImmutableDoubleValueImpl; +import infra.cloud.serialize.format.value.impl.ImmutableExtensionValueImpl; +import infra.cloud.serialize.format.value.impl.ImmutableLongValueImpl; +import infra.cloud.serialize.format.value.impl.ImmutableMapValueImpl; +import infra.cloud.serialize.format.value.impl.ImmutableNilValueImpl; +import infra.cloud.serialize.format.value.impl.ImmutableStringValueImpl; +import infra.cloud.serialize.format.value.impl.ImmutableTimestampValueImpl; + +public final class ValueFactory { + private ValueFactory() { + } + + public static ImmutableNilValue newNil() { + return ImmutableNilValueImpl.get(); + } + + public static ImmutableBooleanValue newBoolean(boolean v) { + return v ? ImmutableBooleanValueImpl.TRUE : ImmutableBooleanValueImpl.FALSE; + } + + public static ImmutableIntegerValue newInteger(byte v) { + return new ImmutableLongValueImpl(v); + } + + public static ImmutableIntegerValue newInteger(short v) { + return new ImmutableLongValueImpl(v); + } + + public static ImmutableIntegerValue newInteger(int v) { + return new ImmutableLongValueImpl(v); + } + + public static ImmutableIntegerValue newInteger(long v) { + return new ImmutableLongValueImpl(v); + } + + public static ImmutableIntegerValue newInteger(BigInteger v) { + return new ImmutableBigIntegerValueImpl(v); + } + + public static ImmutableFloatValue newFloat(float v) { + return new ImmutableDoubleValueImpl(v); + } + + public static ImmutableFloatValue newFloat(double v) { + return new ImmutableDoubleValueImpl(v); + } + + public static ImmutableBinaryValue newBinary(byte[] b) { + return newBinary(b, false); + } + + public static ImmutableBinaryValue newBinary(byte[] b, boolean omitCopy) { + if (omitCopy) { + return new ImmutableBinaryValueImpl(b); + } + else { + return new ImmutableBinaryValueImpl(Arrays.copyOf(b, b.length)); + } + } + + public static ImmutableBinaryValue newBinary(byte[] b, int off, int len) { + return newBinary(b, off, len, false); + } + + public static ImmutableBinaryValue newBinary(byte[] b, int off, int len, boolean omitCopy) { + if (omitCopy && off == 0 && len == b.length) { + return new ImmutableBinaryValueImpl(b); + } + else { + return new ImmutableBinaryValueImpl(Arrays.copyOfRange(b, off, len)); + } + } + + public static ImmutableStringValue newString(String s) { + return new ImmutableStringValueImpl(s); + } + + public static ImmutableStringValue newString(byte[] b) { + return new ImmutableStringValueImpl(b); + } + + public static ImmutableStringValue newString(byte[] b, boolean omitCopy) { + if (omitCopy) { + return new ImmutableStringValueImpl(b); + } + else { + return new ImmutableStringValueImpl(Arrays.copyOf(b, b.length)); + } + } + + public static ImmutableStringValue newString(byte[] b, int off, int len) { + return newString(b, off, len, false); + } + + public static ImmutableStringValue newString(byte[] b, int off, int len, boolean omitCopy) { + if (omitCopy && off == 0 && len == b.length) { + return new ImmutableStringValueImpl(b); + } + else { + return new ImmutableStringValueImpl(Arrays.copyOfRange(b, off, len)); + } + } + + public static ImmutableArrayValue newArray(List list) { + if (list.isEmpty()) { + return ImmutableArrayValueImpl.empty(); + } + Value[] array = list.toArray(new Value[list.size()]); + return new ImmutableArrayValueImpl(array); + } + + public static ImmutableArrayValue newArray(Value... array) { + if (array.length == 0) { + return ImmutableArrayValueImpl.empty(); + } + else { + return new ImmutableArrayValueImpl(Arrays.copyOf(array, array.length)); + } + } + + public static ImmutableArrayValue newArray(Value[] array, boolean omitCopy) { + if (array.length == 0) { + return ImmutableArrayValueImpl.empty(); + } + else if (omitCopy) { + return new ImmutableArrayValueImpl(array); + } + else { + return new ImmutableArrayValueImpl(Arrays.copyOf(array, array.length)); + } + } + + public static ImmutableArrayValue emptyArray() { + return ImmutableArrayValueImpl.empty(); + } + + public static + ImmutableMapValue newMap(Map map) { + Value[] kvs = new Value[map.size() * 2]; + int index = 0; + for (Map.Entry pair : map.entrySet()) { + kvs[index] = pair.getKey(); + index++; + kvs[index] = pair.getValue(); + index++; + } + return new ImmutableMapValueImpl(kvs); + } + + public static ImmutableMapValue newMap(Value... kvs) { + if (kvs.length == 0) { + return ImmutableMapValueImpl.empty(); + } + else { + return new ImmutableMapValueImpl(Arrays.copyOf(kvs, kvs.length)); + } + } + + public static ImmutableMapValue newMap(Value[] kvs, boolean omitCopy) { + if (kvs.length == 0) { + return ImmutableMapValueImpl.empty(); + } + else if (omitCopy) { + return new ImmutableMapValueImpl(kvs); + } + else { + return new ImmutableMapValueImpl(Arrays.copyOf(kvs, kvs.length)); + } + } + + public static ImmutableMapValue emptyMap() { + return ImmutableMapValueImpl.empty(); + } + + @SafeVarargs + public static MapValue newMap(Map.Entry... pairs) { + Value[] kvs = new Value[pairs.length * 2]; + for (int i = 0; i < pairs.length; ++i) { + kvs[i * 2] = pairs[i].getKey(); + kvs[i * 2 + 1] = pairs[i].getValue(); + } + return newMap(kvs, true); + } + + public static MapBuilder newMapBuilder() { + return new MapBuilder(); + } + + public static Map.Entry newMapEntry(Value key, Value value) { + return new AbstractMap.SimpleEntry<>(key, value); + } + + public static class MapBuilder { + private final Map map = new LinkedHashMap(); + + public MapBuilder() { + } + + public MapValue build() { + return newMap(map); + } + + public MapBuilder put(Map.Entry pair) { + put(pair.getKey(), pair.getValue()); + return this; + } + + public MapBuilder put(Value key, Value value) { + map.put(key, value); + return this; + } + + public MapBuilder putAll(Iterable> entries) { + for (Map.Entry entry : entries) { + put(entry.getKey(), entry.getValue()); + } + return this; + } + + public MapBuilder putAll(Map map) { + for (Map.Entry entry : map.entrySet()) { + put(entry); + } + return this; + } + } + + public static ImmutableExtensionValue newExtension(byte type, byte[] data) { + return new ImmutableExtensionValueImpl(type, data); + } + + public static ImmutableTimestampValue newTimestamp(Instant timestamp) { + return new ImmutableTimestampValueImpl(timestamp); + } + + public static ImmutableTimestampValue newTimestamp(long millis) { + return newTimestamp(Instant.ofEpochMilli(millis)); + } + + public static ImmutableTimestampValue newTimestamp(long epochSecond, int nanoAdjustment) { + return newTimestamp(Instant.ofEpochSecond(epochSecond, nanoAdjustment)); + } +} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ValueType.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ValueType.java new file mode 100644 index 0000000..6ace9b8 --- /dev/null +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ValueType.java @@ -0,0 +1,99 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.serialize.format.value; + +import infra.cloud.serialize.format.MessageFormat; + +/** + * Representation of MessagePack types. + *

          + * MessagePack uses hierarchical type system. Integer and Float are subypte of Number, Thus {@link #isNumberType()} + * returns true if type is Integer or Float. String and Binary are subtype of Raw. Thus {@link #isRawType()} returns + * true if type is String or Binary. + * + * @see MessageFormat + */ +public enum ValueType { + NIL(false, false), + BOOLEAN(false, false), + INTEGER(true, false), + FLOAT(true, false), + STRING(false, true), + BINARY(false, true), + ARRAY(false, false), + MAP(false, false), + EXTENSION(false, false); + + /** + * Design note: We do not add Timestamp as a ValueType here because + * detecting Timestamp values requires reading 1-3 bytes ahead while the other + * value types can be determined just by reading the first one byte. + */ + + private final boolean numberType; + private final boolean rawType; + + private ValueType(boolean numberType, boolean rawType) { + this.numberType = numberType; + this.rawType = rawType; + } + + public boolean isNilType() { + return this == NIL; + } + + public boolean isBooleanType() { + return this == BOOLEAN; + } + + public boolean isNumberType() { + return numberType; + } + + public boolean isIntegerType() { + return this == INTEGER; + } + + public boolean isFloatType() { + return this == FLOAT; + } + + public boolean isRawType() { + return rawType; + } + + public boolean isStringType() { + return this == STRING; + } + + public boolean isBinaryType() { + return this == BINARY; + } + + public boolean isArrayType() { + return this == ARRAY; + } + + public boolean isMapType() { + return this == MAP; + } + + public boolean isExtensionType() { + return this == EXTENSION; + } +} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/Variable.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/Variable.java new file mode 100644 index 0000000..6c3ed59 --- /dev/null +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/Variable.java @@ -0,0 +1,1164 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.serialize.format.value; + +import java.io.IOException; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.nio.ByteBuffer; +import java.nio.charset.CharacterCodingException; +import java.nio.charset.CharsetDecoder; +import java.nio.charset.CodingErrorAction; +import java.time.Instant; +import java.util.Arrays; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import infra.cloud.serialize.format.MessageFormat; +import infra.cloud.serialize.format.MessageIntegerOverflowException; +import infra.cloud.serialize.format.MessagePack; +import infra.cloud.serialize.format.MessagePacker; +import infra.cloud.serialize.format.MessageStringCodingException; +import infra.cloud.serialize.format.MessageTypeCastException; +import infra.cloud.serialize.format.value.impl.ImmutableBigIntegerValueImpl; + +public class Variable implements Value { + + private abstract class AbstractValueAccessor implements Value { + + @Override + public boolean isNilValue() { + return getValueType().isNilType(); + } + + @Override + public boolean isBooleanValue() { + return getValueType().isBooleanType(); + } + + @Override + public boolean isNumberValue() { + return getValueType().isNumberType(); + } + + @Override + public boolean isIntegerValue() { + return getValueType().isIntegerType(); + } + + @Override + public boolean isFloatValue() { + return getValueType().isFloatType(); + } + + @Override + public boolean isRawValue() { + return getValueType().isRawType(); + } + + @Override + public boolean isBinaryValue() { + return getValueType().isBinaryType(); + } + + @Override + public boolean isStringValue() { + return getValueType().isStringType(); + } + + @Override + public boolean isArrayValue() { + return getValueType().isArrayType(); + } + + @Override + public boolean isMapValue() { + return getValueType().isMapType(); + } + + @Override + public boolean isExtensionValue() { + return getValueType().isExtensionType(); + } + + @Override + public boolean isTimestampValue() { + return false; + } + + @Override + public NilValue asNilValue() { + throw new MessageTypeCastException(); + } + + @Override + public BooleanValue asBooleanValue() { + throw new MessageTypeCastException(); + } + + @Override + public NumberValue asNumberValue() { + throw new MessageTypeCastException(); + } + + @Override + public IntegerValue asIntegerValue() { + throw new MessageTypeCastException(); + } + + @Override + public FloatValue asFloatValue() { + throw new MessageTypeCastException(); + } + + @Override + public RawValue asRawValue() { + throw new MessageTypeCastException(); + } + + @Override + public BinaryValue asBinaryValue() { + throw new MessageTypeCastException(); + } + + @Override + public StringValue asStringValue() { + throw new MessageTypeCastException(); + } + + @Override + public ArrayValue asArrayValue() { + throw new MessageTypeCastException(); + } + + @Override + public MapValue asMapValue() { + throw new MessageTypeCastException(); + } + + @Override + public ExtensionValue asExtensionValue() { + throw new MessageTypeCastException(); + } + + @Override + public TimestampValue asTimestampValue() { + throw new MessageTypeCastException(); + } + + @Override + public boolean equals(Object obj) { + return Variable.this.equals(obj); + } + + @Override + public int hashCode() { + return Variable.this.hashCode(); + } + + @Override + public String toJson() { + return Variable.this.toJson(); + } + + @Override + public String toString() { + return Variable.this.toString(); + } + } + + public enum Type { + NULL(ValueType.NIL), + BOOLEAN(ValueType.BOOLEAN), + LONG(ValueType.INTEGER), + BIG_INTEGER(ValueType.INTEGER), + DOUBLE(ValueType.FLOAT), + BYTE_ARRAY(ValueType.BINARY), + RAW_STRING(ValueType.STRING), + LIST(ValueType.ARRAY), + MAP(ValueType.MAP), + EXTENSION(ValueType.EXTENSION), + TIMESTAMP(ValueType.EXTENSION); + + private final ValueType valueType; + + Type(ValueType valueType) { + this.valueType = valueType; + } + + public ValueType getValueType() { + return valueType; + } + } + + private final NilValueAccessor nilAccessor = new NilValueAccessor(); + private final BooleanValueAccessor booleanAccessor = new BooleanValueAccessor(); + private final IntegerValueAccessor integerAccessor = new IntegerValueAccessor(); + private final FloatValueAccessor floatAccessor = new FloatValueAccessor(); + private final BinaryValueAccessor binaryAccessor = new BinaryValueAccessor(); + private final StringValueAccessor stringAccessor = new StringValueAccessor(); + private final ArrayValueAccessor arrayAccessor = new ArrayValueAccessor(); + private final MapValueAccessor mapAccessor = new MapValueAccessor(); + private final ExtensionValueAccessor extensionAccessor = new ExtensionValueAccessor(); + private final TimestampValueAccessor timestampAccessor = new TimestampValueAccessor(); + + private Type type; + + private long longValue; + private double doubleValue; + private Object objectValue; + + private AbstractValueAccessor accessor; + + public Variable() { + setNilValue(); + } + + /// / + // NilValue + // + public Variable setNilValue() { + this.type = Type.NULL; + this.accessor = nilAccessor; + return this; + } + + private class NilValueAccessor + extends AbstractValueAccessor + implements NilValue { + @Override + public ValueType getValueType() { + return ValueType.NIL; + } + + @Override + public NilValue asNilValue() { + return this; + } + + @Override + public ImmutableNilValue immutableValue() { + return ValueFactory.newNil(); + } + + @Override + public void writeTo(MessagePacker pk) + throws IOException { + pk.packNil(); + } + } + + /// / + // BooleanValue + // + public Variable setBooleanValue(boolean v) { + this.type = Type.BOOLEAN; + this.accessor = booleanAccessor; + this.longValue = (v ? 1L : 0L); + return this; + } + + private class BooleanValueAccessor + extends AbstractValueAccessor + implements BooleanValue { + @Override + public ValueType getValueType() { + return ValueType.BOOLEAN; + } + + @Override + public BooleanValue asBooleanValue() { + return this; + } + + @Override + public ImmutableBooleanValue immutableValue() { + return ValueFactory.newBoolean(getBoolean()); + } + + @Override + public boolean getBoolean() { + return longValue == 1L; + } + + @Override + public void writeTo(MessagePacker pk) + throws IOException { + pk.packBoolean(longValue == 1L); + } + } + + /// / + // NumberValue + // IntegerValue + // FloatValue + // + + private static final BigInteger LONG_MIN = BigInteger.valueOf(Long.MIN_VALUE); + private static final BigInteger LONG_MAX = BigInteger.valueOf(Long.MAX_VALUE); + private static final long BYTE_MIN = Byte.MIN_VALUE; + private static final long BYTE_MAX = Byte.MAX_VALUE; + private static final long SHORT_MIN = Short.MIN_VALUE; + private static final long SHORT_MAX = Short.MAX_VALUE; + private static final long INT_MIN = Integer.MIN_VALUE; + private static final long INT_MAX = Integer.MAX_VALUE; + + private abstract class AbstractNumberValueAccessor + extends AbstractValueAccessor + implements NumberValue { + @Override + public NumberValue asNumberValue() { + return this; + } + + @Override + public byte toByte() { + if (type == Type.BIG_INTEGER) { + return ((BigInteger) objectValue).byteValue(); + } + return (byte) longValue; + } + + @Override + public short toShort() { + if (type == Type.BIG_INTEGER) { + return ((BigInteger) objectValue).shortValue(); + } + return (short) longValue; + } + + @Override + public int toInt() { + if (type == Type.BIG_INTEGER) { + return ((BigInteger) objectValue).intValue(); + } + return (int) longValue; + } + + @Override + public long toLong() { + if (type == Type.BIG_INTEGER) { + return ((BigInteger) objectValue).longValue(); + } + return longValue; + } + + @Override + public BigInteger toBigInteger() { + if (type == Type.BIG_INTEGER) { + return (BigInteger) objectValue; + } + else if (type == Type.DOUBLE) { + return new BigDecimal(doubleValue).toBigInteger(); + } + return BigInteger.valueOf(longValue); + } + + @Override + public float toFloat() { + if (type == Type.BIG_INTEGER) { + return ((BigInteger) objectValue).floatValue(); + } + else if (type == Type.DOUBLE) { + return (float) doubleValue; + } + return (float) longValue; + } + + @Override + public double toDouble() { + if (type == Type.BIG_INTEGER) { + return ((BigInteger) objectValue).doubleValue(); + } + else if (type == Type.DOUBLE) { + return doubleValue; + } + return (double) longValue; + } + } + + /// / + // IntegerValue + // + public Variable setIntegerValue(long v) { + this.type = Type.LONG; + this.accessor = integerAccessor; + this.longValue = v; + return this; + } + + public Variable setIntegerValue(BigInteger v) { + if (0 <= v.compareTo(LONG_MIN) && v.compareTo(LONG_MAX) <= 0) { + this.type = Type.LONG; + this.accessor = integerAccessor; + this.longValue = v.longValue(); + } + else { + this.type = Type.BIG_INTEGER; + this.accessor = integerAccessor; + this.objectValue = v; + } + return this; + } + + private class IntegerValueAccessor + extends AbstractNumberValueAccessor + implements IntegerValue { + @Override + public ValueType getValueType() { + return ValueType.INTEGER; + } + + @Override + public IntegerValue asIntegerValue() { + return this; + } + + @Override + public ImmutableIntegerValue immutableValue() { + if (type == Type.BIG_INTEGER) { + return ValueFactory.newInteger((BigInteger) objectValue); + } + return ValueFactory.newInteger(longValue); + } + + @Override + public boolean isInByteRange() { + if (type == Type.BIG_INTEGER) { + return false; + } + return BYTE_MIN <= longValue && longValue <= BYTE_MAX; + } + + @Override + public boolean isInShortRange() { + if (type == Type.BIG_INTEGER) { + return false; + } + return SHORT_MIN <= longValue && longValue <= SHORT_MAX; + } + + @Override + public boolean isInIntRange() { + if (type == Type.BIG_INTEGER) { + return false; + } + return INT_MIN <= longValue && longValue <= INT_MAX; + } + + @Override + public boolean isInLongRange() { + return type != Type.BIG_INTEGER; + } + + @Override + public MessageFormat mostSuccinctMessageFormat() { + return ImmutableBigIntegerValueImpl.mostSuccinctMessageFormat(this); + } + + @Override + public byte asByte() { + if (!isInByteRange()) { + throw new MessageIntegerOverflowException(longValue); + } + return (byte) longValue; + } + + @Override + public short asShort() { + if (!isInByteRange()) { + throw new MessageIntegerOverflowException(longValue); + } + return (short) longValue; + } + + @Override + public int asInt() { + if (!isInIntRange()) { + throw new MessageIntegerOverflowException(longValue); + } + return (int) longValue; + } + + @Override + public long asLong() { + if (!isInLongRange()) { + throw new MessageIntegerOverflowException(longValue); + } + return longValue; + } + + @Override + public BigInteger asBigInteger() { + if (type == Type.BIG_INTEGER) { + return (BigInteger) objectValue; + } + else { + return BigInteger.valueOf(longValue); + } + } + + @Override + public void writeTo(MessagePacker pk) + throws IOException { + if (type == Type.BIG_INTEGER) { + pk.packBigInteger((BigInteger) objectValue); + } + else { + pk.packLong(longValue); + } + } + } + + /// / + // FloatValue + // + public Variable setFloatValue(double v) { + this.type = Type.DOUBLE; + this.accessor = floatAccessor; + this.doubleValue = v; + this.longValue = (long) v; // AbstractNumberValueAccessor uses toLong + return this; + } + + public Variable setFloatValue(float v) { + this.type = Type.DOUBLE; + this.accessor = floatAccessor; + this.longValue = (long) v; // AbstractNumberValueAccessor uses toLong + return this; + } + + private class FloatValueAccessor extends AbstractNumberValueAccessor implements FloatValue { + + @Override + public FloatValue asFloatValue() { + return this; + } + + @Override + public ImmutableFloatValue immutableValue() { + return ValueFactory.newFloat(doubleValue); + } + + @Override + public ValueType getValueType() { + return ValueType.FLOAT; + } + + @Override + public void writeTo(MessagePacker pk) throws IOException { + pk.packDouble(doubleValue); + } + } + + /// / + // RawValue + // BinaryValue + // StringValue + // + + private abstract class AbstractRawValueAccessor + extends AbstractValueAccessor + implements RawValue { + @Override + public RawValue asRawValue() { + return this; + } + + @Override + public byte[] asByteArray() { + return (byte[]) objectValue; + } + + @Override + public ByteBuffer asByteBuffer() { + return ByteBuffer.wrap(asByteArray()); + } + + @Override + public String asString() { + byte[] raw = (byte[]) objectValue; + try { + CharsetDecoder reportDecoder = MessagePack.UTF8.newDecoder() + .onMalformedInput(CodingErrorAction.REPORT) + .onUnmappableCharacter(CodingErrorAction.REPORT); + return reportDecoder.decode(ByteBuffer.wrap(raw)).toString(); + } + catch (CharacterCodingException ex) { + throw new MessageStringCodingException(ex); + } + } + + // override for performance optimization + @Override + public String toString() { + byte[] raw = (byte[]) objectValue; + try { + CharsetDecoder reportDecoder = MessagePack.UTF8.newDecoder() + .onMalformedInput(CodingErrorAction.REPLACE) + .onUnmappableCharacter(CodingErrorAction.REPLACE); + return reportDecoder.decode(ByteBuffer.wrap(raw)).toString(); + } + catch (CharacterCodingException ex) { + throw new MessageStringCodingException(ex); + } + } + } + + /// / + // BinaryValue + // + public Variable setBinaryValue(byte[] v) { + this.type = Type.BYTE_ARRAY; + this.accessor = binaryAccessor; + this.objectValue = v; + return this; + } + + private class BinaryValueAccessor + extends AbstractRawValueAccessor + implements BinaryValue { + @Override + public ValueType getValueType() { + return ValueType.BINARY; + } + + @Override + public BinaryValue asBinaryValue() { + return this; + } + + @Override + public ImmutableBinaryValue immutableValue() { + return ValueFactory.newBinary(asByteArray()); + } + + @Override + public void writeTo(MessagePacker pk) + throws IOException { + byte[] data = (byte[]) objectValue; + pk.packBinaryHeader(data.length); + pk.writePayload(data); + } + } + + // StringValue + // + + public Variable setStringValue(String v) { + return setStringValue(v.getBytes(MessagePack.UTF8)); + } + + public Variable setStringValue(byte[] v) { + this.type = Type.RAW_STRING; + this.accessor = stringAccessor; + this.objectValue = v; + return this; + } + + private class StringValueAccessor extends AbstractRawValueAccessor implements StringValue { + + @Override + public ValueType getValueType() { + return ValueType.STRING; + } + + @Override + public StringValue asStringValue() { + return this; + } + + @Override + public ImmutableStringValue immutableValue() { + return ValueFactory.newString((byte[]) objectValue); + } + + @Override + public void writeTo(MessagePacker pk) + throws IOException { + byte[] data = (byte[]) objectValue; + pk.packRawStringHeader(data.length); + pk.writePayload(data); + } + } + + /// / + // ArrayValue + // + public Variable setArrayValue(List v) { + this.type = Type.LIST; + this.accessor = arrayAccessor; + this.objectValue = v.toArray(new Value[v.size()]); + return this; + } + + public Variable setArrayValue(Value[] v) { + this.type = Type.LIST; + this.accessor = arrayAccessor; + this.objectValue = v; + return this; + } + + private class ArrayValueAccessor + extends AbstractValueAccessor + implements ArrayValue { + @Override + public ValueType getValueType() { + return ValueType.ARRAY; + } + + @Override + public ArrayValue asArrayValue() { + return this; + } + + @Override + public ImmutableArrayValue immutableValue() { + return ValueFactory.newArray(array()); + } + + @Override + public int size() { + return array().length; + } + + @Override + public Value get(int index) { + return array()[index]; + } + + @Override + public Value getOrNilValue(int index) { + Value[] a = array(); + if (a.length < index && index >= 0) { + return ValueFactory.newNil(); + } + return a[index]; + } + + @Override + public Iterator iterator() { + return list().iterator(); + } + + @Override + public List list() { + return Arrays.asList(array()); + } + + public Value[] array() { + return (Value[]) objectValue; + } + + @Override + public void writeTo(MessagePacker pk) + throws IOException { + immutableValue().writeTo(pk); + } + } + + /// / + // MapValue + // + public Variable setMapValue(Map v) { + this.type = Type.MAP; + this.accessor = mapAccessor; + Value[] kvs = new Value[v.size() * 2]; + Iterator> ite = v.entrySet().iterator(); + int i = 0; + while (ite.hasNext()) { + Map.Entry pair = ite.next(); + kvs[i] = pair.getKey(); + i++; + kvs[i] = pair.getValue(); + i++; + } + this.objectValue = kvs; + return this; + } + + public Variable setMapValue(Value[] kvs) { + this.type = Type.MAP; + this.accessor = mapAccessor; + this.objectValue = kvs; + return this; + } + + private class MapValueAccessor extends AbstractValueAccessor implements MapValue { + + @Override + public ValueType getValueType() { + return ValueType.MAP; + } + + @Override + public MapValue asMapValue() { + return this; + } + + @Override + public ImmutableMapValue immutableValue() { + return ValueFactory.newMap(getKeyValueArray()); + } + + @Override + public int size() { + return getKeyValueArray().length / 2; + } + + @Override + public Set keySet() { + return immutableValue().keySet(); + } + + @Override + public Set> entrySet() { + return immutableValue().entrySet(); + } + + @Override + public Collection values() { + return immutableValue().values(); + } + + @Override + public Value[] getKeyValueArray() { + return (Value[]) objectValue; + } + + public Map map() { + return immutableValue().map(); + } + + @Override + public void writeTo(MessagePacker pk) + throws IOException { + immutableValue().writeTo(pk); + } + } + + /// / + // ExtensionValue + // + public Variable setExtensionValue(byte type, byte[] data) { + this.type = Type.EXTENSION; + this.accessor = extensionAccessor; + this.objectValue = ValueFactory.newExtension(type, data); + return this; + } + + private class ExtensionValueAccessor + extends AbstractValueAccessor + implements ExtensionValue { + @Override + public ValueType getValueType() { + return ValueType.EXTENSION; + } + + @Override + public ExtensionValue asExtensionValue() { + return this; + } + + @Override + public ImmutableExtensionValue immutableValue() { + return (ImmutableExtensionValue) objectValue; + } + + @Override + public byte getType() { + return ((ImmutableExtensionValue) objectValue).getType(); + } + + @Override + public byte[] getData() { + return ((ImmutableExtensionValue) objectValue).getData(); + } + + @Override + public void writeTo(MessagePacker pk) + throws IOException { + ((ImmutableExtensionValue) objectValue).writeTo(pk); + } + } + + public Variable setTimestampValue(Instant timestamp) { + this.type = Type.TIMESTAMP; + this.accessor = timestampAccessor; + this.objectValue = ValueFactory.newTimestamp(timestamp); + return this; + } + + private class TimestampValueAccessor + extends AbstractValueAccessor + implements TimestampValue { + @Override + public boolean isTimestampValue() { + return true; + } + + @Override + public ValueType getValueType() { + return ValueType.EXTENSION; + } + + @Override + public TimestampValue asTimestampValue() { + return this; + } + + @Override + public ImmutableTimestampValue immutableValue() { + return (ImmutableTimestampValue) objectValue; + } + + @Override + public byte getType() { + return ((ImmutableTimestampValue) objectValue).getType(); + } + + @Override + public byte[] getData() { + return ((ImmutableTimestampValue) objectValue).getData(); + } + + @Override + public void writeTo(MessagePacker pk) + throws IOException { + ((ImmutableTimestampValue) objectValue).writeTo(pk); + } + + @Override + public long getEpochSecond() { + return ((ImmutableTimestampValue) objectValue).getEpochSecond(); + } + + @Override + public int getNano() { + return ((ImmutableTimestampValue) objectValue).getNano(); + } + + @Override + public long toEpochMillis() { + return ((ImmutableTimestampValue) objectValue).toEpochMillis(); + } + + @Override + public Instant toInstant() { + return ((ImmutableTimestampValue) objectValue).toInstant(); + } + } + + /// / + // Value + // + @Override + public ImmutableValue immutableValue() { + return accessor.immutableValue(); + } + + @Override + public void writeTo(MessagePacker pk) + throws IOException { + accessor.writeTo(pk); + } + + @Override + public int hashCode() { + return immutableValue().hashCode(); // TODO optimize + } + + @Override + public boolean equals(Object o) { + return immutableValue().equals(o); // TODO optimize + } + + @Override + public String toJson() { + return immutableValue().toJson(); // TODO optimize + } + + @Override + public String toString() { + return immutableValue().toString(); // TODO optimize + } + + @Override + public ValueType getValueType() { + return type.getValueType(); + } + + @Override + public boolean isNilValue() { + return getValueType().isNilType(); + } + + @Override + public boolean isBooleanValue() { + return getValueType().isBooleanType(); + } + + @Override + public boolean isNumberValue() { + return getValueType().isNumberType(); + } + + @Override + public boolean isIntegerValue() { + return getValueType().isIntegerType(); + } + + @Override + public boolean isFloatValue() { + return getValueType().isFloatType(); + } + + @Override + public boolean isRawValue() { + return getValueType().isRawType(); + } + + @Override + public boolean isBinaryValue() { + return getValueType().isBinaryType(); + } + + @Override + public boolean isStringValue() { + return getValueType().isStringType(); + } + + @Override + public boolean isArrayValue() { + return getValueType().isArrayType(); + } + + @Override + public boolean isMapValue() { + return getValueType().isMapType(); + } + + @Override + public boolean isExtensionValue() { + return getValueType().isExtensionType(); + } + + @Override + public boolean isTimestampValue() { + return this.type == Type.TIMESTAMP; + } + + @Override + public NilValue asNilValue() { + if (!isNilValue()) { + throw new MessageTypeCastException(); + } + return (NilValue) accessor; + } + + @Override + public BooleanValue asBooleanValue() { + if (!isBooleanValue()) { + throw new MessageTypeCastException(); + } + return (BooleanValue) accessor; + } + + @Override + public NumberValue asNumberValue() { + if (!isNumberValue()) { + throw new MessageTypeCastException(); + } + return (NumberValue) accessor; + } + + @Override + public IntegerValue asIntegerValue() { + if (!isIntegerValue()) { + throw new MessageTypeCastException(); + } + return (IntegerValue) accessor; + } + + @Override + public FloatValue asFloatValue() { + if (!isFloatValue()) { + throw new MessageTypeCastException(); + } + return (FloatValue) accessor; + } + + @Override + public RawValue asRawValue() { + if (!isRawValue()) { + throw new MessageTypeCastException(); + } + return (RawValue) accessor; + } + + @Override + public BinaryValue asBinaryValue() { + if (!isBinaryValue()) { + throw new MessageTypeCastException(); + } + return (BinaryValue) accessor; + } + + @Override + public StringValue asStringValue() { + if (!isStringValue()) { + throw new MessageTypeCastException(); + } + return (StringValue) accessor; + } + + @Override + public ArrayValue asArrayValue() { + if (!isArrayValue()) { + throw new MessageTypeCastException(); + } + return (ArrayValue) accessor; + } + + @Override + public MapValue asMapValue() { + if (!isMapValue()) { + throw new MessageTypeCastException(); + } + return (MapValue) accessor; + } + + @Override + public ExtensionValue asExtensionValue() { + if (!isExtensionValue()) { + throw new MessageTypeCastException(); + } + return (ExtensionValue) accessor; + } + + @Override + public TimestampValue asTimestampValue() { + if (!isTimestampValue()) { + throw new MessageTypeCastException(); + } + return (TimestampValue) accessor; + } +} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/AbstractImmutableRawValue.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/AbstractImmutableRawValue.java new file mode 100644 index 0000000..9adcb85 --- /dev/null +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/AbstractImmutableRawValue.java @@ -0,0 +1,175 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.serialize.format.value.impl; + +import java.nio.ByteBuffer; +import java.nio.charset.CharacterCodingException; +import java.nio.charset.CharsetDecoder; +import java.nio.charset.CodingErrorAction; +import java.util.Arrays; + +import infra.cloud.serialize.format.MessagePack; +import infra.cloud.serialize.format.MessageStringCodingException; +import infra.cloud.serialize.format.value.ImmutableRawValue; + +public abstract class AbstractImmutableRawValue + extends AbstractImmutableValue + implements ImmutableRawValue { + protected final byte[] data; + private volatile String decodedStringCache; + private volatile CharacterCodingException codingException; + + public AbstractImmutableRawValue(byte[] data) { + this.data = data; + } + + public AbstractImmutableRawValue(String string) { + this.decodedStringCache = string; + this.data = string.getBytes(MessagePack.UTF8); // TODO + } + + @Override + public ImmutableRawValue asRawValue() { + return this; + } + + @Override + public byte[] asByteArray() { + return Arrays.copyOf(data, data.length); + } + + @Override + public ByteBuffer asByteBuffer() { + return ByteBuffer.wrap(data).asReadOnlyBuffer(); + } + + @Override + public String asString() { + if (decodedStringCache == null) { + decodeString(); + } + if (codingException != null) { + throw new MessageStringCodingException(codingException); + } + else { + return decodedStringCache; + } + } + + @Override + public String toJson() { + StringBuilder sb = new StringBuilder(); + appendJsonString(sb, toString()); + return sb.toString(); + } + + private void decodeString() { + synchronized(data) { + if (decodedStringCache != null) { + return; + } + try { + CharsetDecoder reportDecoder = MessagePack.UTF8.newDecoder() + .onMalformedInput(CodingErrorAction.REPORT) + .onUnmappableCharacter(CodingErrorAction.REPORT); + this.decodedStringCache = reportDecoder.decode(asByteBuffer()).toString(); + } + catch (CharacterCodingException ex) { + try { + CharsetDecoder replaceDecoder = MessagePack.UTF8.newDecoder() + .onMalformedInput(CodingErrorAction.REPLACE) + .onUnmappableCharacter(CodingErrorAction.REPLACE); + this.decodedStringCache = replaceDecoder.decode(asByteBuffer()).toString(); + } + catch (CharacterCodingException neverThrown) { + throw new MessageStringCodingException(neverThrown); + } + this.codingException = ex; + } + } + } + + @Override + public String toString() { + if (decodedStringCache == null) { + decodeString(); + } + return decodedStringCache; + } + + static void appendJsonString(StringBuilder sb, String string) { + sb.append("\""); + for (int i = 0; i < string.length(); i++) { + char ch = string.charAt(i); + if (ch < 0x20) { + switch (ch) { + case '\n': + sb.append("\\n"); + break; + case '\r': + sb.append("\\r"); + break; + case '\t': + sb.append("\\t"); + break; + case '\f': + sb.append("\\f"); + break; + case '\b': + sb.append("\\b"); + break; + default: + // control chars + escapeChar(sb, ch); + break; + } + } + else if (ch <= 0x7f) { + switch (ch) { + case '\\': + sb.append("\\\\"); + break; + case '"': + sb.append("\\\""); + break; + default: + sb.append(ch); + break; + } + } + else if (ch >= 0xd800 && ch <= 0xdfff) { + // surrogates + escapeChar(sb, ch); + } + else { + sb.append(ch); + } + } + sb.append("\""); + } + + private static final char[] HEX_TABLE = "0123456789ABCDEF".toCharArray(); + + private static void escapeChar(StringBuilder sb, int ch) { + sb.append("\\u"); + sb.append(HEX_TABLE[(ch >> 12) & 0x0f]); + sb.append(HEX_TABLE[(ch >> 8) & 0x0f]); + sb.append(HEX_TABLE[(ch >> 4) & 0x0f]); + sb.append(HEX_TABLE[ch & 0x0f]); + } +} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/AbstractImmutableValue.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/AbstractImmutableValue.java new file mode 100644 index 0000000..88814d8 --- /dev/null +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/AbstractImmutableValue.java @@ -0,0 +1,156 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.serialize.format.value.impl; + +import infra.cloud.serialize.format.MessageTypeCastException; +import infra.cloud.serialize.format.value.ImmutableArrayValue; +import infra.cloud.serialize.format.value.ImmutableBinaryValue; +import infra.cloud.serialize.format.value.ImmutableBooleanValue; +import infra.cloud.serialize.format.value.ImmutableExtensionValue; +import infra.cloud.serialize.format.value.ImmutableFloatValue; +import infra.cloud.serialize.format.value.ImmutableIntegerValue; +import infra.cloud.serialize.format.value.ImmutableMapValue; +import infra.cloud.serialize.format.value.ImmutableNilValue; +import infra.cloud.serialize.format.value.ImmutableNumberValue; +import infra.cloud.serialize.format.value.ImmutableRawValue; +import infra.cloud.serialize.format.value.ImmutableStringValue; +import infra.cloud.serialize.format.value.ImmutableTimestampValue; +import infra.cloud.serialize.format.value.ImmutableValue; + +abstract class AbstractImmutableValue implements ImmutableValue { + + @Override + public boolean isNilValue() { + return getValueType().isNilType(); + } + + @Override + public boolean isBooleanValue() { + return getValueType().isBooleanType(); + } + + @Override + public boolean isNumberValue() { + return getValueType().isNumberType(); + } + + @Override + public boolean isIntegerValue() { + return getValueType().isIntegerType(); + } + + @Override + public boolean isFloatValue() { + return getValueType().isFloatType(); + } + + @Override + public boolean isRawValue() { + return getValueType().isRawType(); + } + + @Override + public boolean isBinaryValue() { + return getValueType().isBinaryType(); + } + + @Override + public boolean isStringValue() { + return getValueType().isStringType(); + } + + @Override + public boolean isArrayValue() { + return getValueType().isArrayType(); + } + + @Override + public boolean isMapValue() { + return getValueType().isMapType(); + } + + @Override + public boolean isExtensionValue() { + return getValueType().isExtensionType(); + } + + @Override + public boolean isTimestampValue() { + return false; + } + + @Override + public ImmutableNilValue asNilValue() { + throw new MessageTypeCastException(); + } + + @Override + public ImmutableBooleanValue asBooleanValue() { + throw new MessageTypeCastException(); + } + + @Override + public ImmutableNumberValue asNumberValue() { + throw new MessageTypeCastException(); + } + + @Override + public ImmutableIntegerValue asIntegerValue() { + throw new MessageTypeCastException(); + } + + @Override + public ImmutableFloatValue asFloatValue() { + throw new MessageTypeCastException(); + } + + @Override + public ImmutableRawValue asRawValue() { + throw new MessageTypeCastException(); + } + + @Override + public ImmutableBinaryValue asBinaryValue() { + throw new MessageTypeCastException(); + } + + @Override + public ImmutableStringValue asStringValue() { + throw new MessageTypeCastException(); + } + + @Override + public ImmutableArrayValue asArrayValue() { + throw new MessageTypeCastException(); + } + + @Override + public ImmutableMapValue asMapValue() { + throw new MessageTypeCastException(); + } + + @Override + public ImmutableExtensionValue asExtensionValue() { + throw new MessageTypeCastException(); + } + + @Override + public ImmutableTimestampValue asTimestampValue() { + throw new MessageTypeCastException(); + } +} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableArrayValueImpl.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableArrayValueImpl.java new file mode 100644 index 0000000..0732f7e --- /dev/null +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableArrayValueImpl.java @@ -0,0 +1,240 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.serialize.format.value.impl; + +import java.io.IOException; +import java.util.AbstractList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; +import java.util.NoSuchElementException; + +import infra.cloud.serialize.format.MessagePacker; +import infra.cloud.serialize.format.value.ArrayValue; +import infra.cloud.serialize.format.value.ImmutableArrayValue; +import infra.cloud.serialize.format.value.IntegerValue; +import infra.cloud.serialize.format.value.Value; +import infra.cloud.serialize.format.value.ValueType; + +/** + * {@code ImmutableArrayValueImpl} Implements {@code ImmutableArrayValue} using a {@code Value[]} field. + * + * @see IntegerValue + */ +public class ImmutableArrayValueImpl + extends AbstractImmutableValue + implements ImmutableArrayValue { + private static final ImmutableArrayValueImpl EMPTY = new ImmutableArrayValueImpl(new Value[0]); + + public static ImmutableArrayValue empty() { + return EMPTY; + } + + private final Value[] array; + + public ImmutableArrayValueImpl(Value[] array) { + this.array = array; + } + + @Override + public ValueType getValueType() { + return ValueType.ARRAY; + } + + @Override + public ImmutableArrayValue immutableValue() { + return this; + } + + @Override + public ImmutableArrayValue asArrayValue() { + return this; + } + + @Override + public int size() { + return array.length; + } + + @Override + public Value get(int index) { + return array[index]; + } + + @Override + public Value getOrNilValue(int index) { + if (index < array.length && index >= 0) { + return array[index]; + } + return ImmutableNilValueImpl.get(); + } + + @Override + public Iterator iterator() { + return new Ite(array); + } + + @Override + public List list() { + return new ImmutableArrayValueList(array); + } + + @Override + public void writeTo(MessagePacker pk) + throws IOException { + pk.packArrayHeader(array.length); + for (int i = 0; i < array.length; i++) { + array[i].writeTo(pk); + } + } + + @Override + public boolean equals(Object o) { + if (o == this) { + return true; + } + if (!(o instanceof Value)) { + return false; + } + Value v = (Value) o; + + if (v instanceof ImmutableArrayValueImpl) { + ImmutableArrayValueImpl oa = (ImmutableArrayValueImpl) v; + return Arrays.equals(array, oa.array); + } + else { + if (!v.isArrayValue()) { + return false; + } + ArrayValue av = v.asArrayValue(); + if (size() != av.size()) { + return false; + } + Iterator oi = av.iterator(); + int i = 0; + while (i < array.length) { + if (!oi.hasNext() || !array[i].equals(oi.next())) { + return false; + } + i++; + } + return true; + } + } + + @Override + public int hashCode() { + int h = 1; + for (int i = 0; i < array.length; i++) { + Value obj = array[i]; + h = 31 * h + obj.hashCode(); + } + return h; + } + + @Override + public String toJson() { + if (array.length == 0) { + return "[]"; + } + StringBuilder sb = new StringBuilder(); + sb.append("["); + sb.append(array[0].toJson()); + for (int i = 1; i < array.length; i++) { + sb.append(","); + sb.append(array[i].toJson()); + } + sb.append("]"); + return sb.toString(); + } + + @Override + public String toString() { + if (array.length == 0) { + return "[]"; + } + StringBuilder sb = new StringBuilder(); + sb.append("["); + appendString(sb, array[0]); + for (int i = 1; i < array.length; i++) { + sb.append(","); + appendString(sb, array[i]); + } + sb.append("]"); + return sb.toString(); + } + + private static void appendString(StringBuilder sb, Value value) { + if (value.isRawValue()) { + sb.append(value.toJson()); + } + else { + sb.append(value.toString()); + } + } + + private static class ImmutableArrayValueList + extends AbstractList { + private final Value[] array; + + public ImmutableArrayValueList(Value[] array) { + this.array = array; + } + + @Override + public Value get(int index) { + return array[index]; + } + + @Override + public int size() { + return array.length; + } + } + + private static class Ite + implements Iterator { + private final Value[] array; + private int index; + + public Ite(Value[] array) { + this.array = array; + this.index = 0; + } + + @Override + public boolean hasNext() { + return index != array.length; + } + + @Override + public Value next() { + int i = index; + if (i >= array.length) { + throw new NoSuchElementException(); + } + index = i + 1; + return array[i]; + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + } +} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableBigIntegerValueImpl.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableBigIntegerValueImpl.java new file mode 100644 index 0000000..3cf0f6c --- /dev/null +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableBigIntegerValueImpl.java @@ -0,0 +1,233 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.serialize.format.value.impl; + +import java.io.IOException; +import java.math.BigInteger; + +import infra.cloud.serialize.format.MessageFormat; +import infra.cloud.serialize.format.MessageIntegerOverflowException; +import infra.cloud.serialize.format.MessagePacker; +import infra.cloud.serialize.format.value.ImmutableIntegerValue; +import infra.cloud.serialize.format.value.ImmutableNumberValue; +import infra.cloud.serialize.format.value.IntegerValue; +import infra.cloud.serialize.format.value.Value; +import infra.cloud.serialize.format.value.ValueType; + +/** + * {@code ImmutableBigIntegerValueImpl} Implements {@code ImmutableBigIntegerValue} using a {@code BigInteger} field. + * + * @see IntegerValue + */ +public class ImmutableBigIntegerValueImpl extends AbstractImmutableValue implements ImmutableIntegerValue { + + public static MessageFormat mostSuccinctMessageFormat(IntegerValue v) { + if (v.isInByteRange()) { + return MessageFormat.INT8; + } + else if (v.isInShortRange()) { + return MessageFormat.INT16; + } + else if (v.isInIntRange()) { + return MessageFormat.INT32; + } + else if (v.isInLongRange()) { + return MessageFormat.INT64; + } + else { + return MessageFormat.UINT64; + } + } + + private final BigInteger value; + + public ImmutableBigIntegerValueImpl(BigInteger value) { + this.value = value; + } + + private static final BigInteger BYTE_MIN = BigInteger.valueOf(Byte.MIN_VALUE); + private static final BigInteger BYTE_MAX = BigInteger.valueOf(Byte.MAX_VALUE); + private static final BigInteger SHORT_MIN = BigInteger.valueOf(Short.MIN_VALUE); + private static final BigInteger SHORT_MAX = BigInteger.valueOf(Short.MAX_VALUE); + private static final BigInteger INT_MIN = BigInteger.valueOf(Integer.MIN_VALUE); + private static final BigInteger INT_MAX = BigInteger.valueOf(Integer.MAX_VALUE); + private static final BigInteger LONG_MIN = BigInteger.valueOf(Long.MIN_VALUE); + private static final BigInteger LONG_MAX = BigInteger.valueOf(Long.MAX_VALUE); + + @Override + public ValueType getValueType() { + return ValueType.INTEGER; + } + + @Override + public ImmutableIntegerValue immutableValue() { + return this; + } + + @Override + public ImmutableNumberValue asNumberValue() { + return this; + } + + @Override + public ImmutableIntegerValue asIntegerValue() { + return this; + } + + @Override + public byte toByte() { + return value.byteValue(); + } + + @Override + public short toShort() { + return value.shortValue(); + } + + @Override + public int toInt() { + return value.intValue(); + } + + @Override + public long toLong() { + return value.longValue(); + } + + @Override + public BigInteger toBigInteger() { + return value; + } + + @Override + public float toFloat() { + return value.floatValue(); + } + + @Override + public double toDouble() { + return value.doubleValue(); + } + + @Override + public boolean isInByteRange() { + return 0 <= value.compareTo(BYTE_MIN) && value.compareTo(BYTE_MAX) <= 0; + } + + @Override + public boolean isInShortRange() { + return 0 <= value.compareTo(SHORT_MIN) && value.compareTo(SHORT_MAX) <= 0; + } + + @Override + public boolean isInIntRange() { + return 0 <= value.compareTo(INT_MIN) && value.compareTo(INT_MAX) <= 0; + } + + @Override + public boolean isInLongRange() { + return 0 <= value.compareTo(LONG_MIN) && value.compareTo(LONG_MAX) <= 0; + } + + @Override + public MessageFormat mostSuccinctMessageFormat() { + return mostSuccinctMessageFormat(this); + } + + @Override + public byte asByte() { + if (!isInByteRange()) { + throw new MessageIntegerOverflowException(value); + } + return value.byteValue(); + } + + @Override + public short asShort() { + if (!isInShortRange()) { + throw new MessageIntegerOverflowException(value); + } + return value.shortValue(); + } + + @Override + public int asInt() { + if (!isInIntRange()) { + throw new MessageIntegerOverflowException(value); + } + return value.intValue(); + } + + @Override + public long asLong() { + if (!isInLongRange()) { + throw new MessageIntegerOverflowException(value); + } + return value.longValue(); + } + + @Override + public BigInteger asBigInteger() { + return value; + } + + @Override + public void writeTo(MessagePacker pk) + throws IOException { + pk.packBigInteger(value); + } + + @Override + public boolean equals(Object o) { + if (o == this) { + return true; + } + if (!(o instanceof Value v)) { + return false; + } + + if (!v.isIntegerValue()) { + return false; + } + IntegerValue iv = v.asIntegerValue(); + return value.equals(iv.toBigInteger()); + } + + @Override + public int hashCode() { + if (INT_MIN.compareTo(value) <= 0 && value.compareTo(INT_MAX) <= 0) { + return (int) value.longValue(); + } + else if (LONG_MIN.compareTo(value) <= 0 + && value.compareTo(LONG_MAX) <= 0) { + long v = value.longValue(); + return (int) (v ^ (v >>> 32)); + } + return value.hashCode(); + } + + @Override + public String toJson() { + return value.toString(); + } + + @Override + public String toString() { + return toJson(); + } +} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableBinaryValueImpl.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableBinaryValueImpl.java new file mode 100644 index 0000000..c36cedf --- /dev/null +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableBinaryValueImpl.java @@ -0,0 +1,90 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.serialize.format.value.impl; + +import java.io.IOException; +import java.util.Arrays; + +import infra.cloud.serialize.format.MessagePacker; +import infra.cloud.serialize.format.value.ImmutableBinaryValue; +import infra.cloud.serialize.format.value.StringValue; +import infra.cloud.serialize.format.value.Value; +import infra.cloud.serialize.format.value.ValueType; + +/** + * {@code ImmutableBinaryValueImpl} Implements {@code ImmutableBinaryValue} using a {@code byte[]} field. + * This implementation caches result of {@code toString()} and {@code asString()} using a private {@code String} field. + * + * @see StringValue + */ +public class ImmutableBinaryValueImpl + extends AbstractImmutableRawValue + implements ImmutableBinaryValue { + public ImmutableBinaryValueImpl(byte[] data) { + super(data); + } + + @Override + public ValueType getValueType() { + return ValueType.BINARY; + } + + @Override + public ImmutableBinaryValue immutableValue() { + return this; + } + + @Override + public ImmutableBinaryValue asBinaryValue() { + return this; + } + + @Override + public void writeTo(MessagePacker pk) + throws IOException { + pk.packBinaryHeader(data.length); + pk.writePayload(data); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof Value)) { + return false; + } + Value v = (Value) o; + if (!v.isBinaryValue()) { + return false; + } + + if (v instanceof ImmutableBinaryValueImpl) { + ImmutableBinaryValueImpl bv = (ImmutableBinaryValueImpl) v; + return Arrays.equals(data, bv.data); + } + else { + return Arrays.equals(data, v.asBinaryValue().asByteArray()); + } + } + + @Override + public int hashCode() { + return Arrays.hashCode(data); + } +} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableBooleanValueImpl.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableBooleanValueImpl.java new file mode 100644 index 0000000..ed4e4e3 --- /dev/null +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableBooleanValueImpl.java @@ -0,0 +1,108 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.serialize.format.value.impl; + +import java.io.IOException; + +import infra.cloud.serialize.format.MessagePacker; +import infra.cloud.serialize.format.value.BooleanValue; +import infra.cloud.serialize.format.value.ImmutableBooleanValue; +import infra.cloud.serialize.format.value.Value; +import infra.cloud.serialize.format.value.ValueType; + +/** + * {@code ImmutableBooleanValueImpl} Implements {@code ImmutableBooleanValue} using a {@code boolean} field. + * + * This class is a singleton. {@code ImmutableBooleanValueImpl.trueInstance()} and {@code ImmutableBooleanValueImpl.falseInstance()} are the only instances of this class. + * + * @see BooleanValue + */ +public class ImmutableBooleanValueImpl + extends AbstractImmutableValue + implements ImmutableBooleanValue { + public static final ImmutableBooleanValue TRUE = new ImmutableBooleanValueImpl(true); + public static final ImmutableBooleanValue FALSE = new ImmutableBooleanValueImpl(false); + + private final boolean value; + + private ImmutableBooleanValueImpl(boolean value) { + this.value = value; + } + + @Override + public ValueType getValueType() { + return ValueType.BOOLEAN; + } + + @Override + public ImmutableBooleanValue asBooleanValue() { + return this; + } + + @Override + public ImmutableBooleanValue immutableValue() { + return this; + } + + @Override + public boolean getBoolean() { + return value; + } + + @Override + public void writeTo(MessagePacker packer) + throws IOException { + packer.packBoolean(value); + } + + @Override + public boolean equals(Object o) { + if (o == this) { + return true; + } + if (!(o instanceof Value)) { + return false; + } + Value v = (Value) o; + + if (!v.isBooleanValue()) { + return false; + } + return value == v.asBooleanValue().getBoolean(); + } + + @Override + public int hashCode() { + if (value) { + return 1231; + } + else { + return 1237; + } + } + + @Override + public String toJson() { + return Boolean.toString(value); + } + + @Override + public String toString() { + return toJson(); + } +} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableDoubleValueImpl.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableDoubleValueImpl.java new file mode 100644 index 0000000..f54015f --- /dev/null +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableDoubleValueImpl.java @@ -0,0 +1,141 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.serialize.format.value.impl; + +import java.io.IOException; +import java.math.BigDecimal; +import java.math.BigInteger; + +import infra.cloud.serialize.format.MessagePacker; +import infra.cloud.serialize.format.value.FloatValue; +import infra.cloud.serialize.format.value.ImmutableFloatValue; +import infra.cloud.serialize.format.value.ImmutableNumberValue; +import infra.cloud.serialize.format.value.Value; +import infra.cloud.serialize.format.value.ValueType; + +/** + * {@code ImmutableDoubleValueImpl} Implements {@code ImmutableFloatValue} using a {@code double} field. + * + * @see FloatValue + */ +public class ImmutableDoubleValueImpl extends AbstractImmutableValue implements ImmutableFloatValue { + + private final double value; + + public ImmutableDoubleValueImpl(double value) { + this.value = value; + } + + @Override + public ValueType getValueType() { + return ValueType.FLOAT; + } + + @Override + public ImmutableDoubleValueImpl immutableValue() { + return this; + } + + @Override + public ImmutableNumberValue asNumberValue() { + return this; + } + + @Override + public ImmutableFloatValue asFloatValue() { + return this; + } + + @Override + public byte toByte() { + return (byte) value; + } + + @Override + public short toShort() { + return (short) value; + } + + @Override + public int toInt() { + return (int) value; + } + + @Override + public long toLong() { + return (long) value; + } + + @Override + public BigInteger toBigInteger() { + return new BigDecimal(value).toBigInteger(); + } + + @Override + public float toFloat() { + return (float) value; + } + + @Override + public double toDouble() { + return value; + } + + @Override + public void writeTo(MessagePacker pk) + throws IOException { + pk.packDouble(value); + } + + @Override + public boolean equals(Object o) { + if (o == this) { + return true; + } + if (!(o instanceof Value)) { + return false; + } + Value v = (Value) o; + + if (!v.isFloatValue()) { + return false; + } + return value == v.asFloatValue().toDouble(); + } + + @Override + public int hashCode() { + long v = Double.doubleToLongBits(value); + return (int) (v ^ (v >>> 32)); + } + + @Override + public String toJson() { + if (Double.isNaN(value) || Double.isInfinite(value)) { + return "null"; + } + else { + return Double.toString(value); + } + } + + @Override + public String toString() { + return Double.toString(value); + } +} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableExtensionValueImpl.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableExtensionValueImpl.java new file mode 100644 index 0000000..c361f18 --- /dev/null +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableExtensionValueImpl.java @@ -0,0 +1,128 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.serialize.format.value.impl; + +import java.io.IOException; +import java.util.Arrays; + +import infra.cloud.serialize.format.MessagePacker; +import infra.cloud.serialize.format.value.ExtensionValue; +import infra.cloud.serialize.format.value.ImmutableExtensionValue; +import infra.cloud.serialize.format.value.Value; +import infra.cloud.serialize.format.value.ValueType; + +/** + * {@code ImmutableExtensionValueImpl} Implements {@code ImmutableExtensionValue} using a {@code byte} and a {@code byte[]} fields. + * + * @see ExtensionValue + */ +public class ImmutableExtensionValueImpl + extends AbstractImmutableValue + implements ImmutableExtensionValue { + private final byte type; + private final byte[] data; + + public ImmutableExtensionValueImpl(byte type, byte[] data) { + this.type = type; + this.data = data; + } + + @Override + public ValueType getValueType() { + return ValueType.EXTENSION; + } + + @Override + public ImmutableExtensionValue immutableValue() { + return this; + } + + @Override + public ImmutableExtensionValue asExtensionValue() { + return this; + } + + @Override + public byte getType() { + return type; + } + + @Override + public byte[] getData() { + return data; + } + + @Override + public void writeTo(MessagePacker packer) + throws IOException { + packer.packExtensionTypeHeader(type, data.length); + packer.writePayload(data); + } + + @Override + public boolean equals(Object o) { + if (o == this) { + return true; + } + if (!(o instanceof Value)) { + return false; + } + Value v = (Value) o; + + if (!v.isExtensionValue()) { + return false; + } + ExtensionValue ev = v.asExtensionValue(); + return type == ev.getType() && Arrays.equals(data, ev.getData()); + } + + @Override + public int hashCode() { + int hash = 31 + type; + for (byte e : data) { + hash = 31 * hash + e; + } + return hash; + } + + @Override + public String toJson() { + StringBuilder sb = new StringBuilder(); + sb.append('['); + sb.append(Byte.toString(type)); + sb.append(",\""); + for (byte e : data) { + sb.append(Integer.toString((int) e, 16)); + } + sb.append("\"]"); + return sb.toString(); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append('('); + sb.append(Byte.toString(type)); + sb.append(",0x"); + for (byte e : data) { + sb.append(Integer.toString((int) e, 16)); + } + sb.append(")"); + return sb.toString(); + } +} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableLongValueImpl.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableLongValueImpl.java new file mode 100644 index 0000000..ceadc61 --- /dev/null +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableLongValueImpl.java @@ -0,0 +1,212 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.serialize.format.value.impl; + +import java.io.IOException; +import java.math.BigInteger; + +import infra.cloud.serialize.format.MessageFormat; +import infra.cloud.serialize.format.MessageIntegerOverflowException; +import infra.cloud.serialize.format.MessagePacker; +import infra.cloud.serialize.format.value.ImmutableIntegerValue; +import infra.cloud.serialize.format.value.ImmutableNumberValue; +import infra.cloud.serialize.format.value.IntegerValue; +import infra.cloud.serialize.format.value.Value; +import infra.cloud.serialize.format.value.ValueType; + +/** + * {@code ImmutableLongValueImpl} Implements {@code ImmutableIntegerValue} using a {@code long} field. + * + * @see IntegerValue + */ +public class ImmutableLongValueImpl + extends AbstractImmutableValue + implements ImmutableIntegerValue { + private final long value; + + public ImmutableLongValueImpl(long value) { + this.value = value; + } + + private static final long BYTE_MIN = (long) Byte.MIN_VALUE; + private static final long BYTE_MAX = (long) Byte.MAX_VALUE; + private static final long SHORT_MIN = (long) Short.MIN_VALUE; + private static final long SHORT_MAX = (long) Short.MAX_VALUE; + private static final long INT_MIN = (long) Integer.MIN_VALUE; + private static final long INT_MAX = (long) Integer.MAX_VALUE; + + @Override + public ValueType getValueType() { + return ValueType.INTEGER; + } + + @Override + public ImmutableIntegerValue immutableValue() { + return this; + } + + @Override + public ImmutableNumberValue asNumberValue() { + return this; + } + + @Override + public ImmutableIntegerValue asIntegerValue() { + return this; + } + + @Override + public byte toByte() { + return (byte) value; + } + + @Override + public short toShort() { + return (short) value; + } + + @Override + public int toInt() { + return (int) value; + } + + @Override + public long toLong() { + return value; + } + + @Override + public BigInteger toBigInteger() { + return BigInteger.valueOf(value); + } + + @Override + public float toFloat() { + return (float) value; + } + + @Override + public double toDouble() { + return (double) value; + } + + @Override + public boolean isInByteRange() { + return BYTE_MIN <= value && value <= BYTE_MAX; + } + + @Override + public boolean isInShortRange() { + return SHORT_MIN <= value && value <= SHORT_MAX; + } + + @Override + public boolean isInIntRange() { + return INT_MIN <= value && value <= INT_MAX; + } + + @Override + public boolean isInLongRange() { + return true; + } + + @Override + public MessageFormat mostSuccinctMessageFormat() { + return ImmutableBigIntegerValueImpl.mostSuccinctMessageFormat(this); + } + + @Override + public byte asByte() { + if (!isInByteRange()) { + throw new MessageIntegerOverflowException(value); + } + return (byte) value; + } + + @Override + public short asShort() { + if (!isInShortRange()) { + throw new MessageIntegerOverflowException(value); + } + return (short) value; + } + + @Override + public int asInt() { + if (!isInIntRange()) { + throw new MessageIntegerOverflowException(value); + } + return (int) value; + } + + @Override + public long asLong() { + return value; + } + + @Override + public BigInteger asBigInteger() { + return BigInteger.valueOf(value); + } + + @Override + public void writeTo(MessagePacker pk) + throws IOException { + pk.packLong(value); + } + + @Override + public boolean equals(Object o) { + if (o == this) { + return true; + } + if (!(o instanceof Value)) { + return false; + } + Value v = (Value) o; + if (!v.isIntegerValue()) { + return false; + } + + IntegerValue iv = v.asIntegerValue(); + if (!iv.isInLongRange()) { + return false; + } + return value == iv.toLong(); + } + + @Override + public int hashCode() { + if (INT_MIN <= value && value <= INT_MAX) { + return (int) value; + } + else { + return (int) (value ^ (value >>> 32)); + } + } + + @Override + public String toJson() { + return Long.toString(value); + } + + @Override + public String toString() { + return toJson(); + } +} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableMapValueImpl.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableMapValueImpl.java new file mode 100644 index 0000000..2c073a3 --- /dev/null +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableMapValueImpl.java @@ -0,0 +1,331 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.serialize.format.value.impl; + +import java.io.IOException; +import java.util.AbstractCollection; +import java.util.AbstractMap; +import java.util.AbstractSet; +import java.util.Arrays; +import java.util.Collection; +import java.util.Iterator; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.Set; + +import infra.cloud.serialize.format.MessagePacker; +import infra.cloud.serialize.format.value.ImmutableMapValue; +import infra.cloud.serialize.format.value.MapValue; +import infra.cloud.serialize.format.value.Value; +import infra.cloud.serialize.format.value.ValueType; + +/** + * {@code ImmutableMapValueImpl} Implements {@code ImmutableMapValue} using a {@code Value[]} field. + * + * @see MapValue + */ +public class ImmutableMapValueImpl + extends AbstractImmutableValue + implements ImmutableMapValue { + private static final ImmutableMapValueImpl EMPTY = new ImmutableMapValueImpl(new Value[0]); + + public static ImmutableMapValue empty() { + return EMPTY; + } + + private final Value[] kvs; + + public ImmutableMapValueImpl(Value[] kvs) { + this.kvs = kvs; + } + + @Override + public ValueType getValueType() { + return ValueType.MAP; + } + + @Override + public ImmutableMapValue immutableValue() { + return this; + } + + @Override + public ImmutableMapValue asMapValue() { + return this; + } + + @Override + public Value[] getKeyValueArray() { + return Arrays.copyOf(kvs, kvs.length); + } + + @Override + public int size() { + return kvs.length / 2; + } + + @Override + public Set keySet() { + return new KeySet(kvs); + } + + @Override + public Set> entrySet() { + return new EntrySet(kvs); + } + + @Override + public Collection values() { + return new ValueCollection(kvs); + } + + @Override + public Map map() { + return new ImmutableMapValueMap(kvs); + } + + @Override + public void writeTo(MessagePacker pk) + throws IOException { + pk.packMapHeader(kvs.length / 2); + for (int i = 0; i < kvs.length; i++) { + kvs[i].writeTo(pk); + } + } + + @Override + public boolean equals(Object o) { + if (o == this) { + return true; + } + if (!(o instanceof Value)) { + return false; + } + Value v = (Value) o; + + if (!v.isMapValue()) { + return false; + } + MapValue mv = v.asMapValue(); + return map().equals(mv.map()); + } + + @Override + public int hashCode() { + int h = 0; + for (int i = 0; i < kvs.length; i += 2) { + h += kvs[i].hashCode() ^ kvs[i + 1].hashCode(); + } + return h; + } + + @Override + public String toJson() { + if (kvs.length == 0) { + return "{}"; + } + StringBuilder sb = new StringBuilder(); + sb.append("{"); + appendJsonKey(sb, kvs[0]); + sb.append(":"); + sb.append(kvs[1].toJson()); + for (int i = 2; i < kvs.length; i += 2) { + sb.append(","); + appendJsonKey(sb, kvs[i]); + sb.append(":"); + sb.append(kvs[i + 1].toJson()); + } + sb.append("}"); + return sb.toString(); + } + + private static void appendJsonKey(StringBuilder sb, Value key) { + if (key.isRawValue()) { + sb.append(key.toJson()); + } + else { + ImmutableStringValueImpl.appendJsonString(sb, key.toString()); + } + } + + @Override + public String toString() { + if (kvs.length == 0) { + return "{}"; + } + StringBuilder sb = new StringBuilder(); + sb.append("{"); + appendString(sb, kvs[0]); + sb.append(":"); + appendString(sb, kvs[1]); + for (int i = 2; i < kvs.length; i += 2) { + sb.append(","); + appendString(sb, kvs[i]); + sb.append(":"); + appendString(sb, kvs[i + 1]); + } + sb.append("}"); + return sb.toString(); + } + + private static void appendString(StringBuilder sb, Value value) { + if (value.isRawValue()) { + sb.append(value.toJson()); + } + else { + sb.append(value.toString()); + } + } + + private static class ImmutableMapValueMap + extends AbstractMap { + private final Value[] kvs; + + public ImmutableMapValueMap(Value[] kvs) { + this.kvs = kvs; + } + + @Override + public Set> entrySet() { + return new EntrySet(kvs); + } + } + + private static class EntrySet + extends AbstractSet> { + private final Value[] kvs; + + EntrySet(Value[] kvs) { + this.kvs = kvs; + } + + @Override + public int size() { + return kvs.length / 2; + } + + @Override + public Iterator> iterator() { + return new EntrySetIterator(kvs); + } + } + + private static class EntrySetIterator + implements Iterator> { + private final Value[] kvs; + private int index; + + EntrySetIterator(Value[] kvs) { + this.kvs = kvs; + this.index = 0; + } + + @Override + public boolean hasNext() { + return index < kvs.length; + } + + @Override + public Map.Entry next() { + if (index >= kvs.length) { + throw new NoSuchElementException(); // TODO message + } + + Value key = kvs[index]; + Value value = kvs[index + 1]; + Map.Entry pair = new AbstractMap.SimpleImmutableEntry(key, value); + + index += 2; + return pair; + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); // TODO message + } + } + + private static class KeySet + extends AbstractSet { + private Value[] kvs; + + KeySet(Value[] kvs) { + this.kvs = kvs; + } + + @Override + public int size() { + return kvs.length / 2; + } + + @Override + public Iterator iterator() { + return new EntryIterator(kvs, 0); + } + } + + private static class ValueCollection + extends AbstractCollection { + private Value[] kvs; + + ValueCollection(Value[] kvs) { + this.kvs = kvs; + } + + @Override + public int size() { + return kvs.length / 2; + } + + @Override + public Iterator iterator() { + return new EntryIterator(kvs, 1); + } + } + + private static class EntryIterator + implements Iterator { + private Value[] kvs; + private int index; + + public EntryIterator(Value[] kvs, int offset) { + this.kvs = kvs; + this.index = offset; + } + + @Override + public boolean hasNext() { + return index < kvs.length; + } + + @Override + public Value next() { + int i = index; + if (i >= kvs.length) { + throw new NoSuchElementException(); + } + index = i + 2; + return kvs[i]; + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + } +} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableNilValueImpl.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableNilValueImpl.java new file mode 100644 index 0000000..c13a2f7 --- /dev/null +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableNilValueImpl.java @@ -0,0 +1,92 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.serialize.format.value.impl; + +import java.io.IOException; + +import infra.cloud.serialize.format.MessagePacker; +import infra.cloud.serialize.format.value.ImmutableNilValue; +import infra.cloud.serialize.format.value.NilValue; +import infra.cloud.serialize.format.value.Value; +import infra.cloud.serialize.format.value.ValueType; + +/** + * {@code ImmutableNilValueImpl} Implements {@code ImmutableNilValue}. + *

          + * This class is a singleton. {@code ImmutableNilValueImpl.get()} is the only instances of this class. + * + * @see NilValue + */ +public class ImmutableNilValueImpl extends AbstractImmutableValue implements ImmutableNilValue { + + private static ImmutableNilValue instance = new ImmutableNilValueImpl(); + + public static ImmutableNilValue get() { + return instance; + } + + private ImmutableNilValueImpl() { + } + + @Override + public ValueType getValueType() { + return ValueType.NIL; + } + + @Override + public ImmutableNilValue immutableValue() { + return this; + } + + @Override + public ImmutableNilValue asNilValue() { + return this; + } + + @Override + public void writeTo(MessagePacker pk) + throws IOException { + pk.packNil(); + } + + @Override + public boolean equals(Object o) { + if (o == this) { + return true; + } + if (!(o instanceof Value)) { + return false; + } + return ((Value) o).isNilValue(); + } + + @Override + public int hashCode() { + return 0; + } + + @Override + public String toString() { + return toJson(); + } + + @Override + public String toJson() { + return "null"; + } +} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableStringValueImpl.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableStringValueImpl.java new file mode 100644 index 0000000..483baeb --- /dev/null +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableStringValueImpl.java @@ -0,0 +1,94 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.serialize.format.value.impl; + +import java.io.IOException; +import java.util.Arrays; + +import infra.cloud.serialize.format.MessagePacker; +import infra.cloud.serialize.format.value.ImmutableStringValue; +import infra.cloud.serialize.format.value.StringValue; +import infra.cloud.serialize.format.value.Value; +import infra.cloud.serialize.format.value.ValueType; + +/** + * {@code ImmutableStringValueImpl} Implements {@code ImmutableStringValue} using a {@code byte[]} field. + * This implementation caches result of {@code toString()} and {@code asString()} using a private {@code String} field. + * + * @see StringValue + */ +public class ImmutableStringValueImpl + extends AbstractImmutableRawValue + implements ImmutableStringValue { + public ImmutableStringValueImpl(byte[] data) { + super(data); + } + + public ImmutableStringValueImpl(String string) { + super(string); + } + + @Override + public ValueType getValueType() { + return ValueType.STRING; + } + + @Override + public ImmutableStringValue immutableValue() { + return this; + } + + @Override + public ImmutableStringValue asStringValue() { + return this; + } + + @Override + public void writeTo(MessagePacker pk) + throws IOException { + pk.packRawStringHeader(data.length); + pk.writePayload(data); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof Value)) { + return false; + } + Value v = (Value) o; + if (!v.isStringValue()) { + return false; + } + + if (v instanceof ImmutableStringValueImpl) { + ImmutableStringValueImpl bv = (ImmutableStringValueImpl) v; + return Arrays.equals(data, bv.data); + } + else { + return Arrays.equals(data, v.asStringValue().asByteArray()); + } + } + + @Override + public int hashCode() { + return Arrays.hashCode(data); + } +} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableTimestampValueImpl.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableTimestampValueImpl.java new file mode 100644 index 0000000..3d66eaa --- /dev/null +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableTimestampValueImpl.java @@ -0,0 +1,182 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.serialize.format.value.impl; + +import java.io.IOException; +import java.time.Instant; +import java.util.Arrays; + +import infra.cloud.serialize.format.MessagePacker; +import infra.cloud.serialize.format.buffer.MessageBuffer; +import infra.cloud.serialize.format.value.ExtensionValue; +import infra.cloud.serialize.format.value.ImmutableExtensionValue; +import infra.cloud.serialize.format.value.ImmutableTimestampValue; +import infra.cloud.serialize.format.value.TimestampValue; +import infra.cloud.serialize.format.value.Value; +import infra.cloud.serialize.format.value.ValueType; + +import static infra.cloud.serialize.format.MessagePack.Code.EXT_TIMESTAMP; + +/** + * {@code ImmutableTimestampValueImpl} Implements {@code ImmutableTimestampValue} using a {@code byte} and a {@code byte[]} fields. + * + * @see TimestampValue + */ +public class ImmutableTimestampValueImpl + extends AbstractImmutableValue + implements ImmutableExtensionValue, ImmutableTimestampValue { + private final Instant instant; + private byte[] data; + + public ImmutableTimestampValueImpl(Instant timestamp) { + this.instant = timestamp; + } + + @Override + public boolean isTimestampValue() { + return true; + } + + @Override + public byte getType() { + return EXT_TIMESTAMP; + } + + @Override + public ValueType getValueType() { + // Note: Future version should return ValueType.TIMESTAMP instead. + return ValueType.EXTENSION; + } + + @Override + public ImmutableTimestampValue immutableValue() { + return this; + } + + @Override + public ImmutableExtensionValue asExtensionValue() { + return this; + } + + @Override + public ImmutableTimestampValue asTimestampValue() { + return this; + } + + @Override + public byte[] getData() { + if (data == null) { + // See MessagePacker.packTimestampImpl + byte[] bytes; + long sec = getEpochSecond(); + int nsec = getNano(); + if (sec >>> 34 == 0) { + long data64 = ((long) nsec << 34) | sec; + if ((data64 & 0xffffffff00000000L) == 0L) { + bytes = new byte[4]; + MessageBuffer.wrap(bytes).putInt(0, (int) sec); + } + else { + bytes = new byte[8]; + MessageBuffer.wrap(bytes).putLong(0, data64); + } + } + else { + bytes = new byte[12]; + MessageBuffer buffer = MessageBuffer.wrap(bytes); + buffer.putInt(0, nsec); + buffer.putLong(4, sec); + } + data = bytes; + } + return data; + } + + @Override + public long getEpochSecond() { + return instant.getEpochSecond(); + } + + @Override + public int getNano() { + return instant.getNano(); + } + + @Override + public long toEpochMillis() { + return instant.toEpochMilli(); + } + + @Override + public Instant toInstant() { + return instant; + } + + @Override + public void writeTo(MessagePacker packer) + throws IOException { + packer.packTimestamp(instant); + } + + @Override + public boolean equals(Object o) { + // Implements same behavior with ImmutableExtensionValueImpl. + if (o == this) { + return true; + } + if (!(o instanceof Value)) { + return false; + } + Value v = (Value) o; + + if (!v.isExtensionValue()) { + return false; + } + ExtensionValue ev = v.asExtensionValue(); + + // Here should use isTimestampValue and asTimestampValue instead. However, because + // adding these methods to Value interface can't keep backward compatibility without + // using "default" keyword since Java 7, here uses instanceof of and cast instead. + if (ev instanceof TimestampValue) { + TimestampValue tv = (TimestampValue) ev; + return instant.equals(tv.toInstant()); + } + else { + return EXT_TIMESTAMP == ev.getType() && Arrays.equals(getData(), ev.getData()); + } + } + + @Override + public int hashCode() { + // Implements same behavior with ImmutableExtensionValueImpl. + int hash = EXT_TIMESTAMP; + hash *= 31; + hash = instant.hashCode(); + return hash; + } + + @Override + public String toJson() { + return "\"" + toInstant().toString() + "\""; + } + + @Override + public String toString() { + return toInstant().toString(); + } +} diff --git a/today-service-serialization/src/test/java/infra/cloud/serialize/MessageTests.java b/today-service-serialization/src/test/java/infra/cloud/serialize/MessageTests.java new file mode 100644 index 0000000..1e66087 --- /dev/null +++ b/today-service-serialization/src/test/java/infra/cloud/serialize/MessageTests.java @@ -0,0 +1,81 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.serialize; + +import org.junit.jupiter.api.Test; + +import java.io.Serializable; + +/** + * @author 海子 Yang + * @since 1.0 2025/8/16 23:46 + */ +class MessageTests { + + @Test + void test() { + User user = new User("1", 2); + +// user.write(); + + } + + static class User implements Message, Serializable { + private String name; + + private int age; + + public User() { + } + + public User(String name, int age) { + this.name = name; + this.age = age; + } + + public int getAge() { + return age; + } + + public String getName() { + return name; + } + + public void setAge(int age) { + this.age = age; + } + + public void setName(String name) { + this.name = name; + } + + @Override + public void writeTo(Output output) { + output.write(name); + output.write(age); + } + + @Override + public void readFrom(Input input) { + this.name = input.readString(); + this.age = input.readInt(); + } + + } + +} \ No newline at end of file From 317e859263a0c62a9a4d404f737f6632ffc51692 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Tue, 19 Aug 2025 21:55:30 +0800 Subject: [PATCH 043/104] =?UTF-8?q?:sparkles:=20=E5=BA=8F=E5=88=97?= =?UTF-8?q?=E5=8C=96=20API=20=E5=87=86=E5=A4=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cloud/serialize/DefaultByteBufInput.java | 67 +- .../cloud/serialize/DefaultByteBufOutput.java | 85 ++- .../cloud/serialize/MessagePackInput.java | 659 ++++++++++++++++++ .../cloud/serialize/MessagePackOutput.java | 526 ++++++++++++++ .../java/infra/cloud/serialize/Input.java | 253 +++---- .../java/infra/cloud/serialize/Output.java | 295 ++++---- .../infra/cloud/serialize/InputTests.java | 57 ++ 7 files changed, 1616 insertions(+), 326 deletions(-) create mode 100644 today-service-api/src/main/java/infra/cloud/serialize/MessagePackInput.java create mode 100644 today-service-api/src/main/java/infra/cloud/serialize/MessagePackOutput.java create mode 100644 today-service-serialization/src/test/java/infra/cloud/serialize/InputTests.java diff --git a/today-service-api/src/main/java/infra/cloud/serialize/DefaultByteBufInput.java b/today-service-api/src/main/java/infra/cloud/serialize/DefaultByteBufInput.java index 97b9ffa..dbbba50 100644 --- a/today-service-api/src/main/java/infra/cloud/serialize/DefaultByteBufInput.java +++ b/today-service-api/src/main/java/infra/cloud/serialize/DefaultByteBufInput.java @@ -18,7 +18,15 @@ package infra.cloud.serialize; import java.nio.charset.StandardCharsets; - +import java.time.Instant; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.function.Supplier; + +import infra.util.CollectionUtils; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; @@ -41,7 +49,7 @@ public void read(byte[] b) { @Override public byte[] read() { - return ByteBufUtil.getBytes(buffer); + return read(buffer.readInt()); } @Override @@ -49,6 +57,16 @@ public void read(byte[] b, int off, int len) { buffer.readBytes(b, off, len); } + @Override + public byte[] read(int len) { + return ByteBufUtil.getBytes(buffer, buffer.readerIndex(), len); + } + + @Override + public byte[] readFully() { + return ByteBufUtil.getBytes(buffer); + } + @Override public int skipBytes(int n) { int start = buffer.readerIndex(); @@ -81,11 +99,6 @@ public int readUnsignedShort() { return buffer.readUnsignedShort(); } - @Override - public char readChar() { - return buffer.readChar(); - } - @Override public int readInt() { return buffer.readInt(); @@ -111,4 +124,44 @@ public String readString() { return buffer.readString(readUnsignedShort(), StandardCharsets.UTF_8); } + @Override + public void read(Message message) { + message.readFrom(this); + } + + @Override + public Instant readTimestamp() { + return Instant.ofEpochSecond(buffer.readLong(), buffer.readInt()); + } + + @Override + public List read(Function mapper) { + int size = readInt(); + ArrayList result = new ArrayList<>(size); + for (int i = 0; i < size; i++) { + result.add(mapper.apply(this)); + } + return result; + } + + @Override + public List read(Supplier supplier) { + int size = readInt(); + ArrayList result = new ArrayList<>(size); + for (int i = 0; i < size; i++) { + result.add(supplier.get()); + } + return result; + } + + @Override + public Map read(Function keyMapper, Function valueMapper) { + int size = readInt(); + LinkedHashMap result = CollectionUtils.newLinkedHashMap(size); + for (int i = 0; i < size; i++) { + result.put(keyMapper.apply(this), valueMapper.apply(this)); + } + return result; + } + } diff --git a/today-service-api/src/main/java/infra/cloud/serialize/DefaultByteBufOutput.java b/today-service-api/src/main/java/infra/cloud/serialize/DefaultByteBufOutput.java index 8fb7476..2491054 100644 --- a/today-service-api/src/main/java/infra/cloud/serialize/DefaultByteBufOutput.java +++ b/today-service-api/src/main/java/infra/cloud/serialize/DefaultByteBufOutput.java @@ -18,7 +18,13 @@ package infra.cloud.serialize; import java.nio.charset.StandardCharsets; +import java.time.Instant; +import java.util.List; +import java.util.Map; +import java.util.function.BiConsumer; +import java.util.function.Consumer; +import infra.lang.Nullable; import io.netty.buffer.ByteBuf; /** @@ -39,12 +45,29 @@ public void write(byte b) { } @Override - public void write(byte[] b) { - buffer.writeBytes(b); + public void write(@Nullable byte[] b) { + if (b == null || b.length == 0) { + buffer.writeInt(0); + } + else { + buffer.writeInt(b.length); + buffer.writeBytes(b); + } } @Override public void write(byte[] b, int off, int len) { + buffer.writeInt(len); + buffer.writeBytes(b, off, len); + } + + @Override + public void writeFully(byte[] b) { + buffer.writeBytes(b); + } + + @Override + public void writeFully(byte[] b, int off, int len) { buffer.writeBytes(b, off, len); } @@ -85,4 +108,62 @@ public void write(String s) { buffer.writeCharSequence(s, StandardCharsets.UTF_8); } + @Override + public void writeTimestamp(long millis) { + write(Instant.ofEpochMilli(millis)); + } + + @Override + public void write(Instant instant) { + writeTimestamp(instant.getEpochSecond(), instant.getNano()); + } + + @Override + public void writeTimestamp(long epochSecond, int nanoAdjustment) throws ArithmeticException { + buffer.writeLong(epochSecond); + buffer.writeInt(nanoAdjustment); + } + + @Override + public void write(Message message) { + message.writeTo(this); + } + + @Override + public void write(List list, Consumer mapper) { + int size = list.size(); + buffer.writeInt(size); + for (T t : list) { + mapper.accept(t); + } + } + + @Override + public void write(List list, BiConsumer mapper) { + int size = list.size(); + buffer.writeInt(size); + for (T t : list) { + mapper.accept(this, t); + } + } + + @Override + public void write(Map map, BiConsumer keyMapper, BiConsumer valueMapper) { + int size = map.size(); + buffer.writeInt(size); + for (Map.Entry entry : map.entrySet()) { + keyMapper.accept(this, entry.getKey()); + valueMapper.accept(this, entry.getValue()); + } + } + + @Override + public void write(Map map, Consumer keyMapper, Consumer valueMapper) { + int size = map.size(); + buffer.writeInt(size); + for (Map.Entry entry : map.entrySet()) { + keyMapper.accept(entry.getKey()); + valueMapper.accept(entry.getValue()); + } + } } diff --git a/today-service-api/src/main/java/infra/cloud/serialize/MessagePackInput.java b/today-service-api/src/main/java/infra/cloud/serialize/MessagePackInput.java new file mode 100644 index 0000000..200656d --- /dev/null +++ b/today-service-api/src/main/java/infra/cloud/serialize/MessagePackInput.java @@ -0,0 +1,659 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.serialize; + +import java.math.BigInteger; +import java.nio.charset.Charset; +import java.time.Instant; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.function.Supplier; + +import infra.cloud.serialize.format.ExtensionTypeHeader; +import infra.cloud.serialize.format.MessageFormat; +import infra.cloud.serialize.format.MessageFormatException; +import infra.cloud.serialize.format.MessageIntegerOverflowException; +import infra.cloud.serialize.format.MessageNeverUsedFormatException; +import infra.cloud.serialize.format.MessagePack.Code; +import infra.cloud.serialize.format.MessagePackException; +import infra.cloud.serialize.format.MessageSizeException; +import infra.cloud.serialize.format.MessageTypeException; +import infra.lang.Constant; +import infra.lang.TodayStrategies; +import infra.util.CollectionUtils; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; + +import static infra.cloud.serialize.format.MessagePack.Code.EXT_TIMESTAMP; + +/** + * Message pack specification input + * + * @author 海子 Yang + * @since 1.0 2025/8/18 14:52 + */ +public class MessagePackInput implements Input { + + private static final int stringSizeLimit = TodayStrategies.getInt( + "infra.cloud.serialize.stringSizeLimit", Integer.MAX_VALUE / 2); + + private static final Charset stringCharset = Charset.forName(TodayStrategies.getProperty( + "infra.cloud.serialize.stringCharset", "UTF-8")); + + private final ByteBuf buffer; + + public MessagePackInput(ByteBuf buffer) { + this.buffer = buffer; + } + + @Override + public byte[] readFully() { + return ByteBufUtil.getBytes(buffer); + } + + @Override + public void read(byte[] b) { + buffer.readBytes(b); + } + + @Override + public byte[] read() { + return read(readBinaryHeader()); + } + + @Override + public byte[] read(int len) { + return ByteBufUtil.getBytes(buffer, buffer.readerIndex(), len); + } + + @Override + public void read(byte[] b, int off, int len) { + buffer.readBytes(b, off, len); + } + + @Override + public void read(Message message) { + message.readFrom(this); + } + + @Override + public int skipBytes(int n) { + int start = buffer.readerIndex(); + buffer.skipBytes(n); + return start - buffer.readerIndex(); + } + + @Override + public boolean readBoolean() { + byte b = buffer.readByte(); + if (b == Code.FALSE) { + return false; + } + else if (b == Code.TRUE) { + return true; + } + throw unexpected("boolean", b); + } + + @Override + public byte readByte() { + byte b = readInt8(); + if (Code.isFixInt(b)) { + return b; + } + switch (b) { + case Code.UINT8: // unsigned int 8 + byte u8 = readInt8(); + if (u8 < (byte) 0) { + throw overflowU8(u8); + } + return u8; + case Code.UINT16: // unsigned int 16 + short u16 = readInt16(); + if (u16 < 0 || u16 > Byte.MAX_VALUE) { + throw overflowU16(u16); + } + return (byte) u16; + case Code.UINT32: // unsigned int 32 + int u32 = readInt32(); + if (u32 < 0 || u32 > Byte.MAX_VALUE) { + throw overflowU32(u32); + } + return (byte) u32; + case Code.UINT64: // unsigned int 64 + long u64 = readInt64(); + if (u64 < 0L || u64 > Byte.MAX_VALUE) { + throw overflowU64(u64); + } + return (byte) u64; + case Code.INT8: // signed int 8 + return readInt8(); + case Code.INT16: // signed int 16 + short i16 = readInt16(); + if (i16 < Byte.MIN_VALUE || i16 > Byte.MAX_VALUE) { + throw overflowI16(i16); + } + return (byte) i16; + case Code.INT32: // signed int 32 + int i32 = readInt32(); + if (i32 < Byte.MIN_VALUE || i32 > Byte.MAX_VALUE) { + throw overflowI32(i32); + } + return (byte) i32; + case Code.INT64: // signed int 64 + long i64 = readInt64(); + if (i64 < Byte.MIN_VALUE || i64 > Byte.MAX_VALUE) { + throw overflowI64(i64); + } + return (byte) i64; + } + throw unexpected("Integer", b); + } + + @Override + public int readUnsignedByte() { + return readByte() & 0xff; + } + + @Override + public short readShort() { + byte b = readInt8(); + if (Code.isFixInt(b)) { + return b; + } + switch (b) { + case Code.UINT8: // unsigned int 8 + byte u8 = readInt8(); + return (short) (u8 & 0xff); + case Code.UINT16: // unsigned int 16 + short u16 = readInt16(); + if (u16 < (short) 0) { + throw overflowU16(u16); + } + return u16; + case Code.UINT32: // unsigned int 32 + int u32 = readInt32(); + if (u32 < 0 || u32 > Short.MAX_VALUE) { + throw overflowU32(u32); + } + return (short) u32; + case Code.UINT64: // unsigned int 64 + long u64 = readInt64(); + if (u64 < 0L || u64 > Short.MAX_VALUE) { + throw overflowU64(u64); + } + return (short) u64; + case Code.INT8: // signed int 8 + return readInt8(); + case Code.INT16: // signed int 16 + return readInt16(); + case Code.INT32: // signed int 32 + int i32 = readInt32(); + if (i32 < Short.MIN_VALUE || i32 > Short.MAX_VALUE) { + throw overflowI32(i32); + } + return (short) i32; + case Code.INT64: // signed int 64 + long i64 = readInt64(); + if (i64 < Short.MIN_VALUE || i64 > Short.MAX_VALUE) { + throw overflowI64(i64); + } + return (short) i64; + } + throw unexpected("Integer", b); + } + + @Override + public int readUnsignedShort() { + return readShort() & 0xffff; + } + + @Override + public int readInt() { + byte b = readInt8(); + if (Code.isFixInt(b)) { + return b; + } + switch (b) { + case Code.UINT8: // unsigned int 8 + byte u8 = readInt8(); + return u8 & 0xff; + case Code.UINT16: // unsigned int 16 + short u16 = readInt16(); + return u16 & 0xffff; + case Code.UINT32: // unsigned int 32 + int u32 = readInt32(); + if (u32 < 0) { + throw overflowU32(u32); + } + return u32; + case Code.UINT64: // unsigned int 64 + long u64 = readInt64(); + if (u64 < 0L || u64 > (long) Integer.MAX_VALUE) { + throw overflowU64(u64); + } + return (int) u64; + case Code.INT8: // signed int 8 + return readInt8(); + case Code.INT16: // signed int 16 + return readInt16(); + case Code.INT32: // signed int 32 + return readInt32(); + case Code.INT64: // signed int 64 + long i64 = readInt64(); + if (i64 < (long) Integer.MIN_VALUE || i64 > (long) Integer.MAX_VALUE) { + throw overflowI64(i64); + } + return (int) i64; + } + throw unexpected("Integer", b); + } + + @Override + public long readLong() { + byte b = readInt8(); + if (Code.isFixInt(b)) { + return b; + } + switch (b) { + case Code.UINT8: // unsigned int 8 + byte u8 = readInt8(); + return u8 & 0xff; + case Code.UINT16: // unsigned int 16 + short u16 = readInt16(); + return u16 & 0xffff; + case Code.UINT32: // unsigned int 32 + int u32 = readInt32(); + if (u32 < 0) { + return (long) (u32 & 0x7fffffff) + 0x80000000L; + } + else { + return u32; + } + case Code.UINT64: // unsigned int 64 + long u64 = readInt64(); + if (u64 < 0L) { + throw overflowU64(u64); + } + return u64; + case Code.INT8: // signed int 8 + return readInt8(); + case Code.INT16: // signed int 16 + return readInt16(); + case Code.INT32: // signed int 32 + return readInt32(); + case Code.INT64: // signed int 64 + return readInt64(); + } + throw unexpected("Integer", b); + } + + @Override + public float readFloat() { + byte b = readInt8(); + return switch (b) { + case Code.FLOAT32 -> readFloat32(); + case Code.FLOAT64 -> (float) readFloat64(); + default -> throw unexpected("Float", b); + }; + } + + @Override + public double readDouble() { + byte b = readInt8(); + return switch (b) { + case Code.FLOAT32 -> readFloat32(); + case Code.FLOAT64 -> readFloat64(); + default -> throw unexpected("Float", b); + }; + } + + @Override + public String readString() { + int len = readStringHeader(); + if (len == 0) { + return Constant.BLANK; + } + if (len > stringSizeLimit) { + throw new MessageSizeException("Cannot reading a String of size larger than %,d: %,d" + .formatted(stringSizeLimit, len), len); + } + return buffer.readString(len, stringCharset); + } + + @Override + public Instant readTimestamp() { + ExtensionTypeHeader ext = readExtensionTypeHeader(); + if (!ext.isTimestampType()) { + throw unexpectedExtension("Timestamp", EXT_TIMESTAMP, ext.getType()); + } + switch (ext.getLength()) { + case 4: { + // Need to convert Java's int (int32) to uint32 + long u32 = readInt32() & 0xffffffffL; + return Instant.ofEpochSecond(u32); + } + case 8: { + long data64 = readInt64(); + int nsec = (int) (data64 >>> 34); + long sec = data64 & 0x00000003ffffffffL; + return Instant.ofEpochSecond(sec, nsec); + } + case 12: { + // Need to convert Java's int (int32) to uint32 + long nsecU32 = readInt32() & 0xffffffffL; + long sec = readInt64(); + return Instant.ofEpochSecond(sec, nsecU32); + } + default: + throw new MessageFormatException("Timestamp extension type (%d) expects 4, 8, or 12 bytes of payload but got %d bytes" + .formatted(EXT_TIMESTAMP, ext.getLength())); + } + } + + @Override + public List read(Function mapper) { + int size = readArrayHeader(); + ArrayList result = new ArrayList<>(size); + for (int i = 0; i < size; i++) { + result.add(mapper.apply(this)); + } + return result; + } + + @Override + public List read(Supplier supplier) { + int size = readArrayHeader(); + ArrayList result = new ArrayList<>(size); + for (int i = 0; i < size; i++) { + result.add(supplier.get()); + } + return result; + } + + @Override + public Map read(Function keyMapper, Function valueMapper) { + int size = readMapHeader(); + LinkedHashMap result = CollectionUtils.newLinkedHashMap(size); + for (int i = 0; i < size; i++) { + result.put(keyMapper.apply(this), valueMapper.apply(this)); + } + return result; + } + + /** + * Reads header of an array. + * + *

          + * This method returns number of elements to be read. After this method call, you call unpacker methods for + * each element. You don't have to call anything at the end of iteration. + * + * @return the size of the array to be read + * @throws MessageTypeException when value is not MessagePack Array type + * @throws MessageSizeException when size of the array is larger than 2^31 - 1 + */ + public int readArrayHeader() { + byte b = readInt8(); + if (Code.isFixedArray(b)) { // fixarray + return b & 0x0f; + } + return switch (b) { + // array 16 + case Code.ARRAY16 -> readNextLength16(); + // array 32 + case Code.ARRAY32 -> readNextLength32(); + default -> throw unexpected("Array", b); + }; + } + + /** + * Reads header of a map. + * + *

          + * This method returns number of pairs to be read. After this method call, for each pair, you call unpacker + * methods for key first, and then value. You will call unpacker methods twice as many time as the returned + * count. You don't have to call anything at the end of iteration. + * + * @return the size of the map to be read + * @throws MessageTypeException when value is not MessagePack Map type + * @throws MessageSizeException when size of the map is larger than 2^31 - 1 + */ + public int readMapHeader() { + byte b = readInt8(); + if (Code.isFixedMap(b)) { // fixmap + return b & 0x0f; + } + return switch (b) { + case Code.MAP16 -> readNextLength16();// map 16 + case Code.MAP32 -> readNextLength32();// map 32 + default -> throw unexpected("Map", b); + }; + } + + public ExtensionTypeHeader readExtensionTypeHeader() { + byte b = readInt8(); + switch (b) { + case Code.FIXEXT1: { + byte type = readInt8(); + return new ExtensionTypeHeader(type, 1); + } + case Code.FIXEXT2: { + byte type = readInt8(); + return new ExtensionTypeHeader(type, 2); + } + case Code.FIXEXT4: { + byte type = readInt8(); + return new ExtensionTypeHeader(type, 4); + } + case Code.FIXEXT8: { + byte type = readInt8(); + return new ExtensionTypeHeader(type, 8); + } + case Code.FIXEXT16: { + byte type = readInt8(); + return new ExtensionTypeHeader(type, 16); + } + case Code.EXT8: { + int length = readNextLength8(); + byte type = readInt8(); + return new ExtensionTypeHeader(type, length); + } + case Code.EXT16: { + int length = readNextLength16(); + byte type = readInt8(); + return new ExtensionTypeHeader(type, length); + } + case Code.EXT32: { + int length = readNextLength32(); + byte type = readInt8(); + return new ExtensionTypeHeader(type, length); + } + } + + throw unexpected("Ext", b); + } + + /** + * Read a byte value at the cursor and proceed the cursor. + */ + private byte readInt8() { + return buffer.readByte(); + } + + private short readInt16() { + return buffer.readShort(); + } + + private int readInt32() { + return buffer.readInt(); + } + + private long readInt64() { + return buffer.readLong(); + } + + private float readFloat32() { + return buffer.readFloat(); + } + + private double readFloat64() { + return buffer.readDouble(); + } + + private int readNextLength8() { + byte u8 = readInt8(); + return u8 & 0xff; + } + + private int readNextLength16() { + short u16 = readInt16(); + return u16 & 0xffff; + } + + private int readNextLength32() { + int u32 = readInt32(); + if (u32 < 0) { + throw overflowU32Size(u32); + } + return u32; + } + + private int tryReadStringHeader(byte b) { + return switch (b) { + case Code.STR8 -> readNextLength8(); // str 8 + case Code.STR16 -> readNextLength16(); // str 16 + case Code.STR32 -> readNextLength32(); // str 32 + default -> -1; + }; + } + + private int tryReadBinaryHeader(byte b) { + return switch (b) { + case Code.BIN8 -> readNextLength8(); // bin 8 + case Code.BIN16 -> readNextLength16(); // bin 16 + case Code.BIN32 -> readNextLength32(); // bin 32 + default -> -1; + }; + } + + public int readStringHeader() { + byte b = readInt8(); + if (Code.isFixedRaw(b)) { // FixRaw + return b & 0x1f; + } + int len = tryReadStringHeader(b); + if (len >= 0) { + return len; + } + + throw unexpected("String", b); + } + + /** + * Reads header of a binary. + * + *

          + * This method returns number of bytes to be read. After this method call, you call a readPayload method such as + * {@link #read(int)} with the returned count. + * + *

          + * You can divide readPayload method into multiple calls. In this case, you must repeat readPayload methods + * until total amount of bytes becomes equal to the returned count. + * + * @return the size of the map to be read + * @throws MessageTypeException when value is not MessagePack Map type + * @throws MessageSizeException when size of the map is larger than 2^31 - 1 + * @ when underlying input + */ + public int readBinaryHeader() { + byte b = readInt8(); + if (Code.isFixedRaw(b)) { // FixRaw + return b & 0x1f; + } + int len = tryReadBinaryHeader(b); + if (len >= 0) { + return len; + } + + throw unexpected("Binary", b); + } + + /** + * Create an exception for the case when an unexpected byte value is read + */ + private static MessagePackException unexpected(String expected, byte b) { + MessageFormat format = MessageFormat.valueOf(b); + if (format == MessageFormat.NEVER_USED) { + return new MessageNeverUsedFormatException(String.format("Expected %s, but encountered 0xC1 \"NEVER_USED\" byte", expected)); + } + else { + String name = format.getValueType().name(); + String typeName = name.charAt(0) + name.substring(1).toLowerCase(); + return new MessageTypeException(String.format("Expected %s, but got %s (%02x)", expected, typeName, b)); + } + } + + private static MessagePackException unexpectedExtension(String expected, int expectedType, int actualType) { + return new MessageTypeException(String.format("Expected extension type %s (%d), but got extension type %d", + expected, expectedType, actualType)); + } + + private static MessageIntegerOverflowException overflowU8(byte u8) { + BigInteger bi = BigInteger.valueOf(u8 & 0xff); + return new MessageIntegerOverflowException(bi); + } + + private static MessageIntegerOverflowException overflowU16(short u16) { + BigInteger bi = BigInteger.valueOf(u16 & 0xffff); + return new MessageIntegerOverflowException(bi); + } + + private static MessageIntegerOverflowException overflowU32(int u32) { + BigInteger bi = BigInteger.valueOf((long) (u32 & 0x7fffffff) + 0x80000000L); + return new MessageIntegerOverflowException(bi); + } + + private static MessageIntegerOverflowException overflowU64(long u64) { + BigInteger bi = BigInteger.valueOf(u64 + Long.MAX_VALUE + 1L).setBit(63); + return new MessageIntegerOverflowException(bi); + } + + private static MessageIntegerOverflowException overflowI16(short i16) { + BigInteger bi = BigInteger.valueOf(i16); + return new MessageIntegerOverflowException(bi); + } + + private static MessageIntegerOverflowException overflowI32(int i32) { + BigInteger bi = BigInteger.valueOf(i32); + return new MessageIntegerOverflowException(bi); + } + + private static MessageIntegerOverflowException overflowI64(long i64) { + BigInteger bi = BigInteger.valueOf(i64); + return new MessageIntegerOverflowException(bi); + } + + private static MessageSizeException overflowU32Size(int u32) { + long lv = (long) (u32 & 0x7fffffff) + 0x80000000L; + return new MessageSizeException(lv); + } + +} diff --git a/today-service-api/src/main/java/infra/cloud/serialize/MessagePackOutput.java b/today-service-api/src/main/java/infra/cloud/serialize/MessagePackOutput.java new file mode 100644 index 0000000..947e36c --- /dev/null +++ b/today-service-api/src/main/java/infra/cloud/serialize/MessagePackOutput.java @@ -0,0 +1,526 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.serialize; + +import java.nio.charset.CharsetEncoder; +import java.nio.charset.CodingErrorAction; +import java.nio.charset.StandardCharsets; +import java.time.Instant; +import java.util.List; +import java.util.Map; +import java.util.function.BiConsumer; +import java.util.function.Consumer; + +import infra.cloud.serialize.format.MessagePack; +import infra.lang.Nullable; +import io.netty.buffer.ByteBuf; + +import static infra.cloud.serialize.format.MessagePack.Code.ARRAY16; +import static infra.cloud.serialize.format.MessagePack.Code.ARRAY32; +import static infra.cloud.serialize.format.MessagePack.Code.BIN16; +import static infra.cloud.serialize.format.MessagePack.Code.BIN32; +import static infra.cloud.serialize.format.MessagePack.Code.BIN8; +import static infra.cloud.serialize.format.MessagePack.Code.EXT8; +import static infra.cloud.serialize.format.MessagePack.Code.EXT_TIMESTAMP; +import static infra.cloud.serialize.format.MessagePack.Code.FALSE; +import static infra.cloud.serialize.format.MessagePack.Code.FIXARRAY_PREFIX; +import static infra.cloud.serialize.format.MessagePack.Code.FIXEXT4; +import static infra.cloud.serialize.format.MessagePack.Code.FIXEXT8; +import static infra.cloud.serialize.format.MessagePack.Code.FIXMAP_PREFIX; +import static infra.cloud.serialize.format.MessagePack.Code.FIXSTR_PREFIX; +import static infra.cloud.serialize.format.MessagePack.Code.FLOAT32; +import static infra.cloud.serialize.format.MessagePack.Code.FLOAT64; +import static infra.cloud.serialize.format.MessagePack.Code.INT16; +import static infra.cloud.serialize.format.MessagePack.Code.INT32; +import static infra.cloud.serialize.format.MessagePack.Code.INT64; +import static infra.cloud.serialize.format.MessagePack.Code.INT8; +import static infra.cloud.serialize.format.MessagePack.Code.MAP16; +import static infra.cloud.serialize.format.MessagePack.Code.MAP32; +import static infra.cloud.serialize.format.MessagePack.Code.NIL; +import static infra.cloud.serialize.format.MessagePack.Code.STR16; +import static infra.cloud.serialize.format.MessagePack.Code.STR32; +import static infra.cloud.serialize.format.MessagePack.Code.STR8; +import static infra.cloud.serialize.format.MessagePack.Code.TRUE; +import static infra.cloud.serialize.format.MessagePack.Code.UINT16; +import static infra.cloud.serialize.format.MessagePack.Code.UINT32; +import static infra.cloud.serialize.format.MessagePack.Code.UINT64; +import static infra.cloud.serialize.format.MessagePack.Code.UINT8; + +/** + * @author 海子 Yang + * @since 1.0 2025/8/18 17:50 + */ +public class MessagePackOutput implements Output { + + private static final long NANOS_PER_SECOND = 1000000000L; + + private final ByteBuf buffer; + + /** + * String encoder + */ + private CharsetEncoder encoder; + + public MessagePackOutput(ByteBuf buffer) { + this.buffer = buffer; + } + + /** + * Writes a byte array to the output. + *

          + * This method is used with {@link #writeStringHeader(int)} or {@link #writeBinaryHeader(int)} methods. + *

          + * Unlike {@link #writeFully(byte[])} method, this method does not make a defensive copy of the given byte + * array, even if it is shorter than {@link MessagePack.PackerConfig#withBufferFlushThreshold(int)}. This is + * faster than {@link #writeFully(byte[])} method but caller must not modify the byte array after calling + * this method. + * + * @param b the data to add + * @throws SerializationException if an I/O error occurs. + * @see #writeFully(byte[]) + */ + @Override + public void write(@Nullable byte[] b) { + if (b == null || b.length == 0) { + writeBinaryHeader(0); + } + else { + writeBinaryHeader(b.length); + buffer.writeBytes(b); + } + } + + @Override + public void writeFully(byte[] b) { + buffer.writeBytes(b); + } + + @Override + public void writeFully(byte[] b, int off, int len) { + buffer.writeBytes(b, off, len); + } + + @Override + public void write(byte[] b, int off, int len) { + writeBinaryHeader(len); + buffer.writeBytes(b, off, len); + } + + public void writeNull() { + writeByte(NIL); + } + + @Override + public void write(boolean v) { + writeByte(v ? TRUE : FALSE); + } + + @Override + public void write(byte b) { + if (b < -(1 << 5)) { + writeByteAndByte(INT8, b); + } + else { + writeByte(b); + } + } + + /** + * Writes an Integer value. + * + *

          + * This method writes an integer using the smallest format from the int format family. + * + * @param v the integer to be written + */ + @Override + public void write(short v) { + if (v < -(1 << 5)) { + if (v < -(1 << 7)) { + writeByteAndShort(INT16, v); + } + else { + writeByteAndByte(INT8, (byte) v); + } + } + else if (v < (1 << 7)) { + writeByte((byte) v); + } + else { + if (v < (1 << 8)) { + writeByteAndByte(UINT8, (byte) v); + } + else { + writeByteAndShort(UINT16, v); + } + } + } + + /** + * Writes an Integer value. + * + *

          + * This method writes an integer using the smallest format from the int format family. + * + * @param v the integer to be written + */ + @Override + public void write(int v) { + if (v < -(1 << 5)) { + if (v < -(1 << 15)) { + writeByteAndInt(INT32, v); + } + else if (v < -(1 << 7)) { + writeByteAndShort(INT16, (short) v); + } + else { + writeByteAndByte(INT8, (byte) v); + } + } + else if (v < (1 << 7)) { + writeByte((byte) v); + } + else { + if (v < (1 << 8)) { + writeByteAndByte(UINT8, (byte) v); + } + else if (v < (1 << 16)) { + writeByteAndShort(UINT16, (short) v); + } + else { + // unsigned 32 + writeByteAndInt(UINT32, v); + } + } + } + + /** + * Writes an Integer value. + * + *

          + * This method writes an integer using the smallest format from the int format family. + * + * @param v the integer to be written + */ + @Override + public void write(long v) { + if (v < -(1L << 5)) { + if (v < -(1L << 15)) { + if (v < -(1L << 31)) { + writeByteAndLong(INT64, v); + } + else { + writeByteAndInt(INT32, (int) v); + } + } + else { + if (v < -(1 << 7)) { + writeByteAndShort(INT16, (short) v); + } + else { + writeByteAndByte(INT8, (byte) v); + } + } + } + else if (v < (1 << 7)) { + // fixnum + writeByte((byte) v); + } + else { + if (v < (1L << 16)) { + if (v < (1 << 8)) { + writeByteAndByte(UINT8, (byte) v); + } + else { + writeByteAndShort(UINT16, (short) v); + } + } + else { + if (v < (1L << 32)) { + writeByteAndInt(UINT32, (int) v); + } + else { + writeByteAndLong(UINT64, v); + } + } + } + } + + @Override + public void write(float v) { + writeByteAndFloat(FLOAT32, v); + } + + @Override + public void write(double v) { + writeByteAndDouble(FLOAT64, v); + } + + @Override + public void write(@Nullable String s) { + if (s == null || s.isEmpty()) { + writeStringHeader(0); + } + else { + // JVM performs various optimizations (memory allocation, reusing encoder etc.) when String.getBytes is used + byte[] bytes = s.getBytes(StandardCharsets.UTF_8); + writeStringHeader(bytes.length); + writeFully(bytes); + } + } + + @Override + public void write(Instant instant) { + writeTimestamp(instant.getEpochSecond(), instant.getNano()); + } + + @Override + public void writeTimestamp(long millis) { + write(Instant.ofEpochMilli(millis)); + } + + @Override + public void write(Message message) { + message.writeTo(this); + } + + @Override + public void writeTimestamp(long epochSecond, int nanoAdjustment) { + long sec = Math.addExact(epochSecond, Math.floorDiv(nanoAdjustment, NANOS_PER_SECOND)); + long nsec = Math.floorMod(nanoAdjustment, NANOS_PER_SECOND); + + if (sec >>> 34 == 0) { + // sec can be serialized in 34 bits. + long data64 = (nsec << 34) | sec; + if ((data64 & 0xffffffff00000000L) == 0L) { + // sec can be serialized in 32 bits and nsec is 0. + // use timestamp 32 + writeTimestamp32((int) sec); + } + else { + // sec exceeded 32 bits or nsec is not 0. + // use timestamp 64 + writeTimestamp64(data64); + } + } + else { + // use timestamp 96 format + writeTimestamp96(sec, (int) nsec); + } + } + + @Override + public void write(List list, Consumer mapper) { + int size = list.size(); + writeArrayHeader(size); + for (T t : list) { + mapper.accept(t); + } + } + + @Override + public void write(List list, BiConsumer mapper) { + int size = list.size(); + writeArrayHeader(size); + for (T t : list) { + mapper.accept(this, t); + } + } + + @Override + public void write(Map map, BiConsumer keyMapper, BiConsumer valueMapper) { + int size = map.size(); + writeMapHeader(size); + for (Map.Entry entry : map.entrySet()) { + keyMapper.accept(this, entry.getKey()); + valueMapper.accept(this, entry.getValue()); + } + } + + @Override + public void write(Map map, Consumer keyMapper, Consumer valueMapper) { + int size = map.size(); + writeMapHeader(size); + for (Map.Entry entry : map.entrySet()) { + keyMapper.accept(entry.getKey()); + valueMapper.accept(entry.getValue()); + } + } + + /** + * Writes header of a Binary value. + *

          + * You MUST call {@link #writeFully(byte[])} method to write body binary. + * + * @param len number of bytes of a binary to be written + */ + public void writeBinaryHeader(int len) { + if (len < (1 << 8)) { + writeByteAndByte(BIN8, (byte) len); + } + else if (len < (1 << 16)) { + writeByteAndShort(BIN16, (short) len); + } + else { + writeByteAndInt(BIN32, len); + } + } + + /** + * Writes header of a String value. + *

          + * Length must be number of bytes of a string in UTF-8 encoding. + *

          + * You MUST call {@link #writeFully(byte[])} method to write body of the + * UTF-8 encoded string. + * + * @param len number of bytes of a UTF-8 string to be written + */ + public void writeStringHeader(int len) { + if (len < (1 << 5)) { + writeByte((byte) (FIXSTR_PREFIX | len)); + } + else if (len < (1 << 8)) { + writeByteAndByte(STR8, (byte) len); + } + else if (len < (1 << 16)) { + writeByteAndShort(STR16, (short) len); + } + else { + writeByteAndInt(STR32, len); + } + } + + /** + * Writes header of an Array value. + *

          + * You will call other packer methods for each element after this method call. + *

          + * You don't have to call anything at the end of iteration. + * + * @param arraySize number of elements to be written + */ + public void writeArrayHeader(int arraySize) { + if (arraySize < 0) { + throw new IllegalArgumentException("array size must be >= 0"); + } + + if (arraySize < (1 << 4)) { + writeByte((byte) (FIXARRAY_PREFIX | arraySize)); + } + else if (arraySize < (1 << 16)) { + writeByteAndShort(ARRAY16, (short) arraySize); + } + else { + writeByteAndInt(ARRAY32, arraySize); + } + } + + /** + * Writes header of a Map value. + *

          + * After this method call, for each key-value pair, you will call packer methods for key first, and then value. + * You will call packer methods twice as many time as the size of the map. + *

          + * You don't have to call anything at the end of iteration. + * + * @param mapSize number of pairs to be written + */ + public void writeMapHeader(int mapSize) { + if (mapSize < 0) { + throw new IllegalArgumentException("map size must be >= 0"); + } + + if (mapSize < (1 << 4)) { + writeByte((byte) (FIXMAP_PREFIX | mapSize)); + } + else if (mapSize < (1 << 16)) { + writeByteAndShort(MAP16, (short) mapSize); + } + else { + writeByteAndInt(MAP32, mapSize); + } + } + + private void writeByte(byte b) { + buffer.writeByte(b); + } + + private void writeByteAndByte(byte b, byte v) { + buffer.writeByte(b); + buffer.writeByte(v); + } + + private void writeByteAndShort(byte b, short v) { + buffer.writeByte(b); + buffer.writeShort(v); + } + + private void writeByteAndInt(byte b, int v) { + buffer.writeByte(b); + buffer.writeInt(v); + } + + private void writeByteAndFloat(byte b, float v) { + buffer.writeByte(b); + buffer.writeFloat(v); + } + + private void writeByteAndDouble(byte b, double v) { + buffer.writeByte(b); + buffer.writeDouble(v); + } + + private void writeByteAndLong(byte b, long v) { + buffer.writeByte(b); + buffer.writeLong(v); + } + + private void writeTimestamp32(int sec) { + // timestamp 32 in fixext 4 + buffer.writeByte(FIXEXT4); + buffer.writeByte(EXT_TIMESTAMP); + buffer.writeInt(sec); + } + + private void writeTimestamp64(long data64) { + // timestamp 64 in fixext 8 + buffer.writeByte(FIXEXT8); + buffer.writeByte(EXT_TIMESTAMP); + buffer.writeLong(data64); + } + + private void writeTimestamp96(long sec, int nsec) { + // timestamp 96 in ext 8 + buffer.writeByte(EXT8); + buffer.writeByte((byte) 12); + buffer.writeByte(EXT_TIMESTAMP); + buffer.writeInt(nsec); + buffer.writeLong(sec); + } + + private void prepareEncoder() { + if (encoder == null) { + this.encoder = MessagePack.UTF8.newEncoder() + .onMalformedInput(CodingErrorAction.REPLACE) + .onUnmappableCharacter(CodingErrorAction.REPLACE); + } + encoder.reset(); + } + +} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/Input.java b/today-service-serialization/src/main/java/infra/cloud/serialize/Input.java index fbdf33f..c4c04d9 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/Input.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/Input.java @@ -17,6 +17,12 @@ package infra.cloud.serialize; +import java.time.Instant; +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.function.Supplier; + /** * An Input lets an application read primitive data types and objects from a source of data. * @@ -36,7 +42,7 @@ public interface Input { * @param b the buffer into which the data is read. * @throws NullPointerException if {@code b} is {@code null}. */ - void read(byte[] b) throws SerializationException; + void read(byte[] b); /** * Reads {@code len} bytes from an input. @@ -49,224 +55,149 @@ public interface Input { * {@code len} is negative, or {@code len} is greater than * {@code b.length - off}. */ - void read(byte[] b, int off, int len) throws SerializationException; + void read(byte[] b, int off, int len); + /** + * Reads byte array + */ byte[] read(); - default void read(Message message) throws SerializationException { - message.readFrom(this); - } + /** + * Reads bytes with given length + */ + byte[] read(int len); + + /** + * Reads all left bytes + */ + byte[] readFully(); /** - * Makes an attempt to skip over - * {@code n} bytes - * of data from the input - * stream, discarding the skipped bytes. However, - * it may skip - * over some smaller number of - * bytes, possibly zero. This may result from - * any of a - * number of conditions; reaching - * end of file before {@code n} bytes - * have been skipped is - * only one possibility. - * This method never throws an {@code EOFException}. - * The actual - * number of bytes skipped is returned. + * Skip bytes * * @param n the number of bytes to be skipped. * @return the number of bytes actually skipped. - * @throws SerializationException if an I/O error occurs. + * @throws SerializationException if a serialization error occurs. */ - int skipBytes(int n) throws SerializationException; + int skipBytes(int n); /** - * Reads one input byte and returns - * {@code true} if that byte is nonzero, - * {@code false} if that byte is zero. - * This method is suitable for reading - * the byte written by the {@code writeBoolean} - * method of interface {@code Input}. + * Reads a {@code boolean} value. * * @return the {@code boolean} value read. - * @throws SerializationException if an I/O error occurs. + * @throws SerializationException if a serialization error occurs. */ - boolean readBoolean() throws SerializationException; + boolean readBoolean(); /** - * Reads and returns one input byte. - * The byte is treated as a signed value in - * the range {@code -128} through {@code 127}, - * inclusive. - * This method is suitable for - * reading the byte written by the {@code writeByte} - * method of interface {@code Input}. + * Reads a {@code byte} value. * * @return the 8-bit value read. - * @throws SerializationException if an I/O error occurs. + * @throws SerializationException if a serialization error occurs. */ - byte readByte() throws SerializationException; + byte readByte(); /** - * Reads one input byte, zero-extends - * it to type {@code int}, and returns - * the result, which is therefore in the range - * {@code 0} - * through {@code 255}. - * This method is suitable for reading - * the byte written by the {@code writeByte} - * method of interface {@code Input} - * if the argument to {@code writeByte} - * was intended to be a value in the range - * {@code 0} through {@code 255}. + * Reads a unsigned {@code byte} value. * * @return the unsigned 8-bit value read. - * @throws SerializationException if an I/O error occurs. + * @throws SerializationException if a serialization error occurs. */ - int readUnsignedByte() throws SerializationException; + int readUnsignedByte(); /** - * Reads two input bytes and returns - * a {@code short} value. Let {@code a} - * be the first byte read and {@code b} - * be the second byte. The value - * returned - * is: - *

          {@code (short)((a << 8) | (b & 0xff))
          -   * }
          - * This method - * is suitable for reading the bytes written - * by the {@code writeShort} method of - * interface {@code Input}. + * Reads a {@code short} value. * * @return the 16-bit value read. - * @throws SerializationException if an I/O error occurs. + * @throws SerializationException if a serialization error occurs. */ - short readShort() throws SerializationException; + short readShort(); /** - * Reads two input bytes and returns - * an {@code int} value in the range {@code 0} - * through {@code 65535}. Let {@code a} - * be the first byte read and - * {@code b} - * be the second byte. The value returned is: - *
          {@code (((a & 0xff) << 8) | (b & 0xff))
          -   * }
          - * This method is suitable for reading the bytes - * written by the {@code writeShort} method - * of interface {@code Input} if - * the argument to {@code writeShort} - * was intended to be a value in the range - * {@code 0} through {@code 65535}. + * Reads a unsigned {@code short} value. * * @return the unsigned 16-bit value read. - * @throws SerializationException if an I/O error occurs. + * @throws SerializationException if a serialization error occurs. */ - int readUnsignedShort() throws SerializationException; + int readUnsignedShort(); /** - * Reads two input bytes and returns a {@code char} value. - * Let {@code a} - * be the first byte read and {@code b} - * be the second byte. The value - * returned is: - *
          {@code (char)((a << 8) | (b & 0xff))
          -   * }
          - * This method - * is suitable for reading bytes written by - * the {@code writeChar} method of interface - * {@code Input}. - * - * @return the {@code char} value read. - * @throws SerializationException if an I/O error occurs. - */ - char readChar() throws SerializationException; - - /** - * Reads four input bytes and returns an - * {@code int} value. Let {@code a-d} - * be the first through fourth bytes read. The value returned is: - *
          {@code
          -   * (((a & 0xff) << 24) | ((b & 0xff) << 16) |
          -   *  ((c & 0xff) <<  8) | (d & 0xff))
          -   * }
          - * This method is suitable - * for reading bytes written by the {@code writeInt} - * method of interface {@code Input}. + * Reads a {@code int} value. * * @return the {@code int} value read. - * @throws SerializationException if an I/O error occurs. + * @throws SerializationException if a serialization error occurs. */ - int readInt() throws SerializationException; + int readInt(); /** - * Reads eight input bytes and returns - * a {@code long} value. Let {@code a-h} - * be the first through eighth bytes read. - * The value returned is: - *
          {@code
          -   * (((long)(a & 0xff) << 56) |
          -   *  ((long)(b & 0xff) << 48) |
          -   *  ((long)(c & 0xff) << 40) |
          -   *  ((long)(d & 0xff) << 32) |
          -   *  ((long)(e & 0xff) << 24) |
          -   *  ((long)(f & 0xff) << 16) |
          -   *  ((long)(g & 0xff) <<  8) |
          -   *  ((long)(h & 0xff)))
          -   * }
          - *

          - * This method is suitable - * for reading bytes written by the {@code writeLong} - * method of interface {@code Input}. + * Reads a {@code long} value. * * @return the {@code long} value read. - * @throws SerializationException if an I/O error occurs. + * @throws SerializationException if a serialization error occurs. */ - long readLong() throws SerializationException; + long readLong(); /** - * Reads four input bytes and returns - * a {@code float} value. It does this - * by first constructing an {@code int} - * value in exactly the manner - * of the {@code readInt} - * method, then converting this {@code int} - * value to a {@code float} in - * exactly the manner of the method {@code Float.intBitsToFloat}. - * This method is suitable for reading - * bytes written by the {@code writeFloat} - * method of interface {@code Input}. + * Reads a {@code float} value. * * @return the {@code float} value read. - * @throws SerializationException if an I/O error occurs. + * @throws SerializationException if a serialization error occurs. */ - float readFloat() throws SerializationException; + float readFloat(); /** - * Reads eight input bytes and returns - * a {@code double} value. It does this - * by first constructing a {@code long} - * value in exactly the manner - * of the {@code readLong} - * method, then converting this {@code long} - * value to a {@code double} in exactly - * the manner of the method {@code Double.longBitsToDouble}. - * This method is suitable for reading - * bytes written by the {@code writeDouble} - * method of interface {@code Input}. + * Reads a {@code double} value. * * @return the {@code double} value read. - * @throws SerializationException if an I/O error occurs. + * @throws SerializationException if a serialization error occurs. */ - double readDouble() throws SerializationException; + double readDouble(); /** - * Reads a {@link String} field value. + * Reads a {@link String} value. * * @return a string. - * @throws SerializationException if an I/O error occurs. + * @throws SerializationException if a serialization error occurs. + */ + String readString(); + + /** + * Reads a {@link Instant} value. + * + * @return an Instant object. + * @throws SerializationException if a serialization error occurs. + */ + Instant readTimestamp(); + + /** + * Reads a {@link Message} value. + * + * @throws SerializationException if a serialization error occurs. + */ + void read(Message message); + + /** + * Reads a {@link List} value. + * + * @return a List object. + * @throws SerializationException if a serialization error occurs. + */ + List read(Function mapper); + + /** + * Reads a {@link List} value. + * + * @return a List object. + * @throws SerializationException if a serialization error occurs. + */ + List read(Supplier supplier); + + /** + * Reads a {@link Map} value. + * + * @return a Map object. + * @throws SerializationException if a serialization error occurs. */ - String readString() throws SerializationException; + Map read(Function keyMapper, Function valueMapper); } diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/Output.java b/today-service-serialization/src/main/java/infra/cloud/serialize/Output.java index 37972fa..df462a8 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/Output.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/Output.java @@ -17,6 +17,14 @@ package infra.cloud.serialize; +import java.time.Instant; +import java.util.List; +import java.util.Map; +import java.util.function.BiConsumer; +import java.util.function.Consumer; + +import infra.lang.Nullable; + /** * @author 海子 Yang * @see java.io.DataOutput @@ -25,185 +33,160 @@ public interface Output { /** - * Writes to the output stream the eight - * low-order bits of the argument {@code b}. - * The 24 high-order bits of {@code b} - * are ignored. + * Writes a byte array object to the output. * - * @param b the byte to be written. - * @throws SerializationException if an I/O error occurs. - */ - void write(byte b) throws SerializationException; - - /** - * Writes to the output stream all the bytes in array {@code b}. - * If {@code b} is {@code null}, - * a {@code NullPointerException} is thrown. - * If {@code b.length} is zero, then - * no bytes are written. Otherwise, the byte - * {@code b[0]} is written first, then - * {@code b[1]}, and so on; the last byte - * written is {@code b[b.length-1]}. - * - * @param b the data. - * @throws SerializationException if an I/O error occurs. - */ - void write(byte[] b) throws SerializationException; - - /** - * Writes {@code len} bytes from array - * {@code b}, in order, to - * the output stream. If {@code b} - * is {@code null}, a {@code NullPointerException} - * is thrown. If {@code off} is negative, - * or {@code len} is negative, or {@code off+len} - * is greater than the length of the array - * {@code b}, then an {@code IndexOutOfBoundsException} - * is thrown. If {@code len} is zero, - * then no bytes are written. Otherwise, the - * byte {@code b[off]} is written first, - * then {@code b[off+1]}, and so on; the - * last byte written is {@code b[off+len-1]}. - * - * @param b the data. - * @param off the start offset in the data. - * @param len the number of bytes to write. - * @throws SerializationException if an I/O error occurs. - */ - void write(byte[] b, int off, int len) throws SerializationException; - - /** - * Writes a {@code boolean} value to this output stream. - * If the argument {@code v} - * is {@code true}, the value {@code (byte)1} - * is written; if {@code v} is {@code false}, - * the value {@code (byte)0} is written. - * The byte written by this method may - * be read by the {@code readBoolean} - * method of interface {@code DataInput}, - * which will then return a {@code boolean} - * equal to {@code v}. + * @param b the data to add + * @throws SerializationException if a serialization error occurs. + * @see #writeFully(byte[]) + */ + void write(@Nullable byte[] b); + + /** + * Writes a byte array object to the output. + * + * @param b the data to add + * @throws SerializationException if a serialization error occurs. + * @see #writeFully(byte[]) + */ + void write(byte[] b, int off, int len); + + /** + * Append byte array to this Output + */ + void writeFully(byte[] b); + + /** + * Append byte array to this Output + */ + void writeFully(byte[] b, int off, int len); + + /** + * Writes a {@code boolean} value. * * @param v the boolean to be written. - * @throws SerializationException if an I/O error occurs. + * @throws SerializationException if a serialization error occurs. */ - void write(boolean v) throws SerializationException; + void write(boolean v); /** - * Writes two bytes to the output - * stream to represent the value of the argument. - * The byte values to be written, in the order - * shown, are: - *

          {@code
          -   * (byte)(0xff & (v >> 8))
          -   * (byte)(0xff & v)
          -   * }

          - * The bytes written by this method may be - * read by the {@code readShort} method - * of interface {@code DataInput}, which - * will then return a {@code short} equal - * to {@code (short)v}. + * Writes a {@code byte} value. + * + * @param b the byte to be written. + * @throws SerializationException if a serialization error occurs. + */ + void write(byte b); + + /** + * Writes a {@code short} value. * * @param v the {@code short} value to be written. - * @throws SerializationException if an I/O error occurs. - */ - void write(short v) throws SerializationException; - - /** - * Writes an {@code int} value, which is - * comprised of four bytes, to the output stream. - * The byte values to be written, in the order - * shown, are: - *

          {@code
          -   * (byte)(0xff & (v >> 24))
          -   * (byte)(0xff & (v >> 16))
          -   * (byte)(0xff & (v >>  8))
          -   * (byte)(0xff & v)
          -   * }

          - * The bytes written by this method may be read - * by the {@code readInt} method of interface - * {@code DataInput}, which will then - * return an {@code int} equal to {@code v}. + * @throws SerializationException if a serialization error occurs. + */ + void write(short v); + + /** + * Writes an {@code int} value. * * @param v the {@code int} value to be written. - * @throws SerializationException if an I/O error occurs. - */ - void write(int v) throws SerializationException; - - /** - * Writes a {@code long} value, which is - * comprised of eight bytes, to the output stream. - * The byte values to be written, in the order - * shown, are: - *

          {@code
          -   * (byte)(0xff & (v >> 56))
          -   * (byte)(0xff & (v >> 48))
          -   * (byte)(0xff & (v >> 40))
          -   * (byte)(0xff & (v >> 32))
          -   * (byte)(0xff & (v >> 24))
          -   * (byte)(0xff & (v >> 16))
          -   * (byte)(0xff & (v >>  8))
          -   * (byte)(0xff & v)
          -   * }

          - * The bytes written by this method may be - * read by the {@code readLong} method - * of interface {@code DataInput}, which - * will then return a {@code long} equal - * to {@code v}. - * - * @param v the {@code long} value to be written. - * @throws SerializationException if an I/O error occurs. - */ - void write(long v) throws SerializationException; - - /** - * Writes a {@code float} value, - * which is comprised of four bytes, to the output stream. - * It does this as if it first converts this - * {@code float} value to an {@code int} - * in exactly the manner of the {@code Float.floatToIntBits} - * method and then writes the {@code int} - * value in exactly the manner of the {@code writeInt} - * method. The bytes written by this method - * may be read by the {@code readFloat} - * method of interface {@code DataInput}, - * which will then return a {@code float} - * equal to {@code v}. + * @throws SerializationException if a serialization error occurs. + */ + void write(int v); + + /** + * Writes a {@code long} value. + * + * @param v the integer to be written + * @throws SerializationException if write failed. + */ + void write(long v); + + /** + * Writes a {@code float} value. * * @param v the {@code float} value to be written. - * @throws SerializationException if an I/O error occurs. + * @throws SerializationException if a serialization error occurs. */ - void write(float v) throws SerializationException; + void write(float v); /** - * Writes a {@code double} value, - * which is comprised of eight bytes, to the output stream. - * It does this as if it first converts this - * {@code double} value to a {@code long} - * in exactly the manner of the {@code Double.doubleToLongBits} - * method and then writes the {@code long} - * value in exactly the manner of the {@code writeLong} - * method. The bytes written by this method - * may be read by the {@code readDouble} - * method of interface {@code DataInput}, - * which will then return a {@code double} - * equal to {@code v}. + * Writes a {@code double} value. * * @param v the {@code double} value to be written. - * @throws SerializationException if an I/O error occurs. + * @throws SerializationException if a serialization error occurs. */ - void write(double v) throws SerializationException; + void write(double v); /** - * Writes string + * Writes a {@code String} value. * * @param s the string value to be written. - * @throws SerializationException if an I/O error occurs. + * @throws SerializationException if a serialization error occurs. */ - void write(String s) throws SerializationException; + void write(String s); - default void write(Message message) throws SerializationException { - message.writeTo(this); - } + /** + * Writes a Timestamp value. + * + * @param instant the timestamp to be written + * @throws SerializationException if a serialization error occurs. + */ + void write(Instant instant); + + /** + * Writes a Timestamp value. + * + * @param epochSecond the number of seconds from 1970-01-01T00:00:00Z + * @param nanoAdjustment the nanosecond adjustment to the number of seconds, positive or negative + * @throws SerializationException if a serialization error occurs. + */ + void writeTimestamp(long epochSecond, int nanoAdjustment); + + /** + * Writes a Timestamp value using a millisecond value (e.g., System.currentTimeMillis()) + * + * @param millis the millisecond value + * @throws SerializationException if a serialization error occurs. + */ + void writeTimestamp(long millis); + + /** + * Writes a {@code Message} value. + * + * @param message the Message value to be written. + * @throws SerializationException if a serialization error occurs. + */ + void write(Message message); + + /** + * Writes a {@code List} value. + * + * @param list the List value to be written. + * @throws SerializationException if a serialization error occurs. + */ + void write(List list, Consumer mapper); + + /** + * Writes a {@code List} value. + * + * @param list the List value to be written. + * @throws SerializationException if a serialization error occurs. + */ + void write(List list, BiConsumer mapper); + + /** + * Writes a {@code Map} value. + * + * @param map the Map value to be written. + * @throws SerializationException if a serialization error occurs. + */ + void write(Map map, Consumer keyMapper, Consumer valueMapper); + + /** + * Writes a {@code Map} value. + * + * @param map the Map value to be written. + * @throws SerializationException if a serialization error occurs. + */ + void write(Map map, BiConsumer keyMapper, BiConsumer valueMapper); } diff --git a/today-service-serialization/src/test/java/infra/cloud/serialize/InputTests.java b/today-service-serialization/src/test/java/infra/cloud/serialize/InputTests.java new file mode 100644 index 0000000..7beea17 --- /dev/null +++ b/today-service-serialization/src/test/java/infra/cloud/serialize/InputTests.java @@ -0,0 +1,57 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.serialize; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.util.List; +import java.util.Map; +import java.util.Random; +import java.util.stream.Stream; + +/** + * @author 海子 Yang + * @since 1.0 2025/8/18 17:12 + */ +class InputTests { + + @ParameterizedTest + @MethodSource("args") + void list(Input input) { + List list = input.read(Input::readInt); + + Random random = new Random(); + List read = input.read(() -> random.nextInt()); + + } + + @ParameterizedTest + @MethodSource("args") + void map(Input input) { + Map map = input.read(Input::readString, Input::readString); + + } + + static Stream args() { +// DefaultByteBufInput input = new DefaultByteBufInput(); + return Stream.of(Arguments.arguments()); + } + +} \ No newline at end of file From d0e502ca850911377eaa98db8e155f9bc05af662 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Tue, 19 Aug 2025 22:32:23 +0800 Subject: [PATCH 044/104] =?UTF-8?q?:art:=20=E5=BA=8F=E5=88=97=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/infra/cloud/RpcRequest.java | 38 +++++++--- .../cloud/serialize/DefaultByteBufInput.java | 34 ++++++++- .../cloud/serialize/DefaultByteBufOutput.java | 29 ++++++-- .../cloud/serialize/MessagePackInput.java | 26 +++++++ .../cloud/serialize/MessagePackOutput.java | 16 +++++ .../ProtobufArgumentSerialization.java | 25 +++---- .../serialize/RpcArgumentSerialization.java | 4 +- .../serialize/RpcRequestSerialization.java | 15 +--- .../service/MethodServiceInvocation.java | 2 +- .../cloud/service/ServiceMethodInvoker.java | 16 ++++- .../provider/RpcRequestDeserializer.java | 71 +++++++++---------- .../java/infra/cloud/serialize/Input.java | 16 +++++ .../java/infra/cloud/serialize/Output.java | 18 ++++- 13 files changed, 225 insertions(+), 85 deletions(-) diff --git a/today-service-api/src/main/java/infra/cloud/RpcRequest.java b/today-service-api/src/main/java/infra/cloud/RpcRequest.java index 25e35f5..ddb369b 100644 --- a/today-service-api/src/main/java/infra/cloud/RpcRequest.java +++ b/today-service-api/src/main/java/infra/cloud/RpcRequest.java @@ -22,17 +22,21 @@ import java.util.Arrays; import java.util.Objects; +import infra.cloud.serialize.Input; +import infra.cloud.serialize.Message; +import infra.cloud.serialize.Output; + /** * @author TODAY 2021/7/4 01:19 */ -public class RpcRequest implements Serializable { +public class RpcRequest implements Serializable, Message { @Serial private static final long serialVersionUID = 1L; - private String methodName; + private String serviceClass; - private String serviceName; + private String methodName; private Object[] arguments; @@ -72,12 +76,26 @@ public RpcMethod getRpcMethod() { return rpcMethod; } - public void setServiceName(String serviceName) { - this.serviceName = serviceName; + public void setServiceClass(String serviceName) { + this.serviceClass = serviceName; + } + + public String getServiceClass() { + return serviceClass; } - public String getServiceName() { - return serviceName; + @Override + public void writeTo(Output output) { + output.write(serviceClass); + output.write(methodName); + output.write(paramTypes, Output::write); + } + + @Override + public void readFrom(Input input) { + this.serviceClass = input.readString(); + this.methodName = input.readString(); + this.paramTypes = input.read(String.class, Input::readString); } @Override @@ -87,14 +105,14 @@ public boolean equals(Object o) { if (!(o instanceof RpcRequest request)) return false; return Objects.equals(methodName, request.methodName) - && Objects.equals(serviceName, request.serviceName) + && Objects.equals(serviceClass, request.serviceClass) && Arrays.equals(paramTypes, request.paramTypes) && Arrays.equals(arguments, request.arguments); } @Override public int hashCode() { - int result = Objects.hash(methodName, serviceName); + int result = Objects.hash(methodName, serviceClass); result = 31 * result + Arrays.hashCode(paramTypes); result = 31 * result + Arrays.hashCode(arguments); return result; @@ -104,7 +122,7 @@ public int hashCode() { public String toString() { return "RpcRequest{" + "method='" + methodName + '\'' + - ", serviceName='" + serviceName + '\'' + + ", serviceName='" + serviceClass + '\'' + ", paramTypes=" + Arrays.toString(paramTypes) + ", arguments=" + Arrays.toString(arguments) + '}'; diff --git a/today-service-api/src/main/java/infra/cloud/serialize/DefaultByteBufInput.java b/today-service-api/src/main/java/infra/cloud/serialize/DefaultByteBufInput.java index dbbba50..cffbce7 100644 --- a/today-service-api/src/main/java/infra/cloud/serialize/DefaultByteBufInput.java +++ b/today-service-api/src/main/java/infra/cloud/serialize/DefaultByteBufInput.java @@ -17,6 +17,7 @@ package infra.cloud.serialize; +import java.lang.reflect.Array; import java.nio.charset.StandardCharsets; import java.time.Instant; import java.util.ArrayList; @@ -26,6 +27,7 @@ import java.util.function.Function; import java.util.function.Supplier; +import infra.lang.Constant; import infra.util.CollectionUtils; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; @@ -59,6 +61,9 @@ public void read(byte[] b, int off, int len) { @Override public byte[] read(int len) { + if (len == 0) { + return Constant.EMPTY_BYTES; + } return ByteBufUtil.getBytes(buffer, buffer.readerIndex(), len); } @@ -121,7 +126,12 @@ public double readDouble() { @Override public String readString() { - return buffer.readString(readUnsignedShort(), StandardCharsets.UTF_8); + int length = readUnsignedShort(); + if (length == 0) { + return Constant.BLANK; + } + byte[] array = read(length); + return new String(array, StandardCharsets.UTF_8); } @Override @@ -134,6 +144,28 @@ public Instant readTimestamp() { return Instant.ofEpochSecond(buffer.readLong(), buffer.readInt()); } + @Override + @SuppressWarnings("unchecked") + public T[] read(Class type, Function mapper) { + int size = readInt(); + T[] array = (T[]) Array.newInstance(type, size); + for (int i = 0; i < size; i++) { + array[i] = mapper.apply(this); + } + return array; + } + + @Override + @SuppressWarnings("unchecked") + public T[] read(Class type, Supplier supplier) { + int size = readInt(); + T[] array = (T[]) Array.newInstance(type, size); + for (int i = 0; i < size; i++) { + array[i] = supplier.get(); + } + return array; + } + @Override public List read(Function mapper) { int size = readInt(); diff --git a/today-service-api/src/main/java/infra/cloud/serialize/DefaultByteBufOutput.java b/today-service-api/src/main/java/infra/cloud/serialize/DefaultByteBufOutput.java index 2491054..393debf 100644 --- a/today-service-api/src/main/java/infra/cloud/serialize/DefaultByteBufOutput.java +++ b/today-service-api/src/main/java/infra/cloud/serialize/DefaultByteBufOutput.java @@ -102,10 +102,15 @@ public void write(double v) { } @Override - public void write(String s) { - int length = s.length(); - buffer.writeShort(length); - buffer.writeCharSequence(s, StandardCharsets.UTF_8); + public void write(@Nullable String s) { + if (s == null || s.isEmpty()) { + buffer.writeShort(0); + } + else { + byte[] bytes = s.getBytes(StandardCharsets.UTF_8); + buffer.writeShort(bytes.length); + writeFully(bytes); + } } @Override @@ -129,6 +134,22 @@ public void write(Message message) { message.writeTo(this); } + @Override + public void write(T[] array, Consumer mapper) { + buffer.writeInt(array.length); + for (T t : array) { + mapper.accept(t); + } + } + + @Override + public void write(T[] array, BiConsumer mapper) { + buffer.writeInt(array.length); + for (T t : array) { + mapper.accept(this, t); + } + } + @Override public void write(List list, Consumer mapper) { int size = list.size(); diff --git a/today-service-api/src/main/java/infra/cloud/serialize/MessagePackInput.java b/today-service-api/src/main/java/infra/cloud/serialize/MessagePackInput.java index 200656d..d28a320 100644 --- a/today-service-api/src/main/java/infra/cloud/serialize/MessagePackInput.java +++ b/today-service-api/src/main/java/infra/cloud/serialize/MessagePackInput.java @@ -17,6 +17,7 @@ package infra.cloud.serialize; +import java.lang.reflect.Array; import java.math.BigInteger; import java.nio.charset.Charset; import java.time.Instant; @@ -81,6 +82,9 @@ public byte[] read() { @Override public byte[] read(int len) { + if (len == 0) { + return Constant.EMPTY_BYTES; + } return ByteBufUtil.getBytes(buffer, buffer.readerIndex(), len); } @@ -369,6 +373,28 @@ public Instant readTimestamp() { } } + @Override + @SuppressWarnings("unchecked") + public T[] read(Class type, Function mapper) { + int size = readArrayHeader(); + T[] array = (T[]) Array.newInstance(type, size); + for (int i = 0; i < size; i++) { + array[i] = mapper.apply(this); + } + return array; + } + + @Override + @SuppressWarnings("unchecked") + public T[] read(Class type, Supplier supplier) { + int size = readArrayHeader(); + T[] array = (T[]) Array.newInstance(type, size); + for (int i = 0; i < size; i++) { + array[i] = supplier.get(); + } + return array; + } + @Override public List read(Function mapper) { int size = readArrayHeader(); diff --git a/today-service-api/src/main/java/infra/cloud/serialize/MessagePackOutput.java b/today-service-api/src/main/java/infra/cloud/serialize/MessagePackOutput.java index 947e36c..c8b2a9a 100644 --- a/today-service-api/src/main/java/infra/cloud/serialize/MessagePackOutput.java +++ b/today-service-api/src/main/java/infra/cloud/serialize/MessagePackOutput.java @@ -324,6 +324,22 @@ public void writeTimestamp(long epochSecond, int nanoAdjustment) { } } + @Override + public void write(T[] array, Consumer mapper) { + writeArrayHeader(array.length); + for (T t : array) { + mapper.accept(t); + } + } + + @Override + public void write(T[] array, BiConsumer mapper) { + writeArrayHeader(array.length); + for (T t : array) { + mapper.accept(this, t); + } + } + @Override public void write(List list, Consumer mapper) { int size = list.size(); diff --git a/today-service-api/src/main/java/infra/cloud/serialize/ProtobufArgumentSerialization.java b/today-service-api/src/main/java/infra/cloud/serialize/ProtobufArgumentSerialization.java index d6cb505..87c919b 100644 --- a/today-service-api/src/main/java/infra/cloud/serialize/ProtobufArgumentSerialization.java +++ b/today-service-api/src/main/java/infra/cloud/serialize/ProtobufArgumentSerialization.java @@ -20,7 +20,6 @@ import com.google.protobuf.InvalidProtocolBufferException; import com.google.protobuf.Message; -import java.io.IOException; import java.lang.reflect.Method; import infra.cloud.RpcMethod; @@ -45,17 +44,21 @@ public boolean supportsArgument(MethodParameter parameter) { } @Override - public void serialize(MethodParameter parameter, @Nullable Message value, ByteBuf payload, Output output) throws IOException { - + public void serialize(MethodParameter parameter, @Nullable Message value, ByteBuf payload, Output output) throws SerializationException { + output.write(value == null ? null : value.toByteArray()); } @Override public Message deserialize(MethodParameter parameter, ByteBuf payload, Input input) throws SerializationException { Class parameterType = parameter.getParameterType(); Message.Builder messageBuilder = getMessageBuilder(parameterType); - -// return messageBuilder.mergeFrom(); - return null; + try { + byte[] bytes = input.read(); + return messageBuilder.mergeFrom(bytes).build(); + } + catch (InvalidProtocolBufferException e) { + throw new SerializationException("Invalid protocol buffer", e); + } } /** @@ -93,15 +96,7 @@ public void serialize(RpcMethod method, Message value, ByteBuf payload, Output o @Override public Message deserialize(RpcMethod method, ByteBuf payload, Input input) throws SerializationException { - Class parameterType = method.getReturnType().getParameterType(); - Message.Builder messageBuilder = getMessageBuilder(parameterType); - - try { - return messageBuilder.mergeFrom(input.read()).build(); - } - catch (InvalidProtocolBufferException e) { - throw new SerializationException("Invalid protocol buffer", e); - } + return deserialize(method.getReturnType(), payload, input); } } diff --git a/today-service-api/src/main/java/infra/cloud/serialize/RpcArgumentSerialization.java b/today-service-api/src/main/java/infra/cloud/serialize/RpcArgumentSerialization.java index f109c87..bfe7b02 100644 --- a/today-service-api/src/main/java/infra/cloud/serialize/RpcArgumentSerialization.java +++ b/today-service-api/src/main/java/infra/cloud/serialize/RpcArgumentSerialization.java @@ -17,8 +17,6 @@ package infra.cloud.serialize; -import java.io.IOException; - import infra.core.MethodParameter; import infra.lang.Nullable; import io.netty.buffer.ByteBuf; @@ -37,7 +35,7 @@ public interface RpcArgumentSerialization { */ boolean supportsArgument(MethodParameter parameter); - void serialize(MethodParameter parameter, @Nullable T value, ByteBuf payload, Output output) throws IOException; + void serialize(MethodParameter parameter, @Nullable T value, ByteBuf payload, Output output) throws SerializationException; @Nullable T deserialize(MethodParameter parameter, ByteBuf payload, Input input) throws SerializationException; diff --git a/today-service-api/src/main/java/infra/cloud/serialize/RpcRequestSerialization.java b/today-service-api/src/main/java/infra/cloud/serialize/RpcRequestSerialization.java index c2642ef..3ca8623 100644 --- a/today-service-api/src/main/java/infra/cloud/serialize/RpcRequestSerialization.java +++ b/today-service-api/src/main/java/infra/cloud/serialize/RpcRequestSerialization.java @@ -17,8 +17,6 @@ package infra.cloud.serialize; -import java.io.IOException; -import java.nio.charset.StandardCharsets; import java.util.List; import infra.cloud.RpcMethod; @@ -40,22 +38,15 @@ public RpcRequestSerialization(List argumentSerializat } @SuppressWarnings("unchecked") - public void serialize(RpcRequest request, ByteBuf payload) throws IOException { -// output.writeString(1, request.getMethodName(), true); -// output.writeString(2, request.getServiceName(), true); - - payload.writeInt(request.getMethodName().length()); - payload.writeCharSequence(request.getMethodName(), StandardCharsets.UTF_8); - - payload.writeInt(request.getServiceName().length()); - payload.writeCharSequence(request.getServiceName(), StandardCharsets.UTF_8); + public void serialize(RpcRequest request, ByteBuf payload) { + Output output = new MessagePackOutput(payload); + request.writeTo(output); RpcMethod rpcMethod = request.getRpcMethod(); int idx = 0; Object[] arguments = request.getArguments(); - Output output = new DefaultByteBufOutput(payload); beforeSerializeArguments(output, arguments); for (MethodParameter parameter : rpcMethod.getParameters()) { var serialization = findArgumentSerialization(parameter); diff --git a/today-service-client/src/main/java/infra/cloud/service/MethodServiceInvocation.java b/today-service-client/src/main/java/infra/cloud/service/MethodServiceInvocation.java index d08d533..efadfdf 100644 --- a/today-service-client/src/main/java/infra/cloud/service/MethodServiceInvocation.java +++ b/today-service-client/src/main/java/infra/cloud/service/MethodServiceInvocation.java @@ -25,7 +25,7 @@ */ public abstract class MethodServiceInvocation extends AttributeAccessorSupport implements ServiceInvocation { - private final ServiceInterfaceMethod serviceMethod; + protected final ServiceInterfaceMethod serviceMethod; private final Object[] args; diff --git a/today-service-client/src/main/java/infra/cloud/service/ServiceMethodInvoker.java b/today-service-client/src/main/java/infra/cloud/service/ServiceMethodInvoker.java index 57a87e3..8eff659 100644 --- a/today-service-client/src/main/java/infra/cloud/service/ServiceMethodInvoker.java +++ b/today-service-client/src/main/java/infra/cloud/service/ServiceMethodInvoker.java @@ -21,13 +21,17 @@ import org.reactivestreams.Subscriber; import org.reactivestreams.Subscription; +import infra.cloud.RpcRequest; import infra.cloud.serialize.RpcRequestSerialization; import infra.lang.Nullable; import infra.remoting.Payload; import infra.remoting.RemotingOperations; +import infra.remoting.util.ByteBufPayload; import infra.util.concurrent.Future; import infra.util.concurrent.FutureListener; import infra.util.concurrent.Promise; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import reactor.core.publisher.Operators; @@ -79,8 +83,16 @@ protected InvocationResult invokeRemoting() { } private Mono createMonoPayload() { - - return null; + return Mono.defer(() -> { + RpcRequest request = new RpcRequest(); + request.setServiceClass(serviceMethod.getServiceInterface().getName()); + request.setMethodName(serviceMethod.getMethod().getName()); + + ByteBuf buffer = Unpooled.buffer(); + Payload payload = ByteBufPayload.create(buffer); + requestSerialization.serialize(request, buffer); + return Mono.just(payload); + }); } @SuppressWarnings("unchecked") diff --git a/today-service-provider/src/main/java/infra/cloud/provider/RpcRequestDeserializer.java b/today-service-provider/src/main/java/infra/cloud/provider/RpcRequestDeserializer.java index f27cfe0..966262f 100644 --- a/today-service-provider/src/main/java/infra/cloud/provider/RpcRequestDeserializer.java +++ b/today-service-provider/src/main/java/infra/cloud/provider/RpcRequestDeserializer.java @@ -18,14 +18,14 @@ package infra.cloud.provider; import java.lang.reflect.Method; -import java.nio.charset.StandardCharsets; -import java.util.Arrays; import java.util.List; import java.util.Objects; import infra.cloud.RpcRequest; +import infra.cloud.serialize.MessagePackInput; import infra.cloud.serialize.RpcArgumentSerialization; import infra.cloud.serialize.SerializationException; +import infra.core.MethodParameter; import infra.lang.Nullable; import infra.reflect.MethodInvoker; import infra.util.ClassUtils; @@ -49,25 +49,46 @@ public RpcRequestDeserializer(List argumentSerializati } public RpcRequest deserialize(ByteBuf payload) throws SerializationException { - RpcRequest rpcRequest = new RpcRequest(); -// ByteBufInput input = new ByteBufInput(payload); + MessagePackInput input = new MessagePackInput(payload); - rpcRequest.setMethodName(payload.readCharSequence(payload.readInt(), StandardCharsets.UTF_8).toString()); - rpcRequest.setServiceName(payload.readCharSequence(payload.readInt(), StandardCharsets.UTF_8).toString()); + RpcRequest request = new RpcRequest(); + request.readFrom(input); - InvocableRpcMethod rpcMethod = methodMapCache.get(new MethodCacheKey(rpcRequest), null); + InvocableRpcMethod rpcMethod = methodMapCache.get(new MethodKey(request.getMethodName(), request.getParamTypes()), null); -// body.readInt(); -// body.readCharSequence(); + if (rpcMethod == null) { + throw new IllegalStateException("No method found for method: " + request.getMethodName()); + } + + request.setRpcMethod(rpcMethod); + + MethodParameter[] parameters = rpcMethod.getParameters(); + Object[] args = new Object[parameters.length]; + + int idx = 0; + for (MethodParameter parameter : parameters) { + var serialization = findArgumentSerialization(parameter); + args[idx++] = serialization.deserialize(parameter, payload, input); + } - return rpcRequest; + request.setArguments(args); + return request; + } + + private RpcArgumentSerialization findArgumentSerialization(MethodParameter parameter) { + for (var argumentSerialization : argumentSerializations) { + if (argumentSerialization.supportsArgument(parameter)) { + return argumentSerialization; + } + } + throw new IllegalStateException("RpcArgumentSerialization for parameter %s not found".formatted(parameter)); } - private static final class MethodMapCache extends MapCache { + private static final class MethodMapCache extends MapCache { @Nullable @Override - protected InvocableRpcMethod createValue(MethodCacheKey key, @Nullable Object service) { + protected InvocableRpcMethod createValue(MethodKey key, @Nullable Object service) { Method methodToUse = getMethod(key, service); if (methodToUse == null) { return null; @@ -76,7 +97,7 @@ protected InvocableRpcMethod createValue(MethodCacheKey key, @Nullable Object se return new InvocableRpcMethod(methodToUse, methodInvoker); } - private static Method getMethod(MethodCacheKey key, Object service) { + private static Method getMethod(MethodKey key, Object service) { String method = key.method; String[] paramTypes = key.paramTypes; int parameterLength = paramTypes.length; @@ -103,30 +124,8 @@ private static Method getMethod(MethodCacheKey key, Object service) { } } - private static class MethodCacheKey { - public final String method; + private record MethodKey(String method, String[] paramTypes) { - public final String[] paramTypes; - - MethodCacheKey(RpcRequest request) { - this.method = request.getMethodName(); - this.paramTypes = request.getParamTypes(); - } - - @Override - public boolean equals(Object o) { - if (this == o) - return true; - if (!(o instanceof MethodCacheKey that)) - return false; - return Objects.equals(method, that.method) - && Arrays.equals(paramTypes, that.paramTypes); - } - - @Override - public int hashCode() { - return 31 * Objects.hash(method) + Arrays.hashCode(paramTypes); - } } } diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/Input.java b/today-service-serialization/src/main/java/infra/cloud/serialize/Input.java index c4c04d9..796982b 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/Input.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/Input.java @@ -176,6 +176,22 @@ public interface Input { */ void read(Message message); + /** + * Reads a {@code array} value. + * + * @return a array object. + * @throws SerializationException if a serialization error occurs. + */ + T[] read(Class type, Function mapper); + + /** + * Reads a {@code array} value. + * + * @return a array object. + * @throws SerializationException if a serialization error occurs. + */ + T[] read(Class type, Supplier supplier); + /** * Reads a {@link List} value. * diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/Output.java b/today-service-serialization/src/main/java/infra/cloud/serialize/Output.java index df462a8..cfccaef 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/Output.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/Output.java @@ -122,7 +122,7 @@ public interface Output { * @param s the string value to be written. * @throws SerializationException if a serialization error occurs. */ - void write(String s); + void write(@Nullable String s); /** * Writes a Timestamp value. @@ -157,6 +157,22 @@ public interface Output { */ void write(Message message); + /** + * Writes a {@code array} value. + * + * @param array the array value to be written. + * @throws SerializationException if a serialization error occurs. + */ + void write(T[] array, Consumer mapper); + + /** + * Writes a {@code array} value. + * + * @param array the array value to be written. + * @throws SerializationException if a serialization error occurs. + */ + void write(T[] array, BiConsumer mapper); + /** * Writes a {@code List} value. * From f54a6da764d4b3ef1d671cd10fd70a8c67495fa2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Thu, 21 Aug 2025 23:09:23 +0800 Subject: [PATCH 045/104] =?UTF-8?q?:art:=20=E5=BA=8F=E5=88=97=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../micrometer/MicrometerChannel.java | 17 +- .../micrometer/MicrometerConnection.java | 25 +-- .../java/infra/remoting/ChannelWrapper.java | 4 +- .../infra/remoting/ConnectionWrapper.java | 5 +- .../infra/remoting/RemotingException.java | 7 - .../infra/remoting/core/ReassemblyUtils.java | 47 ++--- .../infra/remoting/core/RemotingServer.java | 9 +- .../src/main/java/infra/cloud/RpcMethod.java | 78 ------- .../src/main/java/infra/cloud/RpcRequest.java | 11 +- .../main/java/infra/cloud/RpcResponse.java | 40 ++-- .../cloud/serialize/DefaultByteBufInput.java | 199 ------------------ .../cloud/serialize/DefaultByteBufOutput.java | 50 ++--- .../cloud/serialize/MessagePackInput.java | 48 +++++ .../cloud/serialize/MessagePackOutput.java | 60 +++--- .../ProtobufArgumentSerialization.java | 21 +- .../serialize/ReturnValueDeserializer.java | 33 +++ .../serialize/ReturnValueSerialization.java | 19 +- .../serialize/ReturnValueSerializer.java | 33 +++ .../serialize/RpcArgumentSerialization.java | 6 +- .../serialize/RpcRequestSerialization.java | 8 +- .../serialize/RpcResponseSerialization.java | 33 +-- .../SimpleValueArgumentSerialization.java | 33 +-- .../value/FuncValueSerialization.java | 16 +- .../serialize/value/ValueSerialization.java | 12 +- ...tractServiceInterfaceMetadataProvider.java | 2 +- .../infra/cloud/service/ServiceMethod.java | 37 +++- today-service-client/build.gradle | 3 +- .../DefaultRemotingOperationsProvider.java | 8 +- ...faultServiceInterfaceMetadataProvider.java | 4 +- .../service/DefaultServiceProxyFactory.java | 5 +- .../cloud/service/ServiceInterfaceMethod.java | 33 --- .../cloud/service/ServiceInvocation.java | 2 +- .../cloud/service/ServiceMethodInvoker.java | 13 +- today-service-provider/build.gradle | 19 +- ...faultServiceInterfaceMetadataProvider.java | 42 ++++ ...bleRpcMethod.java => InvocableMethod.java} | 9 +- .../cloud/provider/LocalServiceHolder.java | 25 ++- .../provider/RpcRequestDeserializer.java | 49 +++-- .../cloud/provider/ServiceChannelHandler.java | 58 +++++ .../cloud/provider/ServiceProviderServer.java | 85 ++++++++ .../ServiceProviderAutoConfiguration.java | 33 +++ .../infra/cloud/provider/package-info.java | 23 ++ .../src/main/resources/application.properties | 18 -- .../java/infra/cloud/serialize/Input.java | 5 + .../java/infra/cloud/serialize/Output.java | 44 ++-- 45 files changed, 676 insertions(+), 655 deletions(-) delete mode 100644 today-service-api/src/main/java/infra/cloud/RpcMethod.java delete mode 100644 today-service-api/src/main/java/infra/cloud/serialize/DefaultByteBufInput.java create mode 100644 today-service-api/src/main/java/infra/cloud/serialize/ReturnValueDeserializer.java create mode 100644 today-service-api/src/main/java/infra/cloud/serialize/ReturnValueSerializer.java create mode 100644 today-service-provider/src/main/java/infra/cloud/provider/DefaultServiceInterfaceMetadataProvider.java rename today-service-provider/src/main/java/infra/cloud/provider/{InvocableRpcMethod.java => InvocableMethod.java} (76%) create mode 100644 today-service-provider/src/main/java/infra/cloud/provider/ServiceChannelHandler.java create mode 100644 today-service-provider/src/main/java/infra/cloud/provider/ServiceProviderServer.java create mode 100644 today-service-provider/src/main/java/infra/cloud/provider/package-info.java delete mode 100644 today-service-registry/src/main/resources/application.properties diff --git a/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/MicrometerChannel.java b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/MicrometerChannel.java index fbf58a1..78f31b3 100644 --- a/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/MicrometerChannel.java +++ b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/MicrometerChannel.java @@ -24,6 +24,7 @@ import java.util.function.Consumer; import infra.remoting.Channel; +import infra.remoting.ChannelWrapper; import infra.remoting.Payload; import io.micrometer.core.instrument.Counter; import io.micrometer.core.instrument.Meter; @@ -50,9 +51,7 @@ * * @see Micrometer */ -final class MicrometerChannel implements Channel { - - private final Channel delegate; +final class MicrometerChannel extends ChannelWrapper { private final InteractionCounters metadataPush; @@ -73,7 +72,7 @@ final class MicrometerChannel implements Channel { * @throws NullPointerException if {@code delegate} or {@code meterRegistry} is {@code null} */ MicrometerChannel(Channel delegate, MeterRegistry meterRegistry, Tag... tags) { - this.delegate = Objects.requireNonNull(delegate, "delegate is required"); + super(delegate); Objects.requireNonNull(meterRegistry, "meterRegistry is required"); this.metadataPush = new InteractionCounters(meterRegistry, "metadata.push", tags); @@ -83,11 +82,6 @@ final class MicrometerChannel implements Channel { this.requestStream = new InteractionCounters(meterRegistry, "request.stream", tags); } - @Override - public void dispose() { - delegate.dispose(); - } - @Override public Mono fireAndForget(Payload payload) { return delegate.fireAndForget(payload).doFinally(requestFireAndForget); @@ -98,11 +92,6 @@ public Mono metadataPush(Payload payload) { return delegate.metadataPush(payload).doFinally(metadataPush); } - @Override - public Mono onClose() { - return delegate.onClose(); - } - @Override public Flux requestChannel(Publisher payloads) { return delegate.requestChannel(payloads).doFinally(requestChannel); diff --git a/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/MicrometerConnection.java b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/MicrometerConnection.java index 287e7c5..d0b5d0c 100644 --- a/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/MicrometerConnection.java +++ b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/MicrometerConnection.java @@ -17,14 +17,13 @@ package infra.remoting.micrometer; -import java.net.SocketAddress; import java.util.Objects; import java.util.function.Consumer; import infra.logging.Logger; import infra.logging.LoggerFactory; import infra.remoting.Connection; -import infra.remoting.ProtocolErrorException; +import infra.remoting.ConnectionWrapper; import infra.remoting.frame.FrameHeaderCodec; import infra.remoting.frame.FrameType; import infra.remoting.plugins.ConnectionDecorator.Type; @@ -34,7 +33,6 @@ import io.micrometer.core.instrument.Tag; import io.micrometer.core.instrument.Tags; import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufAllocator; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; @@ -69,12 +67,10 @@ * * @see Micrometer */ -final class MicrometerConnection implements Connection { +final class MicrometerConnection extends ConnectionWrapper { private final Counter close; - private final Connection delegate; - private final Counter dispose; private final FrameCounters frameCounters; @@ -90,8 +86,8 @@ final class MicrometerConnection implements Connection { * meterRegistry} is {@code null} */ MicrometerConnection(Type connectionType, Connection delegate, MeterRegistry meterRegistry, Tag... tags) { + super(delegate); Objects.requireNonNull(connectionType, "connectionType is required"); - this.delegate = Objects.requireNonNull(delegate, "delegate is required"); Objects.requireNonNull(meterRegistry, "meterRegistry is required"); this.close = meterRegistry.counter("infra.remoting.duplex.connection.close", @@ -103,16 +99,6 @@ final class MicrometerConnection implements Connection { this.frameCounters = new FrameCounters(connectionType, meterRegistry, tags); } - @Override - public ByteBufAllocator alloc() { - return delegate.alloc(); - } - - @Override - public SocketAddress remoteAddress() { - return delegate.remoteAddress(); - } - @Override public void dispose() { delegate.dispose(); @@ -135,11 +121,6 @@ public void sendFrame(int streamId, ByteBuf frame) { delegate.sendFrame(streamId, frame); } - @Override - public void sendErrorAndClose(ProtocolErrorException e) { - delegate.sendErrorAndClose(e); - } - private static final class FrameCounters implements Consumer { private final Logger logger = LoggerFactory.getLogger(this.getClass()); diff --git a/today-remoting/src/main/java/infra/remoting/ChannelWrapper.java b/today-remoting/src/main/java/infra/remoting/ChannelWrapper.java index 9b1ea38..f4b9a51 100644 --- a/today-remoting/src/main/java/infra/remoting/ChannelWrapper.java +++ b/today-remoting/src/main/java/infra/remoting/ChannelWrapper.java @@ -19,6 +19,8 @@ import org.reactivestreams.Publisher; +import java.util.Objects; + import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; @@ -30,7 +32,7 @@ public class ChannelWrapper implements Channel { protected final Channel delegate; public ChannelWrapper(Channel delegate) { - this.delegate = delegate; + this.delegate = Objects.requireNonNull(delegate, "delegate is required"); } @Override diff --git a/today-remoting/src/main/java/infra/remoting/ConnectionWrapper.java b/today-remoting/src/main/java/infra/remoting/ConnectionWrapper.java index 9bfe6c6..feb3737 100644 --- a/today-remoting/src/main/java/infra/remoting/ConnectionWrapper.java +++ b/today-remoting/src/main/java/infra/remoting/ConnectionWrapper.java @@ -18,6 +18,7 @@ package infra.remoting; import java.net.SocketAddress; +import java.util.Objects; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufAllocator; @@ -30,10 +31,10 @@ */ public class ConnectionWrapper implements Connection { - private final Connection delegate; + protected final Connection delegate; public ConnectionWrapper(Connection delegate) { - this.delegate = delegate; + this.delegate = Objects.requireNonNull(delegate, "delegate is required"); } @Override diff --git a/today-remoting/src/main/java/infra/remoting/RemotingException.java b/today-remoting/src/main/java/infra/remoting/RemotingException.java index 06be903..2616982 100644 --- a/today-remoting/src/main/java/infra/remoting/RemotingException.java +++ b/today-remoting/src/main/java/infra/remoting/RemotingException.java @@ -30,13 +30,6 @@ public class RemotingException extends RuntimeException { @Serial private static final long serialVersionUID = 1L; - public RemotingException() { - } - - public RemotingException(@Nullable String message) { - super(message); - } - public RemotingException(@Nullable String message, @Nullable Throwable cause) { super(message, cause); } diff --git a/today-remoting/src/main/java/infra/remoting/core/ReassemblyUtils.java b/today-remoting/src/main/java/infra/remoting/core/ReassemblyUtils.java index 633c9f3..a994999 100644 --- a/today-remoting/src/main/java/infra/remoting/core/ReassemblyUtils.java +++ b/today-remoting/src/main/java/infra/remoting/core/ReassemblyUtils.java @@ -14,6 +14,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see [http://www.gnu.org/licenses/] */ + package infra.remoting.core; import org.reactivestreams.Subscription; @@ -40,8 +41,8 @@ import static infra.remoting.frame.FrameLengthCodec.FRAME_LENGTH_MASK; class ReassemblyUtils { - static final String ILLEGAL_REASSEMBLED_PAYLOAD_SIZE = - "Reassembled payload size went out of allowed %s bytes"; + + static final String ILLEGAL_REASSEMBLED_PAYLOAD_SIZE = "Reassembled payload size went out of allowed %s bytes"; @SuppressWarnings("ConstantConditions") static void release(RequesterFrameHandler framesHolder, long state) { @@ -52,7 +53,7 @@ static void release(RequesterFrameHandler framesHolder, long state) { } } - @SuppressWarnings({ "ConstantConditions", "SynchronizationOnLocalVariableOrMethodParameter" }) + @SuppressWarnings({ "ConstantConditions" }) static void synchronizedRelease(RequesterFrameHandler framesHolder, long state) { if (isReassembling(state)) { final CompositeByteBuf frames = framesHolder.getFrames(); @@ -64,17 +65,9 @@ static void synchronizedRelease(RequesterFrameHandler framesHolder, long state) } } - static void handleNextSupport( - AtomicLongFieldUpdater updater, - T instance, - Subscription subscription, - CoreSubscriber inboundSubscriber, - PayloadDecoder payloadDecoder, - ByteBufAllocator allocator, - int maxInboundPayloadSize, - ByteBuf frame, - boolean hasFollows, - boolean isLastPayload) { + static void handleNextSupport(AtomicLongFieldUpdater updater, + T instance, Subscription subscription, CoreSubscriber inboundSubscriber, PayloadDecoder payloadDecoder, + ByteBufAllocator allocator, int maxInboundPayloadSize, ByteBuf frame, boolean hasFollows, boolean isLastPayload) { long state = updater.get(instance); if (isTerminated(state)) { @@ -104,9 +97,7 @@ static void handleNextSupport( CompositeByteBuf frames = instance.getFrames(); if (frames == null) { - frames = - ReassemblyUtils.addFollowingFrame( - allocator.compositeBuffer(), frame, hasFollows, maxInboundPayloadSize); + frames = ReassemblyUtils.addFollowingFrame(allocator.compositeBuffer(), frame, hasFollows, maxInboundPayloadSize); instance.setFrames(frames); long previousState = markReassembling(updater, instance); @@ -118,8 +109,7 @@ static void handleNextSupport( } else { try { - frames = - ReassemblyUtils.addFollowingFrame(frames, frame, hasFollows, maxInboundPayloadSize); + frames = ReassemblyUtils.addFollowingFrame(frames, frame, hasFollows, maxInboundPayloadSize); } catch (IllegalStateException t) { if (isTerminated(updater.get(instance))) { @@ -167,18 +157,13 @@ static void handleNextSupport( } } - static CompositeByteBuf addFollowingFrame( - CompositeByteBuf frames, - ByteBuf followingFrame, - boolean hasFollows, - int maxInboundPayloadSize) { + static CompositeByteBuf addFollowingFrame(CompositeByteBuf frames, ByteBuf followingFrame, boolean hasFollows, int maxInboundPayloadSize) { int readableBytes = frames.readableBytes(); if (readableBytes == 0) { return frames.addComponent(true, followingFrame.retain()); } else if (maxInboundPayloadSize != Integer.MAX_VALUE - && readableBytes + followingFrame.readableBytes() - FrameHeaderCodec.size() - > maxInboundPayloadSize) { + && readableBytes + followingFrame.readableBytes() - FrameHeaderCodec.size() > maxInboundPayloadSize) { throw new IllegalStateException( String.format(ILLEGAL_REASSEMBLED_PAYLOAD_SIZE, maxInboundPayloadSize)); } @@ -196,8 +181,7 @@ else if (followingFrame.readableBytes() < MIN_MTU_SIZE - 3 && hasFollows) { // CompositeByteBuf if (hasMetadata) { final FrameType frameType = FrameHeaderCodec.frameType(frames); - final int lengthFieldPosition = - FrameHeaderCodec.size() + (frameType.hasInitialRequestN() ? Integer.BYTES : 0); + final int lengthFieldPosition = FrameHeaderCodec.size() + (frameType.hasInitialRequestN() ? Integer.BYTES : 0); frames.markReaderIndex(); frames.skipBytes(lengthFieldPosition); @@ -245,11 +229,8 @@ private static int decodeLength(final ByteBuf byteBuf) { static int assertInboundPayloadSize(int inboundPayloadSize) { if (inboundPayloadSize < MIN_MTU_SIZE) { - String msg = - String.format( - "The min allowed inboundPayloadSize size is %d bytes, provided: %d", - FrameLengthCodec.FRAME_LENGTH_MASK, inboundPayloadSize); - throw new IllegalArgumentException(msg); + throw new IllegalArgumentException("The min allowed inboundPayloadSize size is %d bytes, provided: %d" + .formatted(FrameLengthCodec.FRAME_LENGTH_MASK, inboundPayloadSize)); } else { return inboundPayloadSize; diff --git a/today-remoting/src/main/java/infra/remoting/core/RemotingServer.java b/today-remoting/src/main/java/infra/remoting/core/RemotingServer.java index aca5fbc..c0d5ebc 100644 --- a/today-remoting/src/main/java/infra/remoting/core/RemotingServer.java +++ b/today-remoting/src/main/java/infra/remoting/core/RemotingServer.java @@ -46,6 +46,7 @@ import io.netty.buffer.ByteBuf; import reactor.core.publisher.Mono; import reactor.core.publisher.Sinks; +import reactor.core.scheduler.Schedulers; import static infra.remoting.core.FragmentationUtils.assertMtu; import static infra.remoting.core.PayloadValidationUtils.assertValidateSetup; @@ -154,7 +155,7 @@ public RemotingServer interceptors(Consumer configurer) { *

          Use the {@link Resume} argument to customize the Resume session duration, storage, retry * logic, and others. * - *

          By default this is not enabled. + *

          By default, this is not enabled. * * @param resume configuration for the Resume capability * @return the same instance for method chaining @@ -237,7 +238,7 @@ public RemotingServer maxTimeToFirstFrame(Duration timeout) { * When this is set, frames larger than the given maximum transmission unit (mtu) size value are * fragmented. * - *

          By default this is not set in which case payloads are sent whole up to the maximum frame + *

          By default, this is not set in which case payloads are sent whole up to the maximum frame * size of 16,777,215 bytes. * * @param mtu the threshold size for fragmentation, must be no less than 64 @@ -292,8 +293,8 @@ public Mono get() { int maxFrameLength = transport.getMaxFrameLength(); assertValidateSetup(maxFrameLength, maxInboundPayloadSize, mtu); return transport - .start(duplexConnection -> acceptor(serverSetup, duplexConnection, maxFrameLength)) -// .publishOn(Schedulers.boundedElastic()) + .start(connection -> acceptor(serverSetup, connection, maxFrameLength)) + .publishOn(Schedulers.boundedElastic()) .doOnNext(c -> c.onClose().doFinally(v -> serverSetup.dispose()).subscribe()); } }); diff --git a/today-service-api/src/main/java/infra/cloud/RpcMethod.java b/today-service-api/src/main/java/infra/cloud/RpcMethod.java deleted file mode 100644 index 0fd579d..0000000 --- a/today-service-api/src/main/java/infra/cloud/RpcMethod.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright 2021 - 2024 the original author or authors. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] - */ - -package infra.cloud; - -import java.lang.reflect.Method; - -import infra.core.MethodParameter; -import infra.core.style.ToStringBuilder; -import infra.lang.Nullable; - -/** - * @author 海子 Yang - * @since 1.0 2024/12/20 16:39 - */ -public class RpcMethod { - - private final Method method; - - private final MethodParameter[] parameters; - - @Nullable - private MethodParameter returnTypeParameter; - - public RpcMethod(Method method) { - this.method = method; - this.parameters = initMethodParameters(method); - } - - private MethodParameter[] initMethodParameters(Method method) { - int count = method.getParameterCount(); - MethodParameter[] result = new MethodParameter[count]; - for (int i = 0; i < count; i++) { - result[i] = new MethodParameter(method, i); - } - return result; - } - - public Method getMethod() { - return method; - } - - public MethodParameter[] getParameters() { - return parameters; - } - - public MethodParameter getReturnType() { - MethodParameter returnType = returnTypeParameter; - if (returnType == null) { - returnType = MethodParameter.forExecutable(method, -1); - this.returnTypeParameter = returnType; - } - return returnType; - } - - @Override - public String toString() { - return ToStringBuilder.forInstance(this) - .append("parameters", parameters) - .append("method", method) - .toString(); - } - -} diff --git a/today-service-api/src/main/java/infra/cloud/RpcRequest.java b/today-service-api/src/main/java/infra/cloud/RpcRequest.java index ddb369b..17570ba 100644 --- a/today-service-api/src/main/java/infra/cloud/RpcRequest.java +++ b/today-service-api/src/main/java/infra/cloud/RpcRequest.java @@ -25,6 +25,7 @@ import infra.cloud.serialize.Input; import infra.cloud.serialize.Message; import infra.cloud.serialize.Output; +import infra.cloud.service.ServiceMethod; /** * @author TODAY 2021/7/4 01:19 @@ -42,7 +43,7 @@ public class RpcRequest implements Serializable, Message { private String[] paramTypes; - private RpcMethod rpcMethod; + private ServiceMethod method; public void setArguments(Object[] arguments) { this.arguments = arguments; @@ -68,12 +69,12 @@ public String getMethodName() { return methodName; } - public void setRpcMethod(RpcMethod rpcMethod) { - this.rpcMethod = rpcMethod; + public void setMethod(ServiceMethod method) { + this.method = method; } - public RpcMethod getRpcMethod() { - return rpcMethod; + public ServiceMethod getMethod() { + return method; } public void setServiceClass(String serviceName) { diff --git a/today-service-api/src/main/java/infra/cloud/RpcResponse.java b/today-service-api/src/main/java/infra/cloud/RpcResponse.java index 9f0a357..4c0e06f 100644 --- a/today-service-api/src/main/java/infra/cloud/RpcResponse.java +++ b/today-service-api/src/main/java/infra/cloud/RpcResponse.java @@ -20,6 +20,7 @@ import java.io.Serial; import java.io.Serializable; +import infra.cloud.service.ServiceMethod; import infra.lang.Nullable; /** @@ -27,40 +28,42 @@ */ public class RpcResponse implements Serializable { - public static final RpcResponse empty = new RpcResponse(); - @Serial private static final long serialVersionUID = 1L; /** service result */ + + @Nullable private Object result; @Nullable private Throwable exception; @Nullable - private RpcMethod rpcMethod; + private ServiceMethod method; - public RpcResponse() { } + public RpcResponse() { + } - public RpcResponse(@Nullable RpcMethod rpcMethod, Object result) { - this.rpcMethod = rpcMethod; + public RpcResponse(@Nullable ServiceMethod method, Object result) { + this.method = method; this.result = result; } - public void setRpcMethod(@Nullable RpcMethod rpcMethod) { - this.rpcMethod = rpcMethod; + public void setMethod(@Nullable ServiceMethod rpcMethod) { + this.method = rpcMethod; } @Nullable - public RpcMethod getRpcMethod() { - return rpcMethod; + public ServiceMethod getMethod() { + return method; } - public void setResult(Object result) { + public void setResult(@Nullable Object result) { this.result = result; } + @Nullable public Object getResult() { return result; } @@ -74,19 +77,4 @@ public void setException(@Nullable Throwable exception) { this.exception = exception; } - // static - - public static RpcResponse ofThrowable(@Nullable Throwable throwable) { - final RpcResponse rpcResponse = new RpcResponse(); - rpcResponse.setException(throwable); - return rpcResponse; - } - - public static RpcResponse ofThrowable(RpcMethod rpcMethod, @Nullable Throwable throwable) { - final RpcResponse rpcResponse = new RpcResponse(); - rpcResponse.setException(throwable); - rpcResponse.setRpcMethod(rpcMethod); - return rpcResponse; - } - } diff --git a/today-service-api/src/main/java/infra/cloud/serialize/DefaultByteBufInput.java b/today-service-api/src/main/java/infra/cloud/serialize/DefaultByteBufInput.java deleted file mode 100644 index cffbce7..0000000 --- a/today-service-api/src/main/java/infra/cloud/serialize/DefaultByteBufInput.java +++ /dev/null @@ -1,199 +0,0 @@ -/* - * Copyright 2021 - 2024 the original author or authors. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] - */ - -package infra.cloud.serialize; - -import java.lang.reflect.Array; -import java.nio.charset.StandardCharsets; -import java.time.Instant; -import java.util.ArrayList; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.function.Function; -import java.util.function.Supplier; - -import infra.lang.Constant; -import infra.util.CollectionUtils; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufUtil; - -/** - * @author 海子 Yang - * @since 1.0 2024/12/20 21:35 - */ -public class DefaultByteBufInput implements Input { - - private final ByteBuf buffer; - - public DefaultByteBufInput(ByteBuf buffer) { - this.buffer = buffer; - } - - @Override - public void read(byte[] b) { - buffer.readBytes(b); - } - - @Override - public byte[] read() { - return read(buffer.readInt()); - } - - @Override - public void read(byte[] b, int off, int len) { - buffer.readBytes(b, off, len); - } - - @Override - public byte[] read(int len) { - if (len == 0) { - return Constant.EMPTY_BYTES; - } - return ByteBufUtil.getBytes(buffer, buffer.readerIndex(), len); - } - - @Override - public byte[] readFully() { - return ByteBufUtil.getBytes(buffer); - } - - @Override - public int skipBytes(int n) { - int start = buffer.readerIndex(); - buffer.skipBytes(n); - return start - buffer.readerIndex(); - } - - @Override - public boolean readBoolean() { - return buffer.readBoolean(); - } - - @Override - public byte readByte() { - return buffer.readByte(); - } - - @Override - public int readUnsignedByte() { - return buffer.readUnsignedByte(); - } - - @Override - public short readShort() { - return buffer.readShort(); - } - - @Override - public int readUnsignedShort() { - return buffer.readUnsignedShort(); - } - - @Override - public int readInt() { - return buffer.readInt(); - } - - @Override - public long readLong() { - return buffer.readLong(); - } - - @Override - public float readFloat() { - return buffer.readFloat(); - } - - @Override - public double readDouble() { - return buffer.readDouble(); - } - - @Override - public String readString() { - int length = readUnsignedShort(); - if (length == 0) { - return Constant.BLANK; - } - byte[] array = read(length); - return new String(array, StandardCharsets.UTF_8); - } - - @Override - public void read(Message message) { - message.readFrom(this); - } - - @Override - public Instant readTimestamp() { - return Instant.ofEpochSecond(buffer.readLong(), buffer.readInt()); - } - - @Override - @SuppressWarnings("unchecked") - public T[] read(Class type, Function mapper) { - int size = readInt(); - T[] array = (T[]) Array.newInstance(type, size); - for (int i = 0; i < size; i++) { - array[i] = mapper.apply(this); - } - return array; - } - - @Override - @SuppressWarnings("unchecked") - public T[] read(Class type, Supplier supplier) { - int size = readInt(); - T[] array = (T[]) Array.newInstance(type, size); - for (int i = 0; i < size; i++) { - array[i] = supplier.get(); - } - return array; - } - - @Override - public List read(Function mapper) { - int size = readInt(); - ArrayList result = new ArrayList<>(size); - for (int i = 0; i < size; i++) { - result.add(mapper.apply(this)); - } - return result; - } - - @Override - public List read(Supplier supplier) { - int size = readInt(); - ArrayList result = new ArrayList<>(size); - for (int i = 0; i < size; i++) { - result.add(supplier.get()); - } - return result; - } - - @Override - public Map read(Function keyMapper, Function valueMapper) { - int size = readInt(); - LinkedHashMap result = CollectionUtils.newLinkedHashMap(size); - for (int i = 0; i < size; i++) { - result.put(keyMapper.apply(this), valueMapper.apply(this)); - } - return result; - } - -} diff --git a/today-service-api/src/main/java/infra/cloud/serialize/DefaultByteBufOutput.java b/today-service-api/src/main/java/infra/cloud/serialize/DefaultByteBufOutput.java index 393debf..a33b4e2 100644 --- a/today-service-api/src/main/java/infra/cloud/serialize/DefaultByteBufOutput.java +++ b/today-service-api/src/main/java/infra/cloud/serialize/DefaultByteBufOutput.java @@ -102,12 +102,12 @@ public void write(double v) { } @Override - public void write(@Nullable String s) { - if (s == null || s.isEmpty()) { + public void write(@Nullable String v) { + if (v == null || v.isEmpty()) { buffer.writeShort(0); } else { - byte[] bytes = s.getBytes(StandardCharsets.UTF_8); + byte[] bytes = v.getBytes(StandardCharsets.UTF_8); buffer.writeShort(bytes.length); writeFully(bytes); } @@ -119,8 +119,8 @@ public void writeTimestamp(long millis) { } @Override - public void write(Instant instant) { - writeTimestamp(instant.getEpochSecond(), instant.getNano()); + public void write(Instant v) { + writeTimestamp(v.getEpochSecond(), v.getNano()); } @Override @@ -130,59 +130,59 @@ public void writeTimestamp(long epochSecond, int nanoAdjustment) throws Arithmet } @Override - public void write(Message message) { - message.writeTo(this); + public void write(Message v) { + v.writeTo(this); } @Override - public void write(T[] array, Consumer mapper) { - buffer.writeInt(array.length); - for (T t : array) { + public void write(T[] v, Consumer mapper) { + buffer.writeInt(v.length); + for (T t : v) { mapper.accept(t); } } @Override - public void write(T[] array, BiConsumer mapper) { - buffer.writeInt(array.length); - for (T t : array) { + public void write(T[] v, BiConsumer mapper) { + buffer.writeInt(v.length); + for (T t : v) { mapper.accept(this, t); } } @Override - public void write(List list, Consumer mapper) { - int size = list.size(); + public void write(List v, Consumer mapper) { + int size = v.size(); buffer.writeInt(size); - for (T t : list) { + for (T t : v) { mapper.accept(t); } } @Override - public void write(List list, BiConsumer mapper) { - int size = list.size(); + public void write(List v, BiConsumer mapper) { + int size = v.size(); buffer.writeInt(size); - for (T t : list) { + for (T t : v) { mapper.accept(this, t); } } @Override - public void write(Map map, BiConsumer keyMapper, BiConsumer valueMapper) { - int size = map.size(); + public void write(Map v, BiConsumer keyMapper, BiConsumer valueMapper) { + int size = v.size(); buffer.writeInt(size); - for (Map.Entry entry : map.entrySet()) { + for (Map.Entry entry : v.entrySet()) { keyMapper.accept(this, entry.getKey()); valueMapper.accept(this, entry.getValue()); } } @Override - public void write(Map map, Consumer keyMapper, Consumer valueMapper) { - int size = map.size(); + public void write(Map v, Consumer keyMapper, Consumer valueMapper) { + int size = v.size(); buffer.writeInt(size); - for (Map.Entry entry : map.entrySet()) { + for (Map.Entry entry : v.entrySet()) { keyMapper.accept(entry.getKey()); valueMapper.accept(entry.getValue()); } diff --git a/today-service-api/src/main/java/infra/cloud/serialize/MessagePackInput.java b/today-service-api/src/main/java/infra/cloud/serialize/MessagePackInput.java index d28a320..bc63880 100644 --- a/today-service-api/src/main/java/infra/cloud/serialize/MessagePackInput.java +++ b/today-service-api/src/main/java/infra/cloud/serialize/MessagePackInput.java @@ -31,6 +31,7 @@ import infra.cloud.serialize.format.ExtensionTypeHeader; import infra.cloud.serialize.format.MessageFormat; import infra.cloud.serialize.format.MessageFormatException; +import infra.cloud.serialize.format.MessageInsufficientBufferException; import infra.cloud.serialize.format.MessageIntegerOverflowException; import infra.cloud.serialize.format.MessageNeverUsedFormatException; import infra.cloud.serialize.format.MessagePack.Code; @@ -38,6 +39,7 @@ import infra.cloud.serialize.format.MessageSizeException; import infra.cloud.serialize.format.MessageTypeException; import infra.lang.Constant; +import infra.lang.Nullable; import infra.lang.TodayStrategies; import infra.util.CollectionUtils; import io.netty.buffer.ByteBuf; @@ -98,6 +100,15 @@ public void read(Message message) { message.readFrom(this); } + @Nullable + @Override + public V readNullable(Function valueMapper) { + if (tryReadNull()) { + return null; + } + return valueMapper.apply(this); + } + @Override public int skipBytes(int n) { int start = buffer.readerIndex(); @@ -622,6 +633,43 @@ public int readBinaryHeader() { throw unexpected("Binary", b); } + /** + * Reads a Nil byte. + * + * @throws MessageTypeException when value is not MessagePack Nil type + */ + public void unpackNil() { + byte b = readInt8(); + if (b == Code.NIL) { + return; + } + throw unexpected("Nil", b); + } + + /** + * Peeks a Nil byte and reads it if next byte is a nil value. + *

          + * The difference from {@link #unpackNil()} is that unpackNil throws an exception if the next byte is not nil value + * while this tryUnpackNil method returns false without changing position. + * + * @return true if a {@code null} value is read + * @throws MessageInsufficientBufferException when the end of file reached + */ + public boolean tryReadNull() { + // makes sure that buffer has at least 1 byte + ByteBuf buffer = this.buffer; + if (!buffer.isReadable(1)) { + throw new MessageInsufficientBufferException(); + } + int index = buffer.readerIndex(); + byte b = buffer.getByte(index); + if (b == Code.NIL) { + buffer.readerIndex(index + 1); + return true; + } + return false; + } + /** * Create an exception for the case when an unexpected byte value is read */ diff --git a/today-service-api/src/main/java/infra/cloud/serialize/MessagePackOutput.java b/today-service-api/src/main/java/infra/cloud/serialize/MessagePackOutput.java index c8b2a9a..04979a8 100644 --- a/today-service-api/src/main/java/infra/cloud/serialize/MessagePackOutput.java +++ b/today-service-api/src/main/java/infra/cloud/serialize/MessagePackOutput.java @@ -272,21 +272,21 @@ public void write(double v) { } @Override - public void write(@Nullable String s) { - if (s == null || s.isEmpty()) { + public void write(@Nullable String v) { + if (v == null || v.isEmpty()) { writeStringHeader(0); } else { // JVM performs various optimizations (memory allocation, reusing encoder etc.) when String.getBytes is used - byte[] bytes = s.getBytes(StandardCharsets.UTF_8); + byte[] bytes = v.getBytes(StandardCharsets.UTF_8); writeStringHeader(bytes.length); writeFully(bytes); } } @Override - public void write(Instant instant) { - writeTimestamp(instant.getEpochSecond(), instant.getNano()); + public void write(Instant v) { + writeTimestamp(v.getEpochSecond(), v.getNano()); } @Override @@ -295,8 +295,18 @@ public void writeTimestamp(long millis) { } @Override - public void write(Message message) { - message.writeTo(this); + public void write(Message v) { + v.writeTo(this); + } + + @Override + public void writeNullable(@Nullable V v, BiConsumer valueMapper) { + if (v == null) { + writeNull(); + } + else { + valueMapper.accept(this, v); + } } @Override @@ -325,54 +335,54 @@ public void writeTimestamp(long epochSecond, int nanoAdjustment) { } @Override - public void write(T[] array, Consumer mapper) { - writeArrayHeader(array.length); - for (T t : array) { + public void write(T[] v, Consumer mapper) { + writeArrayHeader(v.length); + for (T t : v) { mapper.accept(t); } } @Override - public void write(T[] array, BiConsumer mapper) { - writeArrayHeader(array.length); - for (T t : array) { + public void write(T[] v, BiConsumer mapper) { + writeArrayHeader(v.length); + for (T t : v) { mapper.accept(this, t); } } @Override - public void write(List list, Consumer mapper) { - int size = list.size(); + public void write(List v, Consumer mapper) { + int size = v.size(); writeArrayHeader(size); - for (T t : list) { + for (T t : v) { mapper.accept(t); } } @Override - public void write(List list, BiConsumer mapper) { - int size = list.size(); + public void write(List v, BiConsumer mapper) { + int size = v.size(); writeArrayHeader(size); - for (T t : list) { + for (T t : v) { mapper.accept(this, t); } } @Override - public void write(Map map, BiConsumer keyMapper, BiConsumer valueMapper) { - int size = map.size(); + public void write(Map v, BiConsumer keyMapper, BiConsumer valueMapper) { + int size = v.size(); writeMapHeader(size); - for (Map.Entry entry : map.entrySet()) { + for (Map.Entry entry : v.entrySet()) { keyMapper.accept(this, entry.getKey()); valueMapper.accept(this, entry.getValue()); } } @Override - public void write(Map map, Consumer keyMapper, Consumer valueMapper) { - int size = map.size(); + public void write(Map v, Consumer keyMapper, Consumer valueMapper) { + int size = v.size(); writeMapHeader(size); - for (Map.Entry entry : map.entrySet()) { + for (Map.Entry entry : v.entrySet()) { keyMapper.accept(entry.getKey()); valueMapper.accept(entry.getValue()); } diff --git a/today-service-api/src/main/java/infra/cloud/serialize/ProtobufArgumentSerialization.java b/today-service-api/src/main/java/infra/cloud/serialize/ProtobufArgumentSerialization.java index 87c919b..5199ec3 100644 --- a/today-service-api/src/main/java/infra/cloud/serialize/ProtobufArgumentSerialization.java +++ b/today-service-api/src/main/java/infra/cloud/serialize/ProtobufArgumentSerialization.java @@ -22,11 +22,10 @@ import java.lang.reflect.Method; -import infra.cloud.RpcMethod; +import infra.cloud.service.ServiceMethod; import infra.core.MethodParameter; import infra.lang.Nullable; import infra.util.ConcurrentReferenceHashMap; -import io.netty.buffer.ByteBuf; /** * Serialization for protobuf @@ -34,7 +33,7 @@ * @author 海子 Yang * @since 1.0 2024/12/20 17:46 */ -public class ProtobufArgumentSerialization implements RpcArgumentSerialization, ReturnValueSerialization { +public class ProtobufArgumentSerialization implements RpcArgumentSerialization, ReturnValueSerializer { private static final ConcurrentReferenceHashMap, Method> methodCache = new ConcurrentReferenceHashMap<>(); @@ -44,12 +43,12 @@ public boolean supportsArgument(MethodParameter parameter) { } @Override - public void serialize(MethodParameter parameter, @Nullable Message value, ByteBuf payload, Output output) throws SerializationException { + public void serialize(MethodParameter parameter, @Nullable Message value, Output output) throws SerializationException { output.write(value == null ? null : value.toByteArray()); } @Override - public Message deserialize(MethodParameter parameter, ByteBuf payload, Input input) throws SerializationException { + public Message deserialize(MethodParameter parameter, Input input) throws SerializationException { Class parameterType = parameter.getParameterType(); Message.Builder messageBuilder = getMessageBuilder(parameterType); try { @@ -85,18 +84,18 @@ private Message.Builder getMessageBuilder(Class clazz) { // ---------------------------------------------------------------------------------------- @Override - public boolean supportsArgument(RpcMethod method) { + public boolean supportsReturnValue(ServiceMethod method) { return Message.class.isAssignableFrom(method.getReturnType().getParameterType()); } @Override - public void serialize(RpcMethod method, Message value, ByteBuf payload, Output output) { + public void serialize(ServiceMethod method, Message value, Output output) { output.write(value.toByteArray()); } - @Override - public Message deserialize(RpcMethod method, ByteBuf payload, Input input) throws SerializationException { - return deserialize(method.getReturnType(), payload, input); - } +// @Override +// public Message deserialize(RpcMethod method, ByteBuf payload, Input input) throws SerializationException { +// return deserialize(method.getReturnType(), payload, input); +// } } diff --git a/today-service-api/src/main/java/infra/cloud/serialize/ReturnValueDeserializer.java b/today-service-api/src/main/java/infra/cloud/serialize/ReturnValueDeserializer.java new file mode 100644 index 0000000..05d460d --- /dev/null +++ b/today-service-api/src/main/java/infra/cloud/serialize/ReturnValueDeserializer.java @@ -0,0 +1,33 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.serialize; + +import infra.cloud.service.ServiceMethod; + +/** + * @author 海子 Yang + * @since 1.0 2025/8/20 22:01 + */ +public interface ReturnValueDeserializer { + + boolean supportsReturnValue(ServiceMethod method); + + T deserialize(ServiceMethod method, Input input) + throws SerializationException; + +} diff --git a/today-service-api/src/main/java/infra/cloud/serialize/ReturnValueSerialization.java b/today-service-api/src/main/java/infra/cloud/serialize/ReturnValueSerialization.java index c936550..aae43ac 100644 --- a/today-service-api/src/main/java/infra/cloud/serialize/ReturnValueSerialization.java +++ b/today-service-api/src/main/java/infra/cloud/serialize/ReturnValueSerialization.java @@ -17,27 +17,10 @@ package infra.cloud.serialize; -import infra.cloud.RpcMethod; -import io.netty.buffer.ByteBuf; - /** * @author 海子 Yang * @since 1.0 2024/12/20 21:42 */ -public interface ReturnValueSerialization { - - /** - * Whether the given parameter is supported by this resolver. - *

          - * static match - *

          - */ - boolean supportsArgument(RpcMethod method); - - void serialize(RpcMethod method, T returnValue, ByteBuf payload, Output output) - throws SerializationException; - - T deserialize(RpcMethod method, ByteBuf payload, Input input) - throws SerializationException; +public interface ReturnValueSerialization extends ReturnValueSerializer, ReturnValueDeserializer { } diff --git a/today-service-api/src/main/java/infra/cloud/serialize/ReturnValueSerializer.java b/today-service-api/src/main/java/infra/cloud/serialize/ReturnValueSerializer.java new file mode 100644 index 0000000..fa79477 --- /dev/null +++ b/today-service-api/src/main/java/infra/cloud/serialize/ReturnValueSerializer.java @@ -0,0 +1,33 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.serialize; + +import infra.cloud.service.ServiceMethod; + +/** + * @author 海子 Yang + * @since 1.0 2025/8/20 21:56 + */ +public interface ReturnValueSerializer { + + boolean supportsReturnValue(ServiceMethod method); + + void serialize(ServiceMethod method, T returnValue, Output output) + throws SerializationException; + +} diff --git a/today-service-api/src/main/java/infra/cloud/serialize/RpcArgumentSerialization.java b/today-service-api/src/main/java/infra/cloud/serialize/RpcArgumentSerialization.java index bfe7b02..0d6b711 100644 --- a/today-service-api/src/main/java/infra/cloud/serialize/RpcArgumentSerialization.java +++ b/today-service-api/src/main/java/infra/cloud/serialize/RpcArgumentSerialization.java @@ -19,7 +19,6 @@ import infra.core.MethodParameter; import infra.lang.Nullable; -import io.netty.buffer.ByteBuf; /** * @author 海子 Yang @@ -35,9 +34,10 @@ public interface RpcArgumentSerialization { */ boolean supportsArgument(MethodParameter parameter); - void serialize(MethodParameter parameter, @Nullable T value, ByteBuf payload, Output output) throws SerializationException; + void serialize(MethodParameter parameter, @Nullable T value, Output output) + throws SerializationException; @Nullable - T deserialize(MethodParameter parameter, ByteBuf payload, Input input) throws SerializationException; + T deserialize(MethodParameter parameter, Input input) throws SerializationException; } diff --git a/today-service-api/src/main/java/infra/cloud/serialize/RpcRequestSerialization.java b/today-service-api/src/main/java/infra/cloud/serialize/RpcRequestSerialization.java index 3ca8623..3a93772 100644 --- a/today-service-api/src/main/java/infra/cloud/serialize/RpcRequestSerialization.java +++ b/today-service-api/src/main/java/infra/cloud/serialize/RpcRequestSerialization.java @@ -19,8 +19,8 @@ import java.util.List; -import infra.cloud.RpcMethod; import infra.cloud.RpcRequest; +import infra.cloud.service.ServiceMethod; import infra.core.MethodParameter; import io.netty.buffer.ByteBuf; @@ -42,15 +42,15 @@ public void serialize(RpcRequest request, ByteBuf payload) { Output output = new MessagePackOutput(payload); request.writeTo(output); - RpcMethod rpcMethod = request.getRpcMethod(); + ServiceMethod method = request.getMethod(); int idx = 0; Object[] arguments = request.getArguments(); beforeSerializeArguments(output, arguments); - for (MethodParameter parameter : rpcMethod.getParameters()) { + for (MethodParameter parameter : method.getParameters()) { var serialization = findArgumentSerialization(parameter); - serialization.serialize(parameter, arguments[idx++], payload, output); + serialization.serialize(parameter, arguments[idx++], output); } afterSerializeArguments(output, arguments); } diff --git a/today-service-api/src/main/java/infra/cloud/serialize/RpcResponseSerialization.java b/today-service-api/src/main/java/infra/cloud/serialize/RpcResponseSerialization.java index 802ec19..4774af3 100644 --- a/today-service-api/src/main/java/infra/cloud/serialize/RpcResponseSerialization.java +++ b/today-service-api/src/main/java/infra/cloud/serialize/RpcResponseSerialization.java @@ -20,9 +20,8 @@ import java.io.IOException; import java.util.List; -import infra.cloud.RpcMethod; -import infra.cloud.RpcRequest; import infra.cloud.RpcResponse; +import infra.cloud.service.ServiceMethod; import io.netty.buffer.ByteBuf; /** @@ -42,46 +41,52 @@ public RpcResponseSerialization(List serializations, T } public void serialize(RpcResponse response, ByteBuf payload) throws IOException { + MessagePackOutput output = new MessagePackOutput(payload); + Throwable exception = response.getException(); + output.writeNullable(exception, (out, throwable) -> { + + }); + if (exception != null) { // has error payload.writeBoolean(true); throwableSerialization.serialize(exception, payload); } else { - RpcMethod rpcMethod = response.getRpcMethod(); - payload.writeBoolean(false); + ServiceMethod method = response.getMethod(); - var serialization = findSerialization(rpcMethod); + payload.writeBoolean(false); + var serialization = findSerialization(method); Object result = response.getResult(); - serialization.serialize(rpcMethod, result, payload, new DefaultByteBufOutput(payload)); + serialization.serialize(method, result, output); } } - public RpcResponse deserialize(RpcRequest rpcRequest, ByteBuf body) throws SerializationException { - RpcMethod rpcMethod = rpcRequest.getRpcMethod(); + public RpcResponse deserialize(ServiceMethod method, ByteBuf body) throws SerializationException { + MessagePackInput input = new MessagePackInput(body); RpcResponse response = new RpcResponse(); - response.setRpcMethod(rpcMethod); + response.setMethod(method); boolean hasError = body.readBoolean(); if (hasError) { Throwable deserialize = throwableSerialization.deserialize(body); response.setException(deserialize); } else { - var serialization = findSerialization(rpcMethod); - Object result = serialization.deserialize(rpcMethod, body, new DefaultByteBufInput(body)); + var serialization = findSerialization(method); + Object result = serialization.deserialize(method, input); response.setResult(result); } return response; } - private ReturnValueSerialization findSerialization(RpcMethod rpcMethod) { + private ReturnValueSerialization findSerialization(ServiceMethod method) { for (ReturnValueSerialization serialization : serializations) { - if (serialization.supportsArgument(rpcMethod)) { + if (serialization.supportsReturnValue(method)) { return serialization; } } - throw new IllegalStateException("ReturnValueSerialization for method %s not found".formatted(rpcMethod)); + throw new IllegalStateException("ReturnValueSerialization for method %s not found".formatted(method)); } } diff --git a/today-service-api/src/main/java/infra/cloud/serialize/SimpleValueArgumentSerialization.java b/today-service-api/src/main/java/infra/cloud/serialize/SimpleValueArgumentSerialization.java index 622b09d..bbb3f8c 100644 --- a/today-service-api/src/main/java/infra/cloud/serialize/SimpleValueArgumentSerialization.java +++ b/today-service-api/src/main/java/infra/cloud/serialize/SimpleValueArgumentSerialization.java @@ -17,7 +17,6 @@ package infra.cloud.serialize; -import java.io.IOException; import java.util.HashMap; import java.util.Map; @@ -25,7 +24,6 @@ import infra.cloud.serialize.value.ValueSerialization; import infra.core.MethodParameter; import infra.lang.Nullable; -import io.netty.buffer.ByteBuf; import static infra.cloud.serialize.value.ValueSerialization.map; @@ -38,15 +36,14 @@ public class SimpleValueArgumentSerialization implements RpcArgumentSerializatio private final Map, ValueSerialization> serializationMap = new HashMap<>(); public SimpleValueArgumentSerialization() { - serializationMap.put(int.class, map(ByteBuf::readInt, ByteBuf::writeInt)); - serializationMap.put(Integer.class, map(ByteBuf::readInt, ByteBuf::writeInt)); + serializationMap.put(int.class, map(Input::readInt, Output::write)); + serializationMap.put(Integer.class, map(Input::readInt, Output::write)); - serializationMap.put(long.class, map(ByteBuf::readLong, ByteBuf::writeLong)); - serializationMap.put(Long.class, map(ByteBuf::readLong, ByteBuf::writeLong)); - -// serializationMap.put(short.class, map(ByteBuf::readShort, ByteBuf::writeShort)); -// serializationMap.put(Short.class, map(ByteBuf::readShort, ByteBuf::writeShort)); + serializationMap.put(long.class, map(Input::readLong, Output::write)); + serializationMap.put(Long.class, map(Input::readLong, Output::write)); + serializationMap.put(short.class, map(Input::readShort, Output::write)); + serializationMap.put(Short.class, map(Input::readShort, Output::write)); } @Override @@ -56,24 +53,16 @@ public boolean supportsArgument(MethodParameter parameter) { @Override @SuppressWarnings({ "rawtypes", "unchecked" }) - public void serialize(MethodParameter parameter, @Nullable Object value, ByteBuf payload, Output output) throws IOException { - payload.writeBoolean(value != null); - if (value != null) { - ValueSerialization serialization = findSerialization(parameter.getParameterType()); - serialization.serialize(parameter, value, payload); - } + public void serialize(MethodParameter parameter, @Nullable Object value, Output output) { + ValueSerialization serialization = findSerialization(parameter.getParameterType()); + serialization.serialize(parameter, value, output); } @Nullable @Override - public Object deserialize(MethodParameter parameter, ByteBuf payload, Input input) throws SerializationException { - boolean isNull = payload.readBoolean(); - if (isNull) { - return null; - } - + public Object deserialize(MethodParameter parameter, Input input) { var serialization = findSerialization(parameter.getParameterType()); - return serialization.deserialize(parameter, payload); + return serialization.deserialize(parameter, input); } @SuppressWarnings({ "rawtypes" }) diff --git a/today-service-api/src/main/java/infra/cloud/serialize/value/FuncValueSerialization.java b/today-service-api/src/main/java/infra/cloud/serialize/value/FuncValueSerialization.java index 5cdbb09..66a7f1a 100644 --- a/today-service-api/src/main/java/infra/cloud/serialize/value/FuncValueSerialization.java +++ b/today-service-api/src/main/java/infra/cloud/serialize/value/FuncValueSerialization.java @@ -17,13 +17,13 @@ package infra.cloud.serialize.value; -import java.io.IOException; import java.util.function.BiConsumer; import java.util.function.Function; +import infra.cloud.serialize.Input; +import infra.cloud.serialize.Output; import infra.cloud.serialize.SerializationException; import infra.core.MethodParameter; -import io.netty.buffer.ByteBuf; /** * @author 海子 Yang @@ -31,23 +31,23 @@ */ final class FuncValueSerialization implements ValueSerialization { - private final Function reader; + private final Function reader; - private final BiConsumer writer; + private final BiConsumer writer; - FuncValueSerialization(Function reader, BiConsumer writer) { + FuncValueSerialization(Function reader, BiConsumer writer) { this.reader = reader; this.writer = writer; } @Override - public void serialize(MethodParameter parameter, T value, ByteBuf payload) throws IOException { + public void serialize(MethodParameter parameter, T value, Output payload) { writer.accept(payload, value); } @Override - public T deserialize(MethodParameter parameter, ByteBuf payload) throws SerializationException { - return reader.apply(payload); + public T deserialize(MethodParameter parameter, Input input) throws SerializationException { + return reader.apply(input); } } diff --git a/today-service-api/src/main/java/infra/cloud/serialize/value/ValueSerialization.java b/today-service-api/src/main/java/infra/cloud/serialize/value/ValueSerialization.java index 17feb1f..586a817 100644 --- a/today-service-api/src/main/java/infra/cloud/serialize/value/ValueSerialization.java +++ b/today-service-api/src/main/java/infra/cloud/serialize/value/ValueSerialization.java @@ -17,14 +17,14 @@ package infra.cloud.serialize.value; -import java.io.IOException; import java.util.function.BiConsumer; import java.util.function.Function; +import infra.cloud.serialize.Input; +import infra.cloud.serialize.Output; import infra.cloud.serialize.SerializationException; import infra.core.MethodParameter; import infra.lang.Assert; -import io.netty.buffer.ByteBuf; /** * @author 海子 Yang @@ -32,11 +32,13 @@ */ public interface ValueSerialization { - void serialize(MethodParameter parameter, T value, ByteBuf payload) throws IOException; + void serialize(MethodParameter parameter, T value, Output payload) + throws SerializationException; - T deserialize(MethodParameter parameter, ByteBuf payload) throws SerializationException; + T deserialize(MethodParameter parameter, Input payload) + throws SerializationException; - static ValueSerialization map(Function reader, BiConsumer writer) { + static ValueSerialization map(Function reader, BiConsumer writer) { Assert.notNull(reader, "reader Function is required"); Assert.notNull(writer, "writer BiConsumer is required"); return new FuncValueSerialization<>(reader, writer); diff --git a/today-service-api/src/main/java/infra/cloud/service/AbstractServiceInterfaceMetadataProvider.java b/today-service-api/src/main/java/infra/cloud/service/AbstractServiceInterfaceMetadataProvider.java index 8df3e69..5e5a20a 100644 --- a/today-service-api/src/main/java/infra/cloud/service/AbstractServiceInterfaceMetadataProvider.java +++ b/today-service-api/src/main/java/infra/cloud/service/AbstractServiceInterfaceMetadataProvider.java @@ -48,7 +48,7 @@ public ServiceInterfaceMetadata getMetadata(Class serviceInterface) { return new ServiceInterfaceMetadata<>(serviceInterface, serviceMetadata, serviceMethods); } - protected abstract M createServiceMethod(ServiceMetadata serviceMetadata, Class service, Method method); + protected abstract M createServiceMethod(ServiceMetadata serviceMetadata, Class serviceInterface, Method method); protected boolean isServiceMethod(Method method) { return !ReflectionUtils.isObjectMethod(method); diff --git a/today-service-api/src/main/java/infra/cloud/service/ServiceMethod.java b/today-service-api/src/main/java/infra/cloud/service/ServiceMethod.java index 21b17cc..14b5223 100644 --- a/today-service-api/src/main/java/infra/cloud/service/ServiceMethod.java +++ b/today-service-api/src/main/java/infra/cloud/service/ServiceMethod.java @@ -19,6 +19,9 @@ import java.lang.reflect.Method; +import infra.core.MethodParameter; +import infra.lang.Nullable; + /** * @author 海子 Yang * @since 1.0 2025/8/10 08:20 @@ -27,13 +30,19 @@ public class ServiceMethod { protected final ServiceMetadata serviceMetadata; + protected final MethodParameter[] parameters; + protected final Class serviceInterface; protected final Method method; + @Nullable + private MethodParameter returnTypeParameter; + public ServiceMethod(ServiceMetadata serviceMetadata, Class serviceInterface, Method method) { - this.serviceMetadata = serviceMetadata; + this.parameters = initMethodParameters(method); this.serviceInterface = serviceInterface; + this.serviceMetadata = serviceMetadata; this.method = method; } @@ -53,4 +62,30 @@ public Method getMethod() { return method; } + public MethodParameter[] getParameters() { + return parameters; + } + + public MethodParameter getReturnType() { + MethodParameter returnType = returnTypeParameter; + if (returnType == null) { + returnType = MethodParameter.forExecutable(method, -1); + this.returnTypeParameter = returnType; + } + return returnType; + } + + private MethodParameter[] initMethodParameters(Method method) { + int count = method.getParameterCount(); + if (count == 0) { + return MethodParameter.EMPTY_ARRAY; + } + + MethodParameter[] result = new MethodParameter[count]; + for (int i = 0; i < count; i++) { + result[i] = new MethodParameter(method, i); + } + return result; + } + } diff --git a/today-service-client/build.gradle b/today-service-client/build.gradle index 36ed6c9..e451bf8 100644 --- a/today-service-client/build.gradle +++ b/today-service-client/build.gradle @@ -7,8 +7,7 @@ dependencies { api project(":today-service-api") api project(":today-service-registry") - api project(":today-remoting-transport-tcp") - + optional project(":today-remoting-transport-tcp") testImplementation project(":today-cloud-samples:demo-tests:demo-user-api") diff --git a/today-service-client/src/main/java/infra/cloud/service/DefaultRemotingOperationsProvider.java b/today-service-client/src/main/java/infra/cloud/service/DefaultRemotingOperationsProvider.java index ef2b62a..cf47df6 100644 --- a/today-service-client/src/main/java/infra/cloud/service/DefaultRemotingOperationsProvider.java +++ b/today-service-client/src/main/java/infra/cloud/service/DefaultRemotingOperationsProvider.java @@ -63,14 +63,14 @@ public RemotingOperations getRemotingOperations(String serviceId) { return remotingClientMap.computeIfAbsent(serviceId, name -> RemotingClient.forLoadBalance(Flux.interval(discoveryPeriod) .map(i -> discoveryClient.getInstances(name)) .map(this)) - .roundRobinLoadBalanceStrategy() + .weightedLoadBalanceStrategy() .build()); } @Override - public List apply(List serviceInstances) { - var targets = new ArrayList(serviceInstances.size()); - for (ServiceInstance instance : serviceInstances) { + public List apply(List instances) { + var targets = new ArrayList(instances.size()); + for (ServiceInstance instance : instances) { targets.add(LoadBalanceTarget.of(instance.getInstanceId(), TcpClientTransport.create(instance.getHost(), instance.getPort()))); } diff --git a/today-service-client/src/main/java/infra/cloud/service/DefaultServiceInterfaceMetadataProvider.java b/today-service-client/src/main/java/infra/cloud/service/DefaultServiceInterfaceMetadataProvider.java index b2ce2bf..2ea27f5 100644 --- a/today-service-client/src/main/java/infra/cloud/service/DefaultServiceInterfaceMetadataProvider.java +++ b/today-service-client/src/main/java/infra/cloud/service/DefaultServiceInterfaceMetadataProvider.java @@ -45,8 +45,8 @@ public DefaultServiceInterfaceMetadataProvider(ServiceMetadataProvider serviceMe } @Override - protected ServiceInterfaceMethod createServiceMethod(ServiceMetadata serviceMetadata, Class service, Method method) { - return new ServiceInterfaceMethod(serviceMetadata, service, method, resolvers); + protected ServiceInterfaceMethod createServiceMethod(ServiceMetadata serviceMetadata, Class serviceInterface, Method method) { + return new ServiceInterfaceMethod(serviceMetadata, serviceInterface, method, resolvers); } static class FutureReturnValueResolver implements ReturnValueResolver { diff --git a/today-service-client/src/main/java/infra/cloud/service/DefaultServiceProxyFactory.java b/today-service-client/src/main/java/infra/cloud/service/DefaultServiceProxyFactory.java index 0e26e34..b20bfdb 100644 --- a/today-service-client/src/main/java/infra/cloud/service/DefaultServiceProxyFactory.java +++ b/today-service-client/src/main/java/infra/cloud/service/DefaultServiceProxyFactory.java @@ -28,6 +28,7 @@ import infra.lang.Assert; import infra.lang.Nullable; import infra.util.ReflectionUtils; +import io.netty.buffer.ByteBufAllocator; /** * @author 海子 Yang @@ -41,6 +42,8 @@ public class DefaultServiceProxyFactory implements ServiceProxyFactory { private final ServiceInterfaceMetadataProvider metadataProvider; + private final ByteBufAllocator allocator = ByteBufAllocator.DEFAULT; + public DefaultServiceProxyFactory(RemotingOperationsProvider remotingOperationsProvider, ServiceInterfaceMetadataProvider metadataProvider, List interceptors) { this.metadataProvider = metadataProvider; @@ -53,7 +56,7 @@ public DefaultServiceProxyFactory(RemotingOperationsProvider remotingOperationsP public S getService(Class serviceInterface) { Assert.isTrue(serviceInterface.isInterface(), "service must be an interface"); var metadata = metadataProvider.getMetadata(serviceInterface); - ServiceInvoker serviceInvoker = new ServiceMethodInvoker(metadata, interceptors, remotingOperationsProvider); + ServiceInvoker serviceInvoker = new ServiceMethodInvoker(metadata, interceptors, remotingOperationsProvider, allocator); List serviceMethods = metadata.getServiceMethods(); return (S) Proxy.newProxyInstance(serviceInterface.getClassLoader(), new Class[] { serviceInterface }, diff --git a/today-service-client/src/main/java/infra/cloud/service/ServiceInterfaceMethod.java b/today-service-client/src/main/java/infra/cloud/service/ServiceInterfaceMethod.java index 377ee8a..dd212c6 100644 --- a/today-service-client/src/main/java/infra/cloud/service/ServiceInterfaceMethod.java +++ b/today-service-client/src/main/java/infra/cloud/service/ServiceInterfaceMethod.java @@ -20,7 +20,6 @@ import java.lang.reflect.Method; import java.util.ArrayList; -import infra.core.MethodParameter; import infra.lang.Nullable; /** @@ -29,20 +28,14 @@ */ public class ServiceInterfaceMethod extends ServiceMethod { - private final MethodParameter[] parameters; - private final InvocationType invocationType; private final ReturnValueResolver returnValueResolver; private final boolean blocking; - @Nullable - private MethodParameter returnTypeParameter; - ServiceInterfaceMethod(ServiceMetadata serviceMetadata, Class serviceInterface, Method method, ArrayList resolvers) { super(serviceMetadata, serviceInterface, method); - this.parameters = initMethodParameters(method); this.returnValueResolver = findReturnValueResolver(resolvers); this.blocking = returnValueResolver.isBlocking(); this.invocationType = returnValueResolver.getInvocationType(this); @@ -56,37 +49,11 @@ public InvocationType getInvocationType() { return invocationType; } - public MethodParameter[] getParameters() { - return parameters; - } - - public MethodParameter getReturnType() { - MethodParameter returnType = returnTypeParameter; - if (returnType == null) { - returnType = MethodParameter.forExecutable(method, -1); - this.returnTypeParameter = returnType; - } - return returnType; - } - @Nullable public Object resolveResult(InvocationResult result) throws Throwable { return returnValueResolver.resolve(this, result); } - private MethodParameter[] initMethodParameters(Method method) { - int count = method.getParameterCount(); - if (count == 0) { - return MethodParameter.EMPTY_ARRAY; - } - - MethodParameter[] result = new MethodParameter[count]; - for (int i = 0; i < count; i++) { - result[i] = new MethodParameter(method, i); - } - return result; - } - private ReturnValueResolver findReturnValueResolver(ArrayList resolvers) { for (ReturnValueResolver resolver : resolvers) { if (resolver.supportsMethod(this)) { diff --git a/today-service-client/src/main/java/infra/cloud/service/ServiceInvocation.java b/today-service-client/src/main/java/infra/cloud/service/ServiceInvocation.java index 13e9397..93b14ea 100644 --- a/today-service-client/src/main/java/infra/cloud/service/ServiceInvocation.java +++ b/today-service-client/src/main/java/infra/cloud/service/ServiceInvocation.java @@ -36,7 +36,7 @@ public interface ServiceInvocation extends AttributeAccessor { InvocationResult proceed() throws Throwable; /** - * Service name + * Service ID */ String getServiceId(); diff --git a/today-service-client/src/main/java/infra/cloud/service/ServiceMethodInvoker.java b/today-service-client/src/main/java/infra/cloud/service/ServiceMethodInvoker.java index 8eff659..48edb9a 100644 --- a/today-service-client/src/main/java/infra/cloud/service/ServiceMethodInvoker.java +++ b/today-service-client/src/main/java/infra/cloud/service/ServiceMethodInvoker.java @@ -23,6 +23,7 @@ import infra.cloud.RpcRequest; import infra.cloud.serialize.RpcRequestSerialization; +import infra.cloud.serialize.RpcResponseSerialization; import infra.lang.Nullable; import infra.remoting.Payload; import infra.remoting.RemotingOperations; @@ -31,7 +32,7 @@ import infra.util.concurrent.FutureListener; import infra.util.concurrent.Promise; import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; +import io.netty.buffer.ByteBufAllocator; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import reactor.core.publisher.Operators; @@ -49,13 +50,18 @@ public class ServiceMethodInvoker implements ServiceInvoker { private final ServiceInterfaceMetadata metadata; + private final ByteBufAllocator allocator; + private RpcRequestSerialization requestSerialization; + private RpcResponseSerialization responseSerialization; + ServiceMethodInvoker(ServiceInterfaceMetadata metadata, - ClientInterceptor[] interceptors, RemotingOperationsProvider remotingOperationsProvider) { + ClientInterceptor[] interceptors, RemotingOperationsProvider remotingOperationsProvider, ByteBufAllocator allocator) { this.metadata = metadata; this.interceptors = interceptors; this.remotingOperationsProvider = remotingOperationsProvider; + this.allocator = allocator; } @Override @@ -88,7 +94,7 @@ private Mono createMonoPayload() { request.setServiceClass(serviceMethod.getServiceInterface().getName()); request.setMethodName(serviceMethod.getMethod().getName()); - ByteBuf buffer = Unpooled.buffer(); + ByteBuf buffer = allocator.ioBuffer(); Payload payload = ByteBufPayload.create(buffer); requestSerialization.serialize(request, buffer); return Mono.just(payload); @@ -105,6 +111,7 @@ private Publisher createChannelPayload() { } private Object deserialize(Payload payload) { +// responseSerialization.deserialize(); return null; } diff --git a/today-service-provider/build.gradle b/today-service-provider/build.gradle index c31a9ef..3799b72 100644 --- a/today-service-provider/build.gradle +++ b/today-service-provider/build.gradle @@ -1,20 +1,3 @@ -/* - * Copyright 2021 - 2024 the original author or authors. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] - */ - description = "TODAY Service Provider" @@ -26,6 +9,8 @@ dependencies { implementation project(":today-service-registry") + optional project(":today-remoting-transport-tcp") + optional 'io.netty:netty-transport' optional 'io.netty:netty-codec' optional 'io.netty:netty-handler' diff --git a/today-service-provider/src/main/java/infra/cloud/provider/DefaultServiceInterfaceMetadataProvider.java b/today-service-provider/src/main/java/infra/cloud/provider/DefaultServiceInterfaceMetadataProvider.java new file mode 100644 index 0000000..97c60f3 --- /dev/null +++ b/today-service-provider/src/main/java/infra/cloud/provider/DefaultServiceInterfaceMetadataProvider.java @@ -0,0 +1,42 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.provider; + +import java.lang.reflect.Method; + +import infra.cloud.service.AbstractServiceInterfaceMetadataProvider; +import infra.cloud.service.ServiceMetadata; +import infra.cloud.service.ServiceMetadataProvider; +import infra.cloud.service.ServiceMethod; + +/** + * @author 海子 Yang + * @since 1.0 2025/8/20 22:12 + */ +public class DefaultServiceInterfaceMetadataProvider extends AbstractServiceInterfaceMetadataProvider { + + public DefaultServiceInterfaceMetadataProvider(ServiceMetadataProvider serviceMetadataProvider) { + super(serviceMetadataProvider); + } + + @Override + protected ServiceMethod createServiceMethod(ServiceMetadata serviceMetadata, Class serviceInterface, Method method) { + return new ServiceMethod(serviceMetadata, serviceInterface, method); + } + +} diff --git a/today-service-provider/src/main/java/infra/cloud/provider/InvocableRpcMethod.java b/today-service-provider/src/main/java/infra/cloud/provider/InvocableMethod.java similarity index 76% rename from today-service-provider/src/main/java/infra/cloud/provider/InvocableRpcMethod.java rename to today-service-provider/src/main/java/infra/cloud/provider/InvocableMethod.java index e4e172b..35385f5 100644 --- a/today-service-provider/src/main/java/infra/cloud/provider/InvocableRpcMethod.java +++ b/today-service-provider/src/main/java/infra/cloud/provider/InvocableMethod.java @@ -19,19 +19,20 @@ import java.lang.reflect.Method; -import infra.cloud.RpcMethod; +import infra.cloud.service.ServiceInterfaceMetadata; +import infra.cloud.service.ServiceMethod; import infra.reflect.MethodInvoker; /** * @author 海子 Yang * @since 1.0 2024/12/20 21:49 */ -public class InvocableRpcMethod extends RpcMethod { +public class InvocableMethod extends ServiceMethod { private final MethodInvoker invoker; - public InvocableRpcMethod(Method method, MethodInvoker invoker) { - super(method); + public InvocableMethod(ServiceInterfaceMetadata metadata, Class serviceInterface, Method method, MethodInvoker invoker) { + super(metadata.getServiceMetadata(), serviceInterface, method); this.invoker = invoker; } diff --git a/today-service-provider/src/main/java/infra/cloud/provider/LocalServiceHolder.java b/today-service-provider/src/main/java/infra/cloud/provider/LocalServiceHolder.java index 476f756..6a17dc6 100644 --- a/today-service-provider/src/main/java/infra/cloud/provider/LocalServiceHolder.java +++ b/today-service-provider/src/main/java/infra/cloud/provider/LocalServiceHolder.java @@ -25,6 +25,9 @@ import infra.context.ApplicationContext; import infra.context.support.ApplicationObjectSupport; import infra.lang.Nullable; +import infra.remoting.core.RemotingServer; +import infra.remoting.frame.decoder.PayloadDecoder; +import infra.remoting.transport.netty.server.TcpServerTransport; import infra.stereotype.Service; import infra.util.ClassUtils; @@ -36,12 +39,19 @@ public class LocalServiceHolder extends ApplicationObjectSupport implements Smar private final HashMap, Object> localServices = new HashMap<>(); + private final HashMap> classNameMap = new HashMap<>(); + @Nullable @SuppressWarnings("unchecked") public T getService(Class serviceInterface) { return (T) localServices.get(serviceInterface); } + @Nullable + public Class getServiceInterface(String serviceClass) { + return classNameMap.get(serviceClass); + } + @Override public void afterSingletonsInstantiated() { ApplicationContext context = obtainApplicationContext(); @@ -57,14 +67,25 @@ public void afterSingletonsInstantiated() { for (final Class anInterface : interfaces) { if (anInterface.isAnnotationPresent(Service.class)) { Object object = localServices.put(anInterface, service); + String interfaceName = anInterface.getName(); if (object != null) { - throw new IllegalStateException("Service '%s' is already registered: [%s]".formatted(anInterface.getName(), object)); + throw new IllegalStateException("Service '%s' is already registered: [%s]".formatted(interfaceName, object)); } - logger.info("add service: [{}] to interface: [{}]", service, anInterface.getName()); + classNameMap.put(interfaceName, anInterface); + logger.info("add service: [{}] to interface: [{}]", service, interfaceName); } } } + startServer(); + } + + private void startServer() { + RemotingServer.create() + .payloadDecoder(PayloadDecoder.ZERO_COPY) + .bind(TcpServerTransport.create(1)) + .subscribe() + ; } } diff --git a/today-service-provider/src/main/java/infra/cloud/provider/RpcRequestDeserializer.java b/today-service-provider/src/main/java/infra/cloud/provider/RpcRequestDeserializer.java index 966262f..3a2e685 100644 --- a/today-service-provider/src/main/java/infra/cloud/provider/RpcRequestDeserializer.java +++ b/today-service-provider/src/main/java/infra/cloud/provider/RpcRequestDeserializer.java @@ -25,10 +25,11 @@ import infra.cloud.serialize.MessagePackInput; import infra.cloud.serialize.RpcArgumentSerialization; import infra.cloud.serialize.SerializationException; +import infra.cloud.service.ServiceInterfaceMetadata; +import infra.cloud.service.ServiceInterfaceMetadataProvider; import infra.core.MethodParameter; -import infra.lang.Nullable; +import infra.lang.Assert; import infra.reflect.MethodInvoker; -import infra.util.ClassUtils; import infra.util.MapCache; import io.netty.buffer.ByteBuf; @@ -44,31 +45,36 @@ public class RpcRequestDeserializer { /** fast method mapping cache */ private final MethodMapCache methodMapCache = new MethodMapCache(); - public RpcRequestDeserializer(List argumentSerializations) { + private final ServiceInterfaceMetadataProvider metadataProvider; + + private final LocalServiceHolder localServiceHolder; + + public RpcRequestDeserializer(List argumentSerializations, + ServiceInterfaceMetadataProvider metadataProvider, LocalServiceHolder localServiceHolder) { this.argumentSerializations = argumentSerializations; + this.metadataProvider = metadataProvider; + this.localServiceHolder = localServiceHolder; } public RpcRequest deserialize(ByteBuf payload) throws SerializationException { MessagePackInput input = new MessagePackInput(payload); - RpcRequest request = new RpcRequest(); request.readFrom(input); - InvocableRpcMethod rpcMethod = methodMapCache.get(new MethodKey(request.getMethodName(), request.getParamTypes()), null); - - if (rpcMethod == null) { - throw new IllegalStateException("No method found for method: " + request.getMethodName()); - } + String serviceClass = request.getServiceClass(); + Class serviceInterface = localServiceHolder.getServiceInterface(serviceClass); + Assert.state(serviceInterface != null, "service interface not found"); + InvocableMethod method = methodMapCache.get(new MethodKey(serviceClass, request.getMethodName(), request.getParamTypes()), serviceInterface); - request.setRpcMethod(rpcMethod); + request.setMethod(method); - MethodParameter[] parameters = rpcMethod.getParameters(); + MethodParameter[] parameters = method.getParameters(); Object[] args = new Object[parameters.length]; int idx = 0; for (MethodParameter parameter : parameters) { var serialization = findArgumentSerialization(parameter); - args[idx++] = serialization.deserialize(parameter, payload, input); + args[idx++] = serialization.deserialize(parameter, input); } request.setArguments(args); @@ -84,26 +90,25 @@ private RpcArgumentSerialization findArgumentSerialization(MethodParameter param throw new IllegalStateException("RpcArgumentSerialization for parameter %s not found".formatted(parameter)); } - private static final class MethodMapCache extends MapCache { + private final class MethodMapCache extends MapCache> { - @Nullable @Override - protected InvocableRpcMethod createValue(MethodKey key, @Nullable Object service) { - Method methodToUse = getMethod(key, service); + protected InvocableMethod createValue(MethodKey key, Class serviceInterface) { + Method methodToUse = getMethod(key, serviceInterface); if (methodToUse == null) { - return null; + throw new IllegalStateException("No method found for method: " + key.method); } MethodInvoker methodInvoker = MethodInvoker.forMethod(methodToUse); - return new InvocableRpcMethod(methodToUse, methodInvoker); + ServiceInterfaceMetadata metadata = metadataProvider.getMetadata(serviceInterface); + return new InvocableMethod(metadata, serviceInterface, methodToUse, methodInvoker); } - private static Method getMethod(MethodKey key, Object service) { + private static Method getMethod(MethodKey key, Class serviceInterface) { String method = key.method; String[] paramTypes = key.paramTypes; int parameterLength = paramTypes.length; - Class serviceImpl = ClassUtils.getUserClass(service); - for (Method serviceMethod : serviceImpl.getMethods()) { + for (Method serviceMethod : serviceInterface.getMethods()) { if (Objects.equals(serviceMethod.getName(), method) && parameterLength == serviceMethod.getParameterCount()) { int current = 0; @@ -124,7 +129,7 @@ private static Method getMethod(MethodKey key, Object service) { } } - private record MethodKey(String method, String[] paramTypes) { + private record MethodKey(String serviceClass, String method, String[] paramTypes) { } diff --git a/today-service-provider/src/main/java/infra/cloud/provider/ServiceChannelHandler.java b/today-service-provider/src/main/java/infra/cloud/provider/ServiceChannelHandler.java new file mode 100644 index 0000000..0cebb71 --- /dev/null +++ b/today-service-provider/src/main/java/infra/cloud/provider/ServiceChannelHandler.java @@ -0,0 +1,58 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.provider; + +import org.reactivestreams.Publisher; + +import infra.remoting.Channel; +import infra.remoting.Payload; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +/** + * @author 海子 Yang + * @since 1.0 2025/8/21 22:58 + */ +public class ServiceChannelHandler implements Channel { + + @Override + public Mono requestResponse(Payload payload) { + return Channel.super.requestResponse(payload); + } + + @Override + public Flux requestStream(Payload payload) { + return Channel.super.requestStream(payload); + } + + @Override + public Flux requestChannel(Publisher payloads) { + return Channel.super.requestChannel(payloads); + } + + @Override + public Mono fireAndForget(Payload payload) { + return Channel.super.fireAndForget(payload); + } + + @Override + public Mono metadataPush(Payload payload) { + return Channel.super.metadataPush(payload); + } + +} diff --git a/today-service-provider/src/main/java/infra/cloud/provider/ServiceProviderServer.java b/today-service-provider/src/main/java/infra/cloud/provider/ServiceProviderServer.java new file mode 100644 index 0000000..71cf504 --- /dev/null +++ b/today-service-provider/src/main/java/infra/cloud/provider/ServiceProviderServer.java @@ -0,0 +1,85 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.provider; + +import infra.context.Lifecycle; +import infra.lang.Nullable; +import infra.remoting.Channel; +import infra.remoting.ChannelAcceptor; +import infra.remoting.Closeable; +import infra.remoting.ConnectionSetupPayload; +import infra.remoting.core.RemotingServer; +import infra.remoting.core.Resume; +import infra.remoting.frame.decoder.PayloadDecoder; +import infra.remoting.transport.ServerTransport; +import infra.remoting.transport.netty.server.TcpServerTransport; +import reactor.core.publisher.Mono; + +/** + * @author 海子 Yang + * @since 1.0 2025/8/21 22:25 + */ +public class ServiceProviderServer implements Lifecycle, ChannelAcceptor { + + private final ServiceChannelHandler channelHandler; + + private final Resume resume = new Resume(); + + private int maxFrameLength; + + private String bindAddress; + + private int port; + + @Nullable + private Closeable serverCloseable; + + public ServiceProviderServer(ServiceChannelHandler channelHandler) { + this.channelHandler = channelHandler; + } + + @Override + public void start() { + serverCloseable = RemotingServer.create(this) + .payloadDecoder(PayloadDecoder.ZERO_COPY) + .resume(resume) + .bindNow(createServerTransport()); + } + + private ServerTransport createServerTransport() { + return TcpServerTransport.create(bindAddress, port); + } + + @Override + public void stop() { + if (serverCloseable != null) { + serverCloseable.dispose(); + } + } + + @Override + public boolean isRunning() { + return serverCloseable != null; + } + + @Override + public Mono accept(ConnectionSetupPayload setup, Channel channel) { + return Mono.just(channelHandler); + } + +} diff --git a/today-service-provider/src/main/java/infra/cloud/provider/annotation/config/ServiceProviderAutoConfiguration.java b/today-service-provider/src/main/java/infra/cloud/provider/annotation/config/ServiceProviderAutoConfiguration.java index 5dd2202..2a5170e 100644 --- a/today-service-provider/src/main/java/infra/cloud/provider/annotation/config/ServiceProviderAutoConfiguration.java +++ b/today-service-provider/src/main/java/infra/cloud/provider/annotation/config/ServiceProviderAutoConfiguration.java @@ -18,9 +18,19 @@ package infra.cloud.provider.annotation.config; import infra.cloud.client.annotation.ConditionalOnDiscoveryEnabled; +import infra.cloud.net.InetProperties; +import infra.cloud.net.InetService; +import infra.cloud.provider.DefaultServiceInterfaceMetadataProvider; import infra.cloud.provider.LocalServiceHolder; +import infra.cloud.provider.ServiceChannelHandler; import infra.cloud.registry.annotation.config.AutoServiceRegistrationAutoConfiguration; +import infra.cloud.service.PackageInfoServiceMetadataProvider; +import infra.cloud.service.ServiceInterfaceMetadataProvider; +import infra.cloud.service.ServiceMetadataProvider; +import infra.cloud.service.ServiceMethod; import infra.context.annotation.config.DisableDIAutoConfiguration; +import infra.context.condition.ConditionalOnMissingBean; +import infra.context.properties.EnableConfigurationProperties; import infra.stereotype.Component; /** @@ -28,6 +38,7 @@ * @since 1.0 2025/8/10 22:31 */ @ConditionalOnDiscoveryEnabled +@EnableConfigurationProperties(InetProperties.class) @DisableDIAutoConfiguration(before = AutoServiceRegistrationAutoConfiguration.class) public class ServiceProviderAutoConfiguration { @@ -36,4 +47,26 @@ public static LocalServiceHolder localServiceHolder() { return new LocalServiceHolder(); } + @Component + @ConditionalOnMissingBean + public static ServiceMetadataProvider serviceMetadataProvider() { + return new PackageInfoServiceMetadataProvider(); + } + + @Component + @ConditionalOnMissingBean + public static ServiceInterfaceMetadataProvider serviceInterfaceMetadataProvider(ServiceMetadataProvider serviceMetadataProvider) { + return new DefaultServiceInterfaceMetadataProvider(serviceMetadataProvider); + } + + @Component + public static InetService inetService(InetProperties inetProperties) { + return new InetService(inetProperties); + } + + @Component + public static ServiceChannelHandler serviceChannelHandler() { + return new ServiceChannelHandler(); + } + } diff --git a/today-service-provider/src/main/java/infra/cloud/provider/package-info.java b/today-service-provider/src/main/java/infra/cloud/provider/package-info.java new file mode 100644 index 0000000..3f37cd6 --- /dev/null +++ b/today-service-provider/src/main/java/infra/cloud/provider/package-info.java @@ -0,0 +1,23 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +@NonNullApi +@NonNullFields +package infra.cloud.provider; + +import infra.lang.NonNullApi; +import infra.lang.NonNullFields; \ No newline at end of file diff --git a/today-service-registry/src/main/resources/application.properties b/today-service-registry/src/main/resources/application.properties deleted file mode 100644 index 78b5f34..0000000 --- a/today-service-registry/src/main/resources/application.properties +++ /dev/null @@ -1,18 +0,0 @@ -# -# Copyright 2021 - 2023 the original author or authors. -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see [http://www.gnu.org/licenses/] -# - -registry.services.uri=/services diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/Input.java b/today-service-serialization/src/main/java/infra/cloud/serialize/Input.java index 796982b..787ead1 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/Input.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/Input.java @@ -23,6 +23,8 @@ import java.util.function.Function; import java.util.function.Supplier; +import infra.lang.Nullable; + /** * An Input lets an application read primitive data types and objects from a source of data. * @@ -176,6 +178,9 @@ public interface Input { */ void read(Message message); + @Nullable + V readNullable(Function valueMapper); + /** * Reads a {@code array} value. * diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/Output.java b/today-service-serialization/src/main/java/infra/cloud/serialize/Output.java index cfccaef..6d7423a 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/Output.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/Output.java @@ -119,18 +119,18 @@ public interface Output { /** * Writes a {@code String} value. * - * @param s the string value to be written. + * @param v the string value to be written. * @throws SerializationException if a serialization error occurs. */ - void write(@Nullable String s); + void write(@Nullable String v); /** * Writes a Timestamp value. * - * @param instant the timestamp to be written + * @param v the timestamp to be written * @throws SerializationException if a serialization error occurs. */ - void write(Instant instant); + void write(Instant v); /** * Writes a Timestamp value. @@ -152,57 +152,65 @@ public interface Output { /** * Writes a {@code Message} value. * - * @param message the Message value to be written. + * @param v the Message value to be written. * @throws SerializationException if a serialization error occurs. */ - void write(Message message); + void write(Message v); + + /** + * Writes a nullable {@code V} value. + * + * @param v the value to be written. + * @throws SerializationException if a serialization error occurs. + */ + void writeNullable(@Nullable V v, BiConsumer valueMapper); /** * Writes a {@code array} value. * - * @param array the array value to be written. + * @param v the array value to be written. * @throws SerializationException if a serialization error occurs. */ - void write(T[] array, Consumer mapper); + void write(T[] v, Consumer mapper); /** * Writes a {@code array} value. * - * @param array the array value to be written. + * @param v the array value to be written. * @throws SerializationException if a serialization error occurs. */ - void write(T[] array, BiConsumer mapper); + void write(T[] v, BiConsumer mapper); /** * Writes a {@code List} value. * - * @param list the List value to be written. + * @param v the List value to be written. * @throws SerializationException if a serialization error occurs. */ - void write(List list, Consumer mapper); + void write(List v, Consumer mapper); /** * Writes a {@code List} value. * - * @param list the List value to be written. + * @param v the List value to be written. * @throws SerializationException if a serialization error occurs. */ - void write(List list, BiConsumer mapper); + void write(List v, BiConsumer mapper); /** * Writes a {@code Map} value. * - * @param map the Map value to be written. + * @param v the Map value to be written. * @throws SerializationException if a serialization error occurs. */ - void write(Map map, Consumer keyMapper, Consumer valueMapper); + void write(Map v, Consumer keyMapper, Consumer valueMapper); /** * Writes a {@code Map} value. * - * @param map the Map value to be written. + * @param v the Map value to be written. * @throws SerializationException if a serialization error occurs. */ - void write(Map map, BiConsumer keyMapper, BiConsumer valueMapper); + void write(Map v, BiConsumer keyMapper, BiConsumer valueMapper); } From 4141f4fc12f912af80389ea1f1f16ae371df493b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Sat, 23 Aug 2025 00:33:44 +0800 Subject: [PATCH 046/104] =?UTF-8?q?:art:=20=E9=85=8D=E7=BD=AE=20Service=20?= =?UTF-8?q?provider=20server?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../infra/remoting/core/ChannelConnector.java | 15 +- .../remoting/core/PayloadValidationUtils.java | 16 +- .../infra/remoting/core/RemotingServer.java | 26 ++-- .../main/java/infra/remoting/core/Resume.java | 83 +++++----- .../java/infra/remoting/core/ServerSetup.java | 41 ++--- .../infra/remoting/core/package-info.java | 2 + .../remoting/frame/FrameLengthCodec.java | 7 +- .../remoting/frame/ResumeFrameCodec.java | 17 +- .../resume/InMemoryResumableFramesStore.java | 5 +- .../InMemoryResumableFramesStoreFactory.java | 47 ++++++ .../RandomUUIDResumeTokenGenerator.java | 42 +++++ .../resume/ResumableFramesStoreFactory.java | 13 +- .../remoting/resume/ResumeTokenGenerator.java | 39 +++++ .../resume/ResumeIntegrationTests.java | 12 +- .../infra/remoting/test/TransportPair.java | 30 ++-- .../service/config/ResumeProperties.java | 132 ++++++++++++++++ .../cloud/provider/LocalServiceHolder.java | 12 -- .../provider/ServerTransportFactory.java | 37 +++++ .../cloud/provider/ServiceProviderServer.java | 30 ++-- .../provider/ServiceServerProperties.java | 146 ++++++++++++++++++ .../provider/TcpServerTransportFactory.java | 50 ++++++ .../ServiceProviderAutoConfiguration.java | 50 +++++- 22 files changed, 677 insertions(+), 175 deletions(-) create mode 100644 today-remoting/src/main/java/infra/remoting/resume/InMemoryResumableFramesStoreFactory.java create mode 100644 today-remoting/src/main/java/infra/remoting/resume/RandomUUIDResumeTokenGenerator.java rename today-service-provider/src/main/java/infra/cloud/provider/ServiceProviderProperties.java => today-remoting/src/main/java/infra/remoting/resume/ResumableFramesStoreFactory.java (73%) create mode 100644 today-remoting/src/main/java/infra/remoting/resume/ResumeTokenGenerator.java create mode 100644 today-service-api/src/main/java/infra/cloud/service/config/ResumeProperties.java create mode 100644 today-service-provider/src/main/java/infra/cloud/provider/ServerTransportFactory.java create mode 100644 today-service-provider/src/main/java/infra/cloud/provider/ServiceServerProperties.java create mode 100644 today-service-provider/src/main/java/infra/cloud/provider/TcpServerTransportFactory.java diff --git a/today-remoting/src/main/java/infra/remoting/core/ChannelConnector.java b/today-remoting/src/main/java/infra/remoting/core/ChannelConnector.java index f9d783b..c6aff91 100644 --- a/today-remoting/src/main/java/infra/remoting/core/ChannelConnector.java +++ b/today-remoting/src/main/java/infra/remoting/core/ChannelConnector.java @@ -40,7 +40,6 @@ import infra.remoting.plugins.RateLimitDecorator; import infra.remoting.resume.ClientChannelSession; import infra.remoting.resume.ResumableConnection; -import infra.remoting.resume.ResumableFramesStore; import infra.remoting.transport.ClientTransport; import infra.remoting.transport.Transport; import infra.remoting.util.ByteBufPayload; @@ -102,8 +101,10 @@ public class ChannelConnector { private final InitializingInterceptorRegistry interceptors = new InitializingInterceptorRegistry(); + @Nullable private Retry retrySpec; + @Nullable private Resume resume; @Nullable @@ -534,7 +535,7 @@ public Mono connect(Supplier transportSupplier) { ByteBuf resumeToken; if (resumeEnabled) { - resumeToken = resume.getTokenSupplier().get(); + resumeToken = resume.tokenGenerator.generate(); } else { resumeToken = Unpooled.EMPTY_BUFFER; @@ -552,11 +553,11 @@ public Mono connect(Supplier transportSupplier) { final KeepAliveHandler keepAliveHandler; if (resumeEnabled) { - final ResumableClientSetup resumableClientSetup = new ResumableClientSetup(); - final ResumableFramesStore resumableFramesStore = resume.getStoreFactory(CLIENT_TAG).apply(resumeToken); - final ResumableConnection resumableConnection = new ResumableConnection(CLIENT_TAG, resumeToken, clientServerConnection, resumableFramesStore); - final ClientChannelSession session = new ClientChannelSession(resumeToken, resumableConnection, connectionMono, resumableClientSetup::init, - resumableFramesStore, resume.getSessionDuration(), resume.getRetry(), resume.isCleanupStoreOnKeepAlive()); + final var resumableClientSetup = new ResumableClientSetup(); + final var resumableFramesStore = resume.getStoreFactory(CLIENT_TAG).create(resumeToken); + final var resumableConnection = new ResumableConnection(CLIENT_TAG, resumeToken, clientServerConnection, resumableFramesStore); + final var session = new ClientChannelSession(resumeToken, resumableConnection, connectionMono, resumableClientSetup::init, + resumableFramesStore, resume.sessionDuration, resume.retry, resume.cleanupStoreOnKeepAlive); keepAliveHandler = new KeepAliveHandler.ResumableKeepAliveHandler(resumableConnection, session, session); wrappedConnection = resumableConnection; diff --git a/today-remoting/src/main/java/infra/remoting/core/PayloadValidationUtils.java b/today-remoting/src/main/java/infra/remoting/core/PayloadValidationUtils.java index a4bba7f..fdeba96 100644 --- a/today-remoting/src/main/java/infra/remoting/core/PayloadValidationUtils.java +++ b/today-remoting/src/main/java/infra/remoting/core/PayloadValidationUtils.java @@ -27,11 +27,11 @@ import static infra.remoting.frame.FrameLengthCodec.FRAME_LENGTH_MASK; final class PayloadValidationUtils { + static final String INVALID_PAYLOAD_ERROR_MESSAGE = "The payload is too big to be send as a single frame with a max frame length %s. Consider enabling fragmentation."; static boolean isValid(int mtu, int maxFrameLength, Payload payload, boolean hasInitialRequestN) { - if (mtu > 0) { return true; } @@ -42,18 +42,12 @@ static boolean isValid(int mtu, int maxFrameLength, Payload payload, boolean has int unitSize; if (hasMetadata) { final ByteBuf metadata = payload.metadata(); - unitSize = - (hasInitialRequestN - ? FRAME_OFFSET_WITH_METADATA_AND_INITIAL_REQUEST_N - : FRAME_OFFSET_WITH_METADATA) - + metadata.readableBytes() - + // metadata payload bytes - data.readableBytes(); // data payload bytes + unitSize = (hasInitialRequestN ? FRAME_OFFSET_WITH_METADATA_AND_INITIAL_REQUEST_N : FRAME_OFFSET_WITH_METADATA) + + metadata.readableBytes()// metadata payload bytes + + data.readableBytes(); // data payload bytes } else { - unitSize = - (hasInitialRequestN ? FRAME_OFFSET_WITH_INITIAL_REQUEST_N : FRAME_OFFSET) - + data.readableBytes(); // data payload bytes + unitSize = (hasInitialRequestN ? FRAME_OFFSET_WITH_INITIAL_REQUEST_N : FRAME_OFFSET) + data.readableBytes(); // data payload bytes } return unitSize <= maxFrameLength; diff --git a/today-remoting/src/main/java/infra/remoting/core/RemotingServer.java b/today-remoting/src/main/java/infra/remoting/core/RemotingServer.java index c0d5ebc..347305e 100644 --- a/today-remoting/src/main/java/infra/remoting/core/RemotingServer.java +++ b/today-remoting/src/main/java/infra/remoting/core/RemotingServer.java @@ -22,6 +22,7 @@ import java.util.function.Consumer; import java.util.function.Supplier; +import infra.lang.Nullable; import infra.remoting.Channel; import infra.remoting.ChannelAcceptor; import infra.remoting.Closeable; @@ -73,8 +74,10 @@ public final class RemotingServer { private final InitializingInterceptorRegistry interceptors = new InitializingInterceptorRegistry(); + @Nullable private Resume resume; + @Nullable private Consumer leaseConfigurer = null; private int mtu = 0; @@ -163,7 +166,7 @@ public RemotingServer interceptors(Consumer configurer) { * href="https://github.com/today-tech/today-cloud/blob/master/today-remoting/Protocol.md#resuming-operation">Resuming * Operation */ - public RemotingServer resume(Resume resume) { + public RemotingServer resume(@Nullable Resume resume) { this.resume = resume; return this; } @@ -192,7 +195,7 @@ public RemotingServer resume(Resume resume) { * @see Lease * Semantics */ - public RemotingServer lease(Consumer leaseConfigurer) { + public RemotingServer lease(@Nullable Consumer leaseConfigurer) { this.leaseConfigurer = leaseConfigurer; return this; } @@ -221,7 +224,7 @@ public RemotingServer maxInboundPayloadSize(int maxInboundPayloadSize) { * Specify the max time to wait for the first frame (e.g. {@code SETUP}) on an accepted * connection. * - *

          By default this is set to 1 minute. + *

          By default, this is set to 1 minute. * * @param timeout duration * @return the same instance for method chaining @@ -286,7 +289,7 @@ public RemotingServer payloadDecoder(PayloadDecoder decoder) { */ public Mono bind(ServerTransport transport) { return Mono.defer(new Supplier>() { - private final ServerSetup serverSetup = serverSetup(timeout); + private final ServerSetup serverSetup = createSetup(timeout); @Override public Mono get() { @@ -323,7 +326,7 @@ public ConnectionAcceptor asConnectionAcceptor() { public ConnectionAcceptor asConnectionAcceptor(int maxFrameLength) { assertValidateSetup(maxFrameLength, maxInboundPayloadSize, mtu); return new ConnectionAcceptor() { - private final ServerSetup serverSetup = serverSetup(timeout); + private final ServerSetup serverSetup = createSetup(timeout); @Override public Mono accept(Connection connection) { @@ -422,13 +425,12 @@ private Mono acceptSetup(ServerSetup serverSetup, ByteBuf setupFrame, Conn }); } - private ServerSetup serverSetup(Duration timeout) { - return resume != null ? createSetup(timeout) : new ServerSetup.DefaultServerSetup(timeout); - } - - ServerSetup createSetup(Duration timeout) { - return new ServerSetup.ResumableServerSetup(timeout, new SessionManager(), resume.getSessionDuration(), - resume.getStreamTimeout(), resume.getStoreFactory(SERVER_TAG), resume.isCleanupStoreOnKeepAlive()); + private ServerSetup createSetup(Duration timeout) { + if (resume == null) { + return new ServerSetup.DefaultServerSetup(timeout); + } + return new ServerSetup.ResumableServerSetup(timeout, new SessionManager(), resume.sessionDuration, + resume.streamTimeout, resume.getStoreFactory(SERVER_TAG), resume.cleanupStoreOnKeepAlive); } private ProtocolErrorException rejectedSetupError(Throwable err) { diff --git a/today-remoting/src/main/java/infra/remoting/core/Resume.java b/today-remoting/src/main/java/infra/remoting/core/Resume.java index ba89b94..a251ee0 100644 --- a/today-remoting/src/main/java/infra/remoting/core/Resume.java +++ b/today-remoting/src/main/java/infra/remoting/core/Resume.java @@ -18,39 +18,40 @@ import java.time.Duration; import java.util.Objects; -import java.util.function.Function; -import java.util.function.Supplier; +import infra.lang.Nullable; import infra.logging.Logger; import infra.logging.LoggerFactory; -import infra.remoting.frame.ResumeFrameCodec; import infra.remoting.resume.InMemoryResumableFramesStore; -import infra.remoting.resume.ResumableFramesStore; -import io.netty.buffer.ByteBuf; +import infra.remoting.resume.InMemoryResumableFramesStoreFactory; +import infra.remoting.resume.RandomUUIDResumeTokenGenerator; +import infra.remoting.resume.ResumableFramesStoreFactory; +import infra.remoting.resume.ResumeTokenGenerator; import reactor.util.retry.Retry; /** * Simple holder of configuration settings for the protocol Resume capability. This can be used to * configure an {@link ChannelConnector} or an {@link RemotingServer} except for {@link - * #retry(Retry)} and {@link #token(Supplier)} which apply only to the client side. + * #retry(Retry)} and {@link #token(ResumeTokenGenerator)} which apply only to the client side. */ public class Resume { private static final Logger logger = LoggerFactory.getLogger(Resume.class); - private Duration sessionDuration = Duration.ofMinutes(2); + Duration sessionDuration = Duration.ofMinutes(2); - /* Storage */ - private boolean cleanupStoreOnKeepAlive; + @Nullable + private ResumableFramesStoreFactory storeFactory; - private Function storeFactory; + /* Storage */ + boolean cleanupStoreOnKeepAlive; - private Duration streamTimeout = Duration.ofSeconds(10); + Duration streamTimeout = Duration.ofSeconds(10); /* Client only */ - private Supplier tokenSupplier = ResumeFrameCodec::generateResumeToken; + ResumeTokenGenerator tokenGenerator = new RandomUUIDResumeTokenGenerator(); - private Retry retry = Retry.backoff(Long.MAX_VALUE, Duration.ofSeconds(1)) + Retry retry = Retry.backoff(Long.MAX_VALUE, Duration.ofSeconds(1)) .maxBackoff(Duration.ofSeconds(16)) .jitter(1.0) .doBeforeRetry(signal -> logger.debug("Connection error", signal.failure())); @@ -75,9 +76,9 @@ public Resume sessionDuration(Duration sessionDuration) { /** * When this property is enabled, hints from {@code KEEPALIVE} frames about how much data has been * received by the other side, is used to proactively clean frames from the {@link - * #storeFactory(Function) store}. + * Resume#storeFactory(ResumableFramesStoreFactory) store}. * - *

          By default this is set to {@code false} in which case information from {@code KEEPALIVE} is + *

          By default, this is set to {@code false} in which case information from {@code KEEPALIVE} is * ignored and old frames from the store are removed only when the store runs out of space. * * @return the same instance for method chaining @@ -87,6 +88,21 @@ public Resume cleanupStoreOnKeepAlive() { return this; } + /** + * When this property is enabled, hints from {@code KEEPALIVE} frames about how much data has been + * received by the other side, is used to proactively clean frames from the {@link + * Resume#storeFactory(ResumableFramesStoreFactory) store}. + * + *

          By default, this is set to {@code false} in which case information from {@code KEEPALIVE} is + * ignored and old frames from the store are removed only when the store runs out of space. + * + * @return the same instance for method chaining + */ + public Resume cleanupStoreOnKeepAlive(boolean cleanupStoreOnKeepAlive) { + this.cleanupStoreOnKeepAlive = cleanupStoreOnKeepAlive; + return this; + } + /** * Configure a factory to create the storage for buffering (or persisting) a window of frames that * may need to be sent again to resume after a dropped connection. @@ -98,17 +114,17 @@ public Resume cleanupStoreOnKeepAlive() { * @param storeFactory the factory to use to create the store * @return the same instance for method chaining */ - public Resume storeFactory(Function storeFactory) { + public Resume storeFactory(@Nullable ResumableFramesStoreFactory storeFactory) { this.storeFactory = storeFactory; return this; } /** * A {@link reactor.core.publisher.Flux#timeout(Duration) timeout} value to apply to the resumed - * session stream obtained from the {@link #storeFactory(Function) store} after a reconnect. The + * session stream obtained from the {@link #storeFactory(ResumableFramesStoreFactory) store} after a reconnect. The * resume stream must not take longer than the specified time to emit each frame. * - *

          By default this is set to 10 seconds. + *

          By default, this is set to 10 seconds. * * @param streamTimeout the timeout value for resuming a session stream * @return the same instance for method chaining @@ -142,41 +158,22 @@ public Resume retry(Retry retry) { * Customize the generation of the resume identification token used to resume. This setting is for * use with {@link ChannelConnector#resume(Resume)} on the client side only. * - *

          By default this is {@code ResumeFrameFlyweight::generateResumeToken}. + *

          By default, this is {@code ResumeFrameFlyweight::generateResumeToken}. * - * @param supplier a custom generator for a resume identification token + * @param generator a custom generator for a resume identification token * @return the same instance for method chaining */ - public Resume token(Supplier supplier) { - this.tokenSupplier = supplier; + public Resume token(ResumeTokenGenerator generator) { + this.tokenGenerator = generator; return this; } // Package private accessors - Duration getSessionDuration() { - return sessionDuration; - } - - boolean isCleanupStoreOnKeepAlive() { - return cleanupStoreOnKeepAlive; - } - - Function getStoreFactory(String tag) { + ResumableFramesStoreFactory getStoreFactory(String tag) { return storeFactory != null ? storeFactory - : token -> new InMemoryResumableFramesStore(tag, token, 100_000); + : new InMemoryResumableFramesStoreFactory(tag, 100_000); } - Duration getStreamTimeout() { - return streamTimeout; - } - - Retry getRetry() { - return retry; - } - - Supplier getTokenSupplier() { - return tokenSupplier; - } } diff --git a/today-remoting/src/main/java/infra/remoting/core/ServerSetup.java b/today-remoting/src/main/java/infra/remoting/core/ServerSetup.java index 3e97fdf..c1e3cc6 100644 --- a/today-remoting/src/main/java/infra/remoting/core/ServerSetup.java +++ b/today-remoting/src/main/java/infra/remoting/core/ServerSetup.java @@ -20,7 +20,6 @@ import java.nio.channels.ClosedChannelException; import java.time.Duration; import java.util.function.BiFunction; -import java.util.function.Function; import infra.remoting.Connection; import infra.remoting.ProtocolErrorException; @@ -30,7 +29,7 @@ import infra.remoting.frame.SetupFrameCodec; import infra.remoting.keepalive.KeepAliveHandler; import infra.remoting.resume.ResumableConnection; -import infra.remoting.resume.ResumableFramesStore; +import infra.remoting.resume.ResumableFramesStoreFactory; import infra.remoting.resume.ServerChannelSession; import infra.remoting.resume.SessionManager; import io.netty.buffer.ByteBuf; @@ -94,48 +93,40 @@ public Mono acceptChannelResume(ByteBuf frame, Connection connection) { } static class ResumableServerSetup extends ServerSetup { + private final Duration resumeStreamTimeout; + private final SessionManager sessionManager; + private final Duration resumeSessionDuration; - private final Duration resumeStreamTimeout; - private final Function resumeStoreFactory; + private final boolean cleanupStoreOnKeepAlive; + private final ResumableFramesStoreFactory resumeStoreFactory; + ResumableServerSetup(Duration timeout, SessionManager sessionManager, Duration resumeSessionDuration, Duration resumeStreamTimeout, - Function resumeStoreFactory, boolean cleanupStoreOnKeepAlive) { + ResumableFramesStoreFactory resumeStoreFactory, boolean cleanupStoreOnKeepAlive) { super(timeout); this.sessionManager = sessionManager; - this.resumeSessionDuration = resumeSessionDuration; - this.resumeStreamTimeout = resumeStreamTimeout; this.resumeStoreFactory = resumeStoreFactory; + this.resumeStreamTimeout = resumeStreamTimeout; + this.resumeSessionDuration = resumeSessionDuration; this.cleanupStoreOnKeepAlive = cleanupStoreOnKeepAlive; } @Override - public Mono acceptChannelSetup(ByteBuf frame, Connection connection, - BiFunction> then) { - + public Mono acceptChannelSetup(ByteBuf frame, Connection connection, BiFunction> then) { if (SetupFrameCodec.resumeEnabled(frame)) { ByteBuf resumeToken = SetupFrameCodec.resumeToken(frame); - final ResumableFramesStore resumableFramesStore = resumeStoreFactory.apply(resumeToken); - final ResumableConnection resumableConnection = - new ResumableConnection( - "server", resumeToken, connection, resumableFramesStore); - final ServerChannelSession serverChannelSession = - new ServerChannelSession( - resumeToken, - resumableConnection, - connection, - resumableFramesStore, - resumeSessionDuration, - cleanupStoreOnKeepAlive); + var resumableFramesStore = resumeStoreFactory.create(resumeToken); + var resumableConnection = new ResumableConnection("server", resumeToken, connection, resumableFramesStore); + var serverChannelSession = new ServerChannelSession(resumeToken, resumableConnection, connection, + resumableFramesStore, resumeSessionDuration, cleanupStoreOnKeepAlive); sessionManager.save(serverChannelSession, resumeToken); - return then.apply(new ResumableKeepAliveHandler( - resumableConnection, serverChannelSession, serverChannelSession), - resumableConnection); + return then.apply(new ResumableKeepAliveHandler(resumableConnection, serverChannelSession, serverChannelSession), resumableConnection); } else { return then.apply(new DefaultKeepAliveHandler(), connection); diff --git a/today-remoting/src/main/java/infra/remoting/core/package-info.java b/today-remoting/src/main/java/infra/remoting/core/package-info.java index d4ed9b8..3273b4c 100644 --- a/today-remoting/src/main/java/infra/remoting/core/package-info.java +++ b/today-remoting/src/main/java/infra/remoting/core/package-info.java @@ -24,6 +24,8 @@ * interactions. */ @NonNullApi +@NonNullFields package infra.remoting.core; import infra.lang.NonNullApi; +import infra.lang.NonNullFields; diff --git a/today-remoting/src/main/java/infra/remoting/frame/FrameLengthCodec.java b/today-remoting/src/main/java/infra/remoting/frame/FrameLengthCodec.java index 519f5b6..7560ec3 100644 --- a/today-remoting/src/main/java/infra/remoting/frame/FrameLengthCodec.java +++ b/today-remoting/src/main/java/infra/remoting/frame/FrameLengthCodec.java @@ -25,10 +25,12 @@ * for transports that need to send length */ public class FrameLengthCodec { + public static final int FRAME_LENGTH_MASK = 0xFFFFFF; public static final int FRAME_LENGTH_SIZE = 3; - private FrameLengthCodec() { } + private FrameLengthCodec() { + } private static void encodeLength(final ByteBuf byteBuf, final int length) { if ((length & ~FRAME_LENGTH_MASK) != 0) { @@ -51,7 +53,8 @@ private static int decodeLength(final ByteBuf byteBuf) { public static ByteBuf encode(ByteBufAllocator allocator, int length, ByteBuf frame) { ByteBuf buffer = allocator.buffer(); encodeLength(buffer, length); - return allocator.compositeBuffer(2).addComponents(true, buffer, frame); + return allocator.compositeBuffer(2) + .addComponents(true, buffer, frame); } public static int length(ByteBuf byteBuf) { diff --git a/today-remoting/src/main/java/infra/remoting/frame/ResumeFrameCodec.java b/today-remoting/src/main/java/infra/remoting/frame/ResumeFrameCodec.java index 63bbbff..76c0bb4 100644 --- a/today-remoting/src/main/java/infra/remoting/frame/ResumeFrameCodec.java +++ b/today-remoting/src/main/java/infra/remoting/frame/ResumeFrameCodec.java @@ -17,20 +17,14 @@ package infra.remoting.frame; -import java.util.UUID; - import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufAllocator; -import io.netty.buffer.Unpooled; public class ResumeFrameCodec { static final int CURRENT_VERSION = SetupFrameCodec.CURRENT_VERSION; - public static ByteBuf encode( - ByteBufAllocator allocator, - ByteBuf token, - long lastReceivedServerPos, - long firstAvailableClientPos) { + public static ByteBuf encode(ByteBufAllocator allocator, ByteBuf token, + long lastReceivedServerPos, long firstAvailableClientPos) { ByteBuf byteBuf = FrameHeaderCodec.encodeStreamZero(allocator, FrameType.RESUME, 0); byteBuf.writeInt(CURRENT_VERSION); @@ -104,11 +98,4 @@ public static long firstAvailableClientPos(ByteBuf byteBuf) { return firstAvailableClientPos; } - public static ByteBuf generateResumeToken() { - UUID uuid = UUID.randomUUID(); - ByteBuf bb = Unpooled.buffer(16); - bb.writeLong(uuid.getMostSignificantBits()); - bb.writeLong(uuid.getLeastSignificantBits()); - return bb; - } } diff --git a/today-remoting/src/main/java/infra/remoting/resume/InMemoryResumableFramesStore.java b/today-remoting/src/main/java/infra/remoting/resume/InMemoryResumableFramesStore.java index 507fd6c..bb013b3 100644 --- a/today-remoting/src/main/java/infra/remoting/resume/InMemoryResumableFramesStore.java +++ b/today-remoting/src/main/java/infra/remoting/resume/InMemoryResumableFramesStore.java @@ -127,15 +127,14 @@ public class InMemoryResumableFramesStore extends Flux implements Resum public InMemoryResumableFramesStore(String side, ByteBuf session, int cacheSizeBytes) { this.side = side; - this.session = session.toString(CharsetUtil.UTF_8); this.cacheLimit = cacheSizeBytes; this.cachedFrames = new ArrayDeque<>(); + this.session = session.toString(CharsetUtil.UTF_8); } @Override public Mono saveFrames(Flux frames) { - return frames - .transform(Operators.lift((__, actual) -> + return frames.transform(Operators.lift((__, actual) -> this.framesSubscriber = new FramesSubscriber(actual, this))) .then(); } diff --git a/today-remoting/src/main/java/infra/remoting/resume/InMemoryResumableFramesStoreFactory.java b/today-remoting/src/main/java/infra/remoting/resume/InMemoryResumableFramesStoreFactory.java new file mode 100644 index 0000000..e10c060 --- /dev/null +++ b/today-remoting/src/main/java/infra/remoting/resume/InMemoryResumableFramesStoreFactory.java @@ -0,0 +1,47 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.remoting.resume; + +import infra.lang.Assert; +import io.netty.buffer.ByteBuf; + +/** + * @author 海子 Yang + * @since 1.0 2025/8/22 22:45 + */ +public class InMemoryResumableFramesStoreFactory implements ResumableFramesStoreFactory { + + private final String side; + + private final int cacheSizeBytes; + + /** + * @param cacheLimit cache size bytes + */ + public InMemoryResumableFramesStoreFactory(String side, int cacheLimit) { + Assert.notNull(side, "side is required"); + this.side = side; + this.cacheSizeBytes = cacheLimit; + } + + @Override + public ResumableFramesStore create(ByteBuf resumeToken) { + return new InMemoryResumableFramesStore(side, resumeToken, cacheSizeBytes); + } + +} diff --git a/today-remoting/src/main/java/infra/remoting/resume/RandomUUIDResumeTokenGenerator.java b/today-remoting/src/main/java/infra/remoting/resume/RandomUUIDResumeTokenGenerator.java new file mode 100644 index 0000000..9716904 --- /dev/null +++ b/today-remoting/src/main/java/infra/remoting/resume/RandomUUIDResumeTokenGenerator.java @@ -0,0 +1,42 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.remoting.resume; + +import java.util.UUID; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; + +/** + * Random UUID ResumeTokenGenerator + * + * @author 海子 Yang + * @since 1.0 2025/8/23 00:26 + */ +public class RandomUUIDResumeTokenGenerator implements ResumeTokenGenerator { + + @Override + public ByteBuf generate() { + UUID uuid = UUID.randomUUID(); + ByteBuf bb = Unpooled.buffer(16); + bb.writeLong(uuid.getMostSignificantBits()); + bb.writeLong(uuid.getLeastSignificantBits()); + return bb; + } + +} diff --git a/today-service-provider/src/main/java/infra/cloud/provider/ServiceProviderProperties.java b/today-remoting/src/main/java/infra/remoting/resume/ResumableFramesStoreFactory.java similarity index 73% rename from today-service-provider/src/main/java/infra/cloud/provider/ServiceProviderProperties.java rename to today-remoting/src/main/java/infra/remoting/resume/ResumableFramesStoreFactory.java index 5240910..7c61442 100644 --- a/today-service-provider/src/main/java/infra/cloud/provider/ServiceProviderProperties.java +++ b/today-remoting/src/main/java/infra/remoting/resume/ResumableFramesStoreFactory.java @@ -15,15 +15,16 @@ * along with this program. If not, see [http://www.gnu.org/licenses/] */ -package infra.cloud.provider; +package infra.remoting.resume; -import infra.context.properties.ConfigurationProperties; +import io.netty.buffer.ByteBuf; /** - * @author Harry Yang - * @since 1.0 2023/9/4 16:56 + * @author 海子 Yang + * @since 1.0 2025/8/22 22:37 */ -@ConfigurationProperties("service.provider") -public class ServiceProviderProperties { +public interface ResumableFramesStoreFactory { + + ResumableFramesStore create(ByteBuf resumeToken); } diff --git a/today-remoting/src/main/java/infra/remoting/resume/ResumeTokenGenerator.java b/today-remoting/src/main/java/infra/remoting/resume/ResumeTokenGenerator.java new file mode 100644 index 0000000..787139a --- /dev/null +++ b/today-remoting/src/main/java/infra/remoting/resume/ResumeTokenGenerator.java @@ -0,0 +1,39 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.remoting.resume; + +import infra.remoting.core.ChannelConnector; +import infra.remoting.core.Resume; +import io.netty.buffer.ByteBuf; + +/** + * Generator for a resume identification token + * + * @author 海子 Yang + * @see ChannelConnector#resume(Resume) + * @since 1.0 2025/8/23 00:21 + */ +public interface ResumeTokenGenerator { + + /** + * Customize the generation of the resume identification token used to resume. + * This setting is for use with {@link ChannelConnector#resume(Resume)} on the client side only. + */ + ByteBuf generate(); + +} diff --git a/today-remoting/src/test/java/infra/remoting/resume/ResumeIntegrationTests.java b/today-remoting/src/test/java/infra/remoting/resume/ResumeIntegrationTests.java index fb88c51..2a1f1ad 100644 --- a/today-remoting/src/test/java/infra/remoting/resume/ResumeIntegrationTests.java +++ b/today-remoting/src/test/java/infra/remoting/resume/ResumeIntegrationTests.java @@ -180,8 +180,8 @@ private static Mono newClientChannel( return ChannelConnector.create() .resume(new Resume() .sessionDuration(Duration.ofSeconds(sessionDurationSeconds)) - .storeFactory(t -> new InMemoryResumableFramesStore("client", t, 500_000)) - .cleanupStoreOnKeepAlive() + .storeFactory(new InMemoryResumableFramesStoreFactory("client", 500_000)) + .cleanupStoreOnKeepAlive(true) .retry(Retry.fixedDelay(Long.MAX_VALUE, Duration.ofSeconds(1)))) .keepAlive(Duration.ofSeconds(5), Duration.ofMinutes(5)) .connect(clientTransport); @@ -193,11 +193,9 @@ private static Mono newServerChannel() { private static Mono newServerChannel(int sessionDurationSeconds) { return RemotingServer.create(ChannelAcceptor.with(new TestResponderChannel())) - .resume( - new Resume() - .sessionDuration(Duration.ofSeconds(sessionDurationSeconds)) - .cleanupStoreOnKeepAlive() - .storeFactory(t -> new InMemoryResumableFramesStore("server", t, 500_000))) + .resume(new Resume().cleanupStoreOnKeepAlive() + .sessionDuration(Duration.ofSeconds(sessionDurationSeconds)) + .storeFactory(new InMemoryResumableFramesStoreFactory("server", 500_000))) .bind(serverTransport(SERVER_HOST, SERVER_PORT)); } diff --git a/today-remoting/src/testFixtures/java/infra/remoting/test/TransportPair.java b/today-remoting/src/testFixtures/java/infra/remoting/test/TransportPair.java index 4a1b47e..11baa1e 100644 --- a/today-remoting/src/testFixtures/java/infra/remoting/test/TransportPair.java +++ b/today-remoting/src/testFixtures/java/infra/remoting/test/TransportPair.java @@ -25,23 +25,23 @@ import java.util.function.BiFunction; import java.util.function.Supplier; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufAllocator; -import io.netty.util.ReferenceCountUtil; -import io.netty.util.ReferenceCounted; -import io.netty.util.ResourceLeakDetector; +import infra.remoting.Channel; import infra.remoting.Closeable; import infra.remoting.Connection; -import infra.remoting.Channel; import infra.remoting.ProtocolErrorException; import infra.remoting.core.ChannelConnector; import infra.remoting.core.RemotingServer; import infra.remoting.core.Resume; import infra.remoting.frame.decoder.PayloadDecoder; import infra.remoting.plugins.ConnectionDecorator; -import infra.remoting.resume.InMemoryResumableFramesStore; +import infra.remoting.resume.InMemoryResumableFramesStoreFactory; import infra.remoting.transport.ClientTransport; import infra.remoting.transport.ServerTransport; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufAllocator; +import io.netty.util.ReferenceCountUtil; +import io.netty.util.ReferenceCounted; +import io.netty.util.ResourceLeakDetector; import reactor.core.CoreSubscriber; import reactor.core.Disposable; import reactor.core.Disposables; @@ -144,7 +144,7 @@ public TransportPair(Supplier addressSupplier, if (withResumability) { remotingServer.resume(new Resume() - .storeFactory(token -> new InMemoryResumableFramesStore("server", token, Integer.MAX_VALUE))); + .storeFactory(new InMemoryResumableFramesStoreFactory("server", Integer.MAX_VALUE))); } if (withRandomFragmentation) { @@ -181,20 +181,18 @@ public TransportPair(Supplier addressSupplier, }); if (withResumability) { - channelConnector.resume( - new Resume().storeFactory( - token -> new InMemoryResumableFramesStore("client", token, Integer.MAX_VALUE))); + channelConnector.resume(new Resume() + .storeFactory(new InMemoryResumableFramesStoreFactory("client", Integer.MAX_VALUE))); } if (withRandomFragmentation) { channelConnector.fragment(ThreadLocalRandom.current().nextInt(256, 512)); } - client = - channelConnector - .connect(clientTransportSupplier.apply(address, server, allocatorToSupply1)) - .doOnError(Throwable::printStackTrace) - .block(); + client = channelConnector + .connect(clientTransportSupplier.apply(address, server, allocatorToSupply1)) + .doOnError(Throwable::printStackTrace) + .block(); } @Override diff --git a/today-service-api/src/main/java/infra/cloud/service/config/ResumeProperties.java b/today-service-api/src/main/java/infra/cloud/service/config/ResumeProperties.java new file mode 100644 index 0000000..4270618 --- /dev/null +++ b/today-service-api/src/main/java/infra/cloud/service/config/ResumeProperties.java @@ -0,0 +1,132 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.service.config; + +import java.time.Duration; + +import infra.remoting.core.Resume; +import infra.remoting.resume.ResumableFramesStoreFactory; +import infra.util.DataSize; + +/** + * Resume config properties + * + * @author 海子 Yang + * @see Resume + * @since 1.0 2025/8/22 21:32 + */ +public class ResumeProperties { + + /** + * Whether connection resume is enabled. Defaults to true. + */ + private boolean enabled = true; + + /** + * The maximum time for a client to keep trying to reconnect. + */ + private Duration sessionDuration = Duration.ofMinutes(2); + + /** + * A timeout value to apply to the resumed session stream obtained from the store after a reconnect. + */ + private Duration streamTimeout = Duration.ofSeconds(10); + + /** + * Memory cache limit bytes + */ + private DataSize memoryCacheLimit = DataSize.ofBytes(100_000); + + private boolean cleanupStoreOnKeepAlive = false; + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + + public boolean isEnabled() { + return enabled; + } + + /** + * A {@link reactor.core.publisher.Flux#timeout(Duration) timeout} value to apply to the resumed + * session stream obtained from the {@link Resume#storeFactory(ResumableFramesStoreFactory) store} after a reconnect. + * The resume stream must not take longer than the specified time to emit each frame. + * + *

          By default, this is set to 10 seconds. + * + * @param streamTimeout the timeout value for resuming a session stream + */ + public void setStreamTimeout(Duration streamTimeout) { + this.streamTimeout = streamTimeout; + } + + public Duration getStreamTimeout() { + return streamTimeout; + } + + /** + * The maximum time for a client to keep trying to reconnect. During this time client and server + * continue to store unsent frames to keep the session warm and ready to resume. + * + *

          By default, this is set to 2 minutes. + * + * @param sessionDuration the max duration for a session + */ + public void setSessionDuration(Duration sessionDuration) { + this.sessionDuration = sessionDuration; + } + + public Duration getSessionDuration() { + return sessionDuration; + } + + public DataSize getMemoryCacheLimit() { + return memoryCacheLimit; + } + + public void setMemoryCacheLimit(DataSize memoryCacheLimit) { + this.memoryCacheLimit = memoryCacheLimit; + } + + /** + * When this property is enabled, hints from {@code KEEPALIVE} frames about how much data has been + * received by the other side, is used to proactively clean frames from the {@link + * Resume#storeFactory(ResumableFramesStoreFactory) store}. + * + *

          By default, this is set to {@code false} in which case information from {@code KEEPALIVE} is + * ignored and old frames from the store are removed only when the store runs out of space. + */ + public void setCleanupStoreOnKeepAlive(boolean cleanupStoreOnKeepAlive) { + this.cleanupStoreOnKeepAlive = cleanupStoreOnKeepAlive; + } + + /** + * When this property is enabled, hints from {@code KEEPALIVE} frames about how much data has been + * received by the other side, is used to proactively clean frames from the {@link + * Resume#storeFactory(ResumableFramesStoreFactory) store}. + * + *

          By default, this is set to {@code false} in which case information from {@code KEEPALIVE} is + * ignored and old frames from the store are removed only when the store runs out of space. + * + * @return the same instance for method chaining + */ + public boolean isCleanupStoreOnKeepAlive() { + return cleanupStoreOnKeepAlive; + } + +} diff --git a/today-service-provider/src/main/java/infra/cloud/provider/LocalServiceHolder.java b/today-service-provider/src/main/java/infra/cloud/provider/LocalServiceHolder.java index 6a17dc6..6f1f306 100644 --- a/today-service-provider/src/main/java/infra/cloud/provider/LocalServiceHolder.java +++ b/today-service-provider/src/main/java/infra/cloud/provider/LocalServiceHolder.java @@ -25,9 +25,6 @@ import infra.context.ApplicationContext; import infra.context.support.ApplicationObjectSupport; import infra.lang.Nullable; -import infra.remoting.core.RemotingServer; -import infra.remoting.frame.decoder.PayloadDecoder; -import infra.remoting.transport.netty.server.TcpServerTransport; import infra.stereotype.Service; import infra.util.ClassUtils; @@ -77,15 +74,6 @@ public void afterSingletonsInstantiated() { } } - startServer(); - } - - private void startServer() { - RemotingServer.create() - .payloadDecoder(PayloadDecoder.ZERO_COPY) - .bind(TcpServerTransport.create(1)) - .subscribe() - ; } } diff --git a/today-service-provider/src/main/java/infra/cloud/provider/ServerTransportFactory.java b/today-service-provider/src/main/java/infra/cloud/provider/ServerTransportFactory.java new file mode 100644 index 0000000..4364a45 --- /dev/null +++ b/today-service-provider/src/main/java/infra/cloud/provider/ServerTransportFactory.java @@ -0,0 +1,37 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.provider; + +import infra.remoting.Closeable; +import infra.remoting.transport.ServerTransport; + +/** + * ServerTransport factory + * + * @author 海子 Yang + * @see ServerTransport + * @since 1.0 2025/8/22 22:18 + */ +public interface ServerTransportFactory { + + /** + * Creates {@link ServerTransport} + */ + ServerTransport createTransport(); + +} diff --git a/today-service-provider/src/main/java/infra/cloud/provider/ServiceProviderServer.java b/today-service-provider/src/main/java/infra/cloud/provider/ServiceProviderServer.java index 71cf504..0cdc978 100644 --- a/today-service-provider/src/main/java/infra/cloud/provider/ServiceProviderServer.java +++ b/today-service-provider/src/main/java/infra/cloud/provider/ServiceProviderServer.java @@ -26,8 +26,6 @@ import infra.remoting.core.RemotingServer; import infra.remoting.core.Resume; import infra.remoting.frame.decoder.PayloadDecoder; -import infra.remoting.transport.ServerTransport; -import infra.remoting.transport.netty.server.TcpServerTransport; import reactor.core.publisher.Mono; /** @@ -36,33 +34,35 @@ */ public class ServiceProviderServer implements Lifecycle, ChannelAcceptor { - private final ServiceChannelHandler channelHandler; - - private final Resume resume = new Resume(); + private final ServiceServerProperties properties; - private int maxFrameLength; + private final ServiceChannelHandler channelHandler; - private String bindAddress; + private final ServerTransportFactory serverTransportFactory; - private int port; + @Nullable + private final Resume resume; @Nullable private Closeable serverCloseable; - public ServiceProviderServer(ServiceChannelHandler channelHandler) { + public ServiceProviderServer(ServiceServerProperties properties, @Nullable Resume resume, + ServiceChannelHandler channelHandler, ServerTransportFactory serverTransportFactory) { + this.properties = properties; + this.resume = resume; this.channelHandler = channelHandler; + this.serverTransportFactory = serverTransportFactory; } @Override public void start() { serverCloseable = RemotingServer.create(this) - .payloadDecoder(PayloadDecoder.ZERO_COPY) .resume(resume) - .bindNow(createServerTransport()); - } - - private ServerTransport createServerTransport() { - return TcpServerTransport.create(bindAddress, port); + .payloadDecoder(PayloadDecoder.ZERO_COPY) + .fragment(properties.getMaxTransmissionUnit().toBytesInt()) + .maxTimeToFirstFrame(properties.getMaxTimeToFirstFrame()) + .maxInboundPayloadSize(properties.getMaxInboundPayloadSize().toBytesInt()) + .bindNow(serverTransportFactory.createTransport()); } @Override diff --git a/today-service-provider/src/main/java/infra/cloud/provider/ServiceServerProperties.java b/today-service-provider/src/main/java/infra/cloud/provider/ServiceServerProperties.java new file mode 100644 index 0000000..6003f1d --- /dev/null +++ b/today-service-provider/src/main/java/infra/cloud/provider/ServiceServerProperties.java @@ -0,0 +1,146 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.provider; + +import java.time.Duration; + +import infra.cloud.service.config.ResumeProperties; +import infra.context.properties.ConfigurationProperties; +import infra.context.properties.NestedConfigurationProperty; +import infra.lang.Nullable; +import infra.remoting.frame.FrameLengthCodec; +import infra.util.DataSize; + +/** + * Service provider server properties + * + * @author Harry Yang + * @since 1.0 2023/9/4 16:56 + */ +@ConfigurationProperties("service.server") +public class ServiceServerProperties { + + /** + * The address to bind + */ + @Nullable + private String bindAddress; + + /** + * The port to bind + */ + private int port; + + /** + * Configurations that exposes the maximum frame size that a Connection can bring up. + */ + private DataSize maxFrameLength = DataSize.ofBytes(FrameLengthCodec.FRAME_LENGTH_MASK); + + /** + * The threshold size for reassembly, must not be less than 64 bytes + */ + private DataSize maxInboundPayloadSize = DataSize.ofBytes(Integer.MAX_VALUE); + + /** + * Specify the max time to wait for the first frame (e.g. {@code SETUP}) + * on an accepted connection. + */ + private Duration maxTimeToFirstFrame = Duration.ofMinutes(1); + + /** + * Protocol frames larger than the given maximum transmission unit (mtu) size value are + * fragmented. the threshold size for fragmentation, must be no less than 64 + */ + private DataSize maxTransmissionUnit = DataSize.ofBytes(0); + + @NestedConfigurationProperty + public final ResumeProperties resume = new ResumeProperties(); + + public void setPort(int port) { + this.port = port; + } + + public int getPort() { + return port; + } + + /** + * The address to bind to + * + * @param bindAddress the address to bind to + */ + public void setBindAddress(@Nullable String bindAddress) { + this.bindAddress = bindAddress; + } + + @Nullable + public String getBindAddress() { + return bindAddress; + } + + /** + * When this is set, frames reassembler control maximum payload size which can be reassembled. + * + *

          By default, this is not set in which case maximum reassembled payloads size is not + * controlled. + * + * @param maxInboundPayloadSize the threshold size for reassembly, must not be less than 64 bytes. + * Please note, {@code maxInboundPayloadSize} must always be greater or equal to {@link + * infra.remoting.transport.Transport#getMaxFrameLength()}, otherwise inbound frame can exceed the + * {@code maxInboundPayloadSize} + */ + public void setMaxInboundPayloadSize(DataSize maxInboundPayloadSize) { + this.maxInboundPayloadSize = maxInboundPayloadSize; + } + + public DataSize getMaxInboundPayloadSize() { + return maxInboundPayloadSize; + } + + /** + * Configurations that exposes the maximum frame size that a {@link infra.remoting.Connection} can bring up. + * + *

          This number should not exist the 16,777,215 (maximum frame size specified by protocol spec) + */ + public void setMaxFrameLength(DataSize maxFrameLength) { + this.maxFrameLength = maxFrameLength; + } + + /** + * @return return maximum configured frame size limit + */ + public DataSize getMaxFrameLength() { + return maxFrameLength; + } + + public void setMaxTimeToFirstFrame(Duration maxTimeToFirstFrame) { + this.maxTimeToFirstFrame = maxTimeToFirstFrame; + } + + public Duration getMaxTimeToFirstFrame() { + return maxTimeToFirstFrame; + } + + public DataSize getMaxTransmissionUnit() { + return maxTransmissionUnit; + } + + public void setMaxTransmissionUnit(DataSize maxTransmissionUnit) { + this.maxTransmissionUnit = maxTransmissionUnit; + } +} diff --git a/today-service-provider/src/main/java/infra/cloud/provider/TcpServerTransportFactory.java b/today-service-provider/src/main/java/infra/cloud/provider/TcpServerTransportFactory.java new file mode 100644 index 0000000..95e6ac9 --- /dev/null +++ b/today-service-provider/src/main/java/infra/cloud/provider/TcpServerTransportFactory.java @@ -0,0 +1,50 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.provider; + +import infra.lang.Assert; +import infra.remoting.transport.netty.server.CloseableChannel; +import infra.remoting.transport.netty.server.TcpServerTransport; +import infra.util.DataSize; +import reactor.netty.tcp.TcpServer; + +/** + * @author 海子 Yang + * @since 1.0 2025/8/22 22:20 + */ +public class TcpServerTransportFactory implements ServerTransportFactory { + + private final ServiceServerProperties properties; + + public TcpServerTransportFactory(ServiceServerProperties properties) { + Assert.notNull(properties, "properties is required"); + this.properties = properties; + } + + @Override + public TcpServerTransport createTransport() { + String bindAddress = properties.getBindAddress(); + DataSize maxFrameLength = properties.getMaxFrameLength(); + if (bindAddress != null) { + TcpServer server = TcpServer.create().host(bindAddress).port(properties.getPort()); + return TcpServerTransport.create(server, maxFrameLength.toBytesInt()); + } + return TcpServerTransport.create(TcpServer.create().port(properties.getPort()), maxFrameLength.toBytesInt()); + } + +} diff --git a/today-service-provider/src/main/java/infra/cloud/provider/annotation/config/ServiceProviderAutoConfiguration.java b/today-service-provider/src/main/java/infra/cloud/provider/annotation/config/ServiceProviderAutoConfiguration.java index 2a5170e..427faf9 100644 --- a/today-service-provider/src/main/java/infra/cloud/provider/annotation/config/ServiceProviderAutoConfiguration.java +++ b/today-service-provider/src/main/java/infra/cloud/provider/annotation/config/ServiceProviderAutoConfiguration.java @@ -22,15 +22,28 @@ import infra.cloud.net.InetService; import infra.cloud.provider.DefaultServiceInterfaceMetadataProvider; import infra.cloud.provider.LocalServiceHolder; +import infra.cloud.provider.ServerTransportFactory; import infra.cloud.provider.ServiceChannelHandler; +import infra.cloud.provider.ServiceProviderServer; +import infra.cloud.provider.ServiceServerProperties; +import infra.cloud.provider.TcpServerTransportFactory; import infra.cloud.registry.annotation.config.AutoServiceRegistrationAutoConfiguration; import infra.cloud.service.PackageInfoServiceMetadataProvider; import infra.cloud.service.ServiceInterfaceMetadataProvider; import infra.cloud.service.ServiceMetadataProvider; import infra.cloud.service.ServiceMethod; +import infra.cloud.service.config.ResumeProperties; import infra.context.annotation.config.DisableDIAutoConfiguration; +import infra.context.condition.ConditionalOnBooleanProperty; import infra.context.condition.ConditionalOnMissingBean; import infra.context.properties.EnableConfigurationProperties; +import infra.lang.Nullable; +import infra.remoting.Closeable; +import infra.remoting.core.Resume; +import infra.remoting.resume.InMemoryResumableFramesStoreFactory; +import infra.remoting.resume.RandomUUIDResumeTokenGenerator; +import infra.remoting.resume.ResumableFramesStoreFactory; +import infra.remoting.resume.ResumeTokenGenerator; import infra.stereotype.Component; /** @@ -38,7 +51,7 @@ * @since 1.0 2025/8/10 22:31 */ @ConditionalOnDiscoveryEnabled -@EnableConfigurationProperties(InetProperties.class) +@EnableConfigurationProperties({ InetProperties.class, ServiceServerProperties.class }) @DisableDIAutoConfiguration(before = AutoServiceRegistrationAutoConfiguration.class) public class ServiceProviderAutoConfiguration { @@ -69,4 +82,39 @@ public static ServiceChannelHandler serviceChannelHandler() { return new ServiceChannelHandler(); } + @Component + @ConditionalOnMissingBean + public static ResumeTokenGenerator resumeTokenGenerator() { + return new RandomUUIDResumeTokenGenerator(); + } + + @Component + @ConditionalOnMissingBean + @ConditionalOnBooleanProperty(name = "service.server.resume.enabled", matchIfMissing = true) + public static Resume remotingResume(@Nullable ResumableFramesStoreFactory storeFactory, + ResumeTokenGenerator resumeTokenGenerator, ServiceServerProperties properties) { + ResumeProperties resume = properties.resume; + if (storeFactory == null) { + storeFactory = new InMemoryResumableFramesStoreFactory("server", resume.getMemoryCacheLimit().toBytesInt()); + } + return new Resume() + .storeFactory(storeFactory) + .token(resumeTokenGenerator) + .streamTimeout(resume.getStreamTimeout()) + .sessionDuration(resume.getSessionDuration()) + .cleanupStoreOnKeepAlive(resume.isCleanupStoreOnKeepAlive()); + } + + @Component + @ConditionalOnMissingBean + public static ServerTransportFactory serverTransportFactory(ServiceServerProperties properties) { + return new TcpServerTransportFactory(properties); + } + + @Component + public static ServiceProviderServer serviceProviderServer(@Nullable Resume resume, ServiceServerProperties properties, + ServiceChannelHandler serviceChannelHandler, ServerTransportFactory serverTransportFactory) { + return new ServiceProviderServer(properties, resume, serviceChannelHandler, serverTransportFactory); + } + } From de46f5b9993949f37a4d4fb9cb4c55f002f75049 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Sat, 23 Aug 2025 00:35:38 +0800 Subject: [PATCH 047/104] :art: --- .../main/java/infra/cloud/net/HostInfo.java | 32 +++---------- .../java/infra/cloud/net/InetProperties.java | 20 +++++---- .../java/infra/cloud/net/InetService.java | 45 ++++++++----------- .../src/main/resources/application.yaml | 10 +---- .../main/java/infra/remoting/core/Resume.java | 8 ++-- 5 files changed, 40 insertions(+), 75 deletions(-) diff --git a/today-cloud-core/src/main/java/infra/cloud/net/HostInfo.java b/today-cloud-core/src/main/java/infra/cloud/net/HostInfo.java index e3497b8..9d22163 100644 --- a/today-cloud-core/src/main/java/infra/cloud/net/HostInfo.java +++ b/today-cloud-core/src/main/java/infra/cloud/net/HostInfo.java @@ -21,6 +21,8 @@ import java.net.UnknownHostException; import java.nio.ByteBuffer; +import infra.lang.Assert; + /** * Host information. * @@ -29,23 +31,17 @@ */ public class HostInfo { - /** - * Should override the host info. - */ - public boolean override; - - private String ipAddress; + private final String hostname; - private String hostname; + private final String ipAddress; public HostInfo(String hostname, String ipAddress) { + Assert.notNull(hostname, "hostname is required"); + Assert.notNull(ipAddress, "ipAddress is required"); this.hostname = hostname; this.ipAddress = ipAddress; } - public HostInfo() { - } - public int getIpAddressAsInt() { InetAddress inetAddress; String host = this.ipAddress; @@ -61,28 +57,12 @@ public int getIpAddressAsInt() { return ByteBuffer.wrap(inetAddress.getAddress()).getInt(); } - public boolean isOverride() { - return this.override; - } - - public void setOverride(boolean override) { - this.override = override; - } - public String getIpAddress() { return this.ipAddress; } - public void setIpAddress(String ipAddress) { - this.ipAddress = ipAddress; - } - public String getHostname() { return this.hostname; } - public void setHostname(String hostname) { - this.hostname = hostname; - } - } diff --git a/today-cloud-core/src/main/java/infra/cloud/net/InetProperties.java b/today-cloud-core/src/main/java/infra/cloud/net/InetProperties.java index 8b56139..ad9bf86 100644 --- a/today-cloud-core/src/main/java/infra/cloud/net/InetProperties.java +++ b/today-cloud-core/src/main/java/infra/cloud/net/InetProperties.java @@ -18,11 +18,13 @@ package infra.cloud.net; import java.net.InetAddress; +import java.time.Duration; +import java.time.temporal.ChronoUnit; import java.util.ArrayList; import java.util.List; -import infra.beans.factory.annotation.Value; import infra.context.properties.ConfigurationProperties; +import infra.format.annotation.DurationUnit; /** * Properties for {@link InetService}. @@ -36,7 +38,7 @@ public class InetProperties { /** * Prefix for the Inet properties. */ - public static final String PREFIX = "cloud.inet"; + public static final String PREFIX = "infra.cloud.inet"; /** * The default hostname. Used in case of errors. @@ -49,10 +51,10 @@ public class InetProperties { private String defaultIpAddress = "127.0.0.1"; /** - * Timeout, in seconds, for calculating hostname. + * Timeout for calculating hostname. */ - @Value("${cloud.inet.timeout.sec:${CLOUD_INET_TIMEOUT_SEC:4}}") - private int timeoutSeconds = 1; + @DurationUnit(ChronoUnit.SECONDS) + private Duration timeout = Duration.ofSeconds(4); /** * List of Java regular expressions for network interfaces that will be ignored. @@ -86,12 +88,12 @@ public void setDefaultIpAddress(String defaultIpAddress) { this.defaultIpAddress = defaultIpAddress; } - public int getTimeoutSeconds() { - return this.timeoutSeconds; + public Duration getTimeout() { + return timeout; } - public void setTimeoutSeconds(int timeoutSeconds) { - this.timeoutSeconds = timeoutSeconds; + public void setTimeout(Duration timeout) { + this.timeout = timeout; } public List getIgnoredInterfaces() { diff --git a/today-cloud-core/src/main/java/infra/cloud/net/InetService.java b/today-cloud-core/src/main/java/infra/cloud/net/InetService.java index 0dafd9c..c00adeb 100644 --- a/today-cloud-core/src/main/java/infra/cloud/net/InetService.java +++ b/today-cloud-core/src/main/java/infra/cloud/net/InetService.java @@ -22,7 +22,6 @@ import java.net.InetAddress; import java.net.NetworkInterface; import java.net.UnknownHostException; -import java.util.Enumeration; import java.util.List; import java.util.concurrent.TimeUnit; @@ -52,19 +51,16 @@ public HostInfo findFirstNonLoopbackHostInfo() { if (address != null) { return convertAddress(address); } - HostInfo hostInfo = new HostInfo(); - hostInfo.setHostname(this.properties.getDefaultHostname()); - hostInfo.setIpAddress(this.properties.getDefaultIpAddress()); - return hostInfo; + return new HostInfo(properties.getDefaultHostname(), properties.getDefaultIpAddress()); } public InetAddress findFirstNonLoopbackAddress() { InetAddress result = null; try { int lowest = Integer.MAX_VALUE; - for (Enumeration nics = NetworkInterface.getNetworkInterfaces(); nics - .hasMoreElements(); ) { - NetworkInterface ifc = nics.nextElement(); + var networkInterfaces = NetworkInterface.getNetworkInterfaces(); + while (networkInterfaces.hasMoreElements()) { + NetworkInterface ifc = networkInterfaces.nextElement(); if (ifc.isUp()) { log.trace("Testing interface: {}", ifc.getDisplayName()); if (ifc.getIndex() < lowest || result == null) { @@ -74,20 +70,16 @@ else if (result != null) { continue; } - // @formatter:off - if (!ignoreInterface(ifc.getDisplayName())) { - for (Enumeration addrs = ifc - .getInetAddresses(); addrs.hasMoreElements();) { - InetAddress address = addrs.nextElement(); - if (address instanceof Inet4Address - && !address.isLoopbackAddress() - && isPreferredAddress(address)) { - log.trace("Found non-loopback interface: {}" , ifc.getDisplayName()); - result = address; - } - } - } - // @formatter:on + if (!ignoreInterface(ifc.getDisplayName())) { + var addresses = ifc.getInetAddresses(); + while (addresses.hasMoreElements()) { + InetAddress address = addresses.nextElement(); + if (address instanceof Inet4Address && !address.isLoopbackAddress() && isPreferredAddress(address)) { + log.trace("Found non-loopback interface: {}", ifc.getDisplayName()); + result = address; + } + } + } } } } @@ -111,15 +103,14 @@ && isPreferredAddress(address)) { // For testing. boolean isPreferredAddress(InetAddress address) { - - if (this.properties.isUseOnlySiteLocalInterfaces()) { + if (properties.isUseOnlySiteLocalInterfaces()) { final boolean siteLocalAddress = address.isSiteLocalAddress(); if (!siteLocalAddress) { log.trace("Ignoring address: {}", address.getHostAddress()); } return siteLocalAddress; } - final List preferredNetworks = this.properties.getPreferredNetworks(); + final List preferredNetworks = properties.getPreferredNetworks(); if (preferredNetworks.isEmpty()) { return true; } @@ -135,7 +126,7 @@ boolean isPreferredAddress(InetAddress address) { // For testing boolean ignoreInterface(String interfaceName) { - for (String regex : this.properties.getIgnoredInterfaces()) { + for (String regex : properties.getIgnoredInterfaces()) { if (interfaceName.matches(regex)) { log.trace("Ignoring interface: {}", interfaceName); return true; @@ -149,7 +140,7 @@ public HostInfo convertAddress(final InetAddress address) { String hostname; try { - hostname = result.get(properties.getTimeoutSeconds(), TimeUnit.SECONDS); + hostname = result.get(properties.getTimeout().toMillis(), TimeUnit.MILLISECONDS); } catch (Exception e) { result.cancel(true); diff --git a/today-cloud-samples/demo-tests/demo-user-rest/src/main/resources/application.yaml b/today-cloud-samples/demo-tests/demo-user-rest/src/main/resources/application.yaml index 102b8bc..7d75d4b 100644 --- a/today-cloud-samples/demo-tests/demo-user-rest/src/main/resources/application.yaml +++ b/today-cloud-samples/demo-tests/demo-user-rest/src/main/resources/application.yaml @@ -1,12 +1,3 @@ -service: - provider: - uri: '/provider' - -registry: - http-url: 'http://localhost:5000/services' - - services: - uri: '/services' infra: profiles: @@ -19,6 +10,7 @@ logging: cn.taketoday.demo: debug infra.cloud.protocol: debug + server: netty: shutdown: diff --git a/today-remoting/src/main/java/infra/remoting/core/Resume.java b/today-remoting/src/main/java/infra/remoting/core/Resume.java index a251ee0..072f7d6 100644 --- a/today-remoting/src/main/java/infra/remoting/core/Resume.java +++ b/today-remoting/src/main/java/infra/remoting/core/Resume.java @@ -38,13 +38,10 @@ public class Resume { private static final Logger logger = LoggerFactory.getLogger(Resume.class); - Duration sessionDuration = Duration.ofMinutes(2); - @Nullable private ResumableFramesStoreFactory storeFactory; - /* Storage */ - boolean cleanupStoreOnKeepAlive; + Duration sessionDuration = Duration.ofMinutes(2); Duration streamTimeout = Duration.ofSeconds(10); @@ -56,6 +53,9 @@ public class Resume { .jitter(1.0) .doBeforeRetry(signal -> logger.debug("Connection error", signal.failure())); + /* Storage */ + boolean cleanupStoreOnKeepAlive; + public Resume() { } From d302912cc542a46627bf829f700bd226e3a6394d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Sun, 24 Aug 2025 18:27:07 +0800 Subject: [PATCH 048/104] =?UTF-8?q?:art:=20=E7=9B=AE=E5=BD=95=E7=BB=93?= =?UTF-8?q?=E6=9E=84=E9=87=8D=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- settings.gradle | 2 + .../infra/cloud/client}/Registration.java | 4 +- .../ConditionalOnDiscoveryEnabled.java | 0 ...ditional-infra-configuration-metadata.json | 10 + .../src/main/resources/application.yaml | 8 +- .../demo-tests/demo-user-rest/build.gradle | 2 + .../src/main/resources/application.yaml | 4 + .../demo-tests/demo-user-service/build.gradle | 9 +- .../demo/service/UserServiceApplication.java | 2 +- .../src/main/resources/application.yaml | 12 +- .../main/java/infra/remoting/core/Resume.java | 1 + .../cloud/serialize/DefaultByteBufOutput.java | 190 ------------------ ...nnotation.config.AutoConfiguration.imports | 1 - today-service-client/build.gradle | 2 +- .../infra/cloud/service/ServiceProvider.java | 3 - today-service-discovery/build.gradle | 12 ++ .../client/CompositeDiscoveryClient.java | 1 - .../infra/cloud/client/DiscoveryClient.java | 0 .../DiscoveryClientAutoConfiguration.java | 2 +- .../client/simple/SimpleDiscoveryClient.java | 0 .../simple/SimpleDiscoveryProperties.java | 0 ...nnotation.config.AutoConfiguration.imports | 1 + .../main/resources/META-INF/today.strategies | 0 ...DiscoveryClientAutoConfigurationTests.java | 0 .../CompositeDiscoveryClientOrderTest.java | 0 .../client/CompositeDiscoveryClientTests.java | 0 .../CompositeDiscoveryClientTestsConfig.java | 0 .../CompositeDiscoveryClientUnitTests.java | 0 ...ryClientAutoConfigurationDefaultTests.java | 4 +- ...DiscoveryClientPropertiesMappingTests.java | 5 +- .../client}/SimpleDiscoveryClientTests.java | 6 +- today-service-provider/build.gradle | 8 - .../ServiceProviderAutoConfiguration.java | 3 +- .../build.gradle | 5 +- .../registry/simple/HttpRegistration.java | 8 +- .../infra/cloud/registry/simple/Status.java | 30 +++ .../api/SimpleHttpServiceRegistryAPI.java | 4 +- .../simple/config/SimpleHttpProperties.java | 41 ++++ ...tpServiceRegistryAPIAutoConfiguration.java | 53 +++++ ...nnotation.config.AutoConfiguration.imports | 1 + .../main/resources/META-INF/today.strategies | 0 .../build.gradle | 1 + .../simple/SimpleAutoServiceRegistration.java | 55 +++++ .../simple/SimpleHttpServiceRegistry.java | 7 +- .../simple/SimpleRegistryProperties.java | 106 ++++++++++ ...eHttpServiceRegistryAutoConfiguration.java | 84 ++++++++ ...nnotation.config.AutoConfiguration.imports | 1 + .../main/resources/META-INF/today.strategies | 0 .../build.gradle | 11 + .../discovery/SimpleHttpDiscoveryClient.java | 63 ++++++ ...eHttpDiscoveryClientAutoConfiguration.java | 41 ++++ ...nnotation.config.AutoConfiguration.imports | 1 + .../build.gradle | 1 + .../server}/ServiceNotFoundException.java | 2 +- .../SimpleHttpServiceRegistryEndpoint.java | 12 +- ...erviceRegistryServerAutoConfiguration.java | 35 ++++ ...nnotation.config.AutoConfiguration.imports | 1 + .../AbstractAutoServiceRegistration.java | 7 +- .../AutoServiceRegistrationProperties.java | 12 -- .../cloud/registry/RegistrationLifecycle.java | 2 + .../ServiceRegisterFailedException.java | 1 + .../infra/cloud/registry/ServiceRegistry.java | 2 + .../event/InstancePreRegisteredEvent.java | 2 +- 63 files changed, 609 insertions(+), 272 deletions(-) rename {today-service-registry/src/main/java/infra/cloud/registry => today-cloud-core/src/main/java/infra/cloud/client}/Registration.java (92%) rename {today-service-api => today-cloud-core}/src/main/java/infra/cloud/client/annotation/ConditionalOnDiscoveryEnabled.java (100%) create mode 100644 today-cloud-core/src/main/resources/META-INF/additional-infra-configuration-metadata.json delete mode 100644 today-service-api/src/main/java/infra/cloud/serialize/DefaultByteBufOutput.java delete mode 100644 today-service-api/src/main/resources/META-INF/config/infra.context.annotation.config.AutoConfiguration.imports create mode 100644 today-service-discovery/build.gradle rename {today-service-api => today-service-discovery}/src/main/java/infra/cloud/client/CompositeDiscoveryClient.java (97%) rename {today-service-api => today-service-discovery}/src/main/java/infra/cloud/client/DiscoveryClient.java (100%) rename {today-service-api/src/main/java/infra/cloud/client/annotation => today-service-discovery/src/main/java/infra/cloud/client}/config/DiscoveryClientAutoConfiguration.java (97%) rename {today-service-api => today-service-discovery}/src/main/java/infra/cloud/client/simple/SimpleDiscoveryClient.java (100%) rename {today-service-api => today-service-discovery}/src/main/java/infra/cloud/client/simple/SimpleDiscoveryProperties.java (100%) create mode 100644 today-service-discovery/src/main/resources/META-INF/config/infra.context.annotation.config.AutoConfiguration.imports create mode 100644 today-service-discovery/src/main/resources/META-INF/today.strategies rename {today-service-api => today-service-discovery}/src/test/java/infra/cloud/client/CompositeDiscoveryClientAutoConfigurationTests.java (100%) rename {today-service-api => today-service-discovery}/src/test/java/infra/cloud/client/CompositeDiscoveryClientOrderTest.java (100%) rename {today-service-api => today-service-discovery}/src/test/java/infra/cloud/client/CompositeDiscoveryClientTests.java (100%) rename {today-service-api => today-service-discovery}/src/test/java/infra/cloud/client/CompositeDiscoveryClientTestsConfig.java (100%) rename {today-service-api => today-service-discovery}/src/test/java/infra/cloud/client/CompositeDiscoveryClientUnitTests.java (100%) rename {today-service-api/src/test/java/infra/cloud/client/simple => today-service-discovery/src/test/java/infra/cloud/client}/DiscoveryClientAutoConfigurationDefaultTests.java (92%) rename {today-service-api/src/test/java/infra/cloud/client/simple => today-service-discovery/src/test/java/infra/cloud/client}/SimpleDiscoveryClientPropertiesMappingTests.java (95%) rename {today-service-api/src/test/java/infra/cloud/client/simple => today-service-discovery/src/test/java/infra/cloud/client}/SimpleDiscoveryClientTests.java (95%) create mode 100644 today-service-registry-simple-api/src/main/java/infra/cloud/registry/simple/Status.java create mode 100644 today-service-registry-simple-api/src/main/java/infra/cloud/registry/simple/config/SimpleHttpProperties.java create mode 100644 today-service-registry-simple-api/src/main/java/infra/cloud/registry/simple/config/SimpleHttpServiceRegistryAPIAutoConfiguration.java create mode 100644 today-service-registry-simple-api/src/main/resources/META-INF/config/infra.context.annotation.config.AutoConfiguration.imports create mode 100644 today-service-registry-simple-api/src/main/resources/META-INF/today.strategies create mode 100644 today-service-registry-simple-client/src/main/java/infra/cloud/registry/simple/SimpleAutoServiceRegistration.java create mode 100644 today-service-registry-simple-client/src/main/java/infra/cloud/registry/simple/SimpleRegistryProperties.java create mode 100644 today-service-registry-simple-client/src/main/java/infra/cloud/registry/simple/annotation/config/SimpleHttpServiceRegistryAutoConfiguration.java create mode 100644 today-service-registry-simple-client/src/main/resources/META-INF/config/infra.context.annotation.config.AutoConfiguration.imports create mode 100644 today-service-registry-simple-client/src/main/resources/META-INF/today.strategies create mode 100644 today-service-registry-simple-discovery/build.gradle create mode 100644 today-service-registry-simple-discovery/src/main/java/infra/cloud/registry/simple/discovery/SimpleHttpDiscoveryClient.java create mode 100644 today-service-registry-simple-discovery/src/main/java/infra/cloud/registry/simple/discovery/SimpleHttpDiscoveryClientAutoConfiguration.java create mode 100644 today-service-registry-simple-discovery/src/main/resources/META-INF/config/infra.context.annotation.config.AutoConfiguration.imports rename {today-service-registry/src/main/java/infra/cloud/registry => today-service-registry-simple-server/src/main/java/infra/cloud/registry/simple/server}/ServiceNotFoundException.java (97%) create mode 100644 today-service-registry-simple-server/src/main/java/infra/cloud/registry/simple/server/SimpleHttpServiceRegistryServerAutoConfiguration.java diff --git a/settings.gradle b/settings.gradle index c852c63..72934b0 100644 --- a/settings.gradle +++ b/settings.gradle @@ -35,10 +35,12 @@ include 'today-service-api' include 'today-service-client' include 'today-service-provider' include 'today-service-registry' +include 'today-service-discovery' include 'today-service-serialization' include 'today-service-registry-simple-api' include 'today-service-registry-simple-client' include 'today-service-registry-simple-server' +include 'today-service-registry-simple-discovery' include 'today-remoting' include 'today-remoting-micrometer' diff --git a/today-service-registry/src/main/java/infra/cloud/registry/Registration.java b/today-cloud-core/src/main/java/infra/cloud/client/Registration.java similarity index 92% rename from today-service-registry/src/main/java/infra/cloud/registry/Registration.java rename to today-cloud-core/src/main/java/infra/cloud/client/Registration.java index 8b4ca24..b1749cd 100644 --- a/today-service-registry/src/main/java/infra/cloud/registry/Registration.java +++ b/today-cloud-core/src/main/java/infra/cloud/client/Registration.java @@ -15,9 +15,7 @@ * along with this program. If not, see [http://www.gnu.org/licenses/] */ -package infra.cloud.registry; - -import infra.cloud.client.ServiceInstance; +package infra.cloud.client; /** * @author Harry Yang diff --git a/today-service-api/src/main/java/infra/cloud/client/annotation/ConditionalOnDiscoveryEnabled.java b/today-cloud-core/src/main/java/infra/cloud/client/annotation/ConditionalOnDiscoveryEnabled.java similarity index 100% rename from today-service-api/src/main/java/infra/cloud/client/annotation/ConditionalOnDiscoveryEnabled.java rename to today-cloud-core/src/main/java/infra/cloud/client/annotation/ConditionalOnDiscoveryEnabled.java diff --git a/today-cloud-core/src/main/resources/META-INF/additional-infra-configuration-metadata.json b/today-cloud-core/src/main/resources/META-INF/additional-infra-configuration-metadata.json new file mode 100644 index 0000000..a64fcb4 --- /dev/null +++ b/today-cloud-core/src/main/resources/META-INF/additional-infra-configuration-metadata.json @@ -0,0 +1,10 @@ +{ + "properties": [ + { + "name": "infra.cloud.discovery.enabled", + "type": "java.lang.Boolean", + "description": "Service discovery enabled.", + "defaultValue": "true" + } + ] +} diff --git a/today-cloud-samples/demo-tests/demo-registry/src/main/resources/application.yaml b/today-cloud-samples/demo-tests/demo-registry/src/main/resources/application.yaml index 3fd37ec..3d8f09d 100644 --- a/today-cloud-samples/demo-tests/demo-registry/src/main/resources/application.yaml +++ b/today-cloud-samples/demo-tests/demo-registry/src/main/resources/application.yaml @@ -1,10 +1,6 @@ server: port: 5000 -registry: - services: - uri: '/services' - web: resources: add-default-mappings: false @@ -12,6 +8,10 @@ web: infra: profiles: active: dev + cloud: + discovery: + enabled: false + config: server: diff --git a/today-cloud-samples/demo-tests/demo-user-rest/build.gradle b/today-cloud-samples/demo-tests/demo-user-rest/build.gradle index 94e7a5e..ae64e51 100644 --- a/today-cloud-samples/demo-tests/demo-user-rest/build.gradle +++ b/today-cloud-samples/demo-tests/demo-user-rest/build.gradle @@ -12,4 +12,6 @@ dependencies { implementation "com.google.protobuf:protobuf-java" + implementation project(":today-service-registry-simple-discovery") + } \ No newline at end of file diff --git a/today-cloud-samples/demo-tests/demo-user-rest/src/main/resources/application.yaml b/today-cloud-samples/demo-tests/demo-user-rest/src/main/resources/application.yaml index 7d75d4b..0fd8750 100644 --- a/today-cloud-samples/demo-tests/demo-user-rest/src/main/resources/application.yaml +++ b/today-cloud-samples/demo-tests/demo-user-rest/src/main/resources/application.yaml @@ -3,6 +3,10 @@ infra: profiles: active: dev + cloud: + service-registry: + uri: http://localhost:5000 + logging: level: root: info diff --git a/today-cloud-samples/demo-tests/demo-user-service/build.gradle b/today-cloud-samples/demo-tests/demo-user-service/build.gradle index 8199b45..a17c103 100644 --- a/today-cloud-samples/demo-tests/demo-user-service/build.gradle +++ b/today-cloud-samples/demo-tests/demo-user-service/build.gradle @@ -6,11 +6,12 @@ dependencies { implementation project(":today-service-provider") implementation project(":today-service-registry-simple-client") - implementation 'cn.taketoday:today-starter-web' - implementation 'cn.taketoday:today-starter-netty' - implementation 'ch.qos.logback:logback-classic' +// implementation 'cn.taketoday:today-starter-web' +// implementation 'cn.taketoday:today-starter-netty' + implementation 'cn.taketoday:today-starter-logback' - implementation "com.google.protobuf:protobuf-java" +// implementation "com.google.protobuf:protobuf-java" + implementation project(":today-remoting-transport-tcp") } \ No newline at end of file diff --git a/today-cloud-samples/demo-tests/demo-user-service/src/main/java/cn/taketoday/demo/service/UserServiceApplication.java b/today-cloud-samples/demo-tests/demo-user-service/src/main/java/cn/taketoday/demo/service/UserServiceApplication.java index 879eed9..ffcaeb9 100644 --- a/today-cloud-samples/demo-tests/demo-user-service/src/main/java/cn/taketoday/demo/service/UserServiceApplication.java +++ b/today-cloud-samples/demo-tests/demo-user-service/src/main/java/cn/taketoday/demo/service/UserServiceApplication.java @@ -30,7 +30,7 @@ public class UserServiceApplication { public static void main(String[] args) { ApplicationBuilder.forSources(UserServiceApplication.class) - .type(ApplicationType.NETTY_WEB) + .type(ApplicationType.NORMAL) .run(args); } diff --git a/today-cloud-samples/demo-tests/demo-user-service/src/main/resources/application.yaml b/today-cloud-samples/demo-tests/demo-user-service/src/main/resources/application.yaml index 2518700..a6cd363 100644 --- a/today-cloud-samples/demo-tests/demo-user-service/src/main/resources/application.yaml +++ b/today-cloud-samples/demo-tests/demo-user-service/src/main/resources/application.yaml @@ -1,9 +1,3 @@ -server: - port: 9000 - -web: - resources: - add-default-mappings: false infra: profiles: @@ -11,9 +5,13 @@ infra: cloud: service-registry: auto-registration: - port: 9000 fail-fast: true + simple: + instance-port: 9000 + uri: http://localhost:5000 + + logging: level: root: info diff --git a/today-remoting/src/main/java/infra/remoting/core/Resume.java b/today-remoting/src/main/java/infra/remoting/core/Resume.java index 072f7d6..1381ded 100644 --- a/today-remoting/src/main/java/infra/remoting/core/Resume.java +++ b/today-remoting/src/main/java/infra/remoting/core/Resume.java @@ -14,6 +14,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see [http://www.gnu.org/licenses/] */ + package infra.remoting.core; import java.time.Duration; diff --git a/today-service-api/src/main/java/infra/cloud/serialize/DefaultByteBufOutput.java b/today-service-api/src/main/java/infra/cloud/serialize/DefaultByteBufOutput.java deleted file mode 100644 index a33b4e2..0000000 --- a/today-service-api/src/main/java/infra/cloud/serialize/DefaultByteBufOutput.java +++ /dev/null @@ -1,190 +0,0 @@ -/* - * Copyright 2021 - 2024 the original author or authors. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] - */ - -package infra.cloud.serialize; - -import java.nio.charset.StandardCharsets; -import java.time.Instant; -import java.util.List; -import java.util.Map; -import java.util.function.BiConsumer; -import java.util.function.Consumer; - -import infra.lang.Nullable; -import io.netty.buffer.ByteBuf; - -/** - * @author 海子 Yang - * @since 1.0 2024/12/20 21:28 - */ -public class DefaultByteBufOutput implements Output { - - private final ByteBuf buffer; - - public DefaultByteBufOutput(ByteBuf buffer) { - this.buffer = buffer; - } - - @Override - public void write(byte b) { - buffer.writeByte(b); - } - - @Override - public void write(@Nullable byte[] b) { - if (b == null || b.length == 0) { - buffer.writeInt(0); - } - else { - buffer.writeInt(b.length); - buffer.writeBytes(b); - } - } - - @Override - public void write(byte[] b, int off, int len) { - buffer.writeInt(len); - buffer.writeBytes(b, off, len); - } - - @Override - public void writeFully(byte[] b) { - buffer.writeBytes(b); - } - - @Override - public void writeFully(byte[] b, int off, int len) { - buffer.writeBytes(b, off, len); - } - - @Override - public void write(boolean v) { - buffer.writeBoolean(v); - } - - @Override - public void write(short v) { - buffer.writeShort(v); - } - - @Override - public void write(int v) { - buffer.writeInt(v); - } - - @Override - public void write(long v) { - buffer.writeLong(v); - } - - @Override - public void write(float v) { - buffer.writeFloat(v); - } - - @Override - public void write(double v) { - buffer.writeDouble(v); - } - - @Override - public void write(@Nullable String v) { - if (v == null || v.isEmpty()) { - buffer.writeShort(0); - } - else { - byte[] bytes = v.getBytes(StandardCharsets.UTF_8); - buffer.writeShort(bytes.length); - writeFully(bytes); - } - } - - @Override - public void writeTimestamp(long millis) { - write(Instant.ofEpochMilli(millis)); - } - - @Override - public void write(Instant v) { - writeTimestamp(v.getEpochSecond(), v.getNano()); - } - - @Override - public void writeTimestamp(long epochSecond, int nanoAdjustment) throws ArithmeticException { - buffer.writeLong(epochSecond); - buffer.writeInt(nanoAdjustment); - } - - @Override - public void write(Message v) { - v.writeTo(this); - } - - @Override - public void write(T[] v, Consumer mapper) { - buffer.writeInt(v.length); - for (T t : v) { - mapper.accept(t); - } - } - - @Override - public void write(T[] v, BiConsumer mapper) { - buffer.writeInt(v.length); - for (T t : v) { - mapper.accept(this, t); - } - } - - @Override - public void write(List v, Consumer mapper) { - int size = v.size(); - buffer.writeInt(size); - for (T t : v) { - mapper.accept(t); - } - } - - @Override - public void write(List v, BiConsumer mapper) { - int size = v.size(); - buffer.writeInt(size); - for (T t : v) { - mapper.accept(this, t); - } - } - - @Override - public void write(Map v, BiConsumer keyMapper, BiConsumer valueMapper) { - int size = v.size(); - buffer.writeInt(size); - for (Map.Entry entry : v.entrySet()) { - keyMapper.accept(this, entry.getKey()); - valueMapper.accept(this, entry.getValue()); - } - } - - @Override - public void write(Map v, Consumer keyMapper, Consumer valueMapper) { - int size = v.size(); - buffer.writeInt(size); - for (Map.Entry entry : v.entrySet()) { - keyMapper.accept(entry.getKey()); - valueMapper.accept(entry.getValue()); - } - } -} diff --git a/today-service-api/src/main/resources/META-INF/config/infra.context.annotation.config.AutoConfiguration.imports b/today-service-api/src/main/resources/META-INF/config/infra.context.annotation.config.AutoConfiguration.imports deleted file mode 100644 index 0d14b8f..0000000 --- a/today-service-api/src/main/resources/META-INF/config/infra.context.annotation.config.AutoConfiguration.imports +++ /dev/null @@ -1 +0,0 @@ -infra.cloud.client.annotation.config.DiscoveryClientAutoConfiguration \ No newline at end of file diff --git a/today-service-client/build.gradle b/today-service-client/build.gradle index e451bf8..61da229 100644 --- a/today-service-client/build.gradle +++ b/today-service-client/build.gradle @@ -5,7 +5,7 @@ dependencies { api project(":today-remoting") api project(":today-cloud-core") api project(":today-service-api") - api project(":today-service-registry") + api project(":today-service-discovery") optional project(":today-remoting-transport-tcp") diff --git a/today-service-client/src/main/java/infra/cloud/service/ServiceProvider.java b/today-service-client/src/main/java/infra/cloud/service/ServiceProvider.java index 318b942..6542cb0 100644 --- a/today-service-client/src/main/java/infra/cloud/service/ServiceProvider.java +++ b/today-service-client/src/main/java/infra/cloud/service/ServiceProvider.java @@ -17,8 +17,6 @@ package infra.cloud.service; -import infra.cloud.registry.ServiceNotFoundException; - /** * @author Harry Yang * @since 1.0 2023/8/14 21:53 @@ -31,7 +29,6 @@ public interface ServiceProvider { * @param serviceInterface service interface type * @param Service type * @return service - * @throws ServiceNotFoundException service not found */ T getService(Class serviceInterface); diff --git a/today-service-discovery/build.gradle b/today-service-discovery/build.gradle new file mode 100644 index 0000000..afa2a2c --- /dev/null +++ b/today-service-discovery/build.gradle @@ -0,0 +1,12 @@ +description = "TODAY Service discovery client" + +dependencies { + api project(":today-cloud-core") + + implementation 'cn.taketoday:today-beans' + implementation 'cn.taketoday:today-context' + + + testImplementation project(":today-cloud-samples:demo-tests:demo-user-api") + +} \ No newline at end of file diff --git a/today-service-api/src/main/java/infra/cloud/client/CompositeDiscoveryClient.java b/today-service-discovery/src/main/java/infra/cloud/client/CompositeDiscoveryClient.java similarity index 97% rename from today-service-api/src/main/java/infra/cloud/client/CompositeDiscoveryClient.java rename to today-service-discovery/src/main/java/infra/cloud/client/CompositeDiscoveryClient.java index 9e83f1d..d172f58 100644 --- a/today-service-api/src/main/java/infra/cloud/client/CompositeDiscoveryClient.java +++ b/today-service-discovery/src/main/java/infra/cloud/client/CompositeDiscoveryClient.java @@ -22,7 +22,6 @@ import java.util.LinkedHashSet; import java.util.List; -import infra.core.annotation.AnnotationAwareOrderComparator; import infra.util.CollectionUtils; /** diff --git a/today-service-api/src/main/java/infra/cloud/client/DiscoveryClient.java b/today-service-discovery/src/main/java/infra/cloud/client/DiscoveryClient.java similarity index 100% rename from today-service-api/src/main/java/infra/cloud/client/DiscoveryClient.java rename to today-service-discovery/src/main/java/infra/cloud/client/DiscoveryClient.java diff --git a/today-service-api/src/main/java/infra/cloud/client/annotation/config/DiscoveryClientAutoConfiguration.java b/today-service-discovery/src/main/java/infra/cloud/client/config/DiscoveryClientAutoConfiguration.java similarity index 97% rename from today-service-api/src/main/java/infra/cloud/client/annotation/config/DiscoveryClientAutoConfiguration.java rename to today-service-discovery/src/main/java/infra/cloud/client/config/DiscoveryClientAutoConfiguration.java index bfb9b90..1c064c5 100644 --- a/today-service-api/src/main/java/infra/cloud/client/annotation/config/DiscoveryClientAutoConfiguration.java +++ b/today-service-discovery/src/main/java/infra/cloud/client/config/DiscoveryClientAutoConfiguration.java @@ -15,7 +15,7 @@ * along with this program. If not, see [http://www.gnu.org/licenses/] */ -package infra.cloud.client.annotation.config; +package infra.cloud.client.config; import infra.beans.factory.ObjectProvider; import infra.cloud.client.CompositeDiscoveryClient; diff --git a/today-service-api/src/main/java/infra/cloud/client/simple/SimpleDiscoveryClient.java b/today-service-discovery/src/main/java/infra/cloud/client/simple/SimpleDiscoveryClient.java similarity index 100% rename from today-service-api/src/main/java/infra/cloud/client/simple/SimpleDiscoveryClient.java rename to today-service-discovery/src/main/java/infra/cloud/client/simple/SimpleDiscoveryClient.java diff --git a/today-service-api/src/main/java/infra/cloud/client/simple/SimpleDiscoveryProperties.java b/today-service-discovery/src/main/java/infra/cloud/client/simple/SimpleDiscoveryProperties.java similarity index 100% rename from today-service-api/src/main/java/infra/cloud/client/simple/SimpleDiscoveryProperties.java rename to today-service-discovery/src/main/java/infra/cloud/client/simple/SimpleDiscoveryProperties.java diff --git a/today-service-discovery/src/main/resources/META-INF/config/infra.context.annotation.config.AutoConfiguration.imports b/today-service-discovery/src/main/resources/META-INF/config/infra.context.annotation.config.AutoConfiguration.imports new file mode 100644 index 0000000..78effe7 --- /dev/null +++ b/today-service-discovery/src/main/resources/META-INF/config/infra.context.annotation.config.AutoConfiguration.imports @@ -0,0 +1 @@ +infra.cloud.client.config.DiscoveryClientAutoConfiguration \ No newline at end of file diff --git a/today-service-discovery/src/main/resources/META-INF/today.strategies b/today-service-discovery/src/main/resources/META-INF/today.strategies new file mode 100644 index 0000000..e69de29 diff --git a/today-service-api/src/test/java/infra/cloud/client/CompositeDiscoveryClientAutoConfigurationTests.java b/today-service-discovery/src/test/java/infra/cloud/client/CompositeDiscoveryClientAutoConfigurationTests.java similarity index 100% rename from today-service-api/src/test/java/infra/cloud/client/CompositeDiscoveryClientAutoConfigurationTests.java rename to today-service-discovery/src/test/java/infra/cloud/client/CompositeDiscoveryClientAutoConfigurationTests.java diff --git a/today-service-api/src/test/java/infra/cloud/client/CompositeDiscoveryClientOrderTest.java b/today-service-discovery/src/test/java/infra/cloud/client/CompositeDiscoveryClientOrderTest.java similarity index 100% rename from today-service-api/src/test/java/infra/cloud/client/CompositeDiscoveryClientOrderTest.java rename to today-service-discovery/src/test/java/infra/cloud/client/CompositeDiscoveryClientOrderTest.java diff --git a/today-service-api/src/test/java/infra/cloud/client/CompositeDiscoveryClientTests.java b/today-service-discovery/src/test/java/infra/cloud/client/CompositeDiscoveryClientTests.java similarity index 100% rename from today-service-api/src/test/java/infra/cloud/client/CompositeDiscoveryClientTests.java rename to today-service-discovery/src/test/java/infra/cloud/client/CompositeDiscoveryClientTests.java diff --git a/today-service-api/src/test/java/infra/cloud/client/CompositeDiscoveryClientTestsConfig.java b/today-service-discovery/src/test/java/infra/cloud/client/CompositeDiscoveryClientTestsConfig.java similarity index 100% rename from today-service-api/src/test/java/infra/cloud/client/CompositeDiscoveryClientTestsConfig.java rename to today-service-discovery/src/test/java/infra/cloud/client/CompositeDiscoveryClientTestsConfig.java diff --git a/today-service-api/src/test/java/infra/cloud/client/CompositeDiscoveryClientUnitTests.java b/today-service-discovery/src/test/java/infra/cloud/client/CompositeDiscoveryClientUnitTests.java similarity index 100% rename from today-service-api/src/test/java/infra/cloud/client/CompositeDiscoveryClientUnitTests.java rename to today-service-discovery/src/test/java/infra/cloud/client/CompositeDiscoveryClientUnitTests.java diff --git a/today-service-api/src/test/java/infra/cloud/client/simple/DiscoveryClientAutoConfigurationDefaultTests.java b/today-service-discovery/src/test/java/infra/cloud/client/DiscoveryClientAutoConfigurationDefaultTests.java similarity index 92% rename from today-service-api/src/test/java/infra/cloud/client/simple/DiscoveryClientAutoConfigurationDefaultTests.java rename to today-service-discovery/src/test/java/infra/cloud/client/DiscoveryClientAutoConfigurationDefaultTests.java index 434d316..79dd1b1 100644 --- a/today-service-api/src/test/java/infra/cloud/client/simple/DiscoveryClientAutoConfigurationDefaultTests.java +++ b/today-service-discovery/src/test/java/infra/cloud/client/DiscoveryClientAutoConfigurationDefaultTests.java @@ -15,14 +15,12 @@ * along with this program. If not, see [http://www.gnu.org/licenses/] */ -package infra.cloud.client.simple; +package infra.cloud.client; import org.junit.jupiter.api.Test; import infra.app.test.context.InfraTest; import infra.beans.factory.annotation.Autowired; -import infra.cloud.client.CompositeDiscoveryClient; -import infra.cloud.client.DiscoveryClient; import infra.context.annotation.Configuration; import infra.context.annotation.config.EnableAutoConfiguration; diff --git a/today-service-api/src/test/java/infra/cloud/client/simple/SimpleDiscoveryClientPropertiesMappingTests.java b/today-service-discovery/src/test/java/infra/cloud/client/SimpleDiscoveryClientPropertiesMappingTests.java similarity index 95% rename from today-service-api/src/test/java/infra/cloud/client/simple/SimpleDiscoveryClientPropertiesMappingTests.java rename to today-service-discovery/src/test/java/infra/cloud/client/SimpleDiscoveryClientPropertiesMappingTests.java index 0905430..cbc9c82 100644 --- a/today-service-api/src/test/java/infra/cloud/client/simple/SimpleDiscoveryClientPropertiesMappingTests.java +++ b/today-service-discovery/src/test/java/infra/cloud/client/SimpleDiscoveryClientPropertiesMappingTests.java @@ -15,13 +15,14 @@ * along with this program. If not, see [http://www.gnu.org/licenses/] */ -package infra.cloud.client.simple; +package infra.cloud.client; import org.junit.jupiter.api.Test; import infra.app.test.context.InfraTest; import infra.beans.factory.annotation.Autowired; -import infra.cloud.client.ServiceInstance; +import infra.cloud.client.simple.SimpleDiscoveryClient; +import infra.cloud.client.simple.SimpleDiscoveryProperties; import infra.context.annotation.Configuration; import infra.context.annotation.config.EnableAutoConfiguration; diff --git a/today-service-api/src/test/java/infra/cloud/client/simple/SimpleDiscoveryClientTests.java b/today-service-discovery/src/test/java/infra/cloud/client/SimpleDiscoveryClientTests.java similarity index 95% rename from today-service-api/src/test/java/infra/cloud/client/simple/SimpleDiscoveryClientTests.java rename to today-service-discovery/src/test/java/infra/cloud/client/SimpleDiscoveryClientTests.java index 9e54ed8..0fb5bce 100644 --- a/today-service-api/src/test/java/infra/cloud/client/simple/SimpleDiscoveryClientTests.java +++ b/today-service-discovery/src/test/java/infra/cloud/client/SimpleDiscoveryClientTests.java @@ -15,7 +15,7 @@ * along with this program. If not, see [http://www.gnu.org/licenses/] */ -package infra.cloud.client.simple; +package infra.cloud.client; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -25,8 +25,8 @@ import java.util.List; import java.util.Map; -import infra.cloud.client.DefaultServiceInstance; -import infra.cloud.client.ServiceInstance; +import infra.cloud.client.simple.SimpleDiscoveryClient; +import infra.cloud.client.simple.SimpleDiscoveryProperties; import static org.assertj.core.api.BDDAssertions.then; diff --git a/today-service-provider/build.gradle b/today-service-provider/build.gradle index 3799b72..1cddb8e 100644 --- a/today-service-provider/build.gradle +++ b/today-service-provider/build.gradle @@ -7,15 +7,7 @@ dependencies { api project(":today-cloud-core") api project(":today-service-api") - implementation project(":today-service-registry") - optional project(":today-remoting-transport-tcp") - - optional 'io.netty:netty-transport' - optional 'io.netty:netty-codec' - optional 'io.netty:netty-handler' - optional 'io.netty:netty-transport-classes-epoll' - } // --add-opens=java.base/java.nio=ALL-UNNAMED diff --git a/today-service-provider/src/main/java/infra/cloud/provider/annotation/config/ServiceProviderAutoConfiguration.java b/today-service-provider/src/main/java/infra/cloud/provider/annotation/config/ServiceProviderAutoConfiguration.java index 427faf9..502f56a 100644 --- a/today-service-provider/src/main/java/infra/cloud/provider/annotation/config/ServiceProviderAutoConfiguration.java +++ b/today-service-provider/src/main/java/infra/cloud/provider/annotation/config/ServiceProviderAutoConfiguration.java @@ -27,7 +27,6 @@ import infra.cloud.provider.ServiceProviderServer; import infra.cloud.provider.ServiceServerProperties; import infra.cloud.provider.TcpServerTransportFactory; -import infra.cloud.registry.annotation.config.AutoServiceRegistrationAutoConfiguration; import infra.cloud.service.PackageInfoServiceMetadataProvider; import infra.cloud.service.ServiceInterfaceMetadataProvider; import infra.cloud.service.ServiceMetadataProvider; @@ -52,7 +51,7 @@ */ @ConditionalOnDiscoveryEnabled @EnableConfigurationProperties({ InetProperties.class, ServiceServerProperties.class }) -@DisableDIAutoConfiguration(before = AutoServiceRegistrationAutoConfiguration.class) +@DisableDIAutoConfiguration public class ServiceProviderAutoConfiguration { @Component diff --git a/today-service-registry-simple-api/build.gradle b/today-service-registry-simple-api/build.gradle index a714a36..f75fa37 100644 --- a/today-service-registry-simple-api/build.gradle +++ b/today-service-registry-simple-api/build.gradle @@ -2,9 +2,8 @@ description = "TODAY Service Simple Registry API" dependencies { - api project(":today-service-registry") - - api 'cn.taketoday:today-starter-web' + implementation project(":today-cloud-core") + implementation 'cn.taketoday:today-starter-web' annotationProcessor 'cn.taketoday:infra-configuration-processor' } \ No newline at end of file diff --git a/today-service-registry-simple-api/src/main/java/infra/cloud/registry/simple/HttpRegistration.java b/today-service-registry-simple-api/src/main/java/infra/cloud/registry/simple/HttpRegistration.java index 2e05124..bea730b 100644 --- a/today-service-registry-simple-api/src/main/java/infra/cloud/registry/simple/HttpRegistration.java +++ b/today-service-registry-simple-api/src/main/java/infra/cloud/registry/simple/HttpRegistration.java @@ -18,7 +18,7 @@ package infra.cloud.registry.simple; import infra.cloud.client.DefaultServiceInstance; -import infra.cloud.registry.Registration; +import infra.cloud.client.Registration; /** * @author Harry Yang @@ -26,13 +26,13 @@ */ public class HttpRegistration extends DefaultServiceInstance implements Registration { - private String status; + private Status status; - public String getStatus() { + public Status getStatus() { return status; } - public void setStatus(String status) { + public void setStatus(Status status) { this.status = status; } } diff --git a/today-service-registry-simple-api/src/main/java/infra/cloud/registry/simple/Status.java b/today-service-registry-simple-api/src/main/java/infra/cloud/registry/simple/Status.java new file mode 100644 index 0000000..611a04a --- /dev/null +++ b/today-service-registry-simple-api/src/main/java/infra/cloud/registry/simple/Status.java @@ -0,0 +1,30 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.registry.simple; + +/** + * @author 海子 Yang + * @since 1.0 2025/8/24 16:48 + */ +public enum Status { + + UP, + + OUT_OF_SERVICE, + +} diff --git a/today-service-registry-simple-api/src/main/java/infra/cloud/registry/simple/api/SimpleHttpServiceRegistryAPI.java b/today-service-registry-simple-api/src/main/java/infra/cloud/registry/simple/api/SimpleHttpServiceRegistryAPI.java index 6e42386..de54e1e 100644 --- a/today-service-registry-simple-api/src/main/java/infra/cloud/registry/simple/api/SimpleHttpServiceRegistryAPI.java +++ b/today-service-registry-simple-api/src/main/java/infra/cloud/registry/simple/api/SimpleHttpServiceRegistryAPI.java @@ -40,8 +40,8 @@ public interface SimpleHttpServiceRegistryAPI { @GET(produces = MediaType.APPLICATION_JSON_VALUE) MultiValueMap services(); - @GET("/{name}") - List lookup(@PathVariable String name); + @GET("/{serviceId}") + List lookup(@PathVariable String serviceId); @POST void register(@RequestBody HttpRegistration registration); diff --git a/today-service-registry-simple-api/src/main/java/infra/cloud/registry/simple/config/SimpleHttpProperties.java b/today-service-registry-simple-api/src/main/java/infra/cloud/registry/simple/config/SimpleHttpProperties.java new file mode 100644 index 0000000..ca07d47 --- /dev/null +++ b/today-service-registry-simple-api/src/main/java/infra/cloud/registry/simple/config/SimpleHttpProperties.java @@ -0,0 +1,41 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.registry.simple.config; + +import java.net.URI; + +import infra.context.properties.ConfigurationProperties; + +/** + * @author 海子 Yang + * @since 1.0 2025/8/24 17:54 + */ +@ConfigurationProperties(prefix = "infra.cloud.service-registry") +public class SimpleHttpProperties { + + private URI uri; + + public void setUri(URI uri) { + this.uri = uri; + } + + public URI getUri() { + return uri; + } + +} diff --git a/today-service-registry-simple-api/src/main/java/infra/cloud/registry/simple/config/SimpleHttpServiceRegistryAPIAutoConfiguration.java b/today-service-registry-simple-api/src/main/java/infra/cloud/registry/simple/config/SimpleHttpServiceRegistryAPIAutoConfiguration.java new file mode 100644 index 0000000..6f1357e --- /dev/null +++ b/today-service-registry-simple-api/src/main/java/infra/cloud/registry/simple/config/SimpleHttpServiceRegistryAPIAutoConfiguration.java @@ -0,0 +1,53 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.registry.simple.config; + +import infra.annotation.config.web.client.RestClientAutoConfiguration; +import infra.beans.factory.config.ConfigurableBeanFactory; +import infra.beans.factory.config.EmbeddedValueResolver; +import infra.cloud.client.annotation.ConditionalOnDiscoveryEnabled; +import infra.cloud.registry.simple.api.SimpleHttpServiceRegistryAPI; +import infra.context.annotation.config.DisableDIAutoConfiguration; +import infra.context.condition.ConditionalOnMissingBean; +import infra.context.properties.EnableConfigurationProperties; +import infra.stereotype.Component; +import infra.web.client.RestClient; +import infra.web.client.support.RestClientAdapter; +import infra.web.service.invoker.HttpServiceProxyFactory; + +/** + * @author 海子 Yang + * @since 1.0 2025/8/24 17:44 + */ +@ConditionalOnDiscoveryEnabled +@EnableConfigurationProperties(SimpleHttpProperties.class) +@DisableDIAutoConfiguration(after = RestClientAutoConfiguration.class) +public class SimpleHttpServiceRegistryAPIAutoConfiguration { + + @Component + @ConditionalOnMissingBean + public static SimpleHttpServiceRegistryAPI simpleHttpServiceRegistryAPI( + ConfigurableBeanFactory factory, SimpleHttpProperties properties, RestClient.Builder builder) { + RestClientAdapter adapter = RestClientAdapter.create(builder.baseURI(properties.getUri()).build()); + return HttpServiceProxyFactory.forAdapter(adapter) + .embeddedValueResolver(new EmbeddedValueResolver(factory)) + .build() + .createClient(SimpleHttpServiceRegistryAPI.class); + } + +} diff --git a/today-service-registry-simple-api/src/main/resources/META-INF/config/infra.context.annotation.config.AutoConfiguration.imports b/today-service-registry-simple-api/src/main/resources/META-INF/config/infra.context.annotation.config.AutoConfiguration.imports new file mode 100644 index 0000000..2d3a786 --- /dev/null +++ b/today-service-registry-simple-api/src/main/resources/META-INF/config/infra.context.annotation.config.AutoConfiguration.imports @@ -0,0 +1 @@ +infra.cloud.registry.simple.config.SimpleHttpServiceRegistryAPIAutoConfiguration \ No newline at end of file diff --git a/today-service-registry-simple-api/src/main/resources/META-INF/today.strategies b/today-service-registry-simple-api/src/main/resources/META-INF/today.strategies new file mode 100644 index 0000000..e69de29 diff --git a/today-service-registry-simple-client/build.gradle b/today-service-registry-simple-client/build.gradle index dbd40e1..e0abab5 100644 --- a/today-service-registry-simple-client/build.gradle +++ b/today-service-registry-simple-client/build.gradle @@ -2,6 +2,7 @@ description = "TODAY Service Simple Registry" dependencies { + api project(":today-service-registry") api project(":today-service-registry-simple-api") implementation 'cn.taketoday:today-starter-web' diff --git a/today-service-registry-simple-client/src/main/java/infra/cloud/registry/simple/SimpleAutoServiceRegistration.java b/today-service-registry-simple-client/src/main/java/infra/cloud/registry/simple/SimpleAutoServiceRegistration.java new file mode 100644 index 0000000..40492c1 --- /dev/null +++ b/today-service-registry-simple-client/src/main/java/infra/cloud/registry/simple/SimpleAutoServiceRegistration.java @@ -0,0 +1,55 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.registry.simple; + +import infra.cloud.registry.AbstractAutoServiceRegistration; +import infra.cloud.registry.ServiceRegistry; + +/** + * @author 海子 Yang + * @since 1.0 2025/8/23 21:50 + */ +public class SimpleAutoServiceRegistration extends AbstractAutoServiceRegistration { + + private final HttpRegistration registration; + + private final SimpleRegistryProperties properties; + + public SimpleAutoServiceRegistration(ServiceRegistry serviceRegistry, + HttpRegistration registration, SimpleRegistryProperties properties) { + super(serviceRegistry); + this.registration = registration; + this.properties = properties; + } + + @Override + protected Object getConfiguration() { + return properties; + } + + @Override + protected HttpRegistration getRegistration() { + return registration; + } + + @Override + protected boolean isEnabled() { + return properties.isEnabled(); + } + +} diff --git a/today-service-registry-simple-client/src/main/java/infra/cloud/registry/simple/SimpleHttpServiceRegistry.java b/today-service-registry-simple-client/src/main/java/infra/cloud/registry/simple/SimpleHttpServiceRegistry.java index 61fc6e1..fc842b4 100644 --- a/today-service-registry-simple-client/src/main/java/infra/cloud/registry/simple/SimpleHttpServiceRegistry.java +++ b/today-service-registry-simple-client/src/main/java/infra/cloud/registry/simple/SimpleHttpServiceRegistry.java @@ -24,7 +24,7 @@ * @author 海子 Yang * @since 1.0 2025/8/7 20:40 */ -public class SimpleHttpServiceRegistry implements ServiceRegistry { +public class SimpleHttpServiceRegistry implements ServiceRegistry { private final SimpleHttpServiceRegistryAPI serviceRegistryAPI; @@ -48,12 +48,13 @@ public void close() { } @Override - public void setStatus(HttpRegistration registration, String status) { + public void setStatus(HttpRegistration registration, Status status) { registration.setStatus(status); + serviceRegistryAPI.update(registration); } @Override - public String getStatus(HttpRegistration registration) { + public Status getStatus(HttpRegistration registration) { return registration.getStatus(); } diff --git a/today-service-registry-simple-client/src/main/java/infra/cloud/registry/simple/SimpleRegistryProperties.java b/today-service-registry-simple-client/src/main/java/infra/cloud/registry/simple/SimpleRegistryProperties.java new file mode 100644 index 0000000..8fdf6d7 --- /dev/null +++ b/today-service-registry-simple-client/src/main/java/infra/cloud/registry/simple/SimpleRegistryProperties.java @@ -0,0 +1,106 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.registry.simple; + +import infra.cloud.net.InetService; +import infra.context.properties.ConfigurationProperties; +import infra.util.StringUtils; + +/** + * @author 海子 Yang + * @since 1.0 2025/8/23 21:52 + */ +@ConfigurationProperties(prefix = "infra.cloud.service-registry.simple") +public class SimpleRegistryProperties { + + private boolean enabled = true; + + /** Id used to register with. Defaults to a random UUID. */ + private String instanceId; + + /** + * Predefined host with which a service can register itself. + */ + private String instanceHost; + + /** + * IP address to use when accessing service (must also set preferIpAddress to use). + */ + private String instanceIpAddress; + + /** + * Use ip address rather than hostname during registration. + */ + private boolean preferIpAddress = false; + + /** Port to register the service under (defaults to listening port). */ + private Integer instancePort; + + public SimpleRegistryProperties(InetService inetService) { + var hostInfo = inetService.findFirstNonLoopbackHostInfo(); + this.instanceHost = hostInfo.getHostname(); + this.instanceIpAddress = hostInfo.getIpAddress(); + } + + public boolean isEnabled() { + return enabled; + } + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + + public String getInstanceHost() { + if (this.preferIpAddress && StringUtils.hasText(this.instanceIpAddress)) { + return this.instanceIpAddress; + } + return this.instanceHost; + } + + public void setInstanceHost(String instanceHost) { + this.instanceHost = instanceHost; + } + + public String getInstanceId() { + return instanceId; + } + + public void setInstanceId(String instanceId) { + this.instanceId = instanceId; + } + + public void setInstanceIpAddress(String instanceIpAddress) { + this.instanceIpAddress = instanceIpAddress; + } + + public Integer getInstancePort() { + return instancePort; + } + + public void setInstancePort(Integer instancePort) { + this.instancePort = instancePort; + } + + public boolean isPreferIpAddress() { + return preferIpAddress; + } + + public void setPreferIpAddress(boolean preferIpAddress) { + this.preferIpAddress = preferIpAddress; + } +} diff --git a/today-service-registry-simple-client/src/main/java/infra/cloud/registry/simple/annotation/config/SimpleHttpServiceRegistryAutoConfiguration.java b/today-service-registry-simple-client/src/main/java/infra/cloud/registry/simple/annotation/config/SimpleHttpServiceRegistryAutoConfiguration.java new file mode 100644 index 0000000..5501802 --- /dev/null +++ b/today-service-registry-simple-client/src/main/java/infra/cloud/registry/simple/annotation/config/SimpleHttpServiceRegistryAutoConfiguration.java @@ -0,0 +1,84 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.registry.simple.annotation.config; + +import infra.cloud.client.annotation.ConditionalOnDiscoveryEnabled; +import infra.cloud.net.InetProperties; +import infra.cloud.net.InetService; +import infra.cloud.registry.simple.HttpRegistration; +import infra.cloud.registry.simple.SimpleAutoServiceRegistration; +import infra.cloud.registry.simple.SimpleHttpServiceRegistry; +import infra.cloud.registry.simple.SimpleRegistryProperties; +import infra.cloud.registry.simple.Status; +import infra.cloud.registry.simple.api.SimpleHttpServiceRegistryAPI; +import infra.cloud.registry.simple.config.SimpleHttpServiceRegistryAPIAutoConfiguration; +import infra.context.annotation.config.DisableDIAutoConfiguration; +import infra.context.condition.ConditionalOnMissingBean; +import infra.context.properties.EnableConfigurationProperties; +import infra.stereotype.Component; +import infra.util.StringUtils; + +/** + * @author 海子 Yang + * @since 1.0 2025/8/23 21:39 + */ +@ConditionalOnDiscoveryEnabled +@EnableConfigurationProperties({ InetProperties.class }) +@DisableDIAutoConfiguration(after = SimpleHttpServiceRegistryAPIAutoConfiguration.class) +public class SimpleHttpServiceRegistryAutoConfiguration { + + @Component + public static SimpleRegistryProperties simpleRegistryProperties(InetService inetService) { + return new SimpleRegistryProperties(inetService); + } + + @Component + @ConditionalOnMissingBean + public static SimpleHttpServiceRegistry simpleHttpServiceRegistry(SimpleHttpServiceRegistryAPI serviceRegistryAPI) { + return new SimpleHttpServiceRegistry(serviceRegistryAPI); + } + + @Component + public static SimpleAutoServiceRegistration autoServiceRegistration(HttpRegistration httpRegistration, + SimpleRegistryProperties properties, SimpleHttpServiceRegistry serviceRegistry) { + return new SimpleAutoServiceRegistration(serviceRegistry, httpRegistration, properties); + } + + @Component + @ConditionalOnMissingBean + public static InetService inetService(InetProperties inetProperties) { + return new InetService(inetProperties); + } + + @Component + public static HttpRegistration httpRegistration(SimpleRegistryProperties properties) { + String host = properties.getInstanceHost(); + if (!StringUtils.hasText(host)) { + throw new IllegalStateException("instanceHost must not be empty"); + } + + HttpRegistration registration = new HttpRegistration(); + registration.setStatus(Status.UP); + registration.setHost(host); + registration.setPort(properties.getInstancePort()); + registration.setInstanceId(properties.getInstanceId()); + registration.setServiceId(properties.getInstanceId()); + return registration; + } + +} diff --git a/today-service-registry-simple-client/src/main/resources/META-INF/config/infra.context.annotation.config.AutoConfiguration.imports b/today-service-registry-simple-client/src/main/resources/META-INF/config/infra.context.annotation.config.AutoConfiguration.imports new file mode 100644 index 0000000..2b72363 --- /dev/null +++ b/today-service-registry-simple-client/src/main/resources/META-INF/config/infra.context.annotation.config.AutoConfiguration.imports @@ -0,0 +1 @@ +infra.cloud.registry.simple.annotation.config.SimpleHttpServiceRegistryAutoConfiguration \ No newline at end of file diff --git a/today-service-registry-simple-client/src/main/resources/META-INF/today.strategies b/today-service-registry-simple-client/src/main/resources/META-INF/today.strategies new file mode 100644 index 0000000..e69de29 diff --git a/today-service-registry-simple-discovery/build.gradle b/today-service-registry-simple-discovery/build.gradle new file mode 100644 index 0000000..d0fd860 --- /dev/null +++ b/today-service-registry-simple-discovery/build.gradle @@ -0,0 +1,11 @@ +description = "TODAY Service Simple Registry discovery" + + +dependencies { + api project(":today-service-discovery") + api project(":today-service-registry-simple-api") + + implementation 'cn.taketoday:today-starter-web' + + annotationProcessor 'cn.taketoday:infra-configuration-processor' +} \ No newline at end of file diff --git a/today-service-registry-simple-discovery/src/main/java/infra/cloud/registry/simple/discovery/SimpleHttpDiscoveryClient.java b/today-service-registry-simple-discovery/src/main/java/infra/cloud/registry/simple/discovery/SimpleHttpDiscoveryClient.java new file mode 100644 index 0000000..c3c526d --- /dev/null +++ b/today-service-registry-simple-discovery/src/main/java/infra/cloud/registry/simple/discovery/SimpleHttpDiscoveryClient.java @@ -0,0 +1,63 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.registry.simple.discovery; + +import java.util.ArrayList; +import java.util.List; + +import infra.cloud.client.DiscoveryClient; +import infra.cloud.client.ServiceInstance; +import infra.cloud.registry.simple.HttpRegistration; +import infra.cloud.registry.simple.Status; +import infra.cloud.registry.simple.api.SimpleHttpServiceRegistryAPI; + +/** + * @author 海子 Yang + * @since 1.0 2025/8/24 16:42 + */ +public class SimpleHttpDiscoveryClient implements DiscoveryClient { + + private final SimpleHttpServiceRegistryAPI serviceRegistryAPI; + + public SimpleHttpDiscoveryClient(SimpleHttpServiceRegistryAPI serviceRegistryAPI) { + this.serviceRegistryAPI = serviceRegistryAPI; + } + + @Override + public String getDescription() { + return "Simple Http DiscoveryClient"; + } + + @Override + public List getInstances(String serviceId) { + List registrations = serviceRegistryAPI.lookup(serviceId); + List instances = new ArrayList<>(registrations.size()); + for (HttpRegistration registration : registrations) { + if (registration.getStatus() == Status.UP) { + instances.add(registration); + } + } + return instances; + } + + @Override + public List getServices() { + return new ArrayList<>(serviceRegistryAPI.services().keySet()); + } + +} diff --git a/today-service-registry-simple-discovery/src/main/java/infra/cloud/registry/simple/discovery/SimpleHttpDiscoveryClientAutoConfiguration.java b/today-service-registry-simple-discovery/src/main/java/infra/cloud/registry/simple/discovery/SimpleHttpDiscoveryClientAutoConfiguration.java new file mode 100644 index 0000000..20225d8 --- /dev/null +++ b/today-service-registry-simple-discovery/src/main/java/infra/cloud/registry/simple/discovery/SimpleHttpDiscoveryClientAutoConfiguration.java @@ -0,0 +1,41 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.registry.simple.discovery; + +import infra.cloud.client.annotation.ConditionalOnDiscoveryEnabled; +import infra.cloud.client.config.DiscoveryClientAutoConfiguration; +import infra.cloud.registry.simple.api.SimpleHttpServiceRegistryAPI; +import infra.cloud.registry.simple.config.SimpleHttpServiceRegistryAPIAutoConfiguration; +import infra.context.annotation.config.DisableDIAutoConfiguration; +import infra.stereotype.Component; + +/** + * @author 海子 Yang + * @since 1.0 2025/8/24 17:40 + */ +@ConditionalOnDiscoveryEnabled +@DisableDIAutoConfiguration(before = DiscoveryClientAutoConfiguration.class, + after = SimpleHttpServiceRegistryAPIAutoConfiguration.class) +public class SimpleHttpDiscoveryClientAutoConfiguration { + + @Component + public static SimpleHttpDiscoveryClient simpleHttpDiscoveryClient(SimpleHttpServiceRegistryAPI simpleHttpServiceRegistryAPI) { + return new SimpleHttpDiscoveryClient(simpleHttpServiceRegistryAPI); + } + +} diff --git a/today-service-registry-simple-discovery/src/main/resources/META-INF/config/infra.context.annotation.config.AutoConfiguration.imports b/today-service-registry-simple-discovery/src/main/resources/META-INF/config/infra.context.annotation.config.AutoConfiguration.imports new file mode 100644 index 0000000..4681e25 --- /dev/null +++ b/today-service-registry-simple-discovery/src/main/resources/META-INF/config/infra.context.annotation.config.AutoConfiguration.imports @@ -0,0 +1 @@ +infra.cloud.registry.simple.discovery.SimpleHttpDiscoveryClientAutoConfiguration \ No newline at end of file diff --git a/today-service-registry-simple-server/build.gradle b/today-service-registry-simple-server/build.gradle index d9b1b58..3392cc9 100644 --- a/today-service-registry-simple-server/build.gradle +++ b/today-service-registry-simple-server/build.gradle @@ -2,6 +2,7 @@ description = "TODAY Service Simple Registry Server" dependencies { + api project(":today-cloud-core") api project(":today-service-registry-simple-api") implementation 'cn.taketoday:today-starter-web' diff --git a/today-service-registry/src/main/java/infra/cloud/registry/ServiceNotFoundException.java b/today-service-registry-simple-server/src/main/java/infra/cloud/registry/simple/server/ServiceNotFoundException.java similarity index 97% rename from today-service-registry/src/main/java/infra/cloud/registry/ServiceNotFoundException.java rename to today-service-registry-simple-server/src/main/java/infra/cloud/registry/simple/server/ServiceNotFoundException.java index 1bede91..373b873 100644 --- a/today-service-registry/src/main/java/infra/cloud/registry/ServiceNotFoundException.java +++ b/today-service-registry-simple-server/src/main/java/infra/cloud/registry/simple/server/ServiceNotFoundException.java @@ -15,7 +15,7 @@ * along with this program. If not, see [http://www.gnu.org/licenses/] */ -package infra.cloud.registry; +package infra.cloud.registry.simple.server; import java.io.Serial; diff --git a/today-service-registry-simple-server/src/main/java/infra/cloud/registry/simple/server/SimpleHttpServiceRegistryEndpoint.java b/today-service-registry-simple-server/src/main/java/infra/cloud/registry/simple/server/SimpleHttpServiceRegistryEndpoint.java index 38e6ff8..7bd3f9e 100644 --- a/today-service-registry-simple-server/src/main/java/infra/cloud/registry/simple/server/SimpleHttpServiceRegistryEndpoint.java +++ b/today-service-registry-simple-server/src/main/java/infra/cloud/registry/simple/server/SimpleHttpServiceRegistryEndpoint.java @@ -21,7 +21,6 @@ import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; -import infra.cloud.registry.ServiceNotFoundException; import infra.cloud.registry.simple.HttpRegistration; import infra.cloud.registry.simple.api.SimpleHttpServiceRegistryAPI; import infra.http.HttpStatus; @@ -37,7 +36,6 @@ import infra.web.annotation.PUT; import infra.web.annotation.PathVariable; import infra.web.annotation.RequestBody; -import infra.web.annotation.RequestMapping; import infra.web.annotation.ResponseStatus; import infra.web.annotation.RestController; @@ -45,7 +43,6 @@ * @author TODAY 2021/7/9 23:08 */ @RestController -@RequestMapping("${registry.services.uri:/services}") class SimpleHttpServiceRegistryEndpoint implements SimpleHttpServiceRegistryAPI { private static final Logger log = LoggerFactory.getLogger(SimpleHttpServiceRegistryEndpoint.class); @@ -59,12 +56,12 @@ public MultiValueMap services() { return serviceMapping; } - @GET("/{name}") @Override - public List lookup(@PathVariable String name) { - List registrations = serviceMapping.get(name); + @GET("/{serviceId}") + public List lookup(@PathVariable String serviceId) { + List registrations = serviceMapping.get(serviceId); if (CollectionUtils.isEmpty(registrations)) { - throw new ServiceNotFoundException(name); + throw new ServiceNotFoundException(serviceId); } return registrations; @@ -87,6 +84,7 @@ public void update(HttpRegistration registration) { } else { registrations.removeIf(r -> r.getInstanceId().equals(registration.getInstanceId())); + registrations.add(registration); } } diff --git a/today-service-registry-simple-server/src/main/java/infra/cloud/registry/simple/server/SimpleHttpServiceRegistryServerAutoConfiguration.java b/today-service-registry-simple-server/src/main/java/infra/cloud/registry/simple/server/SimpleHttpServiceRegistryServerAutoConfiguration.java new file mode 100644 index 0000000..ba8e146 --- /dev/null +++ b/today-service-registry-simple-server/src/main/java/infra/cloud/registry/simple/server/SimpleHttpServiceRegistryServerAutoConfiguration.java @@ -0,0 +1,35 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.registry.simple.server; + +import infra.context.annotation.config.DisableDIAutoConfiguration; +import infra.stereotype.Component; + +/** + * @author 海子 Yang + * @since 1.0 2025/8/24 18:23 + */ +@DisableDIAutoConfiguration +public class SimpleHttpServiceRegistryServerAutoConfiguration { + + @Component + static SimpleHttpServiceRegistryEndpoint simpleHttpServiceRegistryEndpoint() { + return new SimpleHttpServiceRegistryEndpoint(); + } + +} diff --git a/today-service-registry-simple-server/src/main/resources/META-INF/config/infra.context.annotation.config.AutoConfiguration.imports b/today-service-registry-simple-server/src/main/resources/META-INF/config/infra.context.annotation.config.AutoConfiguration.imports index e69de29..faabf92 100644 --- a/today-service-registry-simple-server/src/main/resources/META-INF/config/infra.context.annotation.config.AutoConfiguration.imports +++ b/today-service-registry-simple-server/src/main/resources/META-INF/config/infra.context.annotation.config.AutoConfiguration.imports @@ -0,0 +1 @@ +infra.cloud.registry.simple.server.SimpleHttpServiceRegistryServerAutoConfiguration \ No newline at end of file diff --git a/today-service-registry/src/main/java/infra/cloud/registry/AbstractAutoServiceRegistration.java b/today-service-registry/src/main/java/infra/cloud/registry/AbstractAutoServiceRegistration.java index ebb5ae0..094f323 100644 --- a/today-service-registry/src/main/java/infra/cloud/registry/AbstractAutoServiceRegistration.java +++ b/today-service-registry/src/main/java/infra/cloud/registry/AbstractAutoServiceRegistration.java @@ -21,6 +21,7 @@ import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; +import infra.cloud.client.Registration; import infra.cloud.registry.event.InstancePreRegisteredEvent; import infra.cloud.registry.event.InstanceRegisteredEvent; import infra.context.SmartLifecycle; @@ -141,12 +142,8 @@ public void stop() { /** * @return True, if this is enabled. */ - protected boolean isEnabled() { - return true; - } + protected abstract boolean isEnabled(); protected abstract R getRegistration(); - protected abstract R getManagementRegistration(); - } diff --git a/today-service-registry/src/main/java/infra/cloud/registry/AutoServiceRegistrationProperties.java b/today-service-registry/src/main/java/infra/cloud/registry/AutoServiceRegistrationProperties.java index 5800396..ba63dc4 100644 --- a/today-service-registry/src/main/java/infra/cloud/registry/AutoServiceRegistrationProperties.java +++ b/today-service-registry/src/main/java/infra/cloud/registry/AutoServiceRegistrationProperties.java @@ -36,11 +36,6 @@ public class AutoServiceRegistrationProperties { */ private boolean failFast = false; - /** - * Service provider port - */ - private int port = 9000; - public boolean isEnabled() { return this.enabled; } @@ -57,11 +52,4 @@ public void setFailFast(boolean failFast) { this.failFast = failFast; } - public void setPort(int port) { - this.port = port; - } - - public int getPort() { - return port; - } } diff --git a/today-service-registry/src/main/java/infra/cloud/registry/RegistrationLifecycle.java b/today-service-registry/src/main/java/infra/cloud/registry/RegistrationLifecycle.java index 316955d..82eacb7 100644 --- a/today-service-registry/src/main/java/infra/cloud/registry/RegistrationLifecycle.java +++ b/today-service-registry/src/main/java/infra/cloud/registry/RegistrationLifecycle.java @@ -17,6 +17,8 @@ package infra.cloud.registry; +import infra.cloud.client.Registration; + /** * Service registration life cycle. This life cycle is only related to * {@link Registration}. diff --git a/today-service-registry/src/main/java/infra/cloud/registry/ServiceRegisterFailedException.java b/today-service-registry/src/main/java/infra/cloud/registry/ServiceRegisterFailedException.java index ef3cb7d..c2ca8b2 100644 --- a/today-service-registry/src/main/java/infra/cloud/registry/ServiceRegisterFailedException.java +++ b/today-service-registry/src/main/java/infra/cloud/registry/ServiceRegisterFailedException.java @@ -20,6 +20,7 @@ import java.io.Serial; import infra.cloud.RemotingException; +import infra.cloud.client.Registration; import infra.lang.Nullable; /** diff --git a/today-service-registry/src/main/java/infra/cloud/registry/ServiceRegistry.java b/today-service-registry/src/main/java/infra/cloud/registry/ServiceRegistry.java index fac41d7..b916188 100644 --- a/today-service-registry/src/main/java/infra/cloud/registry/ServiceRegistry.java +++ b/today-service-registry/src/main/java/infra/cloud/registry/ServiceRegistry.java @@ -17,6 +17,8 @@ package infra.cloud.registry; +import infra.cloud.client.Registration; + /** * Contract to register and deregister instances with a Service Registry. * diff --git a/today-service-registry/src/main/java/infra/cloud/registry/event/InstancePreRegisteredEvent.java b/today-service-registry/src/main/java/infra/cloud/registry/event/InstancePreRegisteredEvent.java index ec79b17..6bcf899 100644 --- a/today-service-registry/src/main/java/infra/cloud/registry/event/InstancePreRegisteredEvent.java +++ b/today-service-registry/src/main/java/infra/cloud/registry/event/InstancePreRegisteredEvent.java @@ -17,7 +17,7 @@ package infra.cloud.registry.event; -import infra.cloud.registry.Registration; +import infra.cloud.client.Registration; import infra.context.ApplicationEvent; /** From 97006e782a0fcb2de6d40ccef3bcafa2e9fb6fd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Sun, 24 Aug 2025 21:45:41 +0800 Subject: [PATCH 049/104] =?UTF-8?q?:art:=20=E7=9B=AE=E5=BD=95=E7=BB=93?= =?UTF-8?q?=E6=9E=84=E9=87=8D=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit registry 重命名为 registration --- settings.gradle | 4 ++-- .../demo-tests/demo-user-service/build.gradle | 2 +- .../build.gradle | 5 ++++- .../cloud/registry/AbstractAutoServiceRegistration.java | 0 .../java/infra/cloud/registry/AutoServiceRegistration.java | 0 .../cloud/registry/AutoServiceRegistrationProperties.java | 0 .../java/infra/cloud/registry/RegistrationLifecycle.java | 0 .../infra/cloud/registry/ServiceRegisterFailedException.java | 0 .../src/main/java/infra/cloud/registry/ServiceRegistry.java | 0 .../config/AutoServiceRegistrationAutoConfiguration.java | 0 .../config/AutoServiceRegistrationConfiguration.java | 0 .../cloud/registry/event/InstancePreRegisteredEvent.java | 0 .../infra/cloud/registry/event/InstanceRegisteredEvent.java | 0 ...infra.context.annotation.config.AutoConfiguration.imports | 0 .../build.gradle | 2 +- .../cloud/registry/simple/SimpleAutoServiceRegistration.java | 0 .../cloud/registry/simple/SimpleHttpServiceRegistry.java | 0 .../cloud/registry/simple/SimpleRegistryProperties.java | 0 .../config/SimpleHttpServiceRegistryAutoConfiguration.java | 0 ...infra.context.annotation.config.AutoConfiguration.imports | 0 .../src/main/resources/META-INF/today.strategies | 0 21 files changed, 8 insertions(+), 5 deletions(-) rename {today-service-registry => today-service-registration}/build.gradle (67%) rename {today-service-registry => today-service-registration}/src/main/java/infra/cloud/registry/AbstractAutoServiceRegistration.java (100%) rename {today-service-registry => today-service-registration}/src/main/java/infra/cloud/registry/AutoServiceRegistration.java (100%) rename {today-service-registry => today-service-registration}/src/main/java/infra/cloud/registry/AutoServiceRegistrationProperties.java (100%) rename {today-service-registry => today-service-registration}/src/main/java/infra/cloud/registry/RegistrationLifecycle.java (100%) rename {today-service-registry => today-service-registration}/src/main/java/infra/cloud/registry/ServiceRegisterFailedException.java (100%) rename {today-service-registry => today-service-registration}/src/main/java/infra/cloud/registry/ServiceRegistry.java (100%) rename {today-service-registry => today-service-registration}/src/main/java/infra/cloud/registry/annotation/config/AutoServiceRegistrationAutoConfiguration.java (100%) rename {today-service-registry => today-service-registration}/src/main/java/infra/cloud/registry/annotation/config/AutoServiceRegistrationConfiguration.java (100%) rename {today-service-registry => today-service-registration}/src/main/java/infra/cloud/registry/event/InstancePreRegisteredEvent.java (100%) rename {today-service-registry => today-service-registration}/src/main/java/infra/cloud/registry/event/InstanceRegisteredEvent.java (100%) rename {today-service-registry => today-service-registration}/src/main/resources/META-INF/config/infra.context.annotation.config.AutoConfiguration.imports (100%) rename {today-service-registry-simple-client => today-service-registry-simple-registration}/build.gradle (83%) rename {today-service-registry-simple-client => today-service-registry-simple-registration}/src/main/java/infra/cloud/registry/simple/SimpleAutoServiceRegistration.java (100%) rename {today-service-registry-simple-client => today-service-registry-simple-registration}/src/main/java/infra/cloud/registry/simple/SimpleHttpServiceRegistry.java (100%) rename {today-service-registry-simple-client => today-service-registry-simple-registration}/src/main/java/infra/cloud/registry/simple/SimpleRegistryProperties.java (100%) rename {today-service-registry-simple-client => today-service-registry-simple-registration}/src/main/java/infra/cloud/registry/simple/annotation/config/SimpleHttpServiceRegistryAutoConfiguration.java (100%) rename {today-service-registry-simple-client => today-service-registry-simple-registration}/src/main/resources/META-INF/config/infra.context.annotation.config.AutoConfiguration.imports (100%) rename {today-service-registry-simple-client => today-service-registry-simple-registration}/src/main/resources/META-INF/today.strategies (100%) diff --git a/settings.gradle b/settings.gradle index 72934b0..ec54479 100644 --- a/settings.gradle +++ b/settings.gradle @@ -34,13 +34,13 @@ include 'today-cloud-config-server' include 'today-service-api' include 'today-service-client' include 'today-service-provider' -include 'today-service-registry' include 'today-service-discovery' +include 'today-service-registration' include 'today-service-serialization' include 'today-service-registry-simple-api' -include 'today-service-registry-simple-client' include 'today-service-registry-simple-server' include 'today-service-registry-simple-discovery' +include 'today-service-registry-simple-registration' include 'today-remoting' include 'today-remoting-micrometer' diff --git a/today-cloud-samples/demo-tests/demo-user-service/build.gradle b/today-cloud-samples/demo-tests/demo-user-service/build.gradle index a17c103..12906ea 100644 --- a/today-cloud-samples/demo-tests/demo-user-service/build.gradle +++ b/today-cloud-samples/demo-tests/demo-user-service/build.gradle @@ -4,7 +4,7 @@ dependencies { implementation project(":today-cloud-samples:demo-tests:demo-user-api") implementation project(":today-service-provider") - implementation project(":today-service-registry-simple-client") + implementation project(":today-service-registry-simple-registration") // implementation 'cn.taketoday:today-starter-web' // implementation 'cn.taketoday:today-starter-netty' diff --git a/today-service-registry/build.gradle b/today-service-registration/build.gradle similarity index 67% rename from today-service-registry/build.gradle rename to today-service-registration/build.gradle index 12adf93..130edc1 100644 --- a/today-service-registry/build.gradle +++ b/today-service-registration/build.gradle @@ -1,10 +1,13 @@ -description = "TODAY Service Registry" +description = "TODAY Service Registration API" dependencies { api project(":today-cloud-core") + api project(":today-service-provider") + api 'cn.taketoday:today-core' api 'cn.taketoday:today-context' + annotationProcessor 'cn.taketoday:infra-configuration-processor' } \ No newline at end of file diff --git a/today-service-registry/src/main/java/infra/cloud/registry/AbstractAutoServiceRegistration.java b/today-service-registration/src/main/java/infra/cloud/registry/AbstractAutoServiceRegistration.java similarity index 100% rename from today-service-registry/src/main/java/infra/cloud/registry/AbstractAutoServiceRegistration.java rename to today-service-registration/src/main/java/infra/cloud/registry/AbstractAutoServiceRegistration.java diff --git a/today-service-registry/src/main/java/infra/cloud/registry/AutoServiceRegistration.java b/today-service-registration/src/main/java/infra/cloud/registry/AutoServiceRegistration.java similarity index 100% rename from today-service-registry/src/main/java/infra/cloud/registry/AutoServiceRegistration.java rename to today-service-registration/src/main/java/infra/cloud/registry/AutoServiceRegistration.java diff --git a/today-service-registry/src/main/java/infra/cloud/registry/AutoServiceRegistrationProperties.java b/today-service-registration/src/main/java/infra/cloud/registry/AutoServiceRegistrationProperties.java similarity index 100% rename from today-service-registry/src/main/java/infra/cloud/registry/AutoServiceRegistrationProperties.java rename to today-service-registration/src/main/java/infra/cloud/registry/AutoServiceRegistrationProperties.java diff --git a/today-service-registry/src/main/java/infra/cloud/registry/RegistrationLifecycle.java b/today-service-registration/src/main/java/infra/cloud/registry/RegistrationLifecycle.java similarity index 100% rename from today-service-registry/src/main/java/infra/cloud/registry/RegistrationLifecycle.java rename to today-service-registration/src/main/java/infra/cloud/registry/RegistrationLifecycle.java diff --git a/today-service-registry/src/main/java/infra/cloud/registry/ServiceRegisterFailedException.java b/today-service-registration/src/main/java/infra/cloud/registry/ServiceRegisterFailedException.java similarity index 100% rename from today-service-registry/src/main/java/infra/cloud/registry/ServiceRegisterFailedException.java rename to today-service-registration/src/main/java/infra/cloud/registry/ServiceRegisterFailedException.java diff --git a/today-service-registry/src/main/java/infra/cloud/registry/ServiceRegistry.java b/today-service-registration/src/main/java/infra/cloud/registry/ServiceRegistry.java similarity index 100% rename from today-service-registry/src/main/java/infra/cloud/registry/ServiceRegistry.java rename to today-service-registration/src/main/java/infra/cloud/registry/ServiceRegistry.java diff --git a/today-service-registry/src/main/java/infra/cloud/registry/annotation/config/AutoServiceRegistrationAutoConfiguration.java b/today-service-registration/src/main/java/infra/cloud/registry/annotation/config/AutoServiceRegistrationAutoConfiguration.java similarity index 100% rename from today-service-registry/src/main/java/infra/cloud/registry/annotation/config/AutoServiceRegistrationAutoConfiguration.java rename to today-service-registration/src/main/java/infra/cloud/registry/annotation/config/AutoServiceRegistrationAutoConfiguration.java diff --git a/today-service-registry/src/main/java/infra/cloud/registry/annotation/config/AutoServiceRegistrationConfiguration.java b/today-service-registration/src/main/java/infra/cloud/registry/annotation/config/AutoServiceRegistrationConfiguration.java similarity index 100% rename from today-service-registry/src/main/java/infra/cloud/registry/annotation/config/AutoServiceRegistrationConfiguration.java rename to today-service-registration/src/main/java/infra/cloud/registry/annotation/config/AutoServiceRegistrationConfiguration.java diff --git a/today-service-registry/src/main/java/infra/cloud/registry/event/InstancePreRegisteredEvent.java b/today-service-registration/src/main/java/infra/cloud/registry/event/InstancePreRegisteredEvent.java similarity index 100% rename from today-service-registry/src/main/java/infra/cloud/registry/event/InstancePreRegisteredEvent.java rename to today-service-registration/src/main/java/infra/cloud/registry/event/InstancePreRegisteredEvent.java diff --git a/today-service-registry/src/main/java/infra/cloud/registry/event/InstanceRegisteredEvent.java b/today-service-registration/src/main/java/infra/cloud/registry/event/InstanceRegisteredEvent.java similarity index 100% rename from today-service-registry/src/main/java/infra/cloud/registry/event/InstanceRegisteredEvent.java rename to today-service-registration/src/main/java/infra/cloud/registry/event/InstanceRegisteredEvent.java diff --git a/today-service-registry/src/main/resources/META-INF/config/infra.context.annotation.config.AutoConfiguration.imports b/today-service-registration/src/main/resources/META-INF/config/infra.context.annotation.config.AutoConfiguration.imports similarity index 100% rename from today-service-registry/src/main/resources/META-INF/config/infra.context.annotation.config.AutoConfiguration.imports rename to today-service-registration/src/main/resources/META-INF/config/infra.context.annotation.config.AutoConfiguration.imports diff --git a/today-service-registry-simple-client/build.gradle b/today-service-registry-simple-registration/build.gradle similarity index 83% rename from today-service-registry-simple-client/build.gradle rename to today-service-registry-simple-registration/build.gradle index e0abab5..2856b4a 100644 --- a/today-service-registry-simple-client/build.gradle +++ b/today-service-registry-simple-registration/build.gradle @@ -2,7 +2,7 @@ description = "TODAY Service Simple Registry" dependencies { - api project(":today-service-registry") + api project(":today-service-registration") api project(":today-service-registry-simple-api") implementation 'cn.taketoday:today-starter-web' diff --git a/today-service-registry-simple-client/src/main/java/infra/cloud/registry/simple/SimpleAutoServiceRegistration.java b/today-service-registry-simple-registration/src/main/java/infra/cloud/registry/simple/SimpleAutoServiceRegistration.java similarity index 100% rename from today-service-registry-simple-client/src/main/java/infra/cloud/registry/simple/SimpleAutoServiceRegistration.java rename to today-service-registry-simple-registration/src/main/java/infra/cloud/registry/simple/SimpleAutoServiceRegistration.java diff --git a/today-service-registry-simple-client/src/main/java/infra/cloud/registry/simple/SimpleHttpServiceRegistry.java b/today-service-registry-simple-registration/src/main/java/infra/cloud/registry/simple/SimpleHttpServiceRegistry.java similarity index 100% rename from today-service-registry-simple-client/src/main/java/infra/cloud/registry/simple/SimpleHttpServiceRegistry.java rename to today-service-registry-simple-registration/src/main/java/infra/cloud/registry/simple/SimpleHttpServiceRegistry.java diff --git a/today-service-registry-simple-client/src/main/java/infra/cloud/registry/simple/SimpleRegistryProperties.java b/today-service-registry-simple-registration/src/main/java/infra/cloud/registry/simple/SimpleRegistryProperties.java similarity index 100% rename from today-service-registry-simple-client/src/main/java/infra/cloud/registry/simple/SimpleRegistryProperties.java rename to today-service-registry-simple-registration/src/main/java/infra/cloud/registry/simple/SimpleRegistryProperties.java diff --git a/today-service-registry-simple-client/src/main/java/infra/cloud/registry/simple/annotation/config/SimpleHttpServiceRegistryAutoConfiguration.java b/today-service-registry-simple-registration/src/main/java/infra/cloud/registry/simple/annotation/config/SimpleHttpServiceRegistryAutoConfiguration.java similarity index 100% rename from today-service-registry-simple-client/src/main/java/infra/cloud/registry/simple/annotation/config/SimpleHttpServiceRegistryAutoConfiguration.java rename to today-service-registry-simple-registration/src/main/java/infra/cloud/registry/simple/annotation/config/SimpleHttpServiceRegistryAutoConfiguration.java diff --git a/today-service-registry-simple-client/src/main/resources/META-INF/config/infra.context.annotation.config.AutoConfiguration.imports b/today-service-registry-simple-registration/src/main/resources/META-INF/config/infra.context.annotation.config.AutoConfiguration.imports similarity index 100% rename from today-service-registry-simple-client/src/main/resources/META-INF/config/infra.context.annotation.config.AutoConfiguration.imports rename to today-service-registry-simple-registration/src/main/resources/META-INF/config/infra.context.annotation.config.AutoConfiguration.imports diff --git a/today-service-registry-simple-client/src/main/resources/META-INF/today.strategies b/today-service-registry-simple-registration/src/main/resources/META-INF/today.strategies similarity index 100% rename from today-service-registry-simple-client/src/main/resources/META-INF/today.strategies rename to today-service-registry-simple-registration/src/main/resources/META-INF/today.strategies From 22e53da6d543316e4358d5144ac5cf933800809c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Sun, 24 Aug 2025 22:37:05 +0800 Subject: [PATCH 050/104] :sparkles: --- .../cloud/client/DefaultServiceInstance.java | 4 ++ .../src/main/resources/application.yaml | 3 + .../PackageInfoServiceMetadataProvider.java | 2 +- .../infra/cloud/service/ServiceMetadata.java | 25 +++++++ today-service-provider/build.gradle | 2 + .../cloud/provider/LocalServiceHolder.java | 25 ++++++- .../provider/ServiceServerProperties.java | 2 +- .../cloud/provider/ServicesProvider.java | 32 +++++++++ .../ServiceProviderAutoConfiguration.java | 4 +- .../provider/LocalServiceHolderTests.java | 28 ++++++++ .../AbstractAutoServiceRegistration.java | 69 +++++++++++-------- .../cloud/registry/RegistrationFactory.java | 31 +++++++++ .../event/InstanceRegisteredEvent.java | 11 ++- .../simple/HttpRegistrationFactory.java | 60 ++++++++++++++++ .../simple/SimpleAutoServiceRegistration.java | 18 +++-- .../simple/SimpleRegistryProperties.java | 13 +--- ...eHttpServiceRegistryAutoConfiguration.java | 31 ++++----- 17 files changed, 287 insertions(+), 73 deletions(-) create mode 100644 today-service-provider/src/main/java/infra/cloud/provider/ServicesProvider.java create mode 100644 today-service-provider/src/test/java/infra/cloud/provider/LocalServiceHolderTests.java create mode 100644 today-service-registration/src/main/java/infra/cloud/registry/RegistrationFactory.java create mode 100644 today-service-registry-simple-registration/src/main/java/infra/cloud/registry/simple/HttpRegistrationFactory.java diff --git a/today-cloud-core/src/main/java/infra/cloud/client/DefaultServiceInstance.java b/today-cloud-core/src/main/java/infra/cloud/client/DefaultServiceInstance.java index 785a525..5ed6bce 100644 --- a/today-cloud-core/src/main/java/infra/cloud/client/DefaultServiceInstance.java +++ b/today-cloud-core/src/main/java/infra/cloud/client/DefaultServiceInstance.java @@ -135,6 +135,10 @@ public boolean isSecure() { return secure; } + public void setDefaultInstanceId() { + setInstanceId(getHost() + ":" + getPort() + ":" + getServiceId()); + } + public void setInstanceId(String instanceId) { this.instanceId = instanceId; } diff --git a/today-cloud-samples/demo-tests/demo-user-service/src/main/resources/application.yaml b/today-cloud-samples/demo-tests/demo-user-service/src/main/resources/application.yaml index a6cd363..2db6060 100644 --- a/today-cloud-samples/demo-tests/demo-user-service/src/main/resources/application.yaml +++ b/today-cloud-samples/demo-tests/demo-user-service/src/main/resources/application.yaml @@ -11,6 +11,9 @@ infra: instance-port: 9000 uri: http://localhost:5000 +service: + server: + port: 9000 logging: level: diff --git a/today-service-api/src/main/java/infra/cloud/service/PackageInfoServiceMetadataProvider.java b/today-service-api/src/main/java/infra/cloud/service/PackageInfoServiceMetadataProvider.java index 5a66953..8d9d23a 100644 --- a/today-service-api/src/main/java/infra/cloud/service/PackageInfoServiceMetadataProvider.java +++ b/today-service-api/src/main/java/infra/cloud/service/PackageInfoServiceMetadataProvider.java @@ -28,8 +28,8 @@ public class PackageInfoServiceMetadataProvider implements ServiceMetadataProvid @Override public ServiceMetadata getMetadata(Class serviceInterface) { Package servicePackage = serviceInterface.getPackage(); - String specificationVersion = servicePackage.getSpecificationVersion(); String specificationTitle = servicePackage.getSpecificationTitle(); + String specificationVersion = servicePackage.getSpecificationVersion(); return new ServiceMetadata(specificationTitle, specificationVersion); } diff --git a/today-service-api/src/main/java/infra/cloud/service/ServiceMetadata.java b/today-service-api/src/main/java/infra/cloud/service/ServiceMetadata.java index a179f74..8be5af1 100644 --- a/today-service-api/src/main/java/infra/cloud/service/ServiceMetadata.java +++ b/today-service-api/src/main/java/infra/cloud/service/ServiceMetadata.java @@ -17,6 +17,10 @@ package infra.cloud.service; +import java.util.Objects; + +import infra.core.style.ToStringBuilder; + /** * @author 海子 Yang * @since 1.0 2025/8/9 21:51 @@ -40,4 +44,25 @@ public String getVersion() { return version; } + @Override + public boolean equals(Object o) { + if (!(o instanceof ServiceMetadata that)) + return false; + return Objects.equals(id, that.id) + && Objects.equals(version, that.version); + } + + @Override + public int hashCode() { + return Objects.hash(id, version); + } + + @Override + public String toString() { + return ToStringBuilder.forInstance(this) + .append("id", id) + .append("version", version) + .toString(); + } + } diff --git a/today-service-provider/build.gradle b/today-service-provider/build.gradle index 1cddb8e..c84a066 100644 --- a/today-service-provider/build.gradle +++ b/today-service-provider/build.gradle @@ -8,6 +8,8 @@ dependencies { api project(":today-service-api") optional project(":today-remoting-transport-tcp") + + annotationProcessor 'cn.taketoday:infra-configuration-processor' } // --add-opens=java.base/java.nio=ALL-UNNAMED diff --git a/today-service-provider/src/main/java/infra/cloud/provider/LocalServiceHolder.java b/today-service-provider/src/main/java/infra/cloud/provider/LocalServiceHolder.java index 6f1f306..bc55401 100644 --- a/today-service-provider/src/main/java/infra/cloud/provider/LocalServiceHolder.java +++ b/today-service-provider/src/main/java/infra/cloud/provider/LocalServiceHolder.java @@ -17,27 +17,41 @@ package infra.cloud.provider; +import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Set; import infra.beans.factory.SmartInitializingSingleton; +import infra.cloud.service.ServiceMetadata; +import infra.cloud.service.ServiceMetadataProvider; import infra.context.ApplicationContext; import infra.context.support.ApplicationObjectSupport; +import infra.lang.Assert; import infra.lang.Nullable; import infra.stereotype.Service; import infra.util.ClassUtils; +import infra.util.MultiValueMap; /** * @author Harry Yang * @since 1.0 2022/10/19 21:40 */ -public class LocalServiceHolder extends ApplicationObjectSupport implements SmartInitializingSingleton { +public class LocalServiceHolder extends ApplicationObjectSupport implements SmartInitializingSingleton, ServicesProvider { private final HashMap, Object> localServices = new HashMap<>(); private final HashMap> classNameMap = new HashMap<>(); + private final MultiValueMap> serviceMap = MultiValueMap.forLinkedHashMap(); + + private final ServiceMetadataProvider serviceMetadataProvider; + + public LocalServiceHolder(ServiceMetadataProvider serviceMetadataProvider) { + Assert.notNull(serviceMetadataProvider, "serviceMetadataProvider is required"); + this.serviceMetadataProvider = serviceMetadataProvider; + } + @Nullable @SuppressWarnings("unchecked") public T getService(Class serviceInterface) { @@ -49,6 +63,11 @@ public Class getServiceInterface(String serviceClass) { return classNameMap.get(serviceClass); } + @Override + public List getServices() { + return new ArrayList<>(serviceMap.keySet()); + } + @Override public void afterSingletonsInstantiated() { ApplicationContext context = obtainApplicationContext(); @@ -68,12 +87,14 @@ public void afterSingletonsInstantiated() { if (object != null) { throw new IllegalStateException("Service '%s' is already registered: [%s]".formatted(interfaceName, object)); } + + ServiceMetadata serviceMetadata = serviceMetadataProvider.getMetadata(anInterface); + serviceMap.add(serviceMetadata, anInterface); classNameMap.put(interfaceName, anInterface); logger.info("add service: [{}] to interface: [{}]", service, interfaceName); } } } - } } diff --git a/today-service-provider/src/main/java/infra/cloud/provider/ServiceServerProperties.java b/today-service-provider/src/main/java/infra/cloud/provider/ServiceServerProperties.java index 6003f1d..bc50108 100644 --- a/today-service-provider/src/main/java/infra/cloud/provider/ServiceServerProperties.java +++ b/today-service-provider/src/main/java/infra/cloud/provider/ServiceServerProperties.java @@ -44,7 +44,7 @@ public class ServiceServerProperties { /** * The port to bind */ - private int port; + private int port = 9000; /** * Configurations that exposes the maximum frame size that a Connection can bring up. diff --git a/today-service-provider/src/main/java/infra/cloud/provider/ServicesProvider.java b/today-service-provider/src/main/java/infra/cloud/provider/ServicesProvider.java new file mode 100644 index 0000000..5d145ec --- /dev/null +++ b/today-service-provider/src/main/java/infra/cloud/provider/ServicesProvider.java @@ -0,0 +1,32 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.provider; + +import java.util.List; + +import infra.cloud.service.ServiceMetadata; + +/** + * @author 海子 Yang + * @since 1.0 2025/8/24 22:08 + */ +public interface ServicesProvider { + + List getServices(); + +} diff --git a/today-service-provider/src/main/java/infra/cloud/provider/annotation/config/ServiceProviderAutoConfiguration.java b/today-service-provider/src/main/java/infra/cloud/provider/annotation/config/ServiceProviderAutoConfiguration.java index 502f56a..a9f4d71 100644 --- a/today-service-provider/src/main/java/infra/cloud/provider/annotation/config/ServiceProviderAutoConfiguration.java +++ b/today-service-provider/src/main/java/infra/cloud/provider/annotation/config/ServiceProviderAutoConfiguration.java @@ -55,8 +55,8 @@ public class ServiceProviderAutoConfiguration { @Component - public static LocalServiceHolder localServiceHolder() { - return new LocalServiceHolder(); + public static LocalServiceHolder localServiceHolder(ServiceMetadataProvider metadataProvider) { + return new LocalServiceHolder(metadataProvider); } @Component diff --git a/today-service-provider/src/test/java/infra/cloud/provider/LocalServiceHolderTests.java b/today-service-provider/src/test/java/infra/cloud/provider/LocalServiceHolderTests.java new file mode 100644 index 0000000..592a7ab --- /dev/null +++ b/today-service-provider/src/test/java/infra/cloud/provider/LocalServiceHolderTests.java @@ -0,0 +1,28 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.provider; + +import static org.junit.jupiter.api.Assertions.*; + +/** + * @author 海子 Yang + * @since 1.0 2025/8/24 22:07 + */ +class LocalServiceHolderTests { + +} \ No newline at end of file diff --git a/today-service-registration/src/main/java/infra/cloud/registry/AbstractAutoServiceRegistration.java b/today-service-registration/src/main/java/infra/cloud/registry/AbstractAutoServiceRegistration.java index 094f323..d8b3e05 100644 --- a/today-service-registration/src/main/java/infra/cloud/registry/AbstractAutoServiceRegistration.java +++ b/today-service-registration/src/main/java/infra/cloud/registry/AbstractAutoServiceRegistration.java @@ -22,8 +22,10 @@ import java.util.concurrent.atomic.AtomicBoolean; import infra.cloud.client.Registration; +import infra.cloud.provider.ServicesProvider; import infra.cloud.registry.event.InstancePreRegisteredEvent; import infra.cloud.registry.event.InstanceRegisteredEvent; +import infra.cloud.service.ServiceMetadata; import infra.context.SmartLifecycle; import infra.context.support.ApplicationObjectSupport; @@ -45,14 +47,15 @@ public abstract class AbstractAutoServiceRegistration private final List> registrationLifecycles; - protected AbstractAutoServiceRegistration(ServiceRegistry serviceRegistry) { - this.serviceRegistry = serviceRegistry; - this.registrationLifecycles = new ArrayList<>(); - } + private final ArrayList registrations = new ArrayList<>(); - protected AbstractAutoServiceRegistration(ServiceRegistry serviceRegistry, List> registrationLifecycles) { + private final ServicesProvider servicesProvider; + + protected AbstractAutoServiceRegistration(ServiceRegistry serviceRegistry, + List> registrationLifecycles, ServicesProvider servicesProvider) { this.serviceRegistry = serviceRegistry; this.registrationLifecycles = registrationLifecycles; + this.servicesProvider = servicesProvider; } public void addRegistrationLifecycle(RegistrationLifecycle registrationLifecycle) { @@ -71,18 +74,22 @@ public void start() { logger.info("Registering services to registry: [{}]", serviceRegistry); if (!running.get()) { - R registration = getRegistration(); - obtainApplicationContext().publishEvent(new InstancePreRegisteredEvent(this, registration)); - - for (RegistrationLifecycle lifecycle : registrationLifecycles) { - lifecycle.postProcessBeforeStartRegister(registration); + RegistrationFactory registrationFactory = getRegistrationFactory(); + for (ServiceMetadata serviceMetadata : servicesProvider.getServices()) { + R registration = registrationFactory.createRegistration(serviceMetadata); + obtainApplicationContext().publishEvent(new InstancePreRegisteredEvent(this, registration)); + + for (RegistrationLifecycle lifecycle : registrationLifecycles) { + lifecycle.postProcessBeforeStartRegister(registration); + } + register(registration); + for (RegistrationLifecycle lifecycle : registrationLifecycles) { + lifecycle.postProcessAfterStartRegister(registration); + } + + obtainApplicationContext().publishEvent(new InstanceRegisteredEvent<>(this, registration, getConfiguration())); + registrations.add(registration); } - register(); - for (RegistrationLifecycle lifecycle : registrationLifecycles) { - lifecycle.postProcessAfterStartRegister(registration); - } - - obtainApplicationContext().publishEvent(new InstanceRegisteredEvent<>(this, getConfiguration())); running.compareAndSet(false, true); } } @@ -100,15 +107,17 @@ public int getPhase() { /** * Register the local service with the {@link ServiceRegistry}. */ - protected void register() { - serviceRegistry.register(getRegistration()); + protected void register(R registration) { + logger.debug("Registering registration: [{}]", registration); + serviceRegistry.register(registration); } /** * un-register the local service with the {@link ServiceRegistry}. */ - protected void unregister() { - serviceRegistry.unregister(getRegistration()); + protected void unregister(R registration) { + logger.debug("Unregistering registration: [{}]", registration); + serviceRegistry.unregister(registration); } /** @@ -118,19 +127,19 @@ protected void unregister() { public void stop() { if (running.compareAndSet(true, false) && isEnabled()) { logger.info("Un-Registering services: [{}]", serviceRegistry); + for (R registration : registrations) { + for (RegistrationLifecycle lifecycle : registrationLifecycles) { + lifecycle.postProcessBeforeStopRegister(registration); + } - R registration = getRegistration(); - for (RegistrationLifecycle lifecycle : registrationLifecycles) { - lifecycle.postProcessBeforeStopRegister(registration); - } + unregister(registration); - unregister(); + for (RegistrationLifecycle lifecycle : registrationLifecycles) { + lifecycle.postProcessAfterStopRegister(registration); + } - for (RegistrationLifecycle lifecycle : registrationLifecycles) { - lifecycle.postProcessAfterStopRegister(registration); + serviceRegistry.close(); } - - serviceRegistry.close(); } } @@ -144,6 +153,6 @@ public void stop() { */ protected abstract boolean isEnabled(); - protected abstract R getRegistration(); + protected abstract RegistrationFactory getRegistrationFactory(); } diff --git a/today-service-registration/src/main/java/infra/cloud/registry/RegistrationFactory.java b/today-service-registration/src/main/java/infra/cloud/registry/RegistrationFactory.java new file mode 100644 index 0000000..8462907 --- /dev/null +++ b/today-service-registration/src/main/java/infra/cloud/registry/RegistrationFactory.java @@ -0,0 +1,31 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.registry; + +import infra.cloud.client.Registration; +import infra.cloud.service.ServiceMetadata; + +/** + * @author 海子 Yang + * @since 1.0 2025/8/24 22:12 + */ +public interface RegistrationFactory { + + R createRegistration(ServiceMetadata serviceMetadata); + +} diff --git a/today-service-registration/src/main/java/infra/cloud/registry/event/InstanceRegisteredEvent.java b/today-service-registration/src/main/java/infra/cloud/registry/event/InstanceRegisteredEvent.java index 27887aa..f6d4c3d 100644 --- a/today-service-registration/src/main/java/infra/cloud/registry/event/InstanceRegisteredEvent.java +++ b/today-service-registration/src/main/java/infra/cloud/registry/event/InstanceRegisteredEvent.java @@ -17,6 +17,7 @@ package infra.cloud.registry.event; +import infra.cloud.client.Registration; import infra.context.ApplicationEvent; /** @@ -32,14 +33,18 @@ public class InstanceRegisteredEvent extends ApplicationEvent { private final T config; + private final Registration registration; + /** * Creates a new {@link InstanceRegisteredEvent} instance. * * @param source The component that published the event (never {@code null}). * @param config The configuration of the instance. + * @param registration registration */ - public InstanceRegisteredEvent(Object source, T config) { + public InstanceRegisteredEvent(Object source, Registration registration, T config) { super(source); + this.registration = registration; this.config = config; } @@ -47,4 +52,8 @@ public T getConfig() { return this.config; } + public Registration getRegistration() { + return registration; + } + } diff --git a/today-service-registry-simple-registration/src/main/java/infra/cloud/registry/simple/HttpRegistrationFactory.java b/today-service-registry-simple-registration/src/main/java/infra/cloud/registry/simple/HttpRegistrationFactory.java new file mode 100644 index 0000000..b7fd4f6 --- /dev/null +++ b/today-service-registry-simple-registration/src/main/java/infra/cloud/registry/simple/HttpRegistrationFactory.java @@ -0,0 +1,60 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.registry.simple; + +import infra.cloud.provider.ServiceServerProperties; +import infra.cloud.registry.RegistrationFactory; +import infra.cloud.service.ServiceMetadata; +import infra.util.StringUtils; + +/** + * @author 海子 Yang + * @since 1.0 2025/8/24 22:26 + */ +public class HttpRegistrationFactory implements RegistrationFactory { + + private final ServiceServerProperties serviceServerProperties; + + private final SimpleRegistryProperties registryProperties; + + public HttpRegistrationFactory(ServiceServerProperties serviceServerProperties, SimpleRegistryProperties registryProperties) { + this.serviceServerProperties = serviceServerProperties; + this.registryProperties = registryProperties; + } + + @Override + public HttpRegistration createRegistration(ServiceMetadata serviceMetadata) { + String host = registryProperties.getInstanceHost(); + if (!StringUtils.hasText(host)) { + throw new IllegalStateException("instanceHost must not be empty"); + } + + HttpRegistration registration = new HttpRegistration(); + registration.setStatus(Status.UP); + registration.setHost(host); + + registration.setServiceId(serviceMetadata.getId()); + registration.setPort(serviceServerProperties.getPort()); + registration.setInstanceId(registryProperties.getInstanceId()); + if (registration.getServiceId() == null) { + registration.setDefaultInstanceId(); + } + return registration; + } + +} diff --git a/today-service-registry-simple-registration/src/main/java/infra/cloud/registry/simple/SimpleAutoServiceRegistration.java b/today-service-registry-simple-registration/src/main/java/infra/cloud/registry/simple/SimpleAutoServiceRegistration.java index 40492c1..6526658 100644 --- a/today-service-registry-simple-registration/src/main/java/infra/cloud/registry/simple/SimpleAutoServiceRegistration.java +++ b/today-service-registry-simple-registration/src/main/java/infra/cloud/registry/simple/SimpleAutoServiceRegistration.java @@ -17,7 +17,12 @@ package infra.cloud.registry.simple; +import java.util.List; + +import infra.cloud.provider.ServicesProvider; import infra.cloud.registry.AbstractAutoServiceRegistration; +import infra.cloud.registry.RegistrationFactory; +import infra.cloud.registry.RegistrationLifecycle; import infra.cloud.registry.ServiceRegistry; /** @@ -26,14 +31,15 @@ */ public class SimpleAutoServiceRegistration extends AbstractAutoServiceRegistration { - private final HttpRegistration registration; + private final HttpRegistrationFactory registrationFactory; private final SimpleRegistryProperties properties; public SimpleAutoServiceRegistration(ServiceRegistry serviceRegistry, - HttpRegistration registration, SimpleRegistryProperties properties) { - super(serviceRegistry); - this.registration = registration; + ServicesProvider servicesProvider, HttpRegistrationFactory registrationFactory, + SimpleRegistryProperties properties, List> registrationLifecycles) { + super(serviceRegistry, registrationLifecycles, servicesProvider); + this.registrationFactory = registrationFactory; this.properties = properties; } @@ -43,8 +49,8 @@ protected Object getConfiguration() { } @Override - protected HttpRegistration getRegistration() { - return registration; + protected RegistrationFactory getRegistrationFactory() { + return registrationFactory; } @Override diff --git a/today-service-registry-simple-registration/src/main/java/infra/cloud/registry/simple/SimpleRegistryProperties.java b/today-service-registry-simple-registration/src/main/java/infra/cloud/registry/simple/SimpleRegistryProperties.java index 8fdf6d7..d73705f 100644 --- a/today-service-registry-simple-registration/src/main/java/infra/cloud/registry/simple/SimpleRegistryProperties.java +++ b/today-service-registry-simple-registration/src/main/java/infra/cloud/registry/simple/SimpleRegistryProperties.java @@ -30,7 +30,7 @@ public class SimpleRegistryProperties { private boolean enabled = true; - /** Id used to register with. Defaults to a random UUID. */ + /** ID used to register with. Defaults to a random UUID. */ private String instanceId; /** @@ -48,9 +48,6 @@ public class SimpleRegistryProperties { */ private boolean preferIpAddress = false; - /** Port to register the service under (defaults to listening port). */ - private Integer instancePort; - public SimpleRegistryProperties(InetService inetService) { var hostInfo = inetService.findFirstNonLoopbackHostInfo(); this.instanceHost = hostInfo.getHostname(); @@ -88,14 +85,6 @@ public void setInstanceIpAddress(String instanceIpAddress) { this.instanceIpAddress = instanceIpAddress; } - public Integer getInstancePort() { - return instancePort; - } - - public void setInstancePort(Integer instancePort) { - this.instancePort = instancePort; - } - public boolean isPreferIpAddress() { return preferIpAddress; } diff --git a/today-service-registry-simple-registration/src/main/java/infra/cloud/registry/simple/annotation/config/SimpleHttpServiceRegistryAutoConfiguration.java b/today-service-registry-simple-registration/src/main/java/infra/cloud/registry/simple/annotation/config/SimpleHttpServiceRegistryAutoConfiguration.java index 5501802..17d5ca1 100644 --- a/today-service-registry-simple-registration/src/main/java/infra/cloud/registry/simple/annotation/config/SimpleHttpServiceRegistryAutoConfiguration.java +++ b/today-service-registry-simple-registration/src/main/java/infra/cloud/registry/simple/annotation/config/SimpleHttpServiceRegistryAutoConfiguration.java @@ -17,21 +17,24 @@ package infra.cloud.registry.simple.annotation.config; +import infra.beans.factory.ObjectProvider; import infra.cloud.client.annotation.ConditionalOnDiscoveryEnabled; import infra.cloud.net.InetProperties; import infra.cloud.net.InetService; +import infra.cloud.provider.ServiceServerProperties; +import infra.cloud.provider.ServicesProvider; +import infra.cloud.registry.RegistrationLifecycle; import infra.cloud.registry.simple.HttpRegistration; +import infra.cloud.registry.simple.HttpRegistrationFactory; import infra.cloud.registry.simple.SimpleAutoServiceRegistration; import infra.cloud.registry.simple.SimpleHttpServiceRegistry; import infra.cloud.registry.simple.SimpleRegistryProperties; -import infra.cloud.registry.simple.Status; import infra.cloud.registry.simple.api.SimpleHttpServiceRegistryAPI; import infra.cloud.registry.simple.config.SimpleHttpServiceRegistryAPIAutoConfiguration; import infra.context.annotation.config.DisableDIAutoConfiguration; import infra.context.condition.ConditionalOnMissingBean; import infra.context.properties.EnableConfigurationProperties; import infra.stereotype.Component; -import infra.util.StringUtils; /** * @author 海子 Yang @@ -54,9 +57,12 @@ public static SimpleHttpServiceRegistry simpleHttpServiceRegistry(SimpleHttpServ } @Component - public static SimpleAutoServiceRegistration autoServiceRegistration(HttpRegistration httpRegistration, - SimpleRegistryProperties properties, SimpleHttpServiceRegistry serviceRegistry) { - return new SimpleAutoServiceRegistration(serviceRegistry, httpRegistration, properties); + public static SimpleAutoServiceRegistration autoServiceRegistration( + HttpRegistrationFactory httpRegistrationFactory, ServicesProvider servicesProvider, + SimpleRegistryProperties properties, SimpleHttpServiceRegistry serviceRegistry, + ObjectProvider> registrationLifecycles) { + return new SimpleAutoServiceRegistration(serviceRegistry, servicesProvider, + httpRegistrationFactory, properties, registrationLifecycles.orderedList()); } @Component @@ -66,19 +72,8 @@ public static InetService inetService(InetProperties inetProperties) { } @Component - public static HttpRegistration httpRegistration(SimpleRegistryProperties properties) { - String host = properties.getInstanceHost(); - if (!StringUtils.hasText(host)) { - throw new IllegalStateException("instanceHost must not be empty"); - } - - HttpRegistration registration = new HttpRegistration(); - registration.setStatus(Status.UP); - registration.setHost(host); - registration.setPort(properties.getInstancePort()); - registration.setInstanceId(properties.getInstanceId()); - registration.setServiceId(properties.getInstanceId()); - return registration; + public static HttpRegistrationFactory httpRegistrationFactory(ServiceServerProperties serverProperties, SimpleRegistryProperties properties) { + return new HttpRegistrationFactory(serverProperties, properties); } } From 0e18c94ede6171cab673ff2b0bc5b60b2815db94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Sun, 24 Aug 2025 22:40:49 +0800 Subject: [PATCH 051/104] :art: --- .../infra/cloud/registry/simple/HttpRegistrationFactory.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/today-service-registry-simple-registration/src/main/java/infra/cloud/registry/simple/HttpRegistrationFactory.java b/today-service-registry-simple-registration/src/main/java/infra/cloud/registry/simple/HttpRegistrationFactory.java index b7fd4f6..04292cb 100644 --- a/today-service-registry-simple-registration/src/main/java/infra/cloud/registry/simple/HttpRegistrationFactory.java +++ b/today-service-registry-simple-registration/src/main/java/infra/cloud/registry/simple/HttpRegistrationFactory.java @@ -40,7 +40,7 @@ public HttpRegistrationFactory(ServiceServerProperties serviceServerProperties, @Override public HttpRegistration createRegistration(ServiceMetadata serviceMetadata) { String host = registryProperties.getInstanceHost(); - if (!StringUtils.hasText(host)) { + if (StringUtils.isBlank(host)) { throw new IllegalStateException("instanceHost must not be empty"); } From 1964613d6ef1e9c8ebe930d6f180cab24c9807de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Sun, 24 Aug 2025 22:51:59 +0800 Subject: [PATCH 052/104] :art: --- .../infra/cloud/provider/LocalServiceHolder.java | 2 +- .../cloud/provider/ServiceProviderServer.java | 15 +++++++++++++-- .../config/ServiceProviderAutoConfiguration.java | 2 +- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/today-service-provider/src/main/java/infra/cloud/provider/LocalServiceHolder.java b/today-service-provider/src/main/java/infra/cloud/provider/LocalServiceHolder.java index bc55401..c13742e 100644 --- a/today-service-provider/src/main/java/infra/cloud/provider/LocalServiceHolder.java +++ b/today-service-provider/src/main/java/infra/cloud/provider/LocalServiceHolder.java @@ -91,7 +91,7 @@ public void afterSingletonsInstantiated() { ServiceMetadata serviceMetadata = serviceMetadataProvider.getMetadata(anInterface); serviceMap.add(serviceMetadata, anInterface); classNameMap.put(interfaceName, anInterface); - logger.info("add service: [{}] to interface: [{}]", service, interfaceName); + logger.info("Adding service: [{}] to interface: [{}]", service, interfaceName); } } } diff --git a/today-service-provider/src/main/java/infra/cloud/provider/ServiceProviderServer.java b/today-service-provider/src/main/java/infra/cloud/provider/ServiceProviderServer.java index 0cdc978..25f9401 100644 --- a/today-service-provider/src/main/java/infra/cloud/provider/ServiceProviderServer.java +++ b/today-service-provider/src/main/java/infra/cloud/provider/ServiceProviderServer.java @@ -17,8 +17,10 @@ package infra.cloud.provider; -import infra.context.Lifecycle; +import infra.context.SmartLifecycle; import infra.lang.Nullable; +import infra.logging.Logger; +import infra.logging.LoggerFactory; import infra.remoting.Channel; import infra.remoting.ChannelAcceptor; import infra.remoting.Closeable; @@ -32,7 +34,9 @@ * @author 海子 Yang * @since 1.0 2025/8/21 22:25 */ -public class ServiceProviderServer implements Lifecycle, ChannelAcceptor { +public class ServiceProviderServer implements SmartLifecycle, ChannelAcceptor { + + private static final Logger log = LoggerFactory.getLogger(ServiceProviderServer.class); private final ServiceServerProperties properties; @@ -63,6 +67,8 @@ public void start() { .maxTimeToFirstFrame(properties.getMaxTimeToFirstFrame()) .maxInboundPayloadSize(properties.getMaxInboundPayloadSize().toBytesInt()) .bindNow(serverTransportFactory.createTransport()); + + log.info("Service provider server started on port: {}", properties.getPort()); } @Override @@ -77,6 +83,11 @@ public boolean isRunning() { return serverCloseable != null; } + @Override + public boolean isPausable() { + return false; + } + @Override public Mono accept(ConnectionSetupPayload setup, Channel channel) { return Mono.just(channelHandler); diff --git a/today-service-provider/src/main/java/infra/cloud/provider/annotation/config/ServiceProviderAutoConfiguration.java b/today-service-provider/src/main/java/infra/cloud/provider/annotation/config/ServiceProviderAutoConfiguration.java index a9f4d71..76eb02e 100644 --- a/today-service-provider/src/main/java/infra/cloud/provider/annotation/config/ServiceProviderAutoConfiguration.java +++ b/today-service-provider/src/main/java/infra/cloud/provider/annotation/config/ServiceProviderAutoConfiguration.java @@ -49,9 +49,9 @@ * @author 海子 Yang * @since 1.0 2025/8/10 22:31 */ +@DisableDIAutoConfiguration @ConditionalOnDiscoveryEnabled @EnableConfigurationProperties({ InetProperties.class, ServiceServerProperties.class }) -@DisableDIAutoConfiguration public class ServiceProviderAutoConfiguration { @Component From 99f3bde759c5ecdb888ac1bb78c8ad340d731b04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Sun, 24 Aug 2025 23:11:18 +0800 Subject: [PATCH 053/104] :art: --- .../cn/taketoday/demo/service/UserServiceApplication.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/today-cloud-samples/demo-tests/demo-user-service/src/main/java/cn/taketoday/demo/service/UserServiceApplication.java b/today-cloud-samples/demo-tests/demo-user-service/src/main/java/cn/taketoday/demo/service/UserServiceApplication.java index ffcaeb9..8cc21ca 100644 --- a/today-cloud-samples/demo-tests/demo-user-service/src/main/java/cn/taketoday/demo/service/UserServiceApplication.java +++ b/today-cloud-samples/demo-tests/demo-user-service/src/main/java/cn/taketoday/demo/service/UserServiceApplication.java @@ -17,9 +17,8 @@ package cn.taketoday.demo.service; -import infra.app.ApplicationType; +import infra.app.Application; import infra.app.InfraApplication; -import infra.app.builder.ApplicationBuilder; /** * @author Harry Yang @@ -29,8 +28,8 @@ public class UserServiceApplication { public static void main(String[] args) { - ApplicationBuilder.forSources(UserServiceApplication.class) - .type(ApplicationType.NORMAL) + Application.forNormalApplication(UserServiceApplication.class) + .keepAlive() .run(args); } From 80a338cdceabc482414ec514d11f2d979c51daed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Tue, 26 Aug 2025 21:53:15 +0800 Subject: [PATCH 054/104] :art: --- .../client/config/DiscoveryClientAutoConfiguration.java | 8 ++++++-- .../DiscoveryClientAutoConfigurationDefaultTests.java | 3 ++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/today-service-discovery/src/main/java/infra/cloud/client/config/DiscoveryClientAutoConfiguration.java b/today-service-discovery/src/main/java/infra/cloud/client/config/DiscoveryClientAutoConfiguration.java index 1c064c5..9aaf3e3 100644 --- a/today-service-discovery/src/main/java/infra/cloud/client/config/DiscoveryClientAutoConfiguration.java +++ b/today-service-discovery/src/main/java/infra/cloud/client/config/DiscoveryClientAutoConfiguration.java @@ -42,8 +42,12 @@ public class DiscoveryClientAutoConfiguration { @Primary @Component - public static CompositeDiscoveryClient compositeDiscoveryClient(ObjectProvider discoveryClients) { - return new CompositeDiscoveryClient(discoveryClients.orderedList()); + public static DiscoveryClient primaryDiscoveryClient(ObjectProvider discoveryClients) { + var discoveryClientList = discoveryClients.orderedList(); + if (discoveryClientList.size() == 1) { + return discoveryClientList.get(0); + } + return new CompositeDiscoveryClient(discoveryClientList); } @MissingBean diff --git a/today-service-discovery/src/test/java/infra/cloud/client/DiscoveryClientAutoConfigurationDefaultTests.java b/today-service-discovery/src/test/java/infra/cloud/client/DiscoveryClientAutoConfigurationDefaultTests.java index 79dd1b1..54bf0b0 100644 --- a/today-service-discovery/src/test/java/infra/cloud/client/DiscoveryClientAutoConfigurationDefaultTests.java +++ b/today-service-discovery/src/test/java/infra/cloud/client/DiscoveryClientAutoConfigurationDefaultTests.java @@ -21,6 +21,7 @@ import infra.app.test.context.InfraTest; import infra.beans.factory.annotation.Autowired; +import infra.cloud.client.simple.SimpleDiscoveryClient; import infra.context.annotation.Configuration; import infra.context.annotation.config.EnableAutoConfiguration; @@ -39,7 +40,7 @@ class DiscoveryClientAutoConfigurationDefaultTests { @Test void simpleDiscoveryClientShouldBeTheDefault() { - then(this.discoveryClient).isInstanceOf(CompositeDiscoveryClient.class); + then(this.discoveryClient).isInstanceOf(SimpleDiscoveryClient.class); } @EnableAutoConfiguration From f9b8a15887c7ba166fd40becef9e833b4ba4aed2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Tue, 26 Aug 2025 21:53:37 +0800 Subject: [PATCH 055/104] :art: --- .../main/java/infra/cloud/client/CompositeDiscoveryClient.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/today-service-discovery/src/main/java/infra/cloud/client/CompositeDiscoveryClient.java b/today-service-discovery/src/main/java/infra/cloud/client/CompositeDiscoveryClient.java index d172f58..8be803b 100644 --- a/today-service-discovery/src/main/java/infra/cloud/client/CompositeDiscoveryClient.java +++ b/today-service-discovery/src/main/java/infra/cloud/client/CompositeDiscoveryClient.java @@ -22,6 +22,7 @@ import java.util.LinkedHashSet; import java.util.List; +import infra.lang.Assert; import infra.util.CollectionUtils; /** @@ -36,7 +37,7 @@ public class CompositeDiscoveryClient implements DiscoveryClient { private final List discoveryClients; public CompositeDiscoveryClient(List discoveryClients) { -// AnnotationAwareOrderComparator.sort(discoveryClients); + Assert.notEmpty(discoveryClients, "discoveryClients must not be empty"); this.discoveryClients = discoveryClients; } From dbc1fe5c2f39493cf40f0a38bcd349dd2a29d989 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Wed, 1 Oct 2025 16:24:29 +0800 Subject: [PATCH 056/104] :arrow_up: gradle 9.1.0 --- gradle/wrapper/gradle-wrapper.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index d4081da..2e11132 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.1.0-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME From bb6ffb608ca1d95f31af1e6de90f73e344782073 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Wed, 1 Oct 2025 16:26:00 +0800 Subject: [PATCH 057/104] :art: --- .../infra/remoting/util/ByteBufPayload.java | 1 + .../cloud/serialize/MessagePackInput.java | 6 +- .../cloud/serialize/MessagePackOutput.java | 16 ---- .../serialize/RpcResponseSerialization.java | 92 ------------------- .../java/infra/cloud/service}/Metadata.java | 2 +- .../cloud/service/RequestResponseResult.java | 27 ++++-- .../service/ResponseStreamingResult.java | 21 ++++- .../cloud/service/ServiceMethodInvoker.java | 21 ++--- .../service/serialize/RequestSerializer.java | 9 +- .../serialize/ResponseDeserializer.java | 76 +++++++++++++++ .../infra/cloud/provider/InvocableMethod.java | 13 ++- .../cloud/provider/LocalServiceHolder.java | 6 +- .../infra/cloud/provider/RemoteRequest.java | 53 +++++++++++ .../cloud/provider/ResponseSerializer.java | 79 ++++++++++++++++ .../provider/RpcRequestDeserializer.java | 29 +++--- .../cloud/provider/ServiceChannelHandler.java | 19 +++- .../infra/cloud/provider/ServiceObject.java | 43 +++++++++ .../ServiceProviderAutoConfiguration.java | 4 +- 18 files changed, 356 insertions(+), 161 deletions(-) delete mode 100644 today-service-api/src/main/java/infra/cloud/serialize/RpcResponseSerialization.java rename {today-remoting/src/main/java/infra/remoting/protocol => today-service-api/src/main/java/infra/cloud/service}/Metadata.java (96%) rename today-service-api/src/main/java/infra/cloud/serialize/RpcRequestSerialization.java => today-service-client/src/main/java/infra/cloud/service/serialize/RequestSerializer.java (88%) create mode 100644 today-service-client/src/main/java/infra/cloud/service/serialize/ResponseDeserializer.java create mode 100644 today-service-provider/src/main/java/infra/cloud/provider/RemoteRequest.java create mode 100644 today-service-provider/src/main/java/infra/cloud/provider/ResponseSerializer.java create mode 100644 today-service-provider/src/main/java/infra/cloud/provider/ServiceObject.java diff --git a/today-remoting/src/main/java/infra/remoting/util/ByteBufPayload.java b/today-remoting/src/main/java/infra/remoting/util/ByteBufPayload.java index dc4801d..8ded9d1 100644 --- a/today-remoting/src/main/java/infra/remoting/util/ByteBufPayload.java +++ b/today-remoting/src/main/java/infra/remoting/util/ByteBufPayload.java @@ -44,6 +44,7 @@ protected ByteBufPayload newObject(Handle handle) { private ByteBuf data; + @Nullable private ByteBuf metadata; private ByteBufPayload(final Handle handle) { diff --git a/today-service-api/src/main/java/infra/cloud/serialize/MessagePackInput.java b/today-service-api/src/main/java/infra/cloud/serialize/MessagePackInput.java index bc63880..6c77db6 100644 --- a/today-service-api/src/main/java/infra/cloud/serialize/MessagePackInput.java +++ b/today-service-api/src/main/java/infra/cloud/serialize/MessagePackInput.java @@ -638,7 +638,7 @@ public int readBinaryHeader() { * * @throws MessageTypeException when value is not MessagePack Nil type */ - public void unpackNil() { + public void readNull() { byte b = readInt8(); if (b == Code.NIL) { return; @@ -649,8 +649,8 @@ public void unpackNil() { /** * Peeks a Nil byte and reads it if next byte is a nil value. *

          - * The difference from {@link #unpackNil()} is that unpackNil throws an exception if the next byte is not nil value - * while this tryUnpackNil method returns false without changing position. + * The difference from {@link #readNull()} is that readNull throws an exception if the next byte is not nil value + * while this tryReadNull method returns false without changing position. * * @return true if a {@code null} value is read * @throws MessageInsufficientBufferException when the end of file reached diff --git a/today-service-api/src/main/java/infra/cloud/serialize/MessagePackOutput.java b/today-service-api/src/main/java/infra/cloud/serialize/MessagePackOutput.java index 04979a8..7657647 100644 --- a/today-service-api/src/main/java/infra/cloud/serialize/MessagePackOutput.java +++ b/today-service-api/src/main/java/infra/cloud/serialize/MessagePackOutput.java @@ -17,8 +17,6 @@ package infra.cloud.serialize; -import java.nio.charset.CharsetEncoder; -import java.nio.charset.CodingErrorAction; import java.nio.charset.StandardCharsets; import java.time.Instant; import java.util.List; @@ -71,11 +69,6 @@ public class MessagePackOutput implements Output { private final ByteBuf buffer; - /** - * String encoder - */ - private CharsetEncoder encoder; - public MessagePackOutput(ByteBuf buffer) { this.buffer = buffer; } @@ -540,13 +533,4 @@ private void writeTimestamp96(long sec, int nsec) { buffer.writeLong(sec); } - private void prepareEncoder() { - if (encoder == null) { - this.encoder = MessagePack.UTF8.newEncoder() - .onMalformedInput(CodingErrorAction.REPLACE) - .onUnmappableCharacter(CodingErrorAction.REPLACE); - } - encoder.reset(); - } - } diff --git a/today-service-api/src/main/java/infra/cloud/serialize/RpcResponseSerialization.java b/today-service-api/src/main/java/infra/cloud/serialize/RpcResponseSerialization.java deleted file mode 100644 index 4774af3..0000000 --- a/today-service-api/src/main/java/infra/cloud/serialize/RpcResponseSerialization.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright 2021 - 2024 the original author or authors. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] - */ - -package infra.cloud.serialize; - -import java.io.IOException; -import java.util.List; - -import infra.cloud.RpcResponse; -import infra.cloud.service.ServiceMethod; -import io.netty.buffer.ByteBuf; - -/** - * @author 海子 Yang - * @since 1.0 2024/12/20 21:22 - */ -@SuppressWarnings({ "unchecked", "rawtypes" }) -public class RpcResponseSerialization { - - private final List serializations; - - private final ThrowableSerialization throwableSerialization; - - public RpcResponseSerialization(List serializations, ThrowableSerialization throwableSerialization) { - this.serializations = serializations; - this.throwableSerialization = throwableSerialization; - } - - public void serialize(RpcResponse response, ByteBuf payload) throws IOException { - MessagePackOutput output = new MessagePackOutput(payload); - - Throwable exception = response.getException(); - output.writeNullable(exception, (out, throwable) -> { - - }); - - if (exception != null) { - // has error - payload.writeBoolean(true); - throwableSerialization.serialize(exception, payload); - } - else { - ServiceMethod method = response.getMethod(); - - payload.writeBoolean(false); - var serialization = findSerialization(method); - Object result = response.getResult(); - serialization.serialize(method, result, output); - } - } - - public RpcResponse deserialize(ServiceMethod method, ByteBuf body) throws SerializationException { - MessagePackInput input = new MessagePackInput(body); - RpcResponse response = new RpcResponse(); - response.setMethod(method); - boolean hasError = body.readBoolean(); - if (hasError) { - Throwable deserialize = throwableSerialization.deserialize(body); - response.setException(deserialize); - } - else { - var serialization = findSerialization(method); - Object result = serialization.deserialize(method, input); - response.setResult(result); - } - return response; - } - - private ReturnValueSerialization findSerialization(ServiceMethod method) { - for (ReturnValueSerialization serialization : serializations) { - if (serialization.supportsReturnValue(method)) { - return serialization; - } - } - throw new IllegalStateException("ReturnValueSerialization for method %s not found".formatted(method)); - } - -} diff --git a/today-remoting/src/main/java/infra/remoting/protocol/Metadata.java b/today-service-api/src/main/java/infra/cloud/service/Metadata.java similarity index 96% rename from today-remoting/src/main/java/infra/remoting/protocol/Metadata.java rename to today-service-api/src/main/java/infra/cloud/service/Metadata.java index 26f50b8..ac1f436 100644 --- a/today-remoting/src/main/java/infra/remoting/protocol/Metadata.java +++ b/today-service-api/src/main/java/infra/cloud/service/Metadata.java @@ -15,7 +15,7 @@ * along with this program. If not, see [http://www.gnu.org/licenses/] */ -package infra.remoting.protocol; +package infra.cloud.service; /** * @author 海子 Yang diff --git a/today-service-client/src/main/java/infra/cloud/service/RequestResponseResult.java b/today-service-client/src/main/java/infra/cloud/service/RequestResponseResult.java index 346be66..0f81484 100644 --- a/today-service-client/src/main/java/infra/cloud/service/RequestResponseResult.java +++ b/today-service-client/src/main/java/infra/cloud/service/RequestResponseResult.java @@ -17,29 +17,42 @@ package infra.cloud.service; -import org.reactivestreams.Publisher; +import java.util.function.Function; +import infra.cloud.service.serialize.ResponseDeserializer; import infra.lang.Nullable; import infra.remoting.Payload; import infra.util.concurrent.Future; +import infra.util.concurrent.PublisherFuture; import reactor.core.publisher.Mono; /** * @author 海子 Yang * @since 1.0 2025/8/15 19:55 */ -class RequestResponseResult extends AbstractInvocationResult { +final class RequestResponseResult extends AbstractInvocationResult implements Function { private final Mono payloadMono; - RequestResponseResult(Mono payloadMono) { + private final ServiceInterfaceMethod method; + + private final ResponseDeserializer responseDeserializer; + + RequestResponseResult(ServiceInterfaceMethod method, Mono payloadMono, ResponseDeserializer responseDeserializer) { this.payloadMono = payloadMono; + this.method = method; + this.responseDeserializer = responseDeserializer; } @Nullable @Override public Object getValue() { - return payloadMono.map(this::deserialize).block(); + return publisher().block(); + } + + @Override + public Object apply(Payload payload) { + return responseDeserializer.deserialize(method, payload.data()); } @Override @@ -69,12 +82,12 @@ public boolean isStreaming() { @Override public Future future() { - return null; + return PublisherFuture.of(publisher()); } @Override - public Publisher publisher() { - return null; + public Mono publisher() { + return payloadMono.map(this); } } diff --git a/today-service-client/src/main/java/infra/cloud/service/ResponseStreamingResult.java b/today-service-client/src/main/java/infra/cloud/service/ResponseStreamingResult.java index b9dcb8b..4c22f99 100644 --- a/today-service-client/src/main/java/infra/cloud/service/ResponseStreamingResult.java +++ b/today-service-client/src/main/java/infra/cloud/service/ResponseStreamingResult.java @@ -19,6 +19,9 @@ import org.reactivestreams.Publisher; +import java.util.function.Function; + +import infra.cloud.service.serialize.ResponseDeserializer; import infra.remoting.Payload; import infra.util.concurrent.Future; import reactor.core.publisher.Flux; @@ -27,12 +30,18 @@ * @author 海子 Yang * @since 1.0 2025/8/15 20:34 */ -class ResponseStreamingResult extends AbstractInvocationResult { +final class ResponseStreamingResult extends AbstractInvocationResult implements Function { private final Flux payloadFlux; - public ResponseStreamingResult(Flux payloadFlux) { + private final ServiceInterfaceMethod method; + + private final ResponseDeserializer responseDeserializer; + + public ResponseStreamingResult(ServiceInterfaceMethod method, Flux payloadFlux, ResponseDeserializer responseDeserializer) { + this.method = method; this.payloadFlux = payloadFlux; + this.responseDeserializer = responseDeserializer; } @Override @@ -72,6 +81,12 @@ public Future future() { @Override public Publisher publisher() { - return null; + return payloadFlux.map(this); } + + @Override + public Object apply(Payload payload) { + return responseDeserializer.deserialize(method, payload.data()); + } + } diff --git a/today-service-client/src/main/java/infra/cloud/service/ServiceMethodInvoker.java b/today-service-client/src/main/java/infra/cloud/service/ServiceMethodInvoker.java index 48edb9a..1c3cdb2 100644 --- a/today-service-client/src/main/java/infra/cloud/service/ServiceMethodInvoker.java +++ b/today-service-client/src/main/java/infra/cloud/service/ServiceMethodInvoker.java @@ -22,8 +22,8 @@ import org.reactivestreams.Subscription; import infra.cloud.RpcRequest; -import infra.cloud.serialize.RpcRequestSerialization; -import infra.cloud.serialize.RpcResponseSerialization; +import infra.cloud.service.serialize.RequestSerializer; +import infra.cloud.service.serialize.ResponseDeserializer; import infra.lang.Nullable; import infra.remoting.Payload; import infra.remoting.RemotingOperations; @@ -52,9 +52,9 @@ public class ServiceMethodInvoker implements ServiceInvoker { private final ByteBufAllocator allocator; - private RpcRequestSerialization requestSerialization; + private RequestSerializer requestSerializer; - private RpcResponseSerialization responseSerialization; + private ResponseDeserializer responseDeserializer; ServiceMethodInvoker(ServiceInterfaceMetadata metadata, ClientInterceptor[] interceptors, RemotingOperationsProvider remotingOperationsProvider, ByteBufAllocator allocator) { @@ -82,8 +82,8 @@ protected InvocationResult invokeRemoting() { RemotingOperations operations = remotingOperationsProvider.getRemotingOperations(getServiceMethod()); return switch (getType()) { case FIRE_AND_FORGET -> new FireAndForgetResult(operations.fireAndForget(createMonoPayload())); - case REQUEST_RESPONSE -> new RequestResponseResult(operations.requestResponse(createMonoPayload())); - case RESPONSE_STREAMING -> new ResponseStreamingResult(operations.requestStream(createMonoPayload())); + case REQUEST_RESPONSE -> new RequestResponseResult(getServiceMethod(), operations.requestResponse(createMonoPayload()), responseDeserializer); + case RESPONSE_STREAMING -> new ResponseStreamingResult(getServiceMethod(), operations.requestStream(createMonoPayload()), responseDeserializer); case DUPLEX_STREAMING -> new DuplexStreamingResult(operations.requestChannel(createChannelPayload())); }; } @@ -96,7 +96,7 @@ private Mono createMonoPayload() { ByteBuf buffer = allocator.ioBuffer(); Payload payload = ByteBufPayload.create(buffer); - requestSerialization.serialize(request, buffer); + requestSerializer.serialize(request, buffer); return Mono.just(payload); }); } @@ -105,16 +105,11 @@ private Mono createMonoPayload() { private Publisher createChannelPayload() { Flux flux = (Flux) getArguments()[0]; - return null; + return Flux.empty(); } } - private Object deserialize(Payload payload) { -// responseSerialization.deserialize(); - return null; - } - class InvocationResult0 extends AbstractInvocationResult implements Publisher, Subscriber, FutureListener>, Subscription { diff --git a/today-service-api/src/main/java/infra/cloud/serialize/RpcRequestSerialization.java b/today-service-client/src/main/java/infra/cloud/service/serialize/RequestSerializer.java similarity index 88% rename from today-service-api/src/main/java/infra/cloud/serialize/RpcRequestSerialization.java rename to today-service-client/src/main/java/infra/cloud/service/serialize/RequestSerializer.java index 3a93772..6c371e9 100644 --- a/today-service-api/src/main/java/infra/cloud/serialize/RpcRequestSerialization.java +++ b/today-service-client/src/main/java/infra/cloud/service/serialize/RequestSerializer.java @@ -15,11 +15,14 @@ * along with this program. If not, see [http://www.gnu.org/licenses/] */ -package infra.cloud.serialize; +package infra.cloud.service.serialize; import java.util.List; import infra.cloud.RpcRequest; +import infra.cloud.serialize.MessagePackOutput; +import infra.cloud.serialize.Output; +import infra.cloud.serialize.RpcArgumentSerialization; import infra.cloud.service.ServiceMethod; import infra.core.MethodParameter; import io.netty.buffer.ByteBuf; @@ -29,11 +32,11 @@ * @since 1.0 2024/12/20 15:59 */ @SuppressWarnings({ "unchecked", "rawtypes" }) -public class RpcRequestSerialization { +public class RequestSerializer { private final List argumentSerializations; - public RpcRequestSerialization(List argumentSerializations) { + public RequestSerializer(List argumentSerializations) { this.argumentSerializations = argumentSerializations; } diff --git a/today-service-client/src/main/java/infra/cloud/service/serialize/ResponseDeserializer.java b/today-service-client/src/main/java/infra/cloud/service/serialize/ResponseDeserializer.java new file mode 100644 index 0000000..2fadb78 --- /dev/null +++ b/today-service-client/src/main/java/infra/cloud/service/serialize/ResponseDeserializer.java @@ -0,0 +1,76 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.service.serialize; + +import java.util.List; + +import infra.cloud.RpcResponse; +import infra.cloud.serialize.MessagePackInput; +import infra.cloud.serialize.ReturnValueDeserializer; +import infra.cloud.serialize.SerializationException; +import infra.cloud.serialize.ThrowableSerialization; +import infra.cloud.service.ServiceInterfaceMethod; +import infra.cloud.service.ServiceMethod; +import io.netty.buffer.ByteBuf; + +/** + * @author 海子 Yang + * @since 1.0 2024/12/20 21:22 + */ +@SuppressWarnings({ "rawtypes" }) +public class ResponseDeserializer { + + private final List serializations; + + private final ThrowableSerialization throwableSerialization; + + public ResponseDeserializer(List serializations, ThrowableSerialization throwableSerialization) { + this.serializations = serializations; + this.throwableSerialization = throwableSerialization; + } + + public RpcResponse deserialize(ServiceInterfaceMethod method, ByteBuf body) throws SerializationException { + MessagePackInput input = new MessagePackInput(body); + RpcResponse response = new RpcResponse(); + response.setMethod(method); + + boolean hasError = body.readBoolean(); + if (hasError) { + Throwable deserialize = throwableSerialization.deserialize(body); + response.setException(deserialize); + } + else { + Object result = input.readNullable(in -> { + var deserializer = findDeserializer(method); + return deserializer.deserialize(method, input); + }); + response.setResult(result); + } + return response; + } + + private ReturnValueDeserializer findDeserializer(ServiceMethod method) { + for (ReturnValueDeserializer deserializer : serializations) { + if (deserializer.supportsReturnValue(method)) { + return deserializer; + } + } + throw new IllegalStateException("ReturnValueDeserializer for method %s not found".formatted(method)); + } + +} diff --git a/today-service-provider/src/main/java/infra/cloud/provider/InvocableMethod.java b/today-service-provider/src/main/java/infra/cloud/provider/InvocableMethod.java index 35385f5..b1cc0bb 100644 --- a/today-service-provider/src/main/java/infra/cloud/provider/InvocableMethod.java +++ b/today-service-provider/src/main/java/infra/cloud/provider/InvocableMethod.java @@ -21,6 +21,7 @@ import infra.cloud.service.ServiceInterfaceMetadata; import infra.cloud.service.ServiceMethod; +import infra.lang.Nullable; import infra.reflect.MethodInvoker; /** @@ -29,15 +30,19 @@ */ public class InvocableMethod extends ServiceMethod { + private final Object instance; + private final MethodInvoker invoker; - public InvocableMethod(ServiceInterfaceMetadata metadata, Class serviceInterface, Method method, MethodInvoker invoker) { - super(metadata.getServiceMetadata(), serviceInterface, method); + public InvocableMethod(ServiceInterfaceMetadata metadata, ServiceObject service, Method method, MethodInvoker invoker) { + super(metadata.getServiceMetadata(), service.getInterface(), method); this.invoker = invoker; + this.instance = service.getInstance(); } - public Object invokeAndHandle(Object serviceInstance, Object[] args) throws Throwable { - return invoker.invoke(serviceInstance, args); + @Nullable + public Object invoke(Object[] args) { + return invoker.invoke(instance, args); } } diff --git a/today-service-provider/src/main/java/infra/cloud/provider/LocalServiceHolder.java b/today-service-provider/src/main/java/infra/cloud/provider/LocalServiceHolder.java index c13742e..dcc8b5e 100644 --- a/today-service-provider/src/main/java/infra/cloud/provider/LocalServiceHolder.java +++ b/today-service-provider/src/main/java/infra/cloud/provider/LocalServiceHolder.java @@ -41,7 +41,7 @@ public class LocalServiceHolder extends ApplicationObjectSupport implements Smar private final HashMap, Object> localServices = new HashMap<>(); - private final HashMap> classNameMap = new HashMap<>(); + private final HashMap classNameMap = new HashMap<>(); private final MultiValueMap> serviceMap = MultiValueMap.forLinkedHashMap(); @@ -59,7 +59,7 @@ public T getService(Class serviceInterface) { } @Nullable - public Class getServiceInterface(String serviceClass) { + public ServiceObject getServiceInterface(String serviceClass) { return classNameMap.get(serviceClass); } @@ -90,7 +90,7 @@ public void afterSingletonsInstantiated() { ServiceMetadata serviceMetadata = serviceMetadataProvider.getMetadata(anInterface); serviceMap.add(serviceMetadata, anInterface); - classNameMap.put(interfaceName, anInterface); + classNameMap.put(interfaceName, new ServiceObject(anInterface, service)); logger.info("Adding service: [{}] to interface: [{}]", service, interfaceName); } } diff --git a/today-service-provider/src/main/java/infra/cloud/provider/RemoteRequest.java b/today-service-provider/src/main/java/infra/cloud/provider/RemoteRequest.java new file mode 100644 index 0000000..e1dde95 --- /dev/null +++ b/today-service-provider/src/main/java/infra/cloud/provider/RemoteRequest.java @@ -0,0 +1,53 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.provider; + +import infra.lang.Nullable; + +/** + * @author 海子 Yang + * @since 1.0 2025/8/27 22:11 + */ +public class RemoteRequest { + + private final InvocableMethod method; + + private final Object[] args; + + private final ServiceObject serviceObject; + + public RemoteRequest(InvocableMethod method, Object[] args, ServiceObject serviceObject) { + this.method = method; + this.args = args; + this.serviceObject = serviceObject; + } + + @Nullable + public Object invoke() throws Throwable { + return method.invoke(args); + } + + public InvocableMethod getMethod() { + return method; + } + + public ServiceObject getServiceInterface() { + return serviceObject; + } + +} diff --git a/today-service-provider/src/main/java/infra/cloud/provider/ResponseSerializer.java b/today-service-provider/src/main/java/infra/cloud/provider/ResponseSerializer.java new file mode 100644 index 0000000..b235e5a --- /dev/null +++ b/today-service-provider/src/main/java/infra/cloud/provider/ResponseSerializer.java @@ -0,0 +1,79 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.provider; + +import java.util.List; + +import infra.cloud.serialize.MessagePackOutput; +import infra.cloud.serialize.Output; +import infra.cloud.serialize.ReturnValueSerializer; +import infra.cloud.service.ServiceMethod; +import infra.lang.Nullable; +import infra.remoting.Payload; +import infra.remoting.util.ByteBufPayload; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufAllocator; +import reactor.core.publisher.Mono; + +/** + * @author 海子 Yang + * @since 1.0 2025/8/31 16:21 + */ +public class ResponseSerializer { + + private final List> returnValueSerializers; + + private final ByteBufAllocator allocator = ByteBufAllocator.DEFAULT; + + public ResponseSerializer(List> returnValueSerializers) { + this.returnValueSerializers = returnValueSerializers; + } + + @SuppressWarnings({ "rawtypes", "unchecked" }) + public Mono serialize(RemoteRequest request, @Nullable Object result) { + ByteBuf buffer = allocator.ioBuffer(); + Output output = new MessagePackOutput(buffer); + + output.writeNullable(result, (out, v) -> { + InvocableMethod invocableMethod = request.getMethod(); + ReturnValueSerializer serializer = findSerializer(invocableMethod); + serializer.serialize(invocableMethod, v, out); + }); + + Payload payload = ByteBufPayload.create(buffer); + return Mono.just(payload); + } + + public Mono serialize(RemoteRequest request, Throwable throwable) { + ByteBuf buffer = allocator.ioBuffer(); + + Payload payload = ByteBufPayload.create(buffer); + return Mono.just(payload); + } + + @SuppressWarnings("rawtypes") + private ReturnValueSerializer findSerializer(ServiceMethod method) { + for (ReturnValueSerializer serializer : returnValueSerializers) { + if (serializer.supportsReturnValue(method)) { + return serializer; + } + } + throw new IllegalStateException("ReturnValueSerialization for method %s not found".formatted(method)); + } + +} diff --git a/today-service-provider/src/main/java/infra/cloud/provider/RpcRequestDeserializer.java b/today-service-provider/src/main/java/infra/cloud/provider/RpcRequestDeserializer.java index 3a2e685..cf093a3 100644 --- a/today-service-provider/src/main/java/infra/cloud/provider/RpcRequestDeserializer.java +++ b/today-service-provider/src/main/java/infra/cloud/provider/RpcRequestDeserializer.java @@ -22,6 +22,7 @@ import java.util.Objects; import infra.cloud.RpcRequest; +import infra.cloud.serialize.Input; import infra.cloud.serialize.MessagePackInput; import infra.cloud.serialize.RpcArgumentSerialization; import infra.cloud.serialize.SerializationException; @@ -29,6 +30,7 @@ import infra.cloud.service.ServiceInterfaceMetadataProvider; import infra.core.MethodParameter; import infra.lang.Assert; +import infra.lang.Nullable; import infra.reflect.MethodInvoker; import infra.util.MapCache; import io.netty.buffer.ByteBuf; @@ -56,17 +58,18 @@ public RpcRequestDeserializer(List argumentSerializati this.localServiceHolder = localServiceHolder; } - public RpcRequest deserialize(ByteBuf payload) throws SerializationException { + public RemoteRequest deserialize(ByteBuf payload) throws SerializationException { MessagePackInput input = new MessagePackInput(payload); RpcRequest request = new RpcRequest(); request.readFrom(input); - String serviceClass = request.getServiceClass(); - Class serviceInterface = localServiceHolder.getServiceInterface(serviceClass); - Assert.state(serviceInterface != null, "service interface not found"); - InvocableMethod method = methodMapCache.get(new MethodKey(serviceClass, request.getMethodName(), request.getParamTypes()), serviceInterface); + String serviceClass = input.readString(); + String methodName = input.readString(); + String[] paramTypes = input.read(String.class, Input::readString); - request.setMethod(method); + var serviceInterface = localServiceHolder.getServiceInterface(serviceClass); + Assert.state(serviceInterface != null, "service interface not found"); + InvocableMethod method = methodMapCache.get(new MethodKey(serviceClass, methodName, paramTypes), serviceInterface); MethodParameter[] parameters = method.getParameters(); Object[] args = new Object[parameters.length]; @@ -77,8 +80,7 @@ public RpcRequest deserialize(ByteBuf payload) throws SerializationException { args[idx++] = serialization.deserialize(parameter, input); } - request.setArguments(args); - return request; + return new RemoteRequest(method, args, serviceInterface); } private RpcArgumentSerialization findArgumentSerialization(MethodParameter parameter) { @@ -90,19 +92,20 @@ private RpcArgumentSerialization findArgumentSerialization(MethodParameter param throw new IllegalStateException("RpcArgumentSerialization for parameter %s not found".formatted(parameter)); } - private final class MethodMapCache extends MapCache> { + private final class MethodMapCache extends MapCache { @Override - protected InvocableMethod createValue(MethodKey key, Class serviceInterface) { - Method methodToUse = getMethod(key, serviceInterface); + protected InvocableMethod createValue(MethodKey key, ServiceObject serviceObject) { + Method methodToUse = getMethod(key, serviceObject.getInterface()); if (methodToUse == null) { throw new IllegalStateException("No method found for method: " + key.method); } MethodInvoker methodInvoker = MethodInvoker.forMethod(methodToUse); - ServiceInterfaceMetadata metadata = metadataProvider.getMetadata(serviceInterface); - return new InvocableMethod(metadata, serviceInterface, methodToUse, methodInvoker); + ServiceInterfaceMetadata metadata = metadataProvider.getMetadata(serviceObject.getInterface()); + return new InvocableMethod(metadata, serviceObject, methodToUse, methodInvoker); } + @Nullable private static Method getMethod(MethodKey key, Class serviceInterface) { String method = key.method; String[] paramTypes = key.paramTypes; diff --git a/today-service-provider/src/main/java/infra/cloud/provider/ServiceChannelHandler.java b/today-service-provider/src/main/java/infra/cloud/provider/ServiceChannelHandler.java index 0cebb71..d84b24d 100644 --- a/today-service-provider/src/main/java/infra/cloud/provider/ServiceChannelHandler.java +++ b/today-service-provider/src/main/java/infra/cloud/provider/ServiceChannelHandler.java @@ -30,9 +30,26 @@ */ public class ServiceChannelHandler implements Channel { + private RpcRequestDeserializer requestDeserializer; + + private ResponseSerializer responseSerializer; + + private final LocalServiceHolder localServiceHolder; + + public ServiceChannelHandler(LocalServiceHolder localServiceHolder) { + this.localServiceHolder = localServiceHolder; + } + @Override public Mono requestResponse(Payload payload) { - return Channel.super.requestResponse(payload); + RemoteRequest request = requestDeserializer.deserialize(payload.data()); + try { + Object result = request.invoke(); + return responseSerializer.serialize(request, result); + } + catch (Throwable e) { + return responseSerializer.serialize(request, e); + } } @Override diff --git a/today-service-provider/src/main/java/infra/cloud/provider/ServiceObject.java b/today-service-provider/src/main/java/infra/cloud/provider/ServiceObject.java new file mode 100644 index 0000000..b25e93f --- /dev/null +++ b/today-service-provider/src/main/java/infra/cloud/provider/ServiceObject.java @@ -0,0 +1,43 @@ +/* + * Copyright 2021 - 2024 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/] + */ + +package infra.cloud.provider; + +/** + * @author 海子 Yang + * @since 1.0 2025/8/26 22:07 + */ +public class ServiceObject { + + private final Class serviceInterface; + + private final Object instance; + + public ServiceObject(Class serviceInterface, Object instance) { + this.serviceInterface = serviceInterface; + this.instance = instance; + } + + public Class getInterface() { + return serviceInterface; + } + + public Object getInstance() { + return instance; + } + +} diff --git a/today-service-provider/src/main/java/infra/cloud/provider/annotation/config/ServiceProviderAutoConfiguration.java b/today-service-provider/src/main/java/infra/cloud/provider/annotation/config/ServiceProviderAutoConfiguration.java index 76eb02e..9df3412 100644 --- a/today-service-provider/src/main/java/infra/cloud/provider/annotation/config/ServiceProviderAutoConfiguration.java +++ b/today-service-provider/src/main/java/infra/cloud/provider/annotation/config/ServiceProviderAutoConfiguration.java @@ -77,8 +77,8 @@ public static InetService inetService(InetProperties inetProperties) { } @Component - public static ServiceChannelHandler serviceChannelHandler() { - return new ServiceChannelHandler(); + public static ServiceChannelHandler serviceChannelHandler(LocalServiceHolder localServiceHolder) { + return new ServiceChannelHandler(localServiceHolder); } @Component From 59cf79d0cde3cfa161ac876ceb83c0be61409b34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Wed, 1 Oct 2025 16:47:38 +0800 Subject: [PATCH 058/104] :art: --- .../java/infra/config/DynamicProperty.java | 3 ++- ...micPropertyDependencyResolvingStrategy.java | 3 ++- .../java/infra/cloud/RemotingException.java | 4 ++-- .../cloud/client/DefaultServiceInstance.java | 3 ++- .../main/java/infra/cloud/package-info.java | 2 -- .../micrometer/observation/ChannelContext.java | 3 ++- .../ObservationRequesterChannel.java | 4 ++-- .../ObservationResponderChannel.java | 4 ++-- .../micrometer/observation/PayloadUtils.java | 1 - .../remoting/micrometer/package-info.java | 1 - .../integration/IntegrationTests.java | 2 +- .../integration/TcpIntegrationTests.java | 2 +- .../transport/local/LocalServerTransport.java | 3 ++- .../remoting/transport/local/package-info.java | 2 -- .../transport/netty/client/package-info.java | 1 - .../remoting/transport/netty/package-info.java | 2 -- .../transport/netty/server/package-info.java | 1 - .../transport/tcp/TCPServerTransport.java | 3 ++- .../remoting/transport/tcp/package-info.java | 2 -- .../remoting/integration/FragmentTests.java | 4 ++-- .../netty/TcpResumableTransportTests.java | 2 +- ...sumableWithFragmentationTransportTests.java | 2 +- .../netty/TcpSecureTransportTests.java | 8 ++++---- .../transport/netty/TcpTransportTests.java | 2 +- .../infra/remoting/ConnectionSetupPayload.java | 3 ++- .../infra/remoting/ProtocolErrorException.java | 2 +- .../java/infra/remoting/RemotingException.java | 4 ++-- .../infra/remoting/core/ChannelConnector.java | 3 ++- .../infra/remoting/core/ChannelSupport.java | 3 ++- .../remoting/core/DefaultRemotingClient.java | 2 +- .../core/FireAndForgetRequesterMono.java | 2 +- .../core/FireAndForgetResponderSubscriber.java | 2 +- .../remoting/core/FragmentationUtils.java | 3 ++- .../core/MetadataPushRequesterMono.java | 3 ++- .../infra/remoting/core/ReconnectMono.java | 2 +- .../infra/remoting/core/RemotingServer.java | 3 ++- .../core/RequestChannelRequesterFlux.java | 2 +- .../core/RequestResponseRequesterMono.java | 2 +- .../RequestResponseResponderSubscriber.java | 2 +- .../core/RequestStreamRequesterFlux.java | 2 +- .../infra/remoting/core/RequesterChannel.java | 2 +- .../remoting/core/RequesterFrameHandler.java | 3 ++- .../infra/remoting/core/ResolvingOperator.java | 2 +- .../infra/remoting/core/ResponderChannel.java | 2 +- .../remoting/core/ResponderLeaseTracker.java | 3 ++- .../main/java/infra/remoting/core/Resume.java | 3 ++- .../core/SlowFireAndForgetRequesterMono.java | 2 +- .../java/infra/remoting/core/package-info.java | 2 -- .../error/ApplicationErrorException.java | 3 ++- .../remoting/error/CanceledException.java | 3 ++- .../error/ConnectionCloseException.java | 3 ++- .../error/ConnectionErrorException.java | 3 ++- .../error/CustomProtocolException.java | 3 ++- .../infra/remoting/error/InvalidException.java | 3 ++- .../remoting/error/InvalidSetupException.java | 3 ++- .../remoting/error/RejectedException.java | 3 ++- .../error/RejectedResumeException.java | 3 ++- .../remoting/error/RejectedSetupException.java | 3 ++- .../infra/remoting/error/SetupException.java | 3 ++- .../error/UnsupportedSetupException.java | 3 ++- .../infra/remoting/error/package-info.java | 1 - .../remoting/frame/ExtensionFrameCodec.java | 3 ++- .../infra/remoting/frame/FrameBodyCodec.java | 3 ++- .../remoting/frame/GenericFrameCodec.java | 3 ++- .../infra/remoting/frame/LeaseFrameCodec.java | 3 ++- .../remoting/frame/PayloadFrameCodec.java | 3 ++- .../frame/RequestChannelFrameCodec.java | 3 ++- .../frame/RequestFireAndForgetFrameCodec.java | 3 ++- .../frame/RequestResponseFrameCodec.java | 3 ++- .../frame/RequestStreamFrameCodec.java | 3 ++- .../infra/remoting/frame/SetupFrameCodec.java | 3 ++- .../remoting/frame/decoder/package-info.java | 1 - .../infra/remoting/frame/package-info.java | 1 - .../remoting/internal/UnboundedProcessor.java | 2 +- .../infra/remoting/internal/package-info.java | 2 -- .../infra/remoting/keepalive/package-info.java | 2 -- .../java/infra/remoting/lb/ChannelPool.java | 2 +- .../remoting/lb/FluxDeferredResolution.java | 2 +- .../infra/remoting/lb/Int2LongHashMap.java | 4 ++-- .../remoting/lb/LoadBalanceRemotingClient.java | 2 +- .../remoting/lb/MonoDeferredResolution.java | 2 +- .../infra/remoting/lb/ResolvingOperator.java | 3 ++- .../lb/WeightedLoadBalanceStrategy.java | 3 ++- .../lb/WeightedStatsRequestInterceptor.java | 3 ++- .../java/infra/remoting/lb/package-info.java | 2 -- .../main/java/infra/remoting/lease/Lease.java | 3 ++- .../infra/remoting/lease/package-info.java | 1 - .../main/java/infra/remoting/package-info.java | 2 -- .../plugins/CompositeRequestInterceptor.java | 3 ++- .../InitializingInterceptorRegistry.java | 3 ++- .../remoting/plugins/RequestInterceptor.java | 3 ++- .../infra/remoting/plugins/package-info.java | 1 - .../infra/remoting/protocol/ProtocolFrame.java | 3 ++- .../protocol/ProtocolParsingException.java | 2 +- .../resume/InMemoryResumableFramesStore.java | 2 +- .../remoting/resume/ResumableConnection.java | 2 +- .../infra/remoting/resume/SessionManager.java | 3 ++- .../infra/remoting/resume/package-info.java | 1 - .../infra/remoting/transport/package-info.java | 1 - .../infra/remoting/util/ByteBufPayload.java | 3 ++- .../infra/remoting/util/DefaultPayload.java | 3 ++- .../java/infra/remoting/util/package-info.java | 1 - .../test/java/infra/remoting/FrameAssert.java | 10 +++++----- .../java/infra/remoting/PayloadAssert.java | 6 +++--- .../remoting/core/AbstractChannelRule.java | 2 +- .../remoting/core/ChannelConnectorTests.java | 10 +++++----- .../infra/remoting/core/ChannelLeaseTests.java | 12 ++++++------ .../remoting/core/ChannelReconnectTests.java | 2 +- .../java/infra/remoting/core/ChannelTests.java | 6 +++--- .../core/ClientServerInputMultiplexerTest.java | 6 +++--- .../core/ConnectionSetupPayloadTest.java | 6 +++--- .../core/DefaultChannelClientTests.java | 12 ++++++------ .../remoting/core/RemotingServerTests.java | 6 +++--- .../core/RequestRequesterChannelFluxTests.java | 8 ++++---- ...RequestResponderChannelSubscriberTests.java | 8 ++++---- .../core/RequesterChannelSubscribersTests.java | 8 ++++---- .../core/RequesterChannelTerminationTests.java | 2 +- .../remoting/core/RequesterChannelTests.java | 18 +++++++++--------- .../core/RequesterOperatorsRacingTests.java | 6 +++--- .../remoting/core/ResponderChannelTests.java | 14 +++++++------- .../core/ResponderOperatorsCommonTests.java | 4 ++-- .../remoting/core/SetupRejectionTests.java | 10 +++++----- .../remoting/core/TestChannelSupport.java | 12 ++++++------ .../remoting/frame/ErrorFrameCodecTests.java | 2 +- .../remoting/frame/PayloadFlyweightTests.java | 4 ++-- .../remoting/frame/SetupFrameCodecTests.java | 4 ++-- .../internal/UnboundedProcessorTests.java | 6 +++--- .../infra/remoting/lb/LoadbalanceTests.java | 4 ++-- .../lb/RoundRobinLoadBalanceStrategyTests.java | 2 +- .../lb/WeightedLoadBalanceStrategyTests.java | 2 +- .../plugins/RequestInterceptorTests.java | 10 +++++----- .../plugins/TestRequestInterceptor.java | 2 +- .../infra/remoting/protocol/MetadataTests.java | 2 -- .../resume/InMemoryResumeStoreTests.java | 6 +++--- .../resume/ServerChannelSessionTests.java | 6 +++--- .../remoting/test/util/LocalConnection.java | 4 ++-- .../infra/remoting/test/util/MockChannel.java | 2 +- .../test/util/TestServerTransport.java | 2 +- .../remoting/util/ByteBufPayloadTests.java | 2 +- .../remoting/util/DefaultPayloadTests.java | 4 ++-- .../infra/remoting/test/ClientSetupRule.java | 2 +- .../java/infra/remoting/test/PingClient.java | 2 +- .../java/infra/remoting/test/PingHandler.java | 4 ++-- .../java/infra/remoting/test/TestChannel.java | 2 +- .../infra/remoting/test/TestConnection.java | 6 +++--- .../java/infra/remoting/test/TestFrames.java | 6 +++--- .../infra/remoting/test/TransportTest.java | 4 ++-- .../java/infra/remoting/test/package-info.java | 1 - .../src/main/java/infra/cloud/RpcResponse.java | 3 ++- .../cloud/serialize/MessagePackInput.java | 3 ++- .../cloud/serialize/MessagePackOutput.java | 3 ++- .../ProtobufArgumentSerialization.java | 3 ++- .../serialize/RpcArgumentSerialization.java | 3 ++- .../SimpleValueArgumentSerialization.java | 3 ++- .../infra/cloud/serialize/package-info.java | 2 -- .../infra/cloud/service/InvocationResult.java | 2 +- .../infra/cloud/service/ServiceMethod.java | 3 ++- .../java/infra/cloud/service/package-info.java | 2 -- .../infra/cloud/ServiceTimeoutException.java | 2 +- .../ServiceDependencyResolvingStrategy.java | 3 ++- .../service/DefaultServiceProxyFactory.java | 3 ++- .../cloud/service/RequestResponseResult.java | 3 ++- .../cloud/service/ReturnValueResolver.java | 2 +- .../cloud/service/ServiceInterfaceMethod.java | 4 ++-- .../cloud/service/ServiceMethodInvoker.java | 2 +- .../service/ServiceInvokerFactoryTests.java | 6 ------ .../infra/cloud/provider/InvocableMethod.java | 3 ++- .../cloud/provider/LocalServiceHolder.java | 3 ++- .../infra/cloud/provider/RemoteRequest.java | 2 +- .../cloud/provider/ResponseSerializer.java | 3 ++- .../cloud/provider/RpcRequestDeserializer.java | 3 ++- .../cloud/provider/ServiceProviderServer.java | 3 ++- .../provider/ServiceServerProperties.java | 3 ++- .../ServiceProviderAutoConfiguration.java | 3 ++- .../infra/cloud/provider/package-info.java | 2 -- .../provider/LocalServiceHolderTests.java | 2 -- .../ServiceRegisterFailedException.java | 3 ++- ...toServiceRegistrationAutoConfiguration.java | 3 ++- .../server/ServiceNotFoundException.java | 3 ++- .../main/java/infra/cloud/serialize/Input.java | 4 ++-- .../java/infra/cloud/serialize/Output.java | 4 ++-- .../serialize/SerializationException.java | 2 +- .../format/MessageFormatException.java | 2 +- .../MessageNeverUsedFormatException.java | 2 +- .../cloud/serialize/format/MessagePack.java | 2 +- .../serialize/format/MessagePackException.java | 3 ++- .../cloud/serialize/format/MessagePacker.java | 3 ++- .../serialize/format/MessageTypeException.java | 2 +- .../format/buffer/MessageBufferInput.java | 4 ++-- .../cloud/serialize/format/package-info.java | 2 -- 190 files changed, 328 insertions(+), 307 deletions(-) diff --git a/today-cloud-config-server/src/main/java/infra/config/DynamicProperty.java b/today-cloud-config-server/src/main/java/infra/config/DynamicProperty.java index 8b9efac..80bd016 100644 --- a/today-cloud-config-server/src/main/java/infra/config/DynamicProperty.java +++ b/today-cloud-config-server/src/main/java/infra/config/DynamicProperty.java @@ -17,10 +17,11 @@ package infra.config; +import org.jspecify.annotations.Nullable; + import java.util.function.Supplier; import infra.lang.Assert; -import infra.lang.Nullable; /** * @author Harry Yang diff --git a/today-cloud-config-server/src/main/java/infra/config/DynamicPropertyDependencyResolvingStrategy.java b/today-cloud-config-server/src/main/java/infra/config/DynamicPropertyDependencyResolvingStrategy.java index ed9521c..2aab4f7 100644 --- a/today-cloud-config-server/src/main/java/infra/config/DynamicPropertyDependencyResolvingStrategy.java +++ b/today-cloud-config-server/src/main/java/infra/config/DynamicPropertyDependencyResolvingStrategy.java @@ -17,10 +17,11 @@ package infra.config; +import org.jspecify.annotations.Nullable; + import infra.beans.factory.config.DependencyDescriptor; import infra.beans.factory.support.DependencyResolvingStrategy; import infra.context.BootstrapContext; -import infra.lang.Nullable; /** * for DynamicProperty diff --git a/today-cloud-core/src/main/java/infra/cloud/RemotingException.java b/today-cloud-core/src/main/java/infra/cloud/RemotingException.java index 1ef66c7..15be122 100644 --- a/today-cloud-core/src/main/java/infra/cloud/RemotingException.java +++ b/today-cloud-core/src/main/java/infra/cloud/RemotingException.java @@ -17,9 +17,9 @@ package infra.cloud; -import java.io.Serial; +import org.jspecify.annotations.Nullable; -import infra.lang.Nullable; +import java.io.Serial; /** * Exception for default remoting problems diff --git a/today-cloud-core/src/main/java/infra/cloud/client/DefaultServiceInstance.java b/today-cloud-core/src/main/java/infra/cloud/client/DefaultServiceInstance.java index 5ed6bce..847759b 100644 --- a/today-cloud-core/src/main/java/infra/cloud/client/DefaultServiceInstance.java +++ b/today-cloud-core/src/main/java/infra/cloud/client/DefaultServiceInstance.java @@ -17,13 +17,14 @@ package infra.cloud.client; +import org.jspecify.annotations.Nullable; + import java.net.URI; import java.util.LinkedHashMap; import java.util.Map; import java.util.Objects; import infra.core.style.ToStringBuilder; -import infra.lang.Nullable; /** * Default implementation of {@link ServiceInstance}. diff --git a/today-cloud-core/src/main/java/infra/cloud/package-info.java b/today-cloud-core/src/main/java/infra/cloud/package-info.java index 2590f42..3426815 100644 --- a/today-cloud-core/src/main/java/infra/cloud/package-info.java +++ b/today-cloud-core/src/main/java/infra/cloud/package-info.java @@ -19,5 +19,3 @@ @NonNullFields package infra.cloud; -import infra.lang.NonNullApi; -import infra.lang.NonNullFields; \ No newline at end of file diff --git a/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/ChannelContext.java b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/ChannelContext.java index 0f1832c..7d77d40 100644 --- a/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/ChannelContext.java +++ b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/ChannelContext.java @@ -17,7 +17,8 @@ package infra.remoting.micrometer.observation; -import infra.lang.Nullable; +import org.jspecify.annotations.Nullable; + import infra.remoting.Payload; import infra.remoting.frame.FrameType; import io.micrometer.observation.Observation; diff --git a/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/ObservationRequesterChannel.java b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/ObservationRequesterChannel.java index fe2ed44..b0ae526 100644 --- a/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/ObservationRequesterChannel.java +++ b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/ObservationRequesterChannel.java @@ -17,15 +17,15 @@ package infra.remoting.micrometer.observation; +import org.jspecify.annotations.Nullable; import org.reactivestreams.Publisher; import java.util.function.Function; -import infra.lang.Nullable; import infra.remoting.Channel; +import infra.remoting.ChannelWrapper; import infra.remoting.Payload; import infra.remoting.frame.FrameType; -import infra.remoting.ChannelWrapper; import io.micrometer.common.util.StringUtils; import io.micrometer.observation.Observation; import io.micrometer.observation.ObservationRegistry; diff --git a/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/ObservationResponderChannel.java b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/ObservationResponderChannel.java index 2bf889e..c196e91 100644 --- a/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/ObservationResponderChannel.java +++ b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/ObservationResponderChannel.java @@ -17,13 +17,13 @@ package infra.remoting.micrometer.observation; +import org.jspecify.annotations.Nullable; import org.reactivestreams.Publisher; -import infra.lang.Nullable; import infra.remoting.Channel; +import infra.remoting.ChannelWrapper; import infra.remoting.Payload; import infra.remoting.frame.FrameType; -import infra.remoting.ChannelWrapper; import io.micrometer.common.util.StringUtils; import io.micrometer.observation.Observation; import io.micrometer.observation.ObservationRegistry; diff --git a/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/PayloadUtils.java b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/PayloadUtils.java index 421c822..71aa552 100644 --- a/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/PayloadUtils.java +++ b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/PayloadUtils.java @@ -23,7 +23,6 @@ import infra.remoting.util.ByteBufPayload; import infra.remoting.util.DefaultPayload; import io.netty.buffer.ByteBuf; -import io.netty.buffer.CompositeByteBuf; import io.netty.buffer.Unpooled; final class PayloadUtils { diff --git a/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/package-info.java b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/package-info.java index 036d945..15a919e 100644 --- a/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/package-info.java +++ b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/package-info.java @@ -24,5 +24,4 @@ @NonNullFields package infra.remoting.micrometer; -import infra.lang.NonNullFields; import reactor.util.annotation.NonNullApi; diff --git a/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/IntegrationTests.java b/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/IntegrationTests.java index 4238275..8ae45e0 100644 --- a/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/IntegrationTests.java +++ b/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/IntegrationTests.java @@ -28,6 +28,7 @@ import java.util.concurrent.atomic.AtomicInteger; import infra.remoting.Channel; +import infra.remoting.ChannelWrapper; import infra.remoting.Payload; import infra.remoting.core.ChannelConnector; import infra.remoting.core.RemotingServer; @@ -38,7 +39,6 @@ import infra.remoting.transport.netty.client.TcpClientTransport; import infra.remoting.transport.netty.server.CloseableChannel; import infra.remoting.transport.netty.server.TcpServerTransport; -import infra.remoting.ChannelWrapper; import infra.remoting.util.DefaultPayload; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; diff --git a/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/TcpIntegrationTests.java b/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/TcpIntegrationTests.java index 9106716..2a7bb7a 100644 --- a/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/TcpIntegrationTests.java +++ b/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/TcpIntegrationTests.java @@ -26,13 +26,13 @@ import java.util.concurrent.CountDownLatch; import infra.remoting.Channel; +import infra.remoting.ChannelWrapper; import infra.remoting.Payload; import infra.remoting.core.ChannelConnector; import infra.remoting.core.RemotingServer; import infra.remoting.transport.netty.client.TcpClientTransport; import infra.remoting.transport.netty.server.CloseableChannel; import infra.remoting.transport.netty.server.TcpServerTransport; -import infra.remoting.ChannelWrapper; import infra.remoting.util.DefaultPayload; import infra.remoting.util.EmptyPayload; import reactor.core.publisher.Flux; diff --git a/today-remoting-transport-local/src/main/java/infra/remoting/transport/local/LocalServerTransport.java b/today-remoting-transport-local/src/main/java/infra/remoting/transport/local/LocalServerTransport.java index 87ddc45..50d0330 100644 --- a/today-remoting-transport-local/src/main/java/infra/remoting/transport/local/LocalServerTransport.java +++ b/today-remoting-transport-local/src/main/java/infra/remoting/transport/local/LocalServerTransport.java @@ -17,6 +17,8 @@ package infra.remoting.transport.local; +import org.jspecify.annotations.Nullable; + import java.util.Objects; import java.util.Set; import java.util.UUID; @@ -24,7 +26,6 @@ import java.util.concurrent.ConcurrentMap; import java.util.stream.Collectors; -import infra.lang.Nullable; import infra.remoting.Closeable; import infra.remoting.Connection; import infra.remoting.transport.ClientTransport; diff --git a/today-remoting-transport-local/src/main/java/infra/remoting/transport/local/package-info.java b/today-remoting-transport-local/src/main/java/infra/remoting/transport/local/package-info.java index 8cf3471..bb6a917 100644 --- a/today-remoting-transport-local/src/main/java/infra/remoting/transport/local/package-info.java +++ b/today-remoting-transport-local/src/main/java/infra/remoting/transport/local/package-info.java @@ -22,5 +22,3 @@ @NonNullFields package infra.remoting.transport.local; -import infra.lang.NonNullApi; -import infra.lang.NonNullFields; diff --git a/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/client/package-info.java b/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/client/package-info.java index 7772b94..42684b7 100644 --- a/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/client/package-info.java +++ b/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/client/package-info.java @@ -19,4 +19,3 @@ @NonNullApi package infra.remoting.transport.netty.client; -import infra.lang.NonNullApi; diff --git a/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/package-info.java b/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/package-info.java index 891de8b..c45d6c0 100644 --- a/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/package-info.java +++ b/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/package-info.java @@ -22,5 +22,3 @@ @NonNullFields package infra.remoting.transport.netty; -import infra.lang.NonNullApi; -import infra.lang.NonNullFields; diff --git a/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/server/package-info.java b/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/server/package-info.java index 5da875a..658953c 100644 --- a/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/server/package-info.java +++ b/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/server/package-info.java @@ -19,4 +19,3 @@ @NonNullApi package infra.remoting.transport.netty.server; -import infra.lang.NonNullApi; diff --git a/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/tcp/TCPServerTransport.java b/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/tcp/TCPServerTransport.java index a9d159a..6948686 100644 --- a/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/tcp/TCPServerTransport.java +++ b/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/tcp/TCPServerTransport.java @@ -17,13 +17,14 @@ package infra.remoting.transport.tcp; +import org.jspecify.annotations.Nullable; + import java.net.InetAddress; import java.net.InetSocketAddress; import java.util.concurrent.TimeUnit; import infra.core.FutureMono; import infra.lang.Assert; -import infra.lang.Nullable; import infra.logging.Logger; import infra.logging.LoggerFactory; import infra.remoting.transport.ConnectionAcceptor; diff --git a/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/tcp/package-info.java b/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/tcp/package-info.java index fc1aec3..fb6b835 100644 --- a/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/tcp/package-info.java +++ b/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/tcp/package-info.java @@ -22,5 +22,3 @@ @NonNullFields package infra.remoting.transport.tcp; -import infra.lang.NonNullApi; -import infra.lang.NonNullFields; \ No newline at end of file diff --git a/today-remoting-transport-tcp/src/test/java/infra/remoting/integration/FragmentTests.java b/today-remoting-transport-tcp/src/test/java/infra/remoting/integration/FragmentTests.java index 0821415..e0be1aa 100644 --- a/today-remoting-transport-tcp/src/test/java/infra/remoting/integration/FragmentTests.java +++ b/today-remoting-transport-tcp/src/test/java/infra/remoting/integration/FragmentTests.java @@ -25,15 +25,15 @@ import java.util.concurrent.ThreadLocalRandom; import java.util.stream.Stream; -import infra.remoting.Payload; import infra.remoting.Channel; +import infra.remoting.ChannelWrapper; +import infra.remoting.Payload; import infra.remoting.core.ChannelConnector; import infra.remoting.core.RemotingServer; import infra.remoting.transport.netty.client.TcpClientTransport; import infra.remoting.transport.netty.server.CloseableChannel; import infra.remoting.transport.netty.server.TcpServerTransport; import infra.remoting.util.DefaultPayload; -import infra.remoting.ChannelWrapper; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; diff --git a/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/TcpResumableTransportTests.java b/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/TcpResumableTransportTests.java index 46f722c..19cbfd9 100644 --- a/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/TcpResumableTransportTests.java +++ b/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/TcpResumableTransportTests.java @@ -22,11 +22,11 @@ import java.net.InetSocketAddress; import java.time.Duration; -import io.netty.channel.ChannelOption; import infra.remoting.test.TransportPair; import infra.remoting.test.TransportTest; import infra.remoting.transport.netty.client.TcpClientTransport; import infra.remoting.transport.netty.server.TcpServerTransport; +import io.netty.channel.ChannelOption; import reactor.netty.tcp.TcpClient; import reactor.netty.tcp.TcpServer; diff --git a/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/TcpResumableWithFragmentationTransportTests.java b/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/TcpResumableWithFragmentationTransportTests.java index 0c5c7b2..e237a7e 100644 --- a/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/TcpResumableWithFragmentationTransportTests.java +++ b/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/TcpResumableWithFragmentationTransportTests.java @@ -22,11 +22,11 @@ import java.net.InetSocketAddress; import java.time.Duration; -import io.netty.channel.ChannelOption; import infra.remoting.test.TransportPair; import infra.remoting.test.TransportTest; import infra.remoting.transport.netty.client.TcpClientTransport; import infra.remoting.transport.netty.server.TcpServerTransport; +import io.netty.channel.ChannelOption; import reactor.netty.tcp.TcpClient; import reactor.netty.tcp.TcpServer; diff --git a/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/TcpSecureTransportTests.java b/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/TcpSecureTransportTests.java index f6f4350..91dde2f 100644 --- a/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/TcpSecureTransportTests.java +++ b/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/TcpSecureTransportTests.java @@ -25,14 +25,14 @@ import javax.net.ssl.SSLException; -import io.netty.channel.ChannelOption; -import io.netty.handler.ssl.SslContextBuilder; -import io.netty.handler.ssl.util.InsecureTrustManagerFactory; -import io.netty.handler.ssl.util.SelfSignedCertificate; import infra.remoting.test.TransportPair; import infra.remoting.test.TransportTest; import infra.remoting.transport.netty.client.TcpClientTransport; import infra.remoting.transport.netty.server.TcpServerTransport; +import io.netty.channel.ChannelOption; +import io.netty.handler.ssl.SslContextBuilder; +import io.netty.handler.ssl.util.InsecureTrustManagerFactory; +import io.netty.handler.ssl.util.SelfSignedCertificate; import reactor.core.Exceptions; import reactor.netty.tcp.TcpClient; import reactor.netty.tcp.TcpServer; diff --git a/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/TcpTransportTests.java b/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/TcpTransportTests.java index 99d12c2..e0cdf18 100644 --- a/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/TcpTransportTests.java +++ b/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/TcpTransportTests.java @@ -22,11 +22,11 @@ import java.net.InetSocketAddress; import java.time.Duration; -import io.netty.channel.ChannelOption; import infra.remoting.test.TransportPair; import infra.remoting.test.TransportTest; import infra.remoting.transport.netty.client.TcpClientTransport; import infra.remoting.transport.netty.server.TcpServerTransport; +import io.netty.channel.ChannelOption; import reactor.netty.tcp.TcpClient; import reactor.netty.tcp.TcpServer; diff --git a/today-remoting/src/main/java/infra/remoting/ConnectionSetupPayload.java b/today-remoting/src/main/java/infra/remoting/ConnectionSetupPayload.java index b838ef5..c1118b4 100644 --- a/today-remoting/src/main/java/infra/remoting/ConnectionSetupPayload.java +++ b/today-remoting/src/main/java/infra/remoting/ConnectionSetupPayload.java @@ -17,7 +17,8 @@ package infra.remoting; -import infra.lang.Nullable; +import org.jspecify.annotations.Nullable; + import io.netty.buffer.ByteBuf; import io.netty.util.AbstractReferenceCounted; diff --git a/today-remoting/src/main/java/infra/remoting/ProtocolErrorException.java b/today-remoting/src/main/java/infra/remoting/ProtocolErrorException.java index f5cb1ce..4ac39f9 100644 --- a/today-remoting/src/main/java/infra/remoting/ProtocolErrorException.java +++ b/today-remoting/src/main/java/infra/remoting/ProtocolErrorException.java @@ -17,7 +17,7 @@ package infra.remoting; -import infra.lang.Nullable; +import org.jspecify.annotations.Nullable; /** * Exception that represents a protocol error. diff --git a/today-remoting/src/main/java/infra/remoting/RemotingException.java b/today-remoting/src/main/java/infra/remoting/RemotingException.java index 2616982..21bb0fc 100644 --- a/today-remoting/src/main/java/infra/remoting/RemotingException.java +++ b/today-remoting/src/main/java/infra/remoting/RemotingException.java @@ -17,9 +17,9 @@ package infra.remoting; -import java.io.Serial; +import org.jspecify.annotations.Nullable; -import infra.lang.Nullable; +import java.io.Serial; /** * @author 海子 Yang diff --git a/today-remoting/src/main/java/infra/remoting/core/ChannelConnector.java b/today-remoting/src/main/java/infra/remoting/core/ChannelConnector.java index c6aff91..41317c7 100644 --- a/today-remoting/src/main/java/infra/remoting/core/ChannelConnector.java +++ b/today-remoting/src/main/java/infra/remoting/core/ChannelConnector.java @@ -17,13 +17,14 @@ package infra.remoting.core; +import org.jspecify.annotations.Nullable; + import java.time.Duration; import java.util.Objects; import java.util.function.BiConsumer; import java.util.function.Consumer; import java.util.function.Supplier; -import infra.lang.Nullable; import infra.remoting.Channel; import infra.remoting.ChannelAcceptor; import infra.remoting.Closeable; diff --git a/today-remoting/src/main/java/infra/remoting/core/ChannelSupport.java b/today-remoting/src/main/java/infra/remoting/core/ChannelSupport.java index 844e11f..2e45432 100644 --- a/today-remoting/src/main/java/infra/remoting/core/ChannelSupport.java +++ b/today-remoting/src/main/java/infra/remoting/core/ChannelSupport.java @@ -17,10 +17,11 @@ package infra.remoting.core; +import org.jspecify.annotations.Nullable; + import java.util.Objects; import java.util.function.Function; -import infra.lang.Nullable; import infra.remoting.Channel; import infra.remoting.Connection; import infra.remoting.frame.decoder.PayloadDecoder; diff --git a/today-remoting/src/main/java/infra/remoting/core/DefaultRemotingClient.java b/today-remoting/src/main/java/infra/remoting/core/DefaultRemotingClient.java index 10dbed8..209fa96 100644 --- a/today-remoting/src/main/java/infra/remoting/core/DefaultRemotingClient.java +++ b/today-remoting/src/main/java/infra/remoting/core/DefaultRemotingClient.java @@ -16,6 +16,7 @@ */ package infra.remoting.core; +import org.jspecify.annotations.Nullable; import org.reactivestreams.Publisher; import org.reactivestreams.Subscriber; import org.reactivestreams.Subscription; @@ -26,7 +27,6 @@ import java.util.function.Consumer; import java.util.stream.Stream; -import infra.lang.Nullable; import infra.remoting.Channel; import infra.remoting.Payload; import infra.remoting.frame.FrameType; diff --git a/today-remoting/src/main/java/infra/remoting/core/FireAndForgetRequesterMono.java b/today-remoting/src/main/java/infra/remoting/core/FireAndForgetRequesterMono.java index bbd7db3..5f693fe 100644 --- a/today-remoting/src/main/java/infra/remoting/core/FireAndForgetRequesterMono.java +++ b/today-remoting/src/main/java/infra/remoting/core/FireAndForgetRequesterMono.java @@ -16,12 +16,12 @@ */ package infra.remoting.core; +import org.jspecify.annotations.Nullable; import org.reactivestreams.Subscription; import java.time.Duration; import java.util.concurrent.atomic.AtomicLongFieldUpdater; -import infra.lang.Nullable; import infra.remoting.Payload; import infra.remoting.frame.FrameType; import infra.remoting.plugins.RequestInterceptor; diff --git a/today-remoting/src/main/java/infra/remoting/core/FireAndForgetResponderSubscriber.java b/today-remoting/src/main/java/infra/remoting/core/FireAndForgetResponderSubscriber.java index 5543ebc..70d601b 100644 --- a/today-remoting/src/main/java/infra/remoting/core/FireAndForgetResponderSubscriber.java +++ b/today-remoting/src/main/java/infra/remoting/core/FireAndForgetResponderSubscriber.java @@ -17,9 +17,9 @@ package infra.remoting.core; +import org.jspecify.annotations.Nullable; import org.reactivestreams.Subscription; -import infra.lang.Nullable; import infra.logging.Logger; import infra.logging.LoggerFactory; import infra.remoting.Channel; diff --git a/today-remoting/src/main/java/infra/remoting/core/FragmentationUtils.java b/today-remoting/src/main/java/infra/remoting/core/FragmentationUtils.java index cb95cea..893b687 100644 --- a/today-remoting/src/main/java/infra/remoting/core/FragmentationUtils.java +++ b/today-remoting/src/main/java/infra/remoting/core/FragmentationUtils.java @@ -16,7 +16,8 @@ */ package infra.remoting.core; -import infra.lang.Nullable; +import org.jspecify.annotations.Nullable; + import infra.remoting.frame.FrameHeaderCodec; import infra.remoting.frame.FrameLengthCodec; import infra.remoting.frame.FrameType; diff --git a/today-remoting/src/main/java/infra/remoting/core/MetadataPushRequesterMono.java b/today-remoting/src/main/java/infra/remoting/core/MetadataPushRequesterMono.java index bd9d93c..67f861d 100644 --- a/today-remoting/src/main/java/infra/remoting/core/MetadataPushRequesterMono.java +++ b/today-remoting/src/main/java/infra/remoting/core/MetadataPushRequesterMono.java @@ -16,10 +16,11 @@ */ package infra.remoting.core; +import org.jspecify.annotations.Nullable; + import java.time.Duration; import java.util.concurrent.atomic.AtomicLongFieldUpdater; -import infra.lang.Nullable; import infra.remoting.Payload; import infra.remoting.frame.MetadataPushFrameCodec; import io.netty.buffer.ByteBuf; diff --git a/today-remoting/src/main/java/infra/remoting/core/ReconnectMono.java b/today-remoting/src/main/java/infra/remoting/core/ReconnectMono.java index 4c8a9b5..dc56388 100644 --- a/today-remoting/src/main/java/infra/remoting/core/ReconnectMono.java +++ b/today-remoting/src/main/java/infra/remoting/core/ReconnectMono.java @@ -17,6 +17,7 @@ package infra.remoting.core; +import org.jspecify.annotations.Nullable; import org.reactivestreams.Subscription; import java.time.Duration; @@ -26,7 +27,6 @@ import java.util.function.BiConsumer; import java.util.function.Consumer; -import infra.lang.Nullable; import reactor.core.CoreSubscriber; import reactor.core.Disposable; import reactor.core.Scannable; diff --git a/today-remoting/src/main/java/infra/remoting/core/RemotingServer.java b/today-remoting/src/main/java/infra/remoting/core/RemotingServer.java index 347305e..825a951 100644 --- a/today-remoting/src/main/java/infra/remoting/core/RemotingServer.java +++ b/today-remoting/src/main/java/infra/remoting/core/RemotingServer.java @@ -17,12 +17,13 @@ package infra.remoting.core; +import org.jspecify.annotations.Nullable; + import java.time.Duration; import java.util.Objects; import java.util.function.Consumer; import java.util.function.Supplier; -import infra.lang.Nullable; import infra.remoting.Channel; import infra.remoting.ChannelAcceptor; import infra.remoting.Closeable; diff --git a/today-remoting/src/main/java/infra/remoting/core/RequestChannelRequesterFlux.java b/today-remoting/src/main/java/infra/remoting/core/RequestChannelRequesterFlux.java index 8735192..9a04a0b 100644 --- a/today-remoting/src/main/java/infra/remoting/core/RequestChannelRequesterFlux.java +++ b/today-remoting/src/main/java/infra/remoting/core/RequestChannelRequesterFlux.java @@ -17,6 +17,7 @@ package infra.remoting.core; +import org.jspecify.annotations.Nullable; import org.reactivestreams.Publisher; import org.reactivestreams.Subscription; @@ -24,7 +25,6 @@ import java.util.concurrent.CancellationException; import java.util.concurrent.atomic.AtomicLongFieldUpdater; -import infra.lang.Nullable; import infra.remoting.Connection; import infra.remoting.Payload; import infra.remoting.frame.CancelFrameCodec; diff --git a/today-remoting/src/main/java/infra/remoting/core/RequestResponseRequesterMono.java b/today-remoting/src/main/java/infra/remoting/core/RequestResponseRequesterMono.java index 673d874..fd6993d 100644 --- a/today-remoting/src/main/java/infra/remoting/core/RequestResponseRequesterMono.java +++ b/today-remoting/src/main/java/infra/remoting/core/RequestResponseRequesterMono.java @@ -16,11 +16,11 @@ */ package infra.remoting.core; +import org.jspecify.annotations.Nullable; import org.reactivestreams.Subscription; import java.util.concurrent.atomic.AtomicLongFieldUpdater; -import infra.lang.Nullable; import infra.remoting.Connection; import infra.remoting.Payload; import infra.remoting.frame.CancelFrameCodec; diff --git a/today-remoting/src/main/java/infra/remoting/core/RequestResponseResponderSubscriber.java b/today-remoting/src/main/java/infra/remoting/core/RequestResponseResponderSubscriber.java index 35c13ee..0abc442 100644 --- a/today-remoting/src/main/java/infra/remoting/core/RequestResponseResponderSubscriber.java +++ b/today-remoting/src/main/java/infra/remoting/core/RequestResponseResponderSubscriber.java @@ -17,11 +17,11 @@ package infra.remoting.core; +import org.jspecify.annotations.Nullable; import org.reactivestreams.Subscription; import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; -import infra.lang.Nullable; import infra.logging.Logger; import infra.logging.LoggerFactory; import infra.remoting.Channel; diff --git a/today-remoting/src/main/java/infra/remoting/core/RequestStreamRequesterFlux.java b/today-remoting/src/main/java/infra/remoting/core/RequestStreamRequesterFlux.java index a195d17..c3cb528 100644 --- a/today-remoting/src/main/java/infra/remoting/core/RequestStreamRequesterFlux.java +++ b/today-remoting/src/main/java/infra/remoting/core/RequestStreamRequesterFlux.java @@ -16,11 +16,11 @@ */ package infra.remoting.core; +import org.jspecify.annotations.Nullable; import org.reactivestreams.Subscription; import java.util.concurrent.atomic.AtomicLongFieldUpdater; -import infra.lang.Nullable; import infra.remoting.Connection; import infra.remoting.Payload; import infra.remoting.frame.CancelFrameCodec; diff --git a/today-remoting/src/main/java/infra/remoting/core/RequesterChannel.java b/today-remoting/src/main/java/infra/remoting/core/RequesterChannel.java index 540d68d..1aaf938 100644 --- a/today-remoting/src/main/java/infra/remoting/core/RequesterChannel.java +++ b/today-remoting/src/main/java/infra/remoting/core/RequesterChannel.java @@ -17,6 +17,7 @@ package infra.remoting.core; +import org.jspecify.annotations.Nullable; import org.reactivestreams.Publisher; import java.nio.channels.ClosedChannelException; @@ -25,7 +26,6 @@ import java.util.function.Function; import java.util.function.Supplier; -import infra.lang.Nullable; import infra.logging.Logger; import infra.logging.LoggerFactory; import infra.remoting.Channel; diff --git a/today-remoting/src/main/java/infra/remoting/core/RequesterFrameHandler.java b/today-remoting/src/main/java/infra/remoting/core/RequesterFrameHandler.java index e73a84b..4a8f869 100644 --- a/today-remoting/src/main/java/infra/remoting/core/RequesterFrameHandler.java +++ b/today-remoting/src/main/java/infra/remoting/core/RequesterFrameHandler.java @@ -16,9 +16,10 @@ */ package infra.remoting.core; +import org.jspecify.annotations.Nullable; + import java.util.concurrent.CancellationException; -import infra.lang.Nullable; import infra.remoting.Payload; import io.netty.buffer.CompositeByteBuf; diff --git a/today-remoting/src/main/java/infra/remoting/core/ResolvingOperator.java b/today-remoting/src/main/java/infra/remoting/core/ResolvingOperator.java index b67ec21..21ff44d 100644 --- a/today-remoting/src/main/java/infra/remoting/core/ResolvingOperator.java +++ b/today-remoting/src/main/java/infra/remoting/core/ResolvingOperator.java @@ -16,6 +16,7 @@ */ package infra.remoting.core; +import org.jspecify.annotations.Nullable; import org.reactivestreams.Subscription; import java.time.Duration; @@ -25,7 +26,6 @@ import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; import java.util.function.BiConsumer; -import infra.lang.Nullable; import reactor.core.CoreSubscriber; import reactor.core.Disposable; import reactor.core.Exceptions; diff --git a/today-remoting/src/main/java/infra/remoting/core/ResponderChannel.java b/today-remoting/src/main/java/infra/remoting/core/ResponderChannel.java index 496bca8..6e37116 100644 --- a/today-remoting/src/main/java/infra/remoting/core/ResponderChannel.java +++ b/today-remoting/src/main/java/infra/remoting/core/ResponderChannel.java @@ -17,6 +17,7 @@ package infra.remoting.core; +import org.jspecify.annotations.Nullable; import org.reactivestreams.Publisher; import java.nio.channels.ClosedChannelException; @@ -26,7 +27,6 @@ import java.util.function.Function; import java.util.function.Supplier; -import infra.lang.Nullable; import infra.logging.Logger; import infra.logging.LoggerFactory; import infra.remoting.Channel; diff --git a/today-remoting/src/main/java/infra/remoting/core/ResponderLeaseTracker.java b/today-remoting/src/main/java/infra/remoting/core/ResponderLeaseTracker.java index 4a4d47a..a673d03 100644 --- a/today-remoting/src/main/java/infra/remoting/core/ResponderLeaseTracker.java +++ b/today-remoting/src/main/java/infra/remoting/core/ResponderLeaseTracker.java @@ -17,7 +17,8 @@ package infra.remoting.core; -import infra.lang.Nullable; +import org.jspecify.annotations.Nullable; + import infra.remoting.Availability; import infra.remoting.Connection; import infra.remoting.frame.LeaseFrameCodec; diff --git a/today-remoting/src/main/java/infra/remoting/core/Resume.java b/today-remoting/src/main/java/infra/remoting/core/Resume.java index 1381ded..29e79bf 100644 --- a/today-remoting/src/main/java/infra/remoting/core/Resume.java +++ b/today-remoting/src/main/java/infra/remoting/core/Resume.java @@ -17,10 +17,11 @@ package infra.remoting.core; +import org.jspecify.annotations.Nullable; + import java.time.Duration; import java.util.Objects; -import infra.lang.Nullable; import infra.logging.Logger; import infra.logging.LoggerFactory; import infra.remoting.resume.InMemoryResumableFramesStore; diff --git a/today-remoting/src/main/java/infra/remoting/core/SlowFireAndForgetRequesterMono.java b/today-remoting/src/main/java/infra/remoting/core/SlowFireAndForgetRequesterMono.java index 0663c49..59f5efb 100644 --- a/today-remoting/src/main/java/infra/remoting/core/SlowFireAndForgetRequesterMono.java +++ b/today-remoting/src/main/java/infra/remoting/core/SlowFireAndForgetRequesterMono.java @@ -16,11 +16,11 @@ */ package infra.remoting.core; +import org.jspecify.annotations.Nullable; import org.reactivestreams.Subscription; import java.util.concurrent.atomic.AtomicLongFieldUpdater; -import infra.lang.Nullable; import infra.remoting.Payload; import infra.remoting.frame.FrameType; import infra.remoting.plugins.RequestInterceptor; diff --git a/today-remoting/src/main/java/infra/remoting/core/package-info.java b/today-remoting/src/main/java/infra/remoting/core/package-info.java index 3273b4c..5d64cc3 100644 --- a/today-remoting/src/main/java/infra/remoting/core/package-info.java +++ b/today-remoting/src/main/java/infra/remoting/core/package-info.java @@ -27,5 +27,3 @@ @NonNullFields package infra.remoting.core; -import infra.lang.NonNullApi; -import infra.lang.NonNullFields; diff --git a/today-remoting/src/main/java/infra/remoting/error/ApplicationErrorException.java b/today-remoting/src/main/java/infra/remoting/error/ApplicationErrorException.java index f8acfd3..de3ee80 100644 --- a/today-remoting/src/main/java/infra/remoting/error/ApplicationErrorException.java +++ b/today-remoting/src/main/java/infra/remoting/error/ApplicationErrorException.java @@ -17,7 +17,8 @@ package infra.remoting.error; -import infra.lang.Nullable; +import org.jspecify.annotations.Nullable; + import infra.remoting.ProtocolErrorException; import infra.remoting.frame.ErrorFrameCodec; diff --git a/today-remoting/src/main/java/infra/remoting/error/CanceledException.java b/today-remoting/src/main/java/infra/remoting/error/CanceledException.java index c387eb3..f61eca8 100644 --- a/today-remoting/src/main/java/infra/remoting/error/CanceledException.java +++ b/today-remoting/src/main/java/infra/remoting/error/CanceledException.java @@ -17,7 +17,8 @@ package infra.remoting.error; -import infra.lang.Nullable; +import org.jspecify.annotations.Nullable; + import infra.remoting.ProtocolErrorException; import infra.remoting.frame.ErrorFrameCodec; diff --git a/today-remoting/src/main/java/infra/remoting/error/ConnectionCloseException.java b/today-remoting/src/main/java/infra/remoting/error/ConnectionCloseException.java index 55a80ff..fbc1f29 100644 --- a/today-remoting/src/main/java/infra/remoting/error/ConnectionCloseException.java +++ b/today-remoting/src/main/java/infra/remoting/error/ConnectionCloseException.java @@ -17,7 +17,8 @@ package infra.remoting.error; -import infra.lang.Nullable; +import org.jspecify.annotations.Nullable; + import infra.remoting.ProtocolErrorException; import infra.remoting.frame.ErrorFrameCodec; diff --git a/today-remoting/src/main/java/infra/remoting/error/ConnectionErrorException.java b/today-remoting/src/main/java/infra/remoting/error/ConnectionErrorException.java index ca3bd4d..a107a1a 100644 --- a/today-remoting/src/main/java/infra/remoting/error/ConnectionErrorException.java +++ b/today-remoting/src/main/java/infra/remoting/error/ConnectionErrorException.java @@ -17,7 +17,8 @@ package infra.remoting.error; -import infra.lang.Nullable; +import org.jspecify.annotations.Nullable; + import infra.remoting.ProtocolErrorException; import infra.remoting.frame.ErrorFrameCodec; diff --git a/today-remoting/src/main/java/infra/remoting/error/CustomProtocolException.java b/today-remoting/src/main/java/infra/remoting/error/CustomProtocolException.java index 4497930..bacbc40 100644 --- a/today-remoting/src/main/java/infra/remoting/error/CustomProtocolException.java +++ b/today-remoting/src/main/java/infra/remoting/error/CustomProtocolException.java @@ -17,7 +17,8 @@ package infra.remoting.error; -import infra.lang.Nullable; +import org.jspecify.annotations.Nullable; + import infra.remoting.ProtocolErrorException; import infra.remoting.frame.ErrorFrameCodec; diff --git a/today-remoting/src/main/java/infra/remoting/error/InvalidException.java b/today-remoting/src/main/java/infra/remoting/error/InvalidException.java index 8772b88..7fb7195 100644 --- a/today-remoting/src/main/java/infra/remoting/error/InvalidException.java +++ b/today-remoting/src/main/java/infra/remoting/error/InvalidException.java @@ -17,7 +17,8 @@ package infra.remoting.error; -import infra.lang.Nullable; +import org.jspecify.annotations.Nullable; + import infra.remoting.ProtocolErrorException; import infra.remoting.frame.ErrorFrameCodec; diff --git a/today-remoting/src/main/java/infra/remoting/error/InvalidSetupException.java b/today-remoting/src/main/java/infra/remoting/error/InvalidSetupException.java index 913ec54..da4c9f0 100644 --- a/today-remoting/src/main/java/infra/remoting/error/InvalidSetupException.java +++ b/today-remoting/src/main/java/infra/remoting/error/InvalidSetupException.java @@ -17,7 +17,8 @@ package infra.remoting.error; -import infra.lang.Nullable; +import org.jspecify.annotations.Nullable; + import infra.remoting.frame.ErrorFrameCodec; /** diff --git a/today-remoting/src/main/java/infra/remoting/error/RejectedException.java b/today-remoting/src/main/java/infra/remoting/error/RejectedException.java index 1e55467..2d96c73 100644 --- a/today-remoting/src/main/java/infra/remoting/error/RejectedException.java +++ b/today-remoting/src/main/java/infra/remoting/error/RejectedException.java @@ -17,7 +17,8 @@ package infra.remoting.error; -import infra.lang.Nullable; +import org.jspecify.annotations.Nullable; + import infra.remoting.ProtocolErrorException; import infra.remoting.frame.ErrorFrameCodec; diff --git a/today-remoting/src/main/java/infra/remoting/error/RejectedResumeException.java b/today-remoting/src/main/java/infra/remoting/error/RejectedResumeException.java index a38c512..07f77d9 100644 --- a/today-remoting/src/main/java/infra/remoting/error/RejectedResumeException.java +++ b/today-remoting/src/main/java/infra/remoting/error/RejectedResumeException.java @@ -17,7 +17,8 @@ package infra.remoting.error; -import infra.lang.Nullable; +import org.jspecify.annotations.Nullable; + import infra.remoting.ProtocolErrorException; import infra.remoting.frame.ErrorFrameCodec; diff --git a/today-remoting/src/main/java/infra/remoting/error/RejectedSetupException.java b/today-remoting/src/main/java/infra/remoting/error/RejectedSetupException.java index a0a862c..27b5805 100644 --- a/today-remoting/src/main/java/infra/remoting/error/RejectedSetupException.java +++ b/today-remoting/src/main/java/infra/remoting/error/RejectedSetupException.java @@ -17,7 +17,8 @@ package infra.remoting.error; -import infra.lang.Nullable; +import org.jspecify.annotations.Nullable; + import infra.remoting.frame.ErrorFrameCodec; /** diff --git a/today-remoting/src/main/java/infra/remoting/error/SetupException.java b/today-remoting/src/main/java/infra/remoting/error/SetupException.java index ab25ef6..c816b92 100644 --- a/today-remoting/src/main/java/infra/remoting/error/SetupException.java +++ b/today-remoting/src/main/java/infra/remoting/error/SetupException.java @@ -17,7 +17,8 @@ package infra.remoting.error; -import infra.lang.Nullable; +import org.jspecify.annotations.Nullable; + import infra.remoting.ProtocolErrorException; /** The root of the setup exception hierarchy. */ diff --git a/today-remoting/src/main/java/infra/remoting/error/UnsupportedSetupException.java b/today-remoting/src/main/java/infra/remoting/error/UnsupportedSetupException.java index 774914f..95186c1 100644 --- a/today-remoting/src/main/java/infra/remoting/error/UnsupportedSetupException.java +++ b/today-remoting/src/main/java/infra/remoting/error/UnsupportedSetupException.java @@ -17,7 +17,8 @@ package infra.remoting.error; -import infra.lang.Nullable; +import org.jspecify.annotations.Nullable; + import infra.remoting.frame.ErrorFrameCodec; /** diff --git a/today-remoting/src/main/java/infra/remoting/error/package-info.java b/today-remoting/src/main/java/infra/remoting/error/package-info.java index 919f543..604d6c1 100644 --- a/today-remoting/src/main/java/infra/remoting/error/package-info.java +++ b/today-remoting/src/main/java/infra/remoting/error/package-info.java @@ -24,4 +24,3 @@ @NonNullApi package infra.remoting.error; -import infra.lang.NonNullApi; diff --git a/today-remoting/src/main/java/infra/remoting/frame/ExtensionFrameCodec.java b/today-remoting/src/main/java/infra/remoting/frame/ExtensionFrameCodec.java index dd72620..1860ad6 100644 --- a/today-remoting/src/main/java/infra/remoting/frame/ExtensionFrameCodec.java +++ b/today-remoting/src/main/java/infra/remoting/frame/ExtensionFrameCodec.java @@ -17,7 +17,8 @@ package infra.remoting.frame; -import infra.lang.Nullable; +import org.jspecify.annotations.Nullable; + import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufAllocator; diff --git a/today-remoting/src/main/java/infra/remoting/frame/FrameBodyCodec.java b/today-remoting/src/main/java/infra/remoting/frame/FrameBodyCodec.java index 66d68e5..a2a16cc 100644 --- a/today-remoting/src/main/java/infra/remoting/frame/FrameBodyCodec.java +++ b/today-remoting/src/main/java/infra/remoting/frame/FrameBodyCodec.java @@ -17,7 +17,8 @@ package infra.remoting.frame; -import infra.lang.Nullable; +import org.jspecify.annotations.Nullable; + import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufAllocator; import io.netty.buffer.Unpooled; diff --git a/today-remoting/src/main/java/infra/remoting/frame/GenericFrameCodec.java b/today-remoting/src/main/java/infra/remoting/frame/GenericFrameCodec.java index a46313e..17c9611 100644 --- a/today-remoting/src/main/java/infra/remoting/frame/GenericFrameCodec.java +++ b/today-remoting/src/main/java/infra/remoting/frame/GenericFrameCodec.java @@ -17,7 +17,8 @@ package infra.remoting.frame; -import infra.lang.Nullable; +import org.jspecify.annotations.Nullable; + import infra.remoting.Payload; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufAllocator; diff --git a/today-remoting/src/main/java/infra/remoting/frame/LeaseFrameCodec.java b/today-remoting/src/main/java/infra/remoting/frame/LeaseFrameCodec.java index cd86870..c5c74d5 100644 --- a/today-remoting/src/main/java/infra/remoting/frame/LeaseFrameCodec.java +++ b/today-remoting/src/main/java/infra/remoting/frame/LeaseFrameCodec.java @@ -17,7 +17,8 @@ package infra.remoting.frame; -import infra.lang.Nullable; +import org.jspecify.annotations.Nullable; + import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufAllocator; diff --git a/today-remoting/src/main/java/infra/remoting/frame/PayloadFrameCodec.java b/today-remoting/src/main/java/infra/remoting/frame/PayloadFrameCodec.java index 2ad68f6..41e4b9b 100644 --- a/today-remoting/src/main/java/infra/remoting/frame/PayloadFrameCodec.java +++ b/today-remoting/src/main/java/infra/remoting/frame/PayloadFrameCodec.java @@ -17,7 +17,8 @@ package infra.remoting.frame; -import infra.lang.Nullable; +import org.jspecify.annotations.Nullable; + import infra.remoting.Payload; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufAllocator; diff --git a/today-remoting/src/main/java/infra/remoting/frame/RequestChannelFrameCodec.java b/today-remoting/src/main/java/infra/remoting/frame/RequestChannelFrameCodec.java index abcdf3e..ccf5e4c 100644 --- a/today-remoting/src/main/java/infra/remoting/frame/RequestChannelFrameCodec.java +++ b/today-remoting/src/main/java/infra/remoting/frame/RequestChannelFrameCodec.java @@ -17,7 +17,8 @@ package infra.remoting.frame; -import infra.lang.Nullable; +import org.jspecify.annotations.Nullable; + import infra.remoting.Payload; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufAllocator; diff --git a/today-remoting/src/main/java/infra/remoting/frame/RequestFireAndForgetFrameCodec.java b/today-remoting/src/main/java/infra/remoting/frame/RequestFireAndForgetFrameCodec.java index c1761aa..122f545 100644 --- a/today-remoting/src/main/java/infra/remoting/frame/RequestFireAndForgetFrameCodec.java +++ b/today-remoting/src/main/java/infra/remoting/frame/RequestFireAndForgetFrameCodec.java @@ -17,7 +17,8 @@ package infra.remoting.frame; -import infra.lang.Nullable; +import org.jspecify.annotations.Nullable; + import infra.remoting.Payload; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufAllocator; diff --git a/today-remoting/src/main/java/infra/remoting/frame/RequestResponseFrameCodec.java b/today-remoting/src/main/java/infra/remoting/frame/RequestResponseFrameCodec.java index 174b0f5..75b040b 100644 --- a/today-remoting/src/main/java/infra/remoting/frame/RequestResponseFrameCodec.java +++ b/today-remoting/src/main/java/infra/remoting/frame/RequestResponseFrameCodec.java @@ -17,7 +17,8 @@ package infra.remoting.frame; -import infra.lang.Nullable; +import org.jspecify.annotations.Nullable; + import infra.remoting.Payload; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufAllocator; diff --git a/today-remoting/src/main/java/infra/remoting/frame/RequestStreamFrameCodec.java b/today-remoting/src/main/java/infra/remoting/frame/RequestStreamFrameCodec.java index 29d9281..6a6d8cd 100644 --- a/today-remoting/src/main/java/infra/remoting/frame/RequestStreamFrameCodec.java +++ b/today-remoting/src/main/java/infra/remoting/frame/RequestStreamFrameCodec.java @@ -17,7 +17,8 @@ package infra.remoting.frame; -import infra.lang.Nullable; +import org.jspecify.annotations.Nullable; + import infra.remoting.Payload; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufAllocator; diff --git a/today-remoting/src/main/java/infra/remoting/frame/SetupFrameCodec.java b/today-remoting/src/main/java/infra/remoting/frame/SetupFrameCodec.java index b219db2..d6dc1fe 100644 --- a/today-remoting/src/main/java/infra/remoting/frame/SetupFrameCodec.java +++ b/today-remoting/src/main/java/infra/remoting/frame/SetupFrameCodec.java @@ -17,9 +17,10 @@ package infra.remoting.frame; +import org.jspecify.annotations.Nullable; + import java.nio.charset.StandardCharsets; -import infra.lang.Nullable; import infra.remoting.Payload; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufAllocator; diff --git a/today-remoting/src/main/java/infra/remoting/frame/decoder/package-info.java b/today-remoting/src/main/java/infra/remoting/frame/decoder/package-info.java index 70760c9..904d693 100644 --- a/today-remoting/src/main/java/infra/remoting/frame/decoder/package-info.java +++ b/today-remoting/src/main/java/infra/remoting/frame/decoder/package-info.java @@ -22,4 +22,3 @@ @NonNullApi package infra.remoting.frame.decoder; -import infra.lang.NonNullApi; diff --git a/today-remoting/src/main/java/infra/remoting/frame/package-info.java b/today-remoting/src/main/java/infra/remoting/frame/package-info.java index 509d9a2..9dbd990 100644 --- a/today-remoting/src/main/java/infra/remoting/frame/package-info.java +++ b/today-remoting/src/main/java/infra/remoting/frame/package-info.java @@ -22,4 +22,3 @@ @NonNullApi package infra.remoting.frame; -import infra.lang.NonNullApi; diff --git a/today-remoting/src/main/java/infra/remoting/internal/UnboundedProcessor.java b/today-remoting/src/main/java/infra/remoting/internal/UnboundedProcessor.java index 4cf46c2..24fc0d4 100644 --- a/today-remoting/src/main/java/infra/remoting/internal/UnboundedProcessor.java +++ b/today-remoting/src/main/java/infra/remoting/internal/UnboundedProcessor.java @@ -17,6 +17,7 @@ package infra.remoting.internal; +import org.jspecify.annotations.Nullable; import org.reactivestreams.Subscription; import java.util.Objects; @@ -26,7 +27,6 @@ import java.util.concurrent.atomic.AtomicLongFieldUpdater; import java.util.stream.Stream; -import infra.lang.Nullable; import infra.remoting.internal.jctools.queues.MpscUnboundedArrayQueue; import io.netty.buffer.ByteBuf; import reactor.core.CoreSubscriber; diff --git a/today-remoting/src/main/java/infra/remoting/internal/package-info.java b/today-remoting/src/main/java/infra/remoting/internal/package-info.java index e2ea92f..b19b94e 100644 --- a/today-remoting/src/main/java/infra/remoting/internal/package-info.java +++ b/today-remoting/src/main/java/infra/remoting/internal/package-info.java @@ -23,5 +23,3 @@ @NonNullFields package infra.remoting.internal; -import infra.lang.NonNullApi; -import infra.lang.NonNullFields; diff --git a/today-remoting/src/main/java/infra/remoting/keepalive/package-info.java b/today-remoting/src/main/java/infra/remoting/keepalive/package-info.java index aedaf34..3cbb4ee 100644 --- a/today-remoting/src/main/java/infra/remoting/keepalive/package-info.java +++ b/today-remoting/src/main/java/infra/remoting/keepalive/package-info.java @@ -22,5 +22,3 @@ @NonNullFields package infra.remoting.keepalive; -import infra.lang.NonNullApi; -import infra.lang.NonNullFields; diff --git a/today-remoting/src/main/java/infra/remoting/lb/ChannelPool.java b/today-remoting/src/main/java/infra/remoting/lb/ChannelPool.java index d87adaf..df3773b 100644 --- a/today-remoting/src/main/java/infra/remoting/lb/ChannelPool.java +++ b/today-remoting/src/main/java/infra/remoting/lb/ChannelPool.java @@ -16,6 +16,7 @@ */ package infra.remoting.lb; +import org.jspecify.annotations.Nullable; import org.reactivestreams.Publisher; import org.reactivestreams.Subscription; @@ -29,7 +30,6 @@ import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; import java.util.stream.Collectors; -import infra.lang.Nullable; import infra.remoting.Channel; import infra.remoting.Closeable; import infra.remoting.Payload; diff --git a/today-remoting/src/main/java/infra/remoting/lb/FluxDeferredResolution.java b/today-remoting/src/main/java/infra/remoting/lb/FluxDeferredResolution.java index 76e70c5..326b586 100644 --- a/today-remoting/src/main/java/infra/remoting/lb/FluxDeferredResolution.java +++ b/today-remoting/src/main/java/infra/remoting/lb/FluxDeferredResolution.java @@ -16,12 +16,12 @@ */ package infra.remoting.lb; +import org.jspecify.annotations.Nullable; import org.reactivestreams.Subscription; import java.util.concurrent.atomic.AtomicLongFieldUpdater; import java.util.function.BiConsumer; -import infra.lang.Nullable; import infra.remoting.Payload; import infra.remoting.frame.FrameType; import io.netty.util.ReferenceCountUtil; diff --git a/today-remoting/src/main/java/infra/remoting/lb/Int2LongHashMap.java b/today-remoting/src/main/java/infra/remoting/lb/Int2LongHashMap.java index 44e94fe..93cf409 100644 --- a/today-remoting/src/main/java/infra/remoting/lb/Int2LongHashMap.java +++ b/today-remoting/src/main/java/infra/remoting/lb/Int2LongHashMap.java @@ -16,6 +16,8 @@ */ package infra.remoting.lb; +import org.jspecify.annotations.Nullable; + import java.io.Serializable; import java.util.AbstractCollection; import java.util.AbstractSet; @@ -27,8 +29,6 @@ import java.util.function.Function; import java.util.function.IntToLongFunction; -import infra.lang.Nullable; - /** A open addressing with linear probing hash map specialised for primitive key and value pairs. */ class Int2LongHashMap implements Map, Serializable { static final float DEFAULT_LOAD_FACTOR = 0.55f; diff --git a/today-remoting/src/main/java/infra/remoting/lb/LoadBalanceRemotingClient.java b/today-remoting/src/main/java/infra/remoting/lb/LoadBalanceRemotingClient.java index 285be1c..e3bf720 100644 --- a/today-remoting/src/main/java/infra/remoting/lb/LoadBalanceRemotingClient.java +++ b/today-remoting/src/main/java/infra/remoting/lb/LoadBalanceRemotingClient.java @@ -17,11 +17,11 @@ package infra.remoting.lb; +import org.jspecify.annotations.Nullable; import org.reactivestreams.Publisher; import java.util.List; -import infra.lang.Nullable; import infra.remoting.Channel; import infra.remoting.Payload; import infra.remoting.core.ChannelConnector; diff --git a/today-remoting/src/main/java/infra/remoting/lb/MonoDeferredResolution.java b/today-remoting/src/main/java/infra/remoting/lb/MonoDeferredResolution.java index f6160ad..2bfed3b 100644 --- a/today-remoting/src/main/java/infra/remoting/lb/MonoDeferredResolution.java +++ b/today-remoting/src/main/java/infra/remoting/lb/MonoDeferredResolution.java @@ -16,12 +16,12 @@ */ package infra.remoting.lb; +import org.jspecify.annotations.Nullable; import org.reactivestreams.Subscription; import java.util.concurrent.atomic.AtomicLongFieldUpdater; import java.util.function.BiConsumer; -import infra.lang.Nullable; import infra.remoting.Payload; import infra.remoting.frame.FrameType; import io.netty.util.ReferenceCountUtil; diff --git a/today-remoting/src/main/java/infra/remoting/lb/ResolvingOperator.java b/today-remoting/src/main/java/infra/remoting/lb/ResolvingOperator.java index 541e61b..2848112 100644 --- a/today-remoting/src/main/java/infra/remoting/lb/ResolvingOperator.java +++ b/today-remoting/src/main/java/infra/remoting/lb/ResolvingOperator.java @@ -16,13 +16,14 @@ */ package infra.remoting.lb; +import org.jspecify.annotations.Nullable; + import java.time.Duration; import java.util.concurrent.CancellationException; import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; import java.util.function.BiConsumer; -import infra.lang.Nullable; import reactor.core.Disposable; import reactor.core.Exceptions; import reactor.core.publisher.Operators; diff --git a/today-remoting/src/main/java/infra/remoting/lb/WeightedLoadBalanceStrategy.java b/today-remoting/src/main/java/infra/remoting/lb/WeightedLoadBalanceStrategy.java index 383bd21..da2aee3 100644 --- a/today-remoting/src/main/java/infra/remoting/lb/WeightedLoadBalanceStrategy.java +++ b/today-remoting/src/main/java/infra/remoting/lb/WeightedLoadBalanceStrategy.java @@ -17,12 +17,13 @@ package infra.remoting.lb; +import org.jspecify.annotations.Nullable; + import java.util.List; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ThreadLocalRandom; import java.util.function.Function; -import infra.lang.Nullable; import infra.remoting.Channel; import infra.remoting.core.ChannelConnector; diff --git a/today-remoting/src/main/java/infra/remoting/lb/WeightedStatsRequestInterceptor.java b/today-remoting/src/main/java/infra/remoting/lb/WeightedStatsRequestInterceptor.java index 0661e67..fbbc0d3 100644 --- a/today-remoting/src/main/java/infra/remoting/lb/WeightedStatsRequestInterceptor.java +++ b/today-remoting/src/main/java/infra/remoting/lb/WeightedStatsRequestInterceptor.java @@ -16,7 +16,8 @@ */ package infra.remoting.lb; -import infra.lang.Nullable; +import org.jspecify.annotations.Nullable; + import infra.remoting.frame.FrameType; import infra.remoting.plugins.RequestInterceptor; import io.netty.buffer.ByteBuf; diff --git a/today-remoting/src/main/java/infra/remoting/lb/package-info.java b/today-remoting/src/main/java/infra/remoting/lb/package-info.java index 4d47c73..0e2809d 100644 --- a/today-remoting/src/main/java/infra/remoting/lb/package-info.java +++ b/today-remoting/src/main/java/infra/remoting/lb/package-info.java @@ -22,5 +22,3 @@ @NonNullFields package infra.remoting.lb; -import infra.lang.NonNullApi; -import infra.lang.NonNullFields; \ No newline at end of file diff --git a/today-remoting/src/main/java/infra/remoting/lease/Lease.java b/today-remoting/src/main/java/infra/remoting/lease/Lease.java index cc7c687..4da350e 100644 --- a/today-remoting/src/main/java/infra/remoting/lease/Lease.java +++ b/today-remoting/src/main/java/infra/remoting/lease/Lease.java @@ -17,9 +17,10 @@ package infra.remoting.lease; +import org.jspecify.annotations.Nullable; + import java.time.Duration; -import infra.lang.Nullable; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; diff --git a/today-remoting/src/main/java/infra/remoting/lease/package-info.java b/today-remoting/src/main/java/infra/remoting/lease/package-info.java index ca80211..5592dd2 100644 --- a/today-remoting/src/main/java/infra/remoting/lease/package-info.java +++ b/today-remoting/src/main/java/infra/remoting/lease/package-info.java @@ -25,4 +25,3 @@ @NonNullApi package infra.remoting.lease; -import infra.lang.NonNullApi; diff --git a/today-remoting/src/main/java/infra/remoting/package-info.java b/today-remoting/src/main/java/infra/remoting/package-info.java index e1c71b3..1746cf1 100644 --- a/today-remoting/src/main/java/infra/remoting/package-info.java +++ b/today-remoting/src/main/java/infra/remoting/package-info.java @@ -19,5 +19,3 @@ @NonNullFields package infra.remoting; -import infra.lang.NonNullApi; -import infra.lang.NonNullFields; \ No newline at end of file diff --git a/today-remoting/src/main/java/infra/remoting/plugins/CompositeRequestInterceptor.java b/today-remoting/src/main/java/infra/remoting/plugins/CompositeRequestInterceptor.java index 36c7a30..719fb64 100644 --- a/today-remoting/src/main/java/infra/remoting/plugins/CompositeRequestInterceptor.java +++ b/today-remoting/src/main/java/infra/remoting/plugins/CompositeRequestInterceptor.java @@ -17,9 +17,10 @@ package infra.remoting.plugins; +import org.jspecify.annotations.Nullable; + import java.util.List; -import infra.lang.Nullable; import infra.remoting.frame.FrameType; import io.netty.buffer.ByteBuf; import reactor.core.publisher.Operators; diff --git a/today-remoting/src/main/java/infra/remoting/plugins/InitializingInterceptorRegistry.java b/today-remoting/src/main/java/infra/remoting/plugins/InitializingInterceptorRegistry.java index 6c864ca..12e7921 100644 --- a/today-remoting/src/main/java/infra/remoting/plugins/InitializingInterceptorRegistry.java +++ b/today-remoting/src/main/java/infra/remoting/plugins/InitializingInterceptorRegistry.java @@ -16,10 +16,11 @@ */ package infra.remoting.plugins; +import org.jspecify.annotations.Nullable; + import java.util.stream.Collectors; import java.util.stream.Stream; -import infra.lang.Nullable; import infra.remoting.Channel; import infra.remoting.ChannelAcceptor; import infra.remoting.Connection; diff --git a/today-remoting/src/main/java/infra/remoting/plugins/RequestInterceptor.java b/today-remoting/src/main/java/infra/remoting/plugins/RequestInterceptor.java index afb1569..a6778e7 100644 --- a/today-remoting/src/main/java/infra/remoting/plugins/RequestInterceptor.java +++ b/today-remoting/src/main/java/infra/remoting/plugins/RequestInterceptor.java @@ -17,7 +17,8 @@ package infra.remoting.plugins; -import infra.lang.Nullable; +import org.jspecify.annotations.Nullable; + import infra.remoting.Payload; import infra.remoting.frame.FrameType; import infra.remoting.lease.Lease; diff --git a/today-remoting/src/main/java/infra/remoting/plugins/package-info.java b/today-remoting/src/main/java/infra/remoting/plugins/package-info.java index 4709e52..9f80ddd 100644 --- a/today-remoting/src/main/java/infra/remoting/plugins/package-info.java +++ b/today-remoting/src/main/java/infra/remoting/plugins/package-info.java @@ -19,4 +19,3 @@ @NonNullApi package infra.remoting.plugins; -import infra.lang.NonNullApi; diff --git a/today-remoting/src/main/java/infra/remoting/protocol/ProtocolFrame.java b/today-remoting/src/main/java/infra/remoting/protocol/ProtocolFrame.java index cdafaae..f7861b6 100644 --- a/today-remoting/src/main/java/infra/remoting/protocol/ProtocolFrame.java +++ b/today-remoting/src/main/java/infra/remoting/protocol/ProtocolFrame.java @@ -17,9 +17,10 @@ package infra.remoting.protocol; +import org.jspecify.annotations.Nullable; + import java.util.concurrent.Flow; -import infra.lang.Nullable; import infra.remoting.Payload; import infra.remoting.frame.FrameType; import infra.remoting.frame.decoder.PayloadDecoder; diff --git a/today-remoting/src/main/java/infra/remoting/protocol/ProtocolParsingException.java b/today-remoting/src/main/java/infra/remoting/protocol/ProtocolParsingException.java index 16e4348..d1e7c77 100644 --- a/today-remoting/src/main/java/infra/remoting/protocol/ProtocolParsingException.java +++ b/today-remoting/src/main/java/infra/remoting/protocol/ProtocolParsingException.java @@ -17,7 +17,7 @@ package infra.remoting.protocol; -import infra.lang.Nullable; +import org.jspecify.annotations.Nullable; /** * Protocol parsing exception diff --git a/today-remoting/src/main/java/infra/remoting/resume/InMemoryResumableFramesStore.java b/today-remoting/src/main/java/infra/remoting/resume/InMemoryResumableFramesStore.java index bb013b3..c28c771 100644 --- a/today-remoting/src/main/java/infra/remoting/resume/InMemoryResumableFramesStore.java +++ b/today-remoting/src/main/java/infra/remoting/resume/InMemoryResumableFramesStore.java @@ -17,6 +17,7 @@ package infra.remoting.resume; +import org.jspecify.annotations.Nullable; import org.reactivestreams.Subscription; import java.util.ArrayDeque; @@ -24,7 +25,6 @@ import java.util.concurrent.CancellationException; import java.util.concurrent.atomic.AtomicLongFieldUpdater; -import infra.lang.Nullable; import infra.logging.Logger; import infra.logging.LoggerFactory; import infra.remoting.internal.UnboundedProcessor; diff --git a/today-remoting/src/main/java/infra/remoting/resume/ResumableConnection.java b/today-remoting/src/main/java/infra/remoting/resume/ResumableConnection.java index 53a7b13..7b44db5 100644 --- a/today-remoting/src/main/java/infra/remoting/resume/ResumableConnection.java +++ b/today-remoting/src/main/java/infra/remoting/resume/ResumableConnection.java @@ -17,13 +17,13 @@ package infra.remoting.resume; +import org.jspecify.annotations.Nullable; import org.reactivestreams.Subscription; import java.net.SocketAddress; import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; -import infra.lang.Nullable; import infra.logging.Logger; import infra.logging.LoggerFactory; import infra.remoting.Connection; diff --git a/today-remoting/src/main/java/infra/remoting/resume/SessionManager.java b/today-remoting/src/main/java/infra/remoting/resume/SessionManager.java index 3dbc96e..d72c80c 100644 --- a/today-remoting/src/main/java/infra/remoting/resume/SessionManager.java +++ b/today-remoting/src/main/java/infra/remoting/resume/SessionManager.java @@ -17,10 +17,11 @@ package infra.remoting.resume; +import org.jspecify.annotations.Nullable; + import java.util.Map; import java.util.concurrent.ConcurrentHashMap; -import infra.lang.Nullable; import infra.logging.Logger; import infra.logging.LoggerFactory; import io.netty.buffer.ByteBuf; diff --git a/today-remoting/src/main/java/infra/remoting/resume/package-info.java b/today-remoting/src/main/java/infra/remoting/resume/package-info.java index 85b8e5b..1e6d219 100644 --- a/today-remoting/src/main/java/infra/remoting/resume/package-info.java +++ b/today-remoting/src/main/java/infra/remoting/resume/package-info.java @@ -25,4 +25,3 @@ @NonNullApi package infra.remoting.resume; -import infra.lang.NonNullApi; diff --git a/today-remoting/src/main/java/infra/remoting/transport/package-info.java b/today-remoting/src/main/java/infra/remoting/transport/package-info.java index eed45b0..1b9fc44 100644 --- a/today-remoting/src/main/java/infra/remoting/transport/package-info.java +++ b/today-remoting/src/main/java/infra/remoting/transport/package-info.java @@ -19,4 +19,3 @@ @NonNullApi package infra.remoting.transport; -import infra.lang.NonNullApi; diff --git a/today-remoting/src/main/java/infra/remoting/util/ByteBufPayload.java b/today-remoting/src/main/java/infra/remoting/util/ByteBufPayload.java index 8ded9d1..8f2422b 100644 --- a/today-remoting/src/main/java/infra/remoting/util/ByteBufPayload.java +++ b/today-remoting/src/main/java/infra/remoting/util/ByteBufPayload.java @@ -17,11 +17,12 @@ package infra.remoting.util; +import org.jspecify.annotations.Nullable; + import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.nio.charset.Charset; -import infra.lang.Nullable; import infra.remoting.Payload; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufAllocator; diff --git a/today-remoting/src/main/java/infra/remoting/util/DefaultPayload.java b/today-remoting/src/main/java/infra/remoting/util/DefaultPayload.java index 9efcd80..53011a5 100644 --- a/today-remoting/src/main/java/infra/remoting/util/DefaultPayload.java +++ b/today-remoting/src/main/java/infra/remoting/util/DefaultPayload.java @@ -17,12 +17,13 @@ package infra.remoting.util; +import org.jspecify.annotations.Nullable; + import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; -import infra.lang.Nullable; import infra.remoting.Payload; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; diff --git a/today-remoting/src/main/java/infra/remoting/util/package-info.java b/today-remoting/src/main/java/infra/remoting/util/package-info.java index a19a694..b699ba7 100644 --- a/today-remoting/src/main/java/infra/remoting/util/package-info.java +++ b/today-remoting/src/main/java/infra/remoting/util/package-info.java @@ -19,4 +19,3 @@ @NonNullApi package infra.remoting.util; -import infra.lang.NonNullApi; diff --git a/today-remoting/src/test/java/infra/remoting/FrameAssert.java b/today-remoting/src/test/java/infra/remoting/FrameAssert.java index 9a3cbf4..f270a52 100644 --- a/today-remoting/src/test/java/infra/remoting/FrameAssert.java +++ b/today-remoting/src/test/java/infra/remoting/FrameAssert.java @@ -22,16 +22,12 @@ import org.assertj.core.error.BasicErrorMessageFactory; import org.assertj.core.internal.Failures; import org.assertj.core.internal.Objects; +import org.jspecify.annotations.Nullable; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.List; -import infra.lang.Nullable; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufUtil; -import io.netty.buffer.Unpooled; -import io.netty.util.CharsetUtil; import infra.remoting.frame.ByteBufRepresentation; import infra.remoting.frame.ErrorFrameCodec; import infra.remoting.frame.FrameHeaderCodec; @@ -40,6 +36,10 @@ import infra.remoting.frame.PayloadFrameCodec; import infra.remoting.frame.RequestNFrameCodec; import infra.remoting.frame.RequestStreamFrameCodec; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; +import io.netty.buffer.Unpooled; +import io.netty.util.CharsetUtil; import static org.assertj.core.error.ShouldBe.shouldBe; import static org.assertj.core.error.ShouldBeEqual.shouldBeEqual; diff --git a/today-remoting/src/test/java/infra/remoting/PayloadAssert.java b/today-remoting/src/test/java/infra/remoting/PayloadAssert.java index fe32c9f..f558abb 100755 --- a/today-remoting/src/test/java/infra/remoting/PayloadAssert.java +++ b/today-remoting/src/test/java/infra/remoting/PayloadAssert.java @@ -22,18 +22,18 @@ import org.assertj.core.error.BasicErrorMessageFactory; import org.assertj.core.internal.Failures; import org.assertj.core.internal.Objects; +import org.jspecify.annotations.Nullable; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.List; -import infra.lang.Nullable; +import infra.remoting.frame.ByteBufRepresentation; +import infra.remoting.util.DefaultPayload; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; import io.netty.buffer.Unpooled; import io.netty.util.CharsetUtil; -import infra.remoting.frame.ByteBufRepresentation; -import infra.remoting.util.DefaultPayload; import static org.assertj.core.error.ShouldBeEqual.shouldBeEqual; import static org.assertj.core.error.ShouldHave.shouldHave; diff --git a/today-remoting/src/test/java/infra/remoting/core/AbstractChannelRule.java b/today-remoting/src/test/java/infra/remoting/core/AbstractChannelRule.java index fae89cd..58abace 100644 --- a/today-remoting/src/test/java/infra/remoting/core/AbstractChannelRule.java +++ b/today-remoting/src/test/java/infra/remoting/core/AbstractChannelRule.java @@ -21,11 +21,11 @@ import java.time.Duration; -import io.netty.buffer.ByteBufAllocator; import infra.remoting.Channel; import infra.remoting.buffer.LeaksTrackingByteBufAllocator; import infra.remoting.test.util.TestConnection; import infra.remoting.test.util.TestSubscriber; +import io.netty.buffer.ByteBufAllocator; import static infra.remoting.frame.FrameLengthCodec.FRAME_LENGTH_MASK; diff --git a/today-remoting/src/test/java/infra/remoting/core/ChannelConnectorTests.java b/today-remoting/src/test/java/infra/remoting/core/ChannelConnectorTests.java index 3d12809..2a1716a 100644 --- a/today-remoting/src/test/java/infra/remoting/core/ChannelConnectorTests.java +++ b/today-remoting/src/test/java/infra/remoting/core/ChannelConnectorTests.java @@ -26,20 +26,20 @@ import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicReference; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; -import io.netty.util.CharsetUtil; -import io.netty.util.ReferenceCounted; +import infra.remoting.Channel; import infra.remoting.ConnectionSetupPayload; import infra.remoting.FrameAssert; import infra.remoting.Payload; -import infra.remoting.Channel; import infra.remoting.frame.FrameType; import infra.remoting.frame.KeepAliveFrameCodec; import infra.remoting.frame.RequestResponseFrameCodec; import infra.remoting.test.util.TestClientTransport; import infra.remoting.test.util.TestConnection; import infra.remoting.util.ByteBufPayload; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.util.CharsetUtil; +import io.netty.util.ReferenceCounted; import reactor.core.publisher.Mono; import reactor.test.StepVerifier; import reactor.util.retry.Retry; diff --git a/today-remoting/src/test/java/infra/remoting/core/ChannelLeaseTests.java b/today-remoting/src/test/java/infra/remoting/core/ChannelLeaseTests.java index b7e0304..7e98a4e 100644 --- a/today-remoting/src/test/java/infra/remoting/core/ChannelLeaseTests.java +++ b/today-remoting/src/test/java/infra/remoting/core/ChannelLeaseTests.java @@ -35,13 +35,8 @@ import java.util.function.BiFunction; import java.util.stream.Stream; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufAllocator; -import io.netty.buffer.Unpooled; -import io.netty.util.CharsetUtil; -import io.netty.util.ReferenceCounted; -import infra.remoting.Payload; import infra.remoting.Channel; +import infra.remoting.Payload; import infra.remoting.buffer.LeaksTrackingByteBufAllocator; import infra.remoting.error.Exceptions; import infra.remoting.error.RejectedException; @@ -64,6 +59,11 @@ import infra.remoting.test.util.TestServerTransport; import infra.remoting.util.ByteBufPayload; import infra.remoting.util.DefaultPayload; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufAllocator; +import io.netty.buffer.Unpooled; +import io.netty.util.CharsetUtil; +import io.netty.util.ReferenceCounted; import reactor.core.publisher.BaseSubscriber; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; diff --git a/today-remoting/src/test/java/infra/remoting/core/ChannelReconnectTests.java b/today-remoting/src/test/java/infra/remoting/core/ChannelReconnectTests.java index d66187a..2a4feed 100644 --- a/today-remoting/src/test/java/infra/remoting/core/ChannelReconnectTests.java +++ b/today-remoting/src/test/java/infra/remoting/core/ChannelReconnectTests.java @@ -27,8 +27,8 @@ import java.util.concurrent.ConcurrentLinkedQueue; import java.util.function.Consumer; -import infra.remoting.FrameAssert; import infra.remoting.Channel; +import infra.remoting.FrameAssert; import infra.remoting.frame.FrameType; import infra.remoting.test.util.TestClientTransport; import infra.remoting.test.util.TestConnection; diff --git a/today-remoting/src/test/java/infra/remoting/core/ChannelTests.java b/today-remoting/src/test/java/infra/remoting/core/ChannelTests.java index c5a8b9e..c190e36 100644 --- a/today-remoting/src/test/java/infra/remoting/core/ChannelTests.java +++ b/today-remoting/src/test/java/infra/remoting/core/ChannelTests.java @@ -29,10 +29,8 @@ import java.util.concurrent.CancellationException; import java.util.concurrent.atomic.AtomicReference; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufAllocator; -import infra.remoting.Payload; import infra.remoting.Channel; +import infra.remoting.Payload; import infra.remoting.buffer.LeaksTrackingByteBufAllocator; import infra.remoting.error.ApplicationErrorException; import infra.remoting.error.CustomProtocolException; @@ -41,6 +39,8 @@ import infra.remoting.test.util.LocalConnection; import infra.remoting.util.DefaultPayload; import infra.remoting.util.EmptyPayload; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufAllocator; import reactor.core.Disposable; import reactor.core.Disposables; import reactor.core.publisher.Flux; diff --git a/today-remoting/src/test/java/infra/remoting/core/ClientServerInputMultiplexerTest.java b/today-remoting/src/test/java/infra/remoting/core/ClientServerInputMultiplexerTest.java index f0e2634..fbf074e 100644 --- a/today-remoting/src/test/java/infra/remoting/core/ClientServerInputMultiplexerTest.java +++ b/today-remoting/src/test/java/infra/remoting/core/ClientServerInputMultiplexerTest.java @@ -22,9 +22,6 @@ import java.util.concurrent.atomic.AtomicInteger; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufAllocator; -import io.netty.buffer.Unpooled; import infra.remoting.buffer.LeaksTrackingByteBufAllocator; import infra.remoting.frame.ErrorFrameCodec; import infra.remoting.frame.KeepAliveFrameCodec; @@ -32,6 +29,9 @@ import infra.remoting.frame.MetadataPushFrameCodec; import infra.remoting.plugins.InitializingInterceptorRegistry; import infra.remoting.test.util.TestConnection; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufAllocator; +import io.netty.buffer.Unpooled; import static org.assertj.core.api.Assertions.assertThat; diff --git a/today-remoting/src/test/java/infra/remoting/core/ConnectionSetupPayloadTest.java b/today-remoting/src/test/java/infra/remoting/core/ConnectionSetupPayloadTest.java index edcea5b..bb3eae3 100644 --- a/today-remoting/src/test/java/infra/remoting/core/ConnectionSetupPayloadTest.java +++ b/today-remoting/src/test/java/infra/remoting/core/ConnectionSetupPayloadTest.java @@ -19,13 +19,13 @@ import org.junit.jupiter.api.Test; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufAllocator; -import io.netty.buffer.Unpooled; import infra.remoting.ConnectionSetupPayload; import infra.remoting.Payload; import infra.remoting.frame.SetupFrameCodec; import infra.remoting.util.DefaultPayload; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufAllocator; +import io.netty.buffer.Unpooled; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; diff --git a/today-remoting/src/test/java/infra/remoting/core/DefaultChannelClientTests.java b/today-remoting/src/test/java/infra/remoting/core/DefaultChannelClientTests.java index 7b29a77..067fd29 100644 --- a/today-remoting/src/test/java/infra/remoting/core/DefaultChannelClientTests.java +++ b/today-remoting/src/test/java/infra/remoting/core/DefaultChannelClientTests.java @@ -39,13 +39,10 @@ import java.util.stream.Collectors; import java.util.stream.Stream; -import io.netty.buffer.ByteBuf; -import io.netty.util.CharsetUtil; -import io.netty.util.ReferenceCountUtil; -import io.netty.util.ReferenceCounted; +import infra.remoting.Channel; +import infra.remoting.ChannelWrapper; import infra.remoting.FrameAssert; import infra.remoting.Payload; -import infra.remoting.Channel; import infra.remoting.RaceTestConstants; import infra.remoting.frame.ErrorFrameCodec; import infra.remoting.frame.FrameHeaderCodec; @@ -55,7 +52,10 @@ import infra.remoting.internal.subscriber.AssertSubscriber; import infra.remoting.test.util.TestConnection; import infra.remoting.util.ByteBufPayload; -import infra.remoting.ChannelWrapper; +import io.netty.buffer.ByteBuf; +import io.netty.util.CharsetUtil; +import io.netty.util.ReferenceCountUtil; +import io.netty.util.ReferenceCounted; import reactor.core.Disposable; import reactor.core.publisher.Flux; import reactor.core.publisher.Hooks; diff --git a/today-remoting/src/test/java/infra/remoting/core/RemotingServerTests.java b/today-remoting/src/test/java/infra/remoting/core/RemotingServerTests.java index 2b7ed0c..1b4f51a 100644 --- a/today-remoting/src/test/java/infra/remoting/core/RemotingServerTests.java +++ b/today-remoting/src/test/java/infra/remoting/core/RemotingServerTests.java @@ -22,11 +22,9 @@ import java.time.Duration; import java.util.Random; -import io.netty.buffer.ByteBufAllocator; -import io.netty.buffer.Unpooled; +import infra.remoting.Channel; import infra.remoting.Closeable; import infra.remoting.FrameAssert; -import infra.remoting.Channel; import infra.remoting.error.RejectedSetupException; import infra.remoting.frame.FrameType; import infra.remoting.frame.KeepAliveFrameCodec; @@ -35,6 +33,8 @@ import infra.remoting.test.util.TestConnection; import infra.remoting.test.util.TestServerTransport; import infra.remoting.util.EmptyPayload; +import io.netty.buffer.ByteBufAllocator; +import io.netty.buffer.Unpooled; import reactor.core.Scannable; import reactor.core.publisher.Mono; import reactor.core.publisher.Sinks; diff --git a/today-remoting/src/test/java/infra/remoting/core/RequestRequesterChannelFluxTests.java b/today-remoting/src/test/java/infra/remoting/core/RequestRequesterChannelFluxTests.java index ddcc1f0..c81c4e2 100644 --- a/today-remoting/src/test/java/infra/remoting/core/RequestRequesterChannelFluxTests.java +++ b/today-remoting/src/test/java/infra/remoting/core/RequestRequesterChannelFluxTests.java @@ -31,10 +31,6 @@ import java.util.concurrent.ThreadLocalRandom; import java.util.stream.Stream; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; -import io.netty.util.CharsetUtil; -import io.netty.util.IllegalReferenceCountException; import infra.remoting.FrameAssert; import infra.remoting.Payload; import infra.remoting.PayloadAssert; @@ -46,6 +42,10 @@ import infra.remoting.test.util.TestConnection; import infra.remoting.util.ByteBufPayload; import infra.remoting.util.DefaultPayload; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.util.CharsetUtil; +import io.netty.util.IllegalReferenceCountException; import reactor.core.publisher.Hooks; import reactor.core.publisher.Signal; import reactor.test.StepVerifier; diff --git a/today-remoting/src/test/java/infra/remoting/core/RequestResponderChannelSubscriberTests.java b/today-remoting/src/test/java/infra/remoting/core/RequestResponderChannelSubscriberTests.java index 0ee04ac..c3ab10e 100644 --- a/today-remoting/src/test/java/infra/remoting/core/RequestResponderChannelSubscriberTests.java +++ b/today-remoting/src/test/java/infra/remoting/core/RequestResponderChannelSubscriberTests.java @@ -32,10 +32,6 @@ import java.util.concurrent.ThreadLocalRandom; import java.util.stream.Stream; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; -import io.netty.util.CharsetUtil; -import io.netty.util.IllegalReferenceCountException; import infra.remoting.FrameAssert; import infra.remoting.Payload; import infra.remoting.PayloadAssert; @@ -47,6 +43,10 @@ import infra.remoting.test.util.TestConnection; import infra.remoting.util.ByteBufPayload; import infra.remoting.util.DefaultPayload; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.util.CharsetUtil; +import io.netty.util.IllegalReferenceCountException; import reactor.core.Exceptions; import reactor.core.publisher.Hooks; import reactor.core.publisher.Signal; diff --git a/today-remoting/src/test/java/infra/remoting/core/RequesterChannelSubscribersTests.java b/today-remoting/src/test/java/infra/remoting/core/RequesterChannelSubscribersTests.java index 0891009..908cf87 100644 --- a/today-remoting/src/test/java/infra/remoting/core/RequesterChannelSubscribersTests.java +++ b/today-remoting/src/test/java/infra/remoting/core/RequesterChannelSubscribersTests.java @@ -32,11 +32,8 @@ import java.util.function.Function; import java.util.stream.Stream; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufAllocator; -import io.netty.util.CharsetUtil; -import infra.remoting.FrameAssert; import infra.remoting.Channel; +import infra.remoting.FrameAssert; import infra.remoting.buffer.LeaksTrackingByteBufAllocator; import infra.remoting.frame.FrameHeaderCodec; import infra.remoting.frame.FrameType; @@ -45,6 +42,9 @@ import infra.remoting.internal.subscriber.AssertSubscriber; import infra.remoting.test.util.TestConnection; import infra.remoting.util.DefaultPayload; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufAllocator; +import io.netty.util.CharsetUtil; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import reactor.core.publisher.Sinks; diff --git a/today-remoting/src/test/java/infra/remoting/core/RequesterChannelTerminationTests.java b/today-remoting/src/test/java/infra/remoting/core/RequesterChannelTerminationTests.java index 8ef305d..253a353 100644 --- a/today-remoting/src/test/java/infra/remoting/core/RequesterChannelTerminationTests.java +++ b/today-remoting/src/test/java/infra/remoting/core/RequesterChannelTerminationTests.java @@ -29,9 +29,9 @@ import java.util.Arrays; import java.util.function.Function; +import infra.remoting.Channel; import infra.remoting.FrameAssert; import infra.remoting.Payload; -import infra.remoting.Channel; import infra.remoting.core.RequesterChannelTests.ClientChannelRule; import infra.remoting.frame.FrameType; import infra.remoting.util.EmptyPayload; diff --git a/today-remoting/src/test/java/infra/remoting/core/RequesterChannelTests.java b/today-remoting/src/test/java/infra/remoting/core/RequesterChannelTests.java index 7ca12d8..839d150 100644 --- a/today-remoting/src/test/java/infra/remoting/core/RequesterChannelTests.java +++ b/today-remoting/src/test/java/infra/remoting/core/RequesterChannelTests.java @@ -44,18 +44,10 @@ import java.util.function.Function; import java.util.stream.Stream; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufAllocator; -import io.netty.buffer.ByteBufUtil; -import io.netty.buffer.Unpooled; -import io.netty.util.CharsetUtil; -import io.netty.util.IllegalReferenceCountException; -import io.netty.util.ReferenceCountUtil; -import io.netty.util.ReferenceCounted; +import infra.remoting.Channel; import infra.remoting.FrameAssert; import infra.remoting.Payload; import infra.remoting.PayloadAssert; -import infra.remoting.Channel; import infra.remoting.RaceTestConstants; import infra.remoting.buffer.LeaksTrackingByteBufAllocator; import infra.remoting.error.ApplicationErrorException; @@ -78,6 +70,14 @@ import infra.remoting.util.ByteBufPayload; import infra.remoting.util.DefaultPayload; import infra.remoting.util.EmptyPayload; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufAllocator; +import io.netty.buffer.ByteBufUtil; +import io.netty.buffer.Unpooled; +import io.netty.util.CharsetUtil; +import io.netty.util.IllegalReferenceCountException; +import io.netty.util.ReferenceCountUtil; +import io.netty.util.ReferenceCounted; import reactor.core.Scannable; import reactor.core.publisher.BaseSubscriber; import reactor.core.publisher.Flux; diff --git a/today-remoting/src/test/java/infra/remoting/core/RequesterOperatorsRacingTests.java b/today-remoting/src/test/java/infra/remoting/core/RequesterOperatorsRacingTests.java index 5e83f58..39b26e4 100644 --- a/today-remoting/src/test/java/infra/remoting/core/RequesterOperatorsRacingTests.java +++ b/today-remoting/src/test/java/infra/remoting/core/RequesterOperatorsRacingTests.java @@ -30,9 +30,6 @@ import java.util.function.Supplier; import java.util.stream.Stream; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufUtil; -import io.netty.util.CharsetUtil; import infra.remoting.FrameAssert; import infra.remoting.Payload; import infra.remoting.RaceTestConstants; @@ -41,6 +38,9 @@ import infra.remoting.internal.subscriber.AssertSubscriber; import infra.remoting.plugins.TestRequestInterceptor; import infra.remoting.util.ByteBufPayload; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; +import io.netty.util.CharsetUtil; import reactor.core.CoreSubscriber; import reactor.core.publisher.Flux; import reactor.core.publisher.Hooks; diff --git a/today-remoting/src/test/java/infra/remoting/core/ResponderChannelTests.java b/today-remoting/src/test/java/infra/remoting/core/ResponderChannelTests.java index 5f73ccc..6051aad 100644 --- a/today-remoting/src/test/java/infra/remoting/core/ResponderChannelTests.java +++ b/today-remoting/src/test/java/infra/remoting/core/ResponderChannelTests.java @@ -38,16 +38,10 @@ import java.util.concurrent.atomic.AtomicReference; import java.util.stream.Stream; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufAllocator; -import io.netty.buffer.Unpooled; -import io.netty.util.CharsetUtil; -import io.netty.util.ReferenceCountUtil; -import io.netty.util.ReferenceCounted; +import infra.remoting.Channel; import infra.remoting.FrameAssert; import infra.remoting.Payload; import infra.remoting.PayloadAssert; -import infra.remoting.Channel; import infra.remoting.RaceTestConstants; import infra.remoting.frame.CancelFrameCodec; import infra.remoting.frame.ErrorFrameCodec; @@ -69,6 +63,12 @@ import infra.remoting.util.ByteBufPayload; import infra.remoting.util.DefaultPayload; import infra.remoting.util.EmptyPayload; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufAllocator; +import io.netty.buffer.Unpooled; +import io.netty.util.CharsetUtil; +import io.netty.util.ReferenceCountUtil; +import io.netty.util.ReferenceCounted; import reactor.core.CoreSubscriber; import reactor.core.publisher.BaseSubscriber; import reactor.core.publisher.Flux; diff --git a/today-remoting/src/test/java/infra/remoting/core/ResponderOperatorsCommonTests.java b/today-remoting/src/test/java/infra/remoting/core/ResponderOperatorsCommonTests.java index 19b11f5..34e0121 100755 --- a/today-remoting/src/test/java/infra/remoting/core/ResponderOperatorsCommonTests.java +++ b/today-remoting/src/test/java/infra/remoting/core/ResponderOperatorsCommonTests.java @@ -25,17 +25,17 @@ import java.util.concurrent.ThreadLocalRandom; import java.util.stream.Stream; -import io.netty.buffer.ByteBuf; +import infra.remoting.Channel; import infra.remoting.FrameAssert; import infra.remoting.Payload; import infra.remoting.PayloadAssert; -import infra.remoting.Channel; import infra.remoting.buffer.LeaksTrackingByteBufAllocator; import infra.remoting.frame.FrameType; import infra.remoting.internal.subscriber.AssertSubscriber; import infra.remoting.plugins.RequestInterceptor; import infra.remoting.plugins.TestRequestInterceptor; import infra.remoting.test.util.TestConnection; +import io.netty.buffer.ByteBuf; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import reactor.core.publisher.Operators; diff --git a/today-remoting/src/test/java/infra/remoting/core/SetupRejectionTests.java b/today-remoting/src/test/java/infra/remoting/core/SetupRejectionTests.java index 8c92e4c..2e9d08b 100644 --- a/today-remoting/src/test/java/infra/remoting/core/SetupRejectionTests.java +++ b/today-remoting/src/test/java/infra/remoting/core/SetupRejectionTests.java @@ -20,14 +20,12 @@ import java.time.Duration; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufAllocator; +import infra.remoting.Channel; +import infra.remoting.ChannelAcceptor; import infra.remoting.Closeable; -import infra.remoting.ConnectionSetupPayload; import infra.remoting.Connection; +import infra.remoting.ConnectionSetupPayload; import infra.remoting.Payload; -import infra.remoting.Channel; -import infra.remoting.ChannelAcceptor; import infra.remoting.buffer.LeaksTrackingByteBufAllocator; import infra.remoting.error.Exceptions; import infra.remoting.error.RejectedSetupException; @@ -39,6 +37,8 @@ import infra.remoting.transport.ConnectionAcceptor; import infra.remoting.transport.ServerTransport; import infra.remoting.util.DefaultPayload; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufAllocator; import reactor.core.publisher.Mono; import reactor.core.publisher.Sinks; import reactor.test.StepVerifier; diff --git a/today-remoting/src/test/java/infra/remoting/core/TestChannelSupport.java b/today-remoting/src/test/java/infra/remoting/core/TestChannelSupport.java index d83f371..92884f7 100644 --- a/today-remoting/src/test/java/infra/remoting/core/TestChannelSupport.java +++ b/today-remoting/src/test/java/infra/remoting/core/TestChannelSupport.java @@ -17,24 +17,24 @@ package infra.remoting.core; import org.assertj.core.api.Assertions; +import org.jspecify.annotations.Nullable; import java.util.ArrayList; import java.util.concurrent.ThreadLocalRandom; -import infra.lang.Nullable; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufAllocator; -import io.netty.buffer.Unpooled; -import io.netty.util.CharsetUtil; +import infra.remoting.Channel; import infra.remoting.Connection; import infra.remoting.Payload; -import infra.remoting.Channel; import infra.remoting.buffer.LeaksTrackingByteBufAllocator; import infra.remoting.frame.FrameType; import infra.remoting.frame.decoder.PayloadDecoder; import infra.remoting.plugins.RequestInterceptor; import infra.remoting.test.util.TestConnection; import infra.remoting.util.ByteBufPayload; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufAllocator; +import io.netty.buffer.Unpooled; +import io.netty.util.CharsetUtil; import reactor.core.Exceptions; import static infra.remoting.frame.FrameLengthCodec.FRAME_LENGTH_MASK; diff --git a/today-remoting/src/test/java/infra/remoting/frame/ErrorFrameCodecTests.java b/today-remoting/src/test/java/infra/remoting/frame/ErrorFrameCodecTests.java index 0f57e63..3e95887 100644 --- a/today-remoting/src/test/java/infra/remoting/frame/ErrorFrameCodecTests.java +++ b/today-remoting/src/test/java/infra/remoting/frame/ErrorFrameCodecTests.java @@ -19,10 +19,10 @@ import org.junit.jupiter.api.Test; +import infra.remoting.error.ApplicationErrorException; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufAllocator; import io.netty.buffer.ByteBufUtil; -import infra.remoting.error.ApplicationErrorException; import static org.junit.jupiter.api.Assertions.assertEquals; diff --git a/today-remoting/src/test/java/infra/remoting/frame/PayloadFlyweightTests.java b/today-remoting/src/test/java/infra/remoting/frame/PayloadFlyweightTests.java index 959d6c7..9096d25 100644 --- a/today-remoting/src/test/java/infra/remoting/frame/PayloadFlyweightTests.java +++ b/today-remoting/src/test/java/infra/remoting/frame/PayloadFlyweightTests.java @@ -22,11 +22,11 @@ import java.nio.charset.StandardCharsets; +import infra.remoting.Payload; +import infra.remoting.util.DefaultPayload; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufAllocator; import io.netty.buffer.Unpooled; -import infra.remoting.Payload; -import infra.remoting.util.DefaultPayload; public class PayloadFlyweightTests { diff --git a/today-remoting/src/test/java/infra/remoting/frame/SetupFrameCodecTests.java b/today-remoting/src/test/java/infra/remoting/frame/SetupFrameCodecTests.java index 3d9deb5..399be94 100644 --- a/today-remoting/src/test/java/infra/remoting/frame/SetupFrameCodecTests.java +++ b/today-remoting/src/test/java/infra/remoting/frame/SetupFrameCodecTests.java @@ -21,11 +21,11 @@ import java.util.Arrays; +import infra.remoting.Payload; +import infra.remoting.util.DefaultPayload; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufAllocator; import io.netty.buffer.Unpooled; -import infra.remoting.Payload; -import infra.remoting.util.DefaultPayload; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; diff --git a/today-remoting/src/test/java/infra/remoting/internal/UnboundedProcessorTests.java b/today-remoting/src/test/java/infra/remoting/internal/UnboundedProcessorTests.java index 3beceeb..5407f5a 100644 --- a/today-remoting/src/test/java/infra/remoting/internal/UnboundedProcessorTests.java +++ b/today-remoting/src/test/java/infra/remoting/internal/UnboundedProcessorTests.java @@ -24,14 +24,14 @@ import java.time.Duration; +import infra.remoting.RaceTestConstants; +import infra.remoting.buffer.LeaksTrackingByteBufAllocator; +import infra.remoting.internal.subscriber.AssertSubscriber; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufAllocator; import io.netty.buffer.Unpooled; import io.netty.util.CharsetUtil; import io.netty.util.ReferenceCountUtil; -import infra.remoting.RaceTestConstants; -import infra.remoting.buffer.LeaksTrackingByteBufAllocator; -import infra.remoting.internal.subscriber.AssertSubscriber; import reactor.core.Fuseable; import reactor.core.publisher.Hooks; import reactor.core.scheduler.Schedulers; diff --git a/today-remoting/src/test/java/infra/remoting/lb/LoadbalanceTests.java b/today-remoting/src/test/java/infra/remoting/lb/LoadbalanceTests.java index 27b0efc..8b6da30 100644 --- a/today-remoting/src/test/java/infra/remoting/lb/LoadbalanceTests.java +++ b/today-remoting/src/test/java/infra/remoting/lb/LoadbalanceTests.java @@ -30,15 +30,15 @@ import java.util.List; import java.util.concurrent.atomic.AtomicInteger; -import infra.remoting.Payload; import infra.remoting.Channel; +import infra.remoting.ChannelWrapper; +import infra.remoting.Payload; import infra.remoting.RaceTestConstants; import infra.remoting.core.ChannelConnector; import infra.remoting.internal.subscriber.AssertSubscriber; import infra.remoting.test.util.TestClientTransport; import infra.remoting.transport.ClientTransport; import infra.remoting.util.EmptyPayload; -import infra.remoting.ChannelWrapper; import reactor.core.CoreSubscriber; import reactor.core.publisher.Flux; import reactor.core.publisher.Hooks; diff --git a/today-remoting/src/test/java/infra/remoting/lb/RoundRobinLoadBalanceStrategyTests.java b/today-remoting/src/test/java/infra/remoting/lb/RoundRobinLoadBalanceStrategyTests.java index 61d0285..9e1159a 100644 --- a/today-remoting/src/test/java/infra/remoting/lb/RoundRobinLoadBalanceStrategyTests.java +++ b/today-remoting/src/test/java/infra/remoting/lb/RoundRobinLoadBalanceStrategyTests.java @@ -29,8 +29,8 @@ import java.util.List; import java.util.concurrent.atomic.AtomicInteger; -import infra.remoting.Payload; import infra.remoting.Channel; +import infra.remoting.Payload; import infra.remoting.RaceTestConstants; import infra.remoting.core.ChannelConnector; import infra.remoting.transport.ClientTransport; diff --git a/today-remoting/src/test/java/infra/remoting/lb/WeightedLoadBalanceStrategyTests.java b/today-remoting/src/test/java/infra/remoting/lb/WeightedLoadBalanceStrategyTests.java index fd3ce32..dfe336e 100644 --- a/today-remoting/src/test/java/infra/remoting/lb/WeightedLoadBalanceStrategyTests.java +++ b/today-remoting/src/test/java/infra/remoting/lb/WeightedLoadBalanceStrategyTests.java @@ -29,8 +29,8 @@ import java.util.List; import java.util.concurrent.atomic.AtomicInteger; -import infra.remoting.Payload; import infra.remoting.Channel; +import infra.remoting.Payload; import infra.remoting.RaceTestConstants; import infra.remoting.core.ChannelConnector; import infra.remoting.transport.ClientTransport; diff --git a/today-remoting/src/test/java/infra/remoting/plugins/RequestInterceptorTests.java b/today-remoting/src/test/java/infra/remoting/plugins/RequestInterceptorTests.java index 614e3ed..af653b7 100644 --- a/today-remoting/src/test/java/infra/remoting/plugins/RequestInterceptorTests.java +++ b/today-remoting/src/test/java/infra/remoting/plugins/RequestInterceptorTests.java @@ -17,6 +17,7 @@ package infra.remoting.plugins; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; @@ -27,13 +28,10 @@ import java.util.concurrent.TimeUnit; import java.util.function.Function; -import infra.lang.Nullable; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufAllocator; -import infra.remoting.Closeable; -import infra.remoting.Payload; import infra.remoting.Channel; import infra.remoting.ChannelAcceptor; +import infra.remoting.Closeable; +import infra.remoting.Payload; import infra.remoting.buffer.LeaksTrackingByteBufAllocator; import infra.remoting.core.ChannelConnector; import infra.remoting.core.RemotingServer; @@ -41,6 +39,8 @@ import infra.remoting.transport.local.LocalClientTransport; import infra.remoting.transport.local.LocalServerTransport; import infra.remoting.util.DefaultPayload; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufAllocator; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import reactor.test.StepVerifier; diff --git a/today-remoting/src/test/java/infra/remoting/plugins/TestRequestInterceptor.java b/today-remoting/src/test/java/infra/remoting/plugins/TestRequestInterceptor.java index b397ca4..826fd1e 100644 --- a/today-remoting/src/test/java/infra/remoting/plugins/TestRequestInterceptor.java +++ b/today-remoting/src/test/java/infra/remoting/plugins/TestRequestInterceptor.java @@ -19,11 +19,11 @@ import org.assertj.core.api.Assertions; import org.assertj.core.api.Condition; +import org.jspecify.annotations.Nullable; import java.util.Queue; import java.util.function.Consumer; -import infra.lang.Nullable; import infra.remoting.frame.FrameType; import infra.remoting.internal.jctools.queues.MpscUnboundedArrayQueue; import io.netty.buffer.ByteBuf; diff --git a/today-remoting/src/test/java/infra/remoting/protocol/MetadataTests.java b/today-remoting/src/test/java/infra/remoting/protocol/MetadataTests.java index 15a9daf..a772c2d 100644 --- a/today-remoting/src/test/java/infra/remoting/protocol/MetadataTests.java +++ b/today-remoting/src/test/java/infra/remoting/protocol/MetadataTests.java @@ -17,8 +17,6 @@ package infra.remoting.protocol; -import static org.junit.jupiter.api.Assertions.*; - /** * @author 海子 Yang * @since 1.0 2025/7/31 17:05 diff --git a/today-remoting/src/test/java/infra/remoting/resume/InMemoryResumeStoreTests.java b/today-remoting/src/test/java/infra/remoting/resume/InMemoryResumeStoreTests.java index 427808d..5023403 100644 --- a/today-remoting/src/test/java/infra/remoting/resume/InMemoryResumeStoreTests.java +++ b/today-remoting/src/test/java/infra/remoting/resume/InMemoryResumeStoreTests.java @@ -28,12 +28,12 @@ import java.util.concurrent.atomic.AtomicReference; import java.util.function.Consumer; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; -import io.netty.util.ReferenceCounted; import infra.remoting.RaceTestConstants; import infra.remoting.internal.UnboundedProcessor; import infra.remoting.internal.subscriber.AssertSubscriber; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.util.ReferenceCounted; import reactor.core.Disposable; import reactor.core.publisher.Hooks; import reactor.test.util.RaceTestUtils; diff --git a/today-remoting/src/test/java/infra/remoting/resume/ServerChannelSessionTests.java b/today-remoting/src/test/java/infra/remoting/resume/ServerChannelSessionTests.java index 02057a2..03e320e 100644 --- a/today-remoting/src/test/java/infra/remoting/resume/ServerChannelSessionTests.java +++ b/today-remoting/src/test/java/infra/remoting/resume/ServerChannelSessionTests.java @@ -21,15 +21,15 @@ import java.time.Duration; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; -import io.netty.util.ReferenceCounted; import infra.remoting.FrameAssert; import infra.remoting.frame.FrameType; import infra.remoting.frame.KeepAliveFrameCodec; import infra.remoting.frame.ResumeFrameCodec; import infra.remoting.keepalive.KeepAliveSupport; import infra.remoting.test.util.TestClientTransport; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.util.ReferenceCounted; import reactor.core.publisher.Operators; import reactor.test.StepVerifier; import reactor.test.scheduler.VirtualTimeScheduler; diff --git a/today-remoting/src/test/java/infra/remoting/test/util/LocalConnection.java b/today-remoting/src/test/java/infra/remoting/test/util/LocalConnection.java index 439f07a..26d4623 100644 --- a/today-remoting/src/test/java/infra/remoting/test/util/LocalConnection.java +++ b/today-remoting/src/test/java/infra/remoting/test/util/LocalConnection.java @@ -21,11 +21,11 @@ import java.net.SocketAddress; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufAllocator; import infra.remoting.Connection; import infra.remoting.ProtocolErrorException; import infra.remoting.frame.ErrorFrameCodec; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufAllocator; import reactor.core.CoreSubscriber; import reactor.core.Scannable; import reactor.core.publisher.Flux; diff --git a/today-remoting/src/test/java/infra/remoting/test/util/MockChannel.java b/today-remoting/src/test/java/infra/remoting/test/util/MockChannel.java index 0ea12ce..39bd36f 100644 --- a/today-remoting/src/test/java/infra/remoting/test/util/MockChannel.java +++ b/today-remoting/src/test/java/infra/remoting/test/util/MockChannel.java @@ -21,8 +21,8 @@ import java.util.concurrent.atomic.AtomicInteger; -import infra.remoting.Payload; import infra.remoting.Channel; +import infra.remoting.Payload; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; diff --git a/today-remoting/src/test/java/infra/remoting/test/util/TestServerTransport.java b/today-remoting/src/test/java/infra/remoting/test/util/TestServerTransport.java index 3bc2bba..a166fe0 100644 --- a/today-remoting/src/test/java/infra/remoting/test/util/TestServerTransport.java +++ b/today-remoting/src/test/java/infra/remoting/test/util/TestServerTransport.java @@ -16,11 +16,11 @@ */ package infra.remoting.test.util; -import io.netty.buffer.ByteBufAllocator; import infra.remoting.Closeable; import infra.remoting.buffer.LeaksTrackingByteBufAllocator; import infra.remoting.transport.ConnectionAcceptor; import infra.remoting.transport.ServerTransport; +import io.netty.buffer.ByteBufAllocator; import reactor.core.Scannable; import reactor.core.publisher.Mono; import reactor.core.publisher.Sinks; diff --git a/today-remoting/src/test/java/infra/remoting/util/ByteBufPayloadTests.java b/today-remoting/src/test/java/infra/remoting/util/ByteBufPayloadTests.java index 924f086..f7891fd 100644 --- a/today-remoting/src/test/java/infra/remoting/util/ByteBufPayloadTests.java +++ b/today-remoting/src/test/java/infra/remoting/util/ByteBufPayloadTests.java @@ -20,9 +20,9 @@ import org.assertj.core.api.Assertions; import org.junit.jupiter.api.Test; +import infra.remoting.Payload; import io.netty.buffer.Unpooled; import io.netty.util.IllegalReferenceCountException; -import infra.remoting.Payload; public class ByteBufPayloadTests { diff --git a/today-remoting/src/test/java/infra/remoting/util/DefaultPayloadTests.java b/today-remoting/src/test/java/infra/remoting/util/DefaultPayloadTests.java index 658cd20..4b7dc3a 100644 --- a/today-remoting/src/test/java/infra/remoting/util/DefaultPayloadTests.java +++ b/today-remoting/src/test/java/infra/remoting/util/DefaultPayloadTests.java @@ -22,11 +22,11 @@ import java.nio.ByteBuffer; import java.util.concurrent.ThreadLocalRandom; +import infra.remoting.Payload; +import infra.remoting.buffer.LeaksTrackingByteBufAllocator; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufAllocator; import io.netty.buffer.Unpooled; -import infra.remoting.Payload; -import infra.remoting.buffer.LeaksTrackingByteBufAllocator; import static org.assertj.core.api.Assertions.assertThat; diff --git a/today-remoting/src/testFixtures/java/infra/remoting/test/ClientSetupRule.java b/today-remoting/src/testFixtures/java/infra/remoting/test/ClientSetupRule.java index 68d0c3f..5131f04 100644 --- a/today-remoting/src/testFixtures/java/infra/remoting/test/ClientSetupRule.java +++ b/today-remoting/src/testFixtures/java/infra/remoting/test/ClientSetupRule.java @@ -21,8 +21,8 @@ import java.util.function.Function; import java.util.function.Supplier; -import infra.remoting.Closeable; import infra.remoting.Channel; +import infra.remoting.Closeable; import infra.remoting.core.ChannelConnector; import infra.remoting.core.RemotingServer; import infra.remoting.transport.ClientTransport; diff --git a/today-remoting/src/testFixtures/java/infra/remoting/test/PingClient.java b/today-remoting/src/testFixtures/java/infra/remoting/test/PingClient.java index b402930..7c4abc6 100644 --- a/today-remoting/src/testFixtures/java/infra/remoting/test/PingClient.java +++ b/today-remoting/src/testFixtures/java/infra/remoting/test/PingClient.java @@ -23,8 +23,8 @@ import java.time.Duration; import java.util.function.BiFunction; -import infra.remoting.Payload; import infra.remoting.Channel; +import infra.remoting.Payload; import infra.remoting.util.ByteBufPayload; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; diff --git a/today-remoting/src/testFixtures/java/infra/remoting/test/PingHandler.java b/today-remoting/src/testFixtures/java/infra/remoting/test/PingHandler.java index a662c72..3e584dc 100644 --- a/today-remoting/src/testFixtures/java/infra/remoting/test/PingHandler.java +++ b/today-remoting/src/testFixtures/java/infra/remoting/test/PingHandler.java @@ -19,10 +19,10 @@ import java.util.concurrent.ThreadLocalRandom; -import infra.remoting.ConnectionSetupPayload; -import infra.remoting.Payload; import infra.remoting.Channel; import infra.remoting.ChannelAcceptor; +import infra.remoting.ConnectionSetupPayload; +import infra.remoting.Payload; import infra.remoting.util.ByteBufPayload; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; diff --git a/today-remoting/src/testFixtures/java/infra/remoting/test/TestChannel.java b/today-remoting/src/testFixtures/java/infra/remoting/test/TestChannel.java index 62cee17..8160b25 100644 --- a/today-remoting/src/testFixtures/java/infra/remoting/test/TestChannel.java +++ b/today-remoting/src/testFixtures/java/infra/remoting/test/TestChannel.java @@ -22,8 +22,8 @@ import java.time.Duration; import java.util.concurrent.atomic.AtomicLong; -import infra.remoting.Payload; import infra.remoting.Channel; +import infra.remoting.Payload; import infra.remoting.util.ByteBufPayload; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; diff --git a/today-remoting/src/testFixtures/java/infra/remoting/test/TestConnection.java b/today-remoting/src/testFixtures/java/infra/remoting/test/TestConnection.java index 729a208..de4def8 100644 --- a/today-remoting/src/testFixtures/java/infra/remoting/test/TestConnection.java +++ b/today-remoting/src/testFixtures/java/infra/remoting/test/TestConnection.java @@ -17,17 +17,17 @@ package infra.remoting.test; +import org.jspecify.annotations.Nullable; import org.reactivestreams.Subscription; import java.net.SocketAddress; import java.util.function.BiFunction; -import infra.lang.Nullable; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufAllocator; import infra.remoting.Connection; import infra.remoting.ProtocolErrorException; import infra.remoting.frame.PayloadFrameCodec; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufAllocator; import reactor.core.CoreSubscriber; import reactor.core.Fuseable; import reactor.core.Scannable; diff --git a/today-remoting/src/testFixtures/java/infra/remoting/test/TestFrames.java b/today-remoting/src/testFixtures/java/infra/remoting/test/TestFrames.java index 7f594c4..4dbf700 100644 --- a/today-remoting/src/testFixtures/java/infra/remoting/test/TestFrames.java +++ b/today-remoting/src/testFixtures/java/infra/remoting/test/TestFrames.java @@ -17,9 +17,6 @@ package infra.remoting.test; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufAllocator; -import io.netty.buffer.Unpooled; import infra.remoting.Payload; import infra.remoting.frame.CancelFrameCodec; import infra.remoting.frame.ErrorFrameCodec; @@ -36,6 +33,9 @@ import infra.remoting.frame.SetupFrameCodec; import infra.remoting.util.DefaultPayload; import infra.remoting.util.EmptyPayload; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufAllocator; +import io.netty.buffer.Unpooled; /** Test instances of all frame types. */ public final class TestFrames { diff --git a/today-remoting/src/testFixtures/java/infra/remoting/test/TransportTest.java b/today-remoting/src/testFixtures/java/infra/remoting/test/TransportTest.java index 8429abb..3cde207 100644 --- a/today-remoting/src/testFixtures/java/infra/remoting/test/TransportTest.java +++ b/today-remoting/src/testFixtures/java/infra/remoting/test/TransportTest.java @@ -35,10 +35,10 @@ import java.util.stream.Collectors; import java.util.zip.GZIPInputStream; -import io.netty.util.ReferenceCounted; -import infra.remoting.Payload; import infra.remoting.Channel; +import infra.remoting.Payload; import infra.remoting.util.ByteBufPayload; +import io.netty.util.ReferenceCounted; import reactor.core.Exceptions; import reactor.core.publisher.Flux; import reactor.core.publisher.Hooks; diff --git a/today-remoting/src/testFixtures/java/infra/remoting/test/package-info.java b/today-remoting/src/testFixtures/java/infra/remoting/test/package-info.java index cb1596e..66c675b 100644 --- a/today-remoting/src/testFixtures/java/infra/remoting/test/package-info.java +++ b/today-remoting/src/testFixtures/java/infra/remoting/test/package-info.java @@ -19,4 +19,3 @@ @NonNullApi package infra.remoting.test; -import infra.lang.NonNullApi; diff --git a/today-service-api/src/main/java/infra/cloud/RpcResponse.java b/today-service-api/src/main/java/infra/cloud/RpcResponse.java index 4c0e06f..4e58c14 100644 --- a/today-service-api/src/main/java/infra/cloud/RpcResponse.java +++ b/today-service-api/src/main/java/infra/cloud/RpcResponse.java @@ -17,11 +17,12 @@ package infra.cloud; +import org.jspecify.annotations.Nullable; + import java.io.Serial; import java.io.Serializable; import infra.cloud.service.ServiceMethod; -import infra.lang.Nullable; /** * @author TODAY 2021/7/4 22:31 diff --git a/today-service-api/src/main/java/infra/cloud/serialize/MessagePackInput.java b/today-service-api/src/main/java/infra/cloud/serialize/MessagePackInput.java index 6c77db6..9c3d202 100644 --- a/today-service-api/src/main/java/infra/cloud/serialize/MessagePackInput.java +++ b/today-service-api/src/main/java/infra/cloud/serialize/MessagePackInput.java @@ -17,6 +17,8 @@ package infra.cloud.serialize; +import org.jspecify.annotations.Nullable; + import java.lang.reflect.Array; import java.math.BigInteger; import java.nio.charset.Charset; @@ -39,7 +41,6 @@ import infra.cloud.serialize.format.MessageSizeException; import infra.cloud.serialize.format.MessageTypeException; import infra.lang.Constant; -import infra.lang.Nullable; import infra.lang.TodayStrategies; import infra.util.CollectionUtils; import io.netty.buffer.ByteBuf; diff --git a/today-service-api/src/main/java/infra/cloud/serialize/MessagePackOutput.java b/today-service-api/src/main/java/infra/cloud/serialize/MessagePackOutput.java index 7657647..d35b816 100644 --- a/today-service-api/src/main/java/infra/cloud/serialize/MessagePackOutput.java +++ b/today-service-api/src/main/java/infra/cloud/serialize/MessagePackOutput.java @@ -17,6 +17,8 @@ package infra.cloud.serialize; +import org.jspecify.annotations.Nullable; + import java.nio.charset.StandardCharsets; import java.time.Instant; import java.util.List; @@ -25,7 +27,6 @@ import java.util.function.Consumer; import infra.cloud.serialize.format.MessagePack; -import infra.lang.Nullable; import io.netty.buffer.ByteBuf; import static infra.cloud.serialize.format.MessagePack.Code.ARRAY16; diff --git a/today-service-api/src/main/java/infra/cloud/serialize/ProtobufArgumentSerialization.java b/today-service-api/src/main/java/infra/cloud/serialize/ProtobufArgumentSerialization.java index 5199ec3..479d324 100644 --- a/today-service-api/src/main/java/infra/cloud/serialize/ProtobufArgumentSerialization.java +++ b/today-service-api/src/main/java/infra/cloud/serialize/ProtobufArgumentSerialization.java @@ -20,11 +20,12 @@ import com.google.protobuf.InvalidProtocolBufferException; import com.google.protobuf.Message; +import org.jspecify.annotations.Nullable; + import java.lang.reflect.Method; import infra.cloud.service.ServiceMethod; import infra.core.MethodParameter; -import infra.lang.Nullable; import infra.util.ConcurrentReferenceHashMap; /** diff --git a/today-service-api/src/main/java/infra/cloud/serialize/RpcArgumentSerialization.java b/today-service-api/src/main/java/infra/cloud/serialize/RpcArgumentSerialization.java index 0d6b711..40d3d7a 100644 --- a/today-service-api/src/main/java/infra/cloud/serialize/RpcArgumentSerialization.java +++ b/today-service-api/src/main/java/infra/cloud/serialize/RpcArgumentSerialization.java @@ -17,8 +17,9 @@ package infra.cloud.serialize; +import org.jspecify.annotations.Nullable; + import infra.core.MethodParameter; -import infra.lang.Nullable; /** * @author 海子 Yang diff --git a/today-service-api/src/main/java/infra/cloud/serialize/SimpleValueArgumentSerialization.java b/today-service-api/src/main/java/infra/cloud/serialize/SimpleValueArgumentSerialization.java index bbb3f8c..621bbb2 100644 --- a/today-service-api/src/main/java/infra/cloud/serialize/SimpleValueArgumentSerialization.java +++ b/today-service-api/src/main/java/infra/cloud/serialize/SimpleValueArgumentSerialization.java @@ -17,13 +17,14 @@ package infra.cloud.serialize; +import org.jspecify.annotations.Nullable; + import java.util.HashMap; import java.util.Map; import infra.beans.BeanUtils; import infra.cloud.serialize.value.ValueSerialization; import infra.core.MethodParameter; -import infra.lang.Nullable; import static infra.cloud.serialize.value.ValueSerialization.map; diff --git a/today-service-api/src/main/java/infra/cloud/serialize/package-info.java b/today-service-api/src/main/java/infra/cloud/serialize/package-info.java index e0afbce..7033042 100644 --- a/today-service-api/src/main/java/infra/cloud/serialize/package-info.java +++ b/today-service-api/src/main/java/infra/cloud/serialize/package-info.java @@ -22,5 +22,3 @@ @NonNullFields package infra.cloud.serialize; -import infra.lang.NonNullApi; -import infra.lang.NonNullFields; \ No newline at end of file diff --git a/today-service-api/src/main/java/infra/cloud/service/InvocationResult.java b/today-service-api/src/main/java/infra/cloud/service/InvocationResult.java index ce90d2e..1a3649f 100644 --- a/today-service-api/src/main/java/infra/cloud/service/InvocationResult.java +++ b/today-service-api/src/main/java/infra/cloud/service/InvocationResult.java @@ -17,10 +17,10 @@ package infra.cloud.service; +import org.jspecify.annotations.Nullable; import org.reactivestreams.Publisher; import infra.core.AttributeAccessor; -import infra.lang.Nullable; import infra.util.concurrent.Future; /** diff --git a/today-service-api/src/main/java/infra/cloud/service/ServiceMethod.java b/today-service-api/src/main/java/infra/cloud/service/ServiceMethod.java index 14b5223..82aef4a 100644 --- a/today-service-api/src/main/java/infra/cloud/service/ServiceMethod.java +++ b/today-service-api/src/main/java/infra/cloud/service/ServiceMethod.java @@ -17,10 +17,11 @@ package infra.cloud.service; +import org.jspecify.annotations.Nullable; + import java.lang.reflect.Method; import infra.core.MethodParameter; -import infra.lang.Nullable; /** * @author 海子 Yang diff --git a/today-service-api/src/main/java/infra/cloud/service/package-info.java b/today-service-api/src/main/java/infra/cloud/service/package-info.java index 9b1fd46..5ebfff9 100644 --- a/today-service-api/src/main/java/infra/cloud/service/package-info.java +++ b/today-service-api/src/main/java/infra/cloud/service/package-info.java @@ -19,5 +19,3 @@ @NonNullFields package infra.cloud.service; -import infra.lang.NonNullApi; -import infra.lang.NonNullFields; \ No newline at end of file diff --git a/today-service-client/src/main/java/infra/cloud/ServiceTimeoutException.java b/today-service-client/src/main/java/infra/cloud/ServiceTimeoutException.java index 48012da..b740ef6 100644 --- a/today-service-client/src/main/java/infra/cloud/ServiceTimeoutException.java +++ b/today-service-client/src/main/java/infra/cloud/ServiceTimeoutException.java @@ -17,7 +17,7 @@ package infra.cloud; -import infra.lang.Nullable; +import org.jspecify.annotations.Nullable; /** * @author Harry Yang diff --git a/today-service-client/src/main/java/infra/cloud/client/annotation/ServiceDependencyResolvingStrategy.java b/today-service-client/src/main/java/infra/cloud/client/annotation/ServiceDependencyResolvingStrategy.java index 4393d54..bd20fc2 100644 --- a/today-service-client/src/main/java/infra/cloud/client/annotation/ServiceDependencyResolvingStrategy.java +++ b/today-service-client/src/main/java/infra/cloud/client/annotation/ServiceDependencyResolvingStrategy.java @@ -17,11 +17,12 @@ package infra.cloud.client.annotation; +import org.jspecify.annotations.Nullable; + import infra.beans.factory.config.DependencyDescriptor; import infra.beans.factory.support.DependencyResolvingStrategy; import infra.cloud.service.ServiceProvider; import infra.context.ApplicationContext; -import infra.lang.Nullable; import infra.stereotype.Service; /** diff --git a/today-service-client/src/main/java/infra/cloud/service/DefaultServiceProxyFactory.java b/today-service-client/src/main/java/infra/cloud/service/DefaultServiceProxyFactory.java index b20bfdb..d9d2bb2 100644 --- a/today-service-client/src/main/java/infra/cloud/service/DefaultServiceProxyFactory.java +++ b/today-service-client/src/main/java/infra/cloud/service/DefaultServiceProxyFactory.java @@ -17,6 +17,8 @@ package infra.cloud.service; +import org.jspecify.annotations.Nullable; + import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; @@ -26,7 +28,6 @@ import java.util.stream.Collectors; import infra.lang.Assert; -import infra.lang.Nullable; import infra.util.ReflectionUtils; import io.netty.buffer.ByteBufAllocator; diff --git a/today-service-client/src/main/java/infra/cloud/service/RequestResponseResult.java b/today-service-client/src/main/java/infra/cloud/service/RequestResponseResult.java index 0f81484..c634c73 100644 --- a/today-service-client/src/main/java/infra/cloud/service/RequestResponseResult.java +++ b/today-service-client/src/main/java/infra/cloud/service/RequestResponseResult.java @@ -17,10 +17,11 @@ package infra.cloud.service; +import org.jspecify.annotations.Nullable; + import java.util.function.Function; import infra.cloud.service.serialize.ResponseDeserializer; -import infra.lang.Nullable; import infra.remoting.Payload; import infra.util.concurrent.Future; import infra.util.concurrent.PublisherFuture; diff --git a/today-service-client/src/main/java/infra/cloud/service/ReturnValueResolver.java b/today-service-client/src/main/java/infra/cloud/service/ReturnValueResolver.java index 4bc0cc1..94eed9a 100644 --- a/today-service-client/src/main/java/infra/cloud/service/ReturnValueResolver.java +++ b/today-service-client/src/main/java/infra/cloud/service/ReturnValueResolver.java @@ -17,7 +17,7 @@ package infra.cloud.service; -import infra.lang.Nullable; +import org.jspecify.annotations.Nullable; /** * @author 海子 Yang diff --git a/today-service-client/src/main/java/infra/cloud/service/ServiceInterfaceMethod.java b/today-service-client/src/main/java/infra/cloud/service/ServiceInterfaceMethod.java index dd212c6..a6f6cac 100644 --- a/today-service-client/src/main/java/infra/cloud/service/ServiceInterfaceMethod.java +++ b/today-service-client/src/main/java/infra/cloud/service/ServiceInterfaceMethod.java @@ -17,11 +17,11 @@ package infra.cloud.service; +import org.jspecify.annotations.Nullable; + import java.lang.reflect.Method; import java.util.ArrayList; -import infra.lang.Nullable; - /** * @author Harry Yang * @since 1.0 2024/1/7 21:03 diff --git a/today-service-client/src/main/java/infra/cloud/service/ServiceMethodInvoker.java b/today-service-client/src/main/java/infra/cloud/service/ServiceMethodInvoker.java index 1c3cdb2..68e21b0 100644 --- a/today-service-client/src/main/java/infra/cloud/service/ServiceMethodInvoker.java +++ b/today-service-client/src/main/java/infra/cloud/service/ServiceMethodInvoker.java @@ -17,6 +17,7 @@ package infra.cloud.service; +import org.jspecify.annotations.Nullable; import org.reactivestreams.Publisher; import org.reactivestreams.Subscriber; import org.reactivestreams.Subscription; @@ -24,7 +25,6 @@ import infra.cloud.RpcRequest; import infra.cloud.service.serialize.RequestSerializer; import infra.cloud.service.serialize.ResponseDeserializer; -import infra.lang.Nullable; import infra.remoting.Payload; import infra.remoting.RemotingOperations; import infra.remoting.util.ByteBufPayload; diff --git a/today-service-client/src/test/java/infra/cloud/service/ServiceInvokerFactoryTests.java b/today-service-client/src/test/java/infra/cloud/service/ServiceInvokerFactoryTests.java index df0c59b..2b96802 100644 --- a/today-service-client/src/test/java/infra/cloud/service/ServiceInvokerFactoryTests.java +++ b/today-service-client/src/test/java/infra/cloud/service/ServiceInvokerFactoryTests.java @@ -19,12 +19,6 @@ import org.junit.jupiter.api.Test; -import cn.taketoday.demo.service.UserService; -import infra.cloud.client.simple.SimpleDiscoveryClient; -import infra.cloud.client.simple.SimpleDiscoveryProperties; - -import static org.assertj.core.api.Assertions.assertThat; - /** * @author 海子 Yang * @since 1.0 2025/8/9 20:43 diff --git a/today-service-provider/src/main/java/infra/cloud/provider/InvocableMethod.java b/today-service-provider/src/main/java/infra/cloud/provider/InvocableMethod.java index b1cc0bb..7ad4c37 100644 --- a/today-service-provider/src/main/java/infra/cloud/provider/InvocableMethod.java +++ b/today-service-provider/src/main/java/infra/cloud/provider/InvocableMethod.java @@ -17,11 +17,12 @@ package infra.cloud.provider; +import org.jspecify.annotations.Nullable; + import java.lang.reflect.Method; import infra.cloud.service.ServiceInterfaceMetadata; import infra.cloud.service.ServiceMethod; -import infra.lang.Nullable; import infra.reflect.MethodInvoker; /** diff --git a/today-service-provider/src/main/java/infra/cloud/provider/LocalServiceHolder.java b/today-service-provider/src/main/java/infra/cloud/provider/LocalServiceHolder.java index dcc8b5e..c4c27cb 100644 --- a/today-service-provider/src/main/java/infra/cloud/provider/LocalServiceHolder.java +++ b/today-service-provider/src/main/java/infra/cloud/provider/LocalServiceHolder.java @@ -17,6 +17,8 @@ package infra.cloud.provider; +import org.jspecify.annotations.Nullable; + import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -28,7 +30,6 @@ import infra.context.ApplicationContext; import infra.context.support.ApplicationObjectSupport; import infra.lang.Assert; -import infra.lang.Nullable; import infra.stereotype.Service; import infra.util.ClassUtils; import infra.util.MultiValueMap; diff --git a/today-service-provider/src/main/java/infra/cloud/provider/RemoteRequest.java b/today-service-provider/src/main/java/infra/cloud/provider/RemoteRequest.java index e1dde95..6dda81f 100644 --- a/today-service-provider/src/main/java/infra/cloud/provider/RemoteRequest.java +++ b/today-service-provider/src/main/java/infra/cloud/provider/RemoteRequest.java @@ -17,7 +17,7 @@ package infra.cloud.provider; -import infra.lang.Nullable; +import org.jspecify.annotations.Nullable; /** * @author 海子 Yang diff --git a/today-service-provider/src/main/java/infra/cloud/provider/ResponseSerializer.java b/today-service-provider/src/main/java/infra/cloud/provider/ResponseSerializer.java index b235e5a..21491c8 100644 --- a/today-service-provider/src/main/java/infra/cloud/provider/ResponseSerializer.java +++ b/today-service-provider/src/main/java/infra/cloud/provider/ResponseSerializer.java @@ -17,13 +17,14 @@ package infra.cloud.provider; +import org.jspecify.annotations.Nullable; + import java.util.List; import infra.cloud.serialize.MessagePackOutput; import infra.cloud.serialize.Output; import infra.cloud.serialize.ReturnValueSerializer; import infra.cloud.service.ServiceMethod; -import infra.lang.Nullable; import infra.remoting.Payload; import infra.remoting.util.ByteBufPayload; import io.netty.buffer.ByteBuf; diff --git a/today-service-provider/src/main/java/infra/cloud/provider/RpcRequestDeserializer.java b/today-service-provider/src/main/java/infra/cloud/provider/RpcRequestDeserializer.java index cf093a3..05dcd83 100644 --- a/today-service-provider/src/main/java/infra/cloud/provider/RpcRequestDeserializer.java +++ b/today-service-provider/src/main/java/infra/cloud/provider/RpcRequestDeserializer.java @@ -17,6 +17,8 @@ package infra.cloud.provider; +import org.jspecify.annotations.Nullable; + import java.lang.reflect.Method; import java.util.List; import java.util.Objects; @@ -30,7 +32,6 @@ import infra.cloud.service.ServiceInterfaceMetadataProvider; import infra.core.MethodParameter; import infra.lang.Assert; -import infra.lang.Nullable; import infra.reflect.MethodInvoker; import infra.util.MapCache; import io.netty.buffer.ByteBuf; diff --git a/today-service-provider/src/main/java/infra/cloud/provider/ServiceProviderServer.java b/today-service-provider/src/main/java/infra/cloud/provider/ServiceProviderServer.java index 25f9401..60e5586 100644 --- a/today-service-provider/src/main/java/infra/cloud/provider/ServiceProviderServer.java +++ b/today-service-provider/src/main/java/infra/cloud/provider/ServiceProviderServer.java @@ -17,8 +17,9 @@ package infra.cloud.provider; +import org.jspecify.annotations.Nullable; + import infra.context.SmartLifecycle; -import infra.lang.Nullable; import infra.logging.Logger; import infra.logging.LoggerFactory; import infra.remoting.Channel; diff --git a/today-service-provider/src/main/java/infra/cloud/provider/ServiceServerProperties.java b/today-service-provider/src/main/java/infra/cloud/provider/ServiceServerProperties.java index bc50108..00a634b 100644 --- a/today-service-provider/src/main/java/infra/cloud/provider/ServiceServerProperties.java +++ b/today-service-provider/src/main/java/infra/cloud/provider/ServiceServerProperties.java @@ -17,12 +17,13 @@ package infra.cloud.provider; +import org.jspecify.annotations.Nullable; + import java.time.Duration; import infra.cloud.service.config.ResumeProperties; import infra.context.properties.ConfigurationProperties; import infra.context.properties.NestedConfigurationProperty; -import infra.lang.Nullable; import infra.remoting.frame.FrameLengthCodec; import infra.util.DataSize; diff --git a/today-service-provider/src/main/java/infra/cloud/provider/annotation/config/ServiceProviderAutoConfiguration.java b/today-service-provider/src/main/java/infra/cloud/provider/annotation/config/ServiceProviderAutoConfiguration.java index 9df3412..890be98 100644 --- a/today-service-provider/src/main/java/infra/cloud/provider/annotation/config/ServiceProviderAutoConfiguration.java +++ b/today-service-provider/src/main/java/infra/cloud/provider/annotation/config/ServiceProviderAutoConfiguration.java @@ -17,6 +17,8 @@ package infra.cloud.provider.annotation.config; +import org.jspecify.annotations.Nullable; + import infra.cloud.client.annotation.ConditionalOnDiscoveryEnabled; import infra.cloud.net.InetProperties; import infra.cloud.net.InetService; @@ -36,7 +38,6 @@ import infra.context.condition.ConditionalOnBooleanProperty; import infra.context.condition.ConditionalOnMissingBean; import infra.context.properties.EnableConfigurationProperties; -import infra.lang.Nullable; import infra.remoting.Closeable; import infra.remoting.core.Resume; import infra.remoting.resume.InMemoryResumableFramesStoreFactory; diff --git a/today-service-provider/src/main/java/infra/cloud/provider/package-info.java b/today-service-provider/src/main/java/infra/cloud/provider/package-info.java index 3f37cd6..a84857b 100644 --- a/today-service-provider/src/main/java/infra/cloud/provider/package-info.java +++ b/today-service-provider/src/main/java/infra/cloud/provider/package-info.java @@ -19,5 +19,3 @@ @NonNullFields package infra.cloud.provider; -import infra.lang.NonNullApi; -import infra.lang.NonNullFields; \ No newline at end of file diff --git a/today-service-provider/src/test/java/infra/cloud/provider/LocalServiceHolderTests.java b/today-service-provider/src/test/java/infra/cloud/provider/LocalServiceHolderTests.java index 592a7ab..efcd0a4 100644 --- a/today-service-provider/src/test/java/infra/cloud/provider/LocalServiceHolderTests.java +++ b/today-service-provider/src/test/java/infra/cloud/provider/LocalServiceHolderTests.java @@ -17,8 +17,6 @@ package infra.cloud.provider; -import static org.junit.jupiter.api.Assertions.*; - /** * @author 海子 Yang * @since 1.0 2025/8/24 22:07 diff --git a/today-service-registration/src/main/java/infra/cloud/registry/ServiceRegisterFailedException.java b/today-service-registration/src/main/java/infra/cloud/registry/ServiceRegisterFailedException.java index c2ca8b2..ad43fcc 100644 --- a/today-service-registration/src/main/java/infra/cloud/registry/ServiceRegisterFailedException.java +++ b/today-service-registration/src/main/java/infra/cloud/registry/ServiceRegisterFailedException.java @@ -17,11 +17,12 @@ package infra.cloud.registry; +import org.jspecify.annotations.Nullable; + import java.io.Serial; import infra.cloud.RemotingException; import infra.cloud.client.Registration; -import infra.lang.Nullable; /** * @author TODAY 2021/7/11 17:19 diff --git a/today-service-registration/src/main/java/infra/cloud/registry/annotation/config/AutoServiceRegistrationAutoConfiguration.java b/today-service-registration/src/main/java/infra/cloud/registry/annotation/config/AutoServiceRegistrationAutoConfiguration.java index 3311888..4e36cd6 100644 --- a/today-service-registration/src/main/java/infra/cloud/registry/annotation/config/AutoServiceRegistrationAutoConfiguration.java +++ b/today-service-registration/src/main/java/infra/cloud/registry/annotation/config/AutoServiceRegistrationAutoConfiguration.java @@ -17,13 +17,14 @@ package infra.cloud.registry.annotation.config; +import org.jspecify.annotations.Nullable; + import infra.beans.factory.annotation.DisableDependencyInjection; import infra.cloud.registry.AutoServiceRegistration; import infra.cloud.registry.AutoServiceRegistrationProperties; import infra.context.annotation.Configuration; import infra.context.annotation.Import; import infra.context.condition.ConditionalOnProperty; -import infra.lang.Nullable; /** * @author Spencer Gibb diff --git a/today-service-registry-simple-server/src/main/java/infra/cloud/registry/simple/server/ServiceNotFoundException.java b/today-service-registry-simple-server/src/main/java/infra/cloud/registry/simple/server/ServiceNotFoundException.java index 373b873..c058fe2 100644 --- a/today-service-registry-simple-server/src/main/java/infra/cloud/registry/simple/server/ServiceNotFoundException.java +++ b/today-service-registry-simple-server/src/main/java/infra/cloud/registry/simple/server/ServiceNotFoundException.java @@ -17,10 +17,11 @@ package infra.cloud.registry.simple.server; +import org.jspecify.annotations.Nullable; + import java.io.Serial; import infra.cloud.RemotingException; -import infra.lang.Nullable; /** * @author Harry Yang diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/Input.java b/today-service-serialization/src/main/java/infra/cloud/serialize/Input.java index 787ead1..f7e1753 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/Input.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/Input.java @@ -17,14 +17,14 @@ package infra.cloud.serialize; +import org.jspecify.annotations.Nullable; + import java.time.Instant; import java.util.List; import java.util.Map; import java.util.function.Function; import java.util.function.Supplier; -import infra.lang.Nullable; - /** * An Input lets an application read primitive data types and objects from a source of data. * diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/Output.java b/today-service-serialization/src/main/java/infra/cloud/serialize/Output.java index 6d7423a..e14e07d 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/Output.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/Output.java @@ -17,14 +17,14 @@ package infra.cloud.serialize; +import org.jspecify.annotations.Nullable; + import java.time.Instant; import java.util.List; import java.util.Map; import java.util.function.BiConsumer; import java.util.function.Consumer; -import infra.lang.Nullable; - /** * @author 海子 Yang * @see java.io.DataOutput diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/SerializationException.java b/today-service-serialization/src/main/java/infra/cloud/serialize/SerializationException.java index 156a67b..a9af766 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/SerializationException.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/SerializationException.java @@ -17,7 +17,7 @@ package infra.cloud.serialize; -import infra.lang.Nullable; +import org.jspecify.annotations.Nullable; /** * @author 海子 Yang diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageFormatException.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageFormatException.java index d16b996..ce99b6f 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageFormatException.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageFormatException.java @@ -17,7 +17,7 @@ package infra.cloud.serialize.format; -import infra.lang.Nullable; +import org.jspecify.annotations.Nullable; /** * Thrown when the input message pack format is invalid diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageNeverUsedFormatException.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageNeverUsedFormatException.java index def13b5..da9745c 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageNeverUsedFormatException.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageNeverUsedFormatException.java @@ -17,7 +17,7 @@ package infra.cloud.serialize.format; -import infra.lang.Nullable; +import org.jspecify.annotations.Nullable; /** * Thrown when the input message pack format is invalid diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessagePack.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessagePack.java index f127a17..7c4de6a 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessagePack.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessagePack.java @@ -696,5 +696,5 @@ public int getBufferSize() { return bufferSize; } } - + } diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessagePackException.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessagePackException.java index 9cbab7c..7069879 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessagePackException.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessagePackException.java @@ -17,8 +17,9 @@ package infra.cloud.serialize.format; +import org.jspecify.annotations.Nullable; + import infra.cloud.serialize.SerializationException; -import infra.lang.Nullable; /** * A base class of all the message pack exceptions. diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessagePacker.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessagePacker.java index f8a1c78..8bcc8c9 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessagePacker.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessagePacker.java @@ -17,6 +17,8 @@ package infra.cloud.serialize.format; +import org.jspecify.annotations.Nullable; + import java.io.Closeable; import java.io.Flushable; import java.io.IOException; @@ -35,7 +37,6 @@ import infra.cloud.serialize.format.buffer.MessageBufferOutput; import infra.cloud.serialize.format.buffer.OutputStreamBufferOutput; import infra.cloud.serialize.format.value.Value; -import infra.lang.Nullable; import static infra.cloud.serialize.format.MessagePack.Code.ARRAY16; import static infra.cloud.serialize.format.MessagePack.Code.ARRAY32; diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageTypeException.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageTypeException.java index 51a9802..5b4968f 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageTypeException.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageTypeException.java @@ -17,7 +17,7 @@ package infra.cloud.serialize.format; -import infra.lang.Nullable; +import org.jspecify.annotations.Nullable; /** * Thrown when a type mismatch error occurs diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/MessageBufferInput.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/MessageBufferInput.java index 36ed055..6d0108c 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/MessageBufferInput.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/MessageBufferInput.java @@ -17,11 +17,11 @@ package infra.cloud.serialize.format.buffer; +import org.jspecify.annotations.Nullable; + import java.io.Closeable; import java.io.IOException; -import infra.lang.Nullable; - /** * Provides a sequence of MessageBuffer instances. *

          diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/package-info.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/package-info.java index 91f9755..7fe4ec8 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/package-info.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/package-info.java @@ -22,5 +22,3 @@ @NonNullApi package infra.cloud.serialize.format; -import infra.lang.NonNullApi; -import infra.lang.NonNullFields; \ No newline at end of file From d626124fdf1d131ae2d8a79b69046d9c1ee7640a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Wed, 1 Oct 2025 16:49:21 +0800 Subject: [PATCH 059/104] :art: --- today-cloud-core/src/main/java/infra/cloud/package-info.java | 4 ++-- .../src/main/java/infra/remoting/micrometer/package-info.java | 3 +-- .../java/infra/remoting/transport/local/package-info.java | 3 +-- .../infra/remoting/transport/netty/client/package-info.java | 2 +- .../java/infra/remoting/transport/netty/package-info.java | 3 +-- .../infra/remoting/transport/netty/server/package-info.java | 2 +- .../main/java/infra/remoting/transport/tcp/package-info.java | 3 +-- .../src/main/java/infra/remoting/core/package-info.java | 4 ++-- .../src/main/java/infra/remoting/error/package-info.java | 3 ++- .../main/java/infra/remoting/frame/decoder/package-info.java | 3 ++- .../src/main/java/infra/remoting/frame/package-info.java | 3 ++- .../src/main/java/infra/remoting/internal/package-info.java | 4 ++-- .../src/main/java/infra/remoting/keepalive/package-info.java | 4 ++-- .../src/main/java/infra/remoting/lb/package-info.java | 4 ++-- .../src/main/java/infra/remoting/lease/package-info.java | 3 ++- today-remoting/src/main/java/infra/remoting/package-info.java | 4 ++-- .../src/main/java/infra/remoting/plugins/package-info.java | 3 ++- .../src/main/java/infra/remoting/resume/package-info.java | 3 ++- .../src/main/java/infra/remoting/transport/package-info.java | 3 ++- .../src/main/java/infra/remoting/util/package-info.java | 3 ++- .../testFixtures/java/infra/remoting/test/package-info.java | 2 +- .../src/main/java/infra/cloud/serialize/package-info.java | 3 +-- .../src/main/java/infra/cloud/service/package-info.java | 3 +-- .../src/main/java/infra/cloud/provider/package-info.java | 3 +-- .../main/java/infra/cloud/serialize/format/package-info.java | 4 ++-- 25 files changed, 40 insertions(+), 39 deletions(-) diff --git a/today-cloud-core/src/main/java/infra/cloud/package-info.java b/today-cloud-core/src/main/java/infra/cloud/package-info.java index 3426815..fa784e7 100644 --- a/today-cloud-core/src/main/java/infra/cloud/package-info.java +++ b/today-cloud-core/src/main/java/infra/cloud/package-info.java @@ -15,7 +15,7 @@ * along with this program. If not, see [http://www.gnu.org/licenses/] */ -@NonNullApi -@NonNullFields +@NullMarked package infra.cloud; +import org.jspecify.annotations.NullMarked; \ No newline at end of file diff --git a/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/package-info.java b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/package-info.java index 15a919e..46034dd 100644 --- a/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/package-info.java +++ b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/package-info.java @@ -20,8 +20,7 @@ * * @see Micrometer */ -@NonNullApi -@NonNullFields +@NullMarked package infra.remoting.micrometer; import reactor.util.annotation.NonNullApi; diff --git a/today-remoting-transport-local/src/main/java/infra/remoting/transport/local/package-info.java b/today-remoting-transport-local/src/main/java/infra/remoting/transport/local/package-info.java index bb6a917..6db3a5e 100644 --- a/today-remoting-transport-local/src/main/java/infra/remoting/transport/local/package-info.java +++ b/today-remoting-transport-local/src/main/java/infra/remoting/transport/local/package-info.java @@ -18,7 +18,6 @@ /** * The local remoting transport implementation. */ -@NonNullApi -@NonNullFields +@NullMarked package infra.remoting.transport.local; diff --git a/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/client/package-info.java b/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/client/package-info.java index 42684b7..25acd10 100644 --- a/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/client/package-info.java +++ b/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/client/package-info.java @@ -16,6 +16,6 @@ */ /** The Netty-based client transport implementations. */ -@NonNullApi +@NullMarked package infra.remoting.transport.netty.client; diff --git a/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/package-info.java b/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/package-info.java index c45d6c0..752669b 100644 --- a/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/package-info.java +++ b/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/package-info.java @@ -18,7 +18,6 @@ /** * The Netty-based remoting transport implementations. */ -@NonNullApi -@NonNullFields +@NullMarked package infra.remoting.transport.netty; diff --git a/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/server/package-info.java b/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/server/package-info.java index 658953c..21b0f28 100644 --- a/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/server/package-info.java +++ b/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/server/package-info.java @@ -16,6 +16,6 @@ */ /** The Netty-based server transport implementations. */ -@NonNullApi +@NullMarked package infra.remoting.transport.netty.server; diff --git a/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/tcp/package-info.java b/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/tcp/package-info.java index fb6b835..5b54897 100644 --- a/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/tcp/package-info.java +++ b/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/tcp/package-info.java @@ -18,7 +18,6 @@ /** * The Netty-based TCP transport implementations. */ -@NonNullApi -@NonNullFields +@NullMarked package infra.remoting.transport.tcp; diff --git a/today-remoting/src/main/java/infra/remoting/core/package-info.java b/today-remoting/src/main/java/infra/remoting/core/package-info.java index 5d64cc3..6b8f77e 100644 --- a/today-remoting/src/main/java/infra/remoting/core/package-info.java +++ b/today-remoting/src/main/java/infra/remoting/core/package-info.java @@ -23,7 +23,7 @@ *

          This package also contains a package private classes that implement support for the main * interactions. */ -@NonNullApi -@NonNullFields +@NullMarked package infra.remoting.core; +import org.jspecify.annotations.NullMarked; \ No newline at end of file diff --git a/today-remoting/src/main/java/infra/remoting/error/package-info.java b/today-remoting/src/main/java/infra/remoting/error/package-info.java index 604d6c1..f719d7e 100644 --- a/today-remoting/src/main/java/infra/remoting/error/package-info.java +++ b/today-remoting/src/main/java/infra/remoting/error/package-info.java @@ -21,6 +21,7 @@ * @see Error * Codes */ -@NonNullApi +@NullMarked package infra.remoting.error; +import org.jspecify.annotations.NullMarked; \ No newline at end of file diff --git a/today-remoting/src/main/java/infra/remoting/frame/decoder/package-info.java b/today-remoting/src/main/java/infra/remoting/frame/decoder/package-info.java index 904d693..8f767df 100644 --- a/today-remoting/src/main/java/infra/remoting/frame/decoder/package-info.java +++ b/today-remoting/src/main/java/infra/remoting/frame/decoder/package-info.java @@ -19,6 +19,7 @@ * Support for encoding and decoding of protocol frames to and from {@link infra.remoting.Payload * Payload}. */ -@NonNullApi +@NullMarked package infra.remoting.frame.decoder; +import org.jspecify.annotations.NullMarked; \ No newline at end of file diff --git a/today-remoting/src/main/java/infra/remoting/frame/package-info.java b/today-remoting/src/main/java/infra/remoting/frame/package-info.java index 9dbd990..1aee553 100644 --- a/today-remoting/src/main/java/infra/remoting/frame/package-info.java +++ b/today-remoting/src/main/java/infra/remoting/frame/package-info.java @@ -19,6 +19,7 @@ * Support for encoding and decoding of protocol frames to and from {@link infra.remoting.Payload * Payload}. */ -@NonNullApi +@NullMarked package infra.remoting.frame; +import org.jspecify.annotations.NullMarked; \ No newline at end of file diff --git a/today-remoting/src/main/java/infra/remoting/internal/package-info.java b/today-remoting/src/main/java/infra/remoting/internal/package-info.java index b19b94e..f9c6ebb 100644 --- a/today-remoting/src/main/java/infra/remoting/internal/package-info.java +++ b/today-remoting/src/main/java/infra/remoting/internal/package-info.java @@ -19,7 +19,7 @@ * Internal package and must not be used outside this project. There are no guarantees for * API compatibility. */ -@NonNullApi -@NonNullFields +@NullMarked package infra.remoting.internal; +import org.jspecify.annotations.NullMarked; \ No newline at end of file diff --git a/today-remoting/src/main/java/infra/remoting/keepalive/package-info.java b/today-remoting/src/main/java/infra/remoting/keepalive/package-info.java index 3cbb4ee..a5424f9 100644 --- a/today-remoting/src/main/java/infra/remoting/keepalive/package-info.java +++ b/today-remoting/src/main/java/infra/remoting/keepalive/package-info.java @@ -18,7 +18,7 @@ /** * Support classes for sending and keeping track of KEEPALIVE frames from the remote. */ -@NonNullApi -@NonNullFields +@NullMarked package infra.remoting.keepalive; +import org.jspecify.annotations.NullMarked; \ No newline at end of file diff --git a/today-remoting/src/main/java/infra/remoting/lb/package-info.java b/today-remoting/src/main/java/infra/remoting/lb/package-info.java index 0e2809d..6efed23 100644 --- a/today-remoting/src/main/java/infra/remoting/lb/package-info.java +++ b/today-remoting/src/main/java/infra/remoting/lb/package-info.java @@ -18,7 +18,7 @@ /** * Support client load-balancing in remoting Java. */ -@NonNullApi -@NonNullFields +@NullMarked package infra.remoting.lb; +import org.jspecify.annotations.NullMarked; \ No newline at end of file diff --git a/today-remoting/src/main/java/infra/remoting/lease/package-info.java b/today-remoting/src/main/java/infra/remoting/lease/package-info.java index 5592dd2..9126f5e 100644 --- a/today-remoting/src/main/java/infra/remoting/lease/package-info.java +++ b/today-remoting/src/main/java/infra/remoting/lease/package-info.java @@ -22,6 +22,7 @@ * href="https://github.com/today-tech/today-cloud/blob/master/today-remoting/Protocol.md#resuming-operation">Resuming * Operation */ -@NonNullApi +@NullMarked package infra.remoting.lease; +import org.jspecify.annotations.NullMarked; \ No newline at end of file diff --git a/today-remoting/src/main/java/infra/remoting/package-info.java b/today-remoting/src/main/java/infra/remoting/package-info.java index 1746cf1..4315062 100644 --- a/today-remoting/src/main/java/infra/remoting/package-info.java +++ b/today-remoting/src/main/java/infra/remoting/package-info.java @@ -15,7 +15,7 @@ * along with this program. If not, see [http://www.gnu.org/licenses/] */ -@NonNullApi -@NonNullFields +@NullMarked package infra.remoting; +import org.jspecify.annotations.NullMarked; \ No newline at end of file diff --git a/today-remoting/src/main/java/infra/remoting/plugins/package-info.java b/today-remoting/src/main/java/infra/remoting/plugins/package-info.java index 9f80ddd..836c1d4 100644 --- a/today-remoting/src/main/java/infra/remoting/plugins/package-info.java +++ b/today-remoting/src/main/java/infra/remoting/plugins/package-info.java @@ -16,6 +16,7 @@ */ /** Contracts for interception of transports, connections, and requests. */ -@NonNullApi +@NullMarked package infra.remoting.plugins; +import org.jspecify.annotations.NullMarked; \ No newline at end of file diff --git a/today-remoting/src/main/java/infra/remoting/resume/package-info.java b/today-remoting/src/main/java/infra/remoting/resume/package-info.java index 1e6d219..2435b1d 100644 --- a/today-remoting/src/main/java/infra/remoting/resume/package-info.java +++ b/today-remoting/src/main/java/infra/remoting/resume/package-info.java @@ -22,6 +22,7 @@ * href="https://github.com/today-tech/today-cloud/blob/master/today-remoting/Protocol.md#resuming-operation">Resuming * Operation */ -@NonNullApi +@NullMarked package infra.remoting.resume; +import org.jspecify.annotations.NullMarked; \ No newline at end of file diff --git a/today-remoting/src/main/java/infra/remoting/transport/package-info.java b/today-remoting/src/main/java/infra/remoting/transport/package-info.java index 1b9fc44..d7878b8 100644 --- a/today-remoting/src/main/java/infra/remoting/transport/package-info.java +++ b/today-remoting/src/main/java/infra/remoting/transport/package-info.java @@ -16,6 +16,7 @@ */ /** Client and server transport contracts for pluggable transports. */ -@NonNullApi +@NullMarked package infra.remoting.transport; +import org.jspecify.annotations.NullMarked; \ No newline at end of file diff --git a/today-remoting/src/main/java/infra/remoting/util/package-info.java b/today-remoting/src/main/java/infra/remoting/util/package-info.java index b699ba7..70e446b 100644 --- a/today-remoting/src/main/java/infra/remoting/util/package-info.java +++ b/today-remoting/src/main/java/infra/remoting/util/package-info.java @@ -16,6 +16,7 @@ */ /** Shared utility classes and {@link infra.remoting.Payload} implementations. */ -@NonNullApi +@NullMarked package infra.remoting.util; +import org.jspecify.annotations.NullMarked; \ No newline at end of file diff --git a/today-remoting/src/testFixtures/java/infra/remoting/test/package-info.java b/today-remoting/src/testFixtures/java/infra/remoting/test/package-info.java index 66c675b..b85e89a 100644 --- a/today-remoting/src/testFixtures/java/infra/remoting/test/package-info.java +++ b/today-remoting/src/testFixtures/java/infra/remoting/test/package-info.java @@ -16,6 +16,6 @@ */ /** Utilities for testing components. */ -@NonNullApi +@NullMarked package infra.remoting.test; diff --git a/today-service-api/src/main/java/infra/cloud/serialize/package-info.java b/today-service-api/src/main/java/infra/cloud/serialize/package-info.java index 7033042..b365476 100644 --- a/today-service-api/src/main/java/infra/cloud/serialize/package-info.java +++ b/today-service-api/src/main/java/infra/cloud/serialize/package-info.java @@ -18,7 +18,6 @@ /** * serialize */ -@NonNullApi -@NonNullFields +@NullMarked package infra.cloud.serialize; diff --git a/today-service-api/src/main/java/infra/cloud/service/package-info.java b/today-service-api/src/main/java/infra/cloud/service/package-info.java index 5ebfff9..d937934 100644 --- a/today-service-api/src/main/java/infra/cloud/service/package-info.java +++ b/today-service-api/src/main/java/infra/cloud/service/package-info.java @@ -15,7 +15,6 @@ * along with this program. If not, see [http://www.gnu.org/licenses/] */ -@NonNullApi -@NonNullFields +@NullMarked package infra.cloud.service; diff --git a/today-service-provider/src/main/java/infra/cloud/provider/package-info.java b/today-service-provider/src/main/java/infra/cloud/provider/package-info.java index a84857b..37caa80 100644 --- a/today-service-provider/src/main/java/infra/cloud/provider/package-info.java +++ b/today-service-provider/src/main/java/infra/cloud/provider/package-info.java @@ -15,7 +15,6 @@ * along with this program. If not, see [http://www.gnu.org/licenses/] */ -@NonNullApi -@NonNullFields +@NullMarked package infra.cloud.provider; diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/package-info.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/package-info.java index 7fe4ec8..74cb601 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/package-info.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/package-info.java @@ -18,7 +18,7 @@ /** * msgpack specification implementation */ -@NonNullFields -@NonNullApi +@NullMarked package infra.cloud.serialize.format; +import org.jspecify.annotations.NullMarked; \ No newline at end of file From 8e33773835cc429f740c7f05ec4b20a5d1e63d17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Wed, 1 Oct 2025 16:50:29 +0800 Subject: [PATCH 060/104] :art: --- .../src/main/java/infra/remoting/micrometer/package-info.java | 2 +- .../main/java/infra/remoting/transport/local/package-info.java | 1 + .../infra/remoting/transport/netty/client/package-info.java | 1 + .../main/java/infra/remoting/transport/netty/package-info.java | 1 + .../infra/remoting/transport/netty/server/package-info.java | 1 + .../main/java/infra/remoting/transport/tcp/package-info.java | 1 + .../src/testFixtures/java/infra/remoting/test/package-info.java | 1 + .../src/main/java/infra/cloud/serialize/package-info.java | 1 + .../src/main/java/infra/cloud/service/package-info.java | 1 + .../src/main/java/infra/cloud/provider/package-info.java | 1 + 10 files changed, 10 insertions(+), 1 deletion(-) diff --git a/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/package-info.java b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/package-info.java index 46034dd..16603bc 100644 --- a/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/package-info.java +++ b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/package-info.java @@ -23,4 +23,4 @@ @NullMarked package infra.remoting.micrometer; -import reactor.util.annotation.NonNullApi; +import org.jspecify.annotations.NullMarked; diff --git a/today-remoting-transport-local/src/main/java/infra/remoting/transport/local/package-info.java b/today-remoting-transport-local/src/main/java/infra/remoting/transport/local/package-info.java index 6db3a5e..0566d12 100644 --- a/today-remoting-transport-local/src/main/java/infra/remoting/transport/local/package-info.java +++ b/today-remoting-transport-local/src/main/java/infra/remoting/transport/local/package-info.java @@ -21,3 +21,4 @@ @NullMarked package infra.remoting.transport.local; +import org.jspecify.annotations.NullMarked; \ No newline at end of file diff --git a/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/client/package-info.java b/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/client/package-info.java index 25acd10..dae3f34 100644 --- a/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/client/package-info.java +++ b/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/client/package-info.java @@ -19,3 +19,4 @@ @NullMarked package infra.remoting.transport.netty.client; +import org.jspecify.annotations.NullMarked; \ No newline at end of file diff --git a/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/package-info.java b/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/package-info.java index 752669b..59ff962 100644 --- a/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/package-info.java +++ b/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/package-info.java @@ -21,3 +21,4 @@ @NullMarked package infra.remoting.transport.netty; +import org.jspecify.annotations.NullMarked; \ No newline at end of file diff --git a/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/server/package-info.java b/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/server/package-info.java index 21b0f28..d40bed1 100644 --- a/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/server/package-info.java +++ b/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/server/package-info.java @@ -19,3 +19,4 @@ @NullMarked package infra.remoting.transport.netty.server; +import org.jspecify.annotations.NullMarked; \ No newline at end of file diff --git a/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/tcp/package-info.java b/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/tcp/package-info.java index 5b54897..50e7ebe 100644 --- a/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/tcp/package-info.java +++ b/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/tcp/package-info.java @@ -21,3 +21,4 @@ @NullMarked package infra.remoting.transport.tcp; +import org.jspecify.annotations.NullMarked; \ No newline at end of file diff --git a/today-remoting/src/testFixtures/java/infra/remoting/test/package-info.java b/today-remoting/src/testFixtures/java/infra/remoting/test/package-info.java index b85e89a..c69a2e3 100644 --- a/today-remoting/src/testFixtures/java/infra/remoting/test/package-info.java +++ b/today-remoting/src/testFixtures/java/infra/remoting/test/package-info.java @@ -19,3 +19,4 @@ @NullMarked package infra.remoting.test; +import org.jspecify.annotations.NullMarked; \ No newline at end of file diff --git a/today-service-api/src/main/java/infra/cloud/serialize/package-info.java b/today-service-api/src/main/java/infra/cloud/serialize/package-info.java index b365476..17b26a5 100644 --- a/today-service-api/src/main/java/infra/cloud/serialize/package-info.java +++ b/today-service-api/src/main/java/infra/cloud/serialize/package-info.java @@ -21,3 +21,4 @@ @NullMarked package infra.cloud.serialize; +import org.jspecify.annotations.NullMarked; \ No newline at end of file diff --git a/today-service-api/src/main/java/infra/cloud/service/package-info.java b/today-service-api/src/main/java/infra/cloud/service/package-info.java index d937934..4fd4b46 100644 --- a/today-service-api/src/main/java/infra/cloud/service/package-info.java +++ b/today-service-api/src/main/java/infra/cloud/service/package-info.java @@ -18,3 +18,4 @@ @NullMarked package infra.cloud.service; +import org.jspecify.annotations.NullMarked; \ No newline at end of file diff --git a/today-service-provider/src/main/java/infra/cloud/provider/package-info.java b/today-service-provider/src/main/java/infra/cloud/provider/package-info.java index 37caa80..f17060e 100644 --- a/today-service-provider/src/main/java/infra/cloud/provider/package-info.java +++ b/today-service-provider/src/main/java/infra/cloud/provider/package-info.java @@ -18,3 +18,4 @@ @NullMarked package infra.cloud.provider; +import org.jspecify.annotations.NullMarked; \ No newline at end of file From 363eea829854543e7c40801f0a2563852ed47df2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Fri, 31 Oct 2025 19:17:07 +0800 Subject: [PATCH 061/104] :arrow_up: ./gradlew wrapper --gradle-version=9.2.0 --- gradle/wrapper/gradle-wrapper.jar | Bin 43764 -> 45457 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 5 +---- gradlew.bat | 3 +-- 4 files changed, 3 insertions(+), 7 deletions(-) diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 1b33c55baabb587c669f562ae36f953de2481846..8bdaf60c75ab801e22807dde59e12a8735a34077 100644 GIT binary patch delta 37256 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 delta 35551 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 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 2e11132..bad7c24 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-9.1.0-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.0-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew index 23d15a9..adff685 100755 --- a/gradlew +++ b/gradlew @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright © 2015-2021 the original authors. +# Copyright © 2015 the original authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -114,7 +114,6 @@ case "$( uname )" in #( NONSTOP* ) nonstop=true ;; esac -CLASSPATH="\\\"\\\"" # Determine the Java command to use to start the JVM. @@ -172,7 +171,6 @@ fi # For Cygwin or MSYS, switch paths to Windows format before running java if "$cygwin" || "$msys" ; then APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) - CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) JAVACMD=$( cygpath --unix "$JAVACMD" ) @@ -212,7 +210,6 @@ DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ - -classpath "$CLASSPATH" \ -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ "$@" diff --git a/gradlew.bat b/gradlew.bat index db3a6ac..c4bdd3a 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -70,11 +70,10 @@ goto fail :execute @rem Setup the command line -set CLASSPATH= @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* :end @rem End local scope for the variables with windows NT shell From b67c7f546874ab80b9b50d69dcc2660defd11122 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Fri, 30 Jan 2026 15:21:08 +0800 Subject: [PATCH 062/104] :recycle: --- .../src/main/java/infra/cloud/RpcRequest.java | 22 +++++------ ...ePackInput.java => MessagePackReader.java} | 14 +++---- ...PackOutput.java => MessagePackWriter.java} | 16 ++++---- .../ProtobufArgumentSerialization.java | 14 +++---- .../serialize/ReturnValueDeserializer.java | 4 +- .../serialize/ReturnValueSerializer.java | 4 +- .../serialize/RpcArgumentSerialization.java | 6 +-- .../SimpleValueArgumentSerialization.java | 22 +++++------ .../value/FuncValueSerialization.java | 18 ++++----- .../serialize/value/ValueSerialization.java | 12 +++--- .../service/serialize/RequestSerializer.java | 20 +++++----- .../serialize/ResponseDeserializer.java | 6 +-- .../cloud/provider/ResponseSerializer.java | 10 ++--- .../provider/RpcRequestDeserializer.java | 10 ++--- .../infra/cloud/serialize/Deserializer.java | 4 +- .../java/infra/cloud/serialize/Message.java | 37 +++++++++++++++---- .../serialize/{Input.java => Readable.java} | 12 +++--- .../infra/cloud/serialize/Serializer.java | 6 +-- .../serialize/{Output.java => Writable.java} | 14 +++---- .../infra/cloud/serialize/MessageTests.java | 14 +++---- .../{InputTests.java => ReadableTests.java} | 14 +++---- 21 files changed, 151 insertions(+), 128 deletions(-) rename today-service-api/src/main/java/infra/cloud/serialize/{MessagePackInput.java => MessagePackReader.java} (97%) rename today-service-api/src/main/java/infra/cloud/serialize/{MessagePackOutput.java => MessagePackWriter.java} (96%) rename today-service-serialization/src/main/java/infra/cloud/serialize/{Input.java => Readable.java} (93%) rename today-service-serialization/src/main/java/infra/cloud/serialize/{Output.java => Writable.java} (92%) rename today-service-serialization/src/test/java/infra/cloud/serialize/{InputTests.java => ReadableTests.java} (79%) diff --git a/today-service-api/src/main/java/infra/cloud/RpcRequest.java b/today-service-api/src/main/java/infra/cloud/RpcRequest.java index 17570ba..d29921d 100644 --- a/today-service-api/src/main/java/infra/cloud/RpcRequest.java +++ b/today-service-api/src/main/java/infra/cloud/RpcRequest.java @@ -1,5 +1,5 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the original author or authors. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -22,9 +22,9 @@ import java.util.Arrays; import java.util.Objects; -import infra.cloud.serialize.Input; +import infra.cloud.serialize.Readable; import infra.cloud.serialize.Message; -import infra.cloud.serialize.Output; +import infra.cloud.serialize.Writable; import infra.cloud.service.ServiceMethod; /** @@ -86,17 +86,17 @@ public String getServiceClass() { } @Override - public void writeTo(Output output) { - output.write(serviceClass); - output.write(methodName); - output.write(paramTypes, Output::write); + public void writeTo(Writable writable) { + writable.write(serviceClass); + writable.write(methodName); + writable.write(paramTypes, Writable::write); } @Override - public void readFrom(Input input) { - this.serviceClass = input.readString(); - this.methodName = input.readString(); - this.paramTypes = input.read(String.class, Input::readString); + public void readFrom(Readable readable) { + this.serviceClass = readable.readString(); + this.methodName = readable.readString(); + this.paramTypes = readable.read(String.class, Readable::readString); } @Override diff --git a/today-service-api/src/main/java/infra/cloud/serialize/MessagePackInput.java b/today-service-api/src/main/java/infra/cloud/serialize/MessagePackReader.java similarity index 97% rename from today-service-api/src/main/java/infra/cloud/serialize/MessagePackInput.java rename to today-service-api/src/main/java/infra/cloud/serialize/MessagePackReader.java index 9c3d202..ef3e147 100644 --- a/today-service-api/src/main/java/infra/cloud/serialize/MessagePackInput.java +++ b/today-service-api/src/main/java/infra/cloud/serialize/MessagePackReader.java @@ -1,5 +1,5 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the original author or authors. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -54,7 +54,7 @@ * @author 海子 Yang * @since 1.0 2025/8/18 14:52 */ -public class MessagePackInput implements Input { +public class MessagePackReader implements Readable { private static final int stringSizeLimit = TodayStrategies.getInt( "infra.cloud.serialize.stringSizeLimit", Integer.MAX_VALUE / 2); @@ -64,7 +64,7 @@ public class MessagePackInput implements Input { private final ByteBuf buffer; - public MessagePackInput(ByteBuf buffer) { + public MessagePackReader(ByteBuf buffer) { this.buffer = buffer; } @@ -103,7 +103,7 @@ public void read(Message message) { @Nullable @Override - public V readNullable(Function valueMapper) { + public V readNullable(Function valueMapper) { if (tryReadNull()) { return null; } @@ -387,7 +387,7 @@ public Instant readTimestamp() { @Override @SuppressWarnings("unchecked") - public T[] read(Class type, Function mapper) { + public T[] read(Class type, Function mapper) { int size = readArrayHeader(); T[] array = (T[]) Array.newInstance(type, size); for (int i = 0; i < size; i++) { @@ -408,7 +408,7 @@ public T[] read(Class type, Supplier supplier) { } @Override - public List read(Function mapper) { + public List read(Function mapper) { int size = readArrayHeader(); ArrayList result = new ArrayList<>(size); for (int i = 0; i < size; i++) { @@ -428,7 +428,7 @@ public List read(Supplier supplier) { } @Override - public Map read(Function keyMapper, Function valueMapper) { + public Map read(Function keyMapper, Function valueMapper) { int size = readMapHeader(); LinkedHashMap result = CollectionUtils.newLinkedHashMap(size); for (int i = 0; i < size; i++) { diff --git a/today-service-api/src/main/java/infra/cloud/serialize/MessagePackOutput.java b/today-service-api/src/main/java/infra/cloud/serialize/MessagePackWriter.java similarity index 96% rename from today-service-api/src/main/java/infra/cloud/serialize/MessagePackOutput.java rename to today-service-api/src/main/java/infra/cloud/serialize/MessagePackWriter.java index d35b816..ee8321a 100644 --- a/today-service-api/src/main/java/infra/cloud/serialize/MessagePackOutput.java +++ b/today-service-api/src/main/java/infra/cloud/serialize/MessagePackWriter.java @@ -1,5 +1,5 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the original author or authors. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -64,13 +64,13 @@ * @author 海子 Yang * @since 1.0 2025/8/18 17:50 */ -public class MessagePackOutput implements Output { +public class MessagePackWriter implements Writable { private static final long NANOS_PER_SECOND = 1000000000L; private final ByteBuf buffer; - public MessagePackOutput(ByteBuf buffer) { + public MessagePackWriter(ByteBuf buffer) { this.buffer = buffer; } @@ -89,7 +89,7 @@ public MessagePackOutput(ByteBuf buffer) { * @see #writeFully(byte[]) */ @Override - public void write(@Nullable byte[] b) { + public void write(byte @Nullable [] b) { if (b == null || b.length == 0) { writeBinaryHeader(0); } @@ -294,7 +294,7 @@ public void write(Message v) { } @Override - public void writeNullable(@Nullable V v, BiConsumer valueMapper) { + public void writeNullable(@Nullable V v, BiConsumer valueMapper) { if (v == null) { writeNull(); } @@ -337,7 +337,7 @@ public void write(T[] v, Consumer mapper) { } @Override - public void write(T[] v, BiConsumer mapper) { + public void write(T[] v, BiConsumer mapper) { writeArrayHeader(v.length); for (T t : v) { mapper.accept(this, t); @@ -354,7 +354,7 @@ public void write(List v, Consumer mapper) { } @Override - public void write(List v, BiConsumer mapper) { + public void write(List v, BiConsumer mapper) { int size = v.size(); writeArrayHeader(size); for (T t : v) { @@ -363,7 +363,7 @@ public void write(List v, BiConsumer mapper) { } @Override - public void write(Map v, BiConsumer keyMapper, BiConsumer valueMapper) { + public void write(Map v, BiConsumer keyMapper, BiConsumer valueMapper) { int size = v.size(); writeMapHeader(size); for (Map.Entry entry : v.entrySet()) { diff --git a/today-service-api/src/main/java/infra/cloud/serialize/ProtobufArgumentSerialization.java b/today-service-api/src/main/java/infra/cloud/serialize/ProtobufArgumentSerialization.java index 479d324..9df78ad 100644 --- a/today-service-api/src/main/java/infra/cloud/serialize/ProtobufArgumentSerialization.java +++ b/today-service-api/src/main/java/infra/cloud/serialize/ProtobufArgumentSerialization.java @@ -1,5 +1,5 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the original author or authors. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -44,16 +44,16 @@ public boolean supportsArgument(MethodParameter parameter) { } @Override - public void serialize(MethodParameter parameter, @Nullable Message value, Output output) throws SerializationException { - output.write(value == null ? null : value.toByteArray()); + public void serialize(MethodParameter parameter, @Nullable Message value, Writable writable) throws SerializationException { + writable.write(value == null ? null : value.toByteArray()); } @Override - public Message deserialize(MethodParameter parameter, Input input) throws SerializationException { + public Message deserialize(MethodParameter parameter, Readable readable) throws SerializationException { Class parameterType = parameter.getParameterType(); Message.Builder messageBuilder = getMessageBuilder(parameterType); try { - byte[] bytes = input.read(); + byte[] bytes = readable.read(); return messageBuilder.mergeFrom(bytes).build(); } catch (InvalidProtocolBufferException e) { @@ -90,8 +90,8 @@ public boolean supportsReturnValue(ServiceMethod method) { } @Override - public void serialize(ServiceMethod method, Message value, Output output) { - output.write(value.toByteArray()); + public void serialize(ServiceMethod method, Message value, Writable writable) { + writable.write(value.toByteArray()); } // @Override diff --git a/today-service-api/src/main/java/infra/cloud/serialize/ReturnValueDeserializer.java b/today-service-api/src/main/java/infra/cloud/serialize/ReturnValueDeserializer.java index 05d460d..2e44386 100644 --- a/today-service-api/src/main/java/infra/cloud/serialize/ReturnValueDeserializer.java +++ b/today-service-api/src/main/java/infra/cloud/serialize/ReturnValueDeserializer.java @@ -1,5 +1,5 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the original author or authors. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -27,7 +27,7 @@ public interface ReturnValueDeserializer { boolean supportsReturnValue(ServiceMethod method); - T deserialize(ServiceMethod method, Input input) + T deserialize(ServiceMethod method, Readable readable) throws SerializationException; } diff --git a/today-service-api/src/main/java/infra/cloud/serialize/ReturnValueSerializer.java b/today-service-api/src/main/java/infra/cloud/serialize/ReturnValueSerializer.java index fa79477..6192b0c 100644 --- a/today-service-api/src/main/java/infra/cloud/serialize/ReturnValueSerializer.java +++ b/today-service-api/src/main/java/infra/cloud/serialize/ReturnValueSerializer.java @@ -1,5 +1,5 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the original author or authors. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -27,7 +27,7 @@ public interface ReturnValueSerializer { boolean supportsReturnValue(ServiceMethod method); - void serialize(ServiceMethod method, T returnValue, Output output) + void serialize(ServiceMethod method, T returnValue, Writable writable) throws SerializationException; } diff --git a/today-service-api/src/main/java/infra/cloud/serialize/RpcArgumentSerialization.java b/today-service-api/src/main/java/infra/cloud/serialize/RpcArgumentSerialization.java index 40d3d7a..0378556 100644 --- a/today-service-api/src/main/java/infra/cloud/serialize/RpcArgumentSerialization.java +++ b/today-service-api/src/main/java/infra/cloud/serialize/RpcArgumentSerialization.java @@ -1,5 +1,5 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the original author or authors. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -35,10 +35,10 @@ public interface RpcArgumentSerialization { */ boolean supportsArgument(MethodParameter parameter); - void serialize(MethodParameter parameter, @Nullable T value, Output output) + void serialize(MethodParameter parameter, @Nullable T value, Writable writable) throws SerializationException; @Nullable - T deserialize(MethodParameter parameter, Input input) throws SerializationException; + T deserialize(MethodParameter parameter, Readable readable) throws SerializationException; } diff --git a/today-service-api/src/main/java/infra/cloud/serialize/SimpleValueArgumentSerialization.java b/today-service-api/src/main/java/infra/cloud/serialize/SimpleValueArgumentSerialization.java index 621bbb2..1c150b0 100644 --- a/today-service-api/src/main/java/infra/cloud/serialize/SimpleValueArgumentSerialization.java +++ b/today-service-api/src/main/java/infra/cloud/serialize/SimpleValueArgumentSerialization.java @@ -1,5 +1,5 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the original author or authors. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -37,14 +37,14 @@ public class SimpleValueArgumentSerialization implements RpcArgumentSerializatio private final Map, ValueSerialization> serializationMap = new HashMap<>(); public SimpleValueArgumentSerialization() { - serializationMap.put(int.class, map(Input::readInt, Output::write)); - serializationMap.put(Integer.class, map(Input::readInt, Output::write)); + serializationMap.put(int.class, map(Readable::readInt, Writable::write)); + serializationMap.put(Integer.class, map(Readable::readInt, Writable::write)); - serializationMap.put(long.class, map(Input::readLong, Output::write)); - serializationMap.put(Long.class, map(Input::readLong, Output::write)); + serializationMap.put(long.class, map(Readable::readLong, Writable::write)); + serializationMap.put(Long.class, map(Readable::readLong, Writable::write)); - serializationMap.put(short.class, map(Input::readShort, Output::write)); - serializationMap.put(Short.class, map(Input::readShort, Output::write)); + serializationMap.put(short.class, map(Readable::readShort, Writable::write)); + serializationMap.put(Short.class, map(Readable::readShort, Writable::write)); } @Override @@ -54,16 +54,16 @@ public boolean supportsArgument(MethodParameter parameter) { @Override @SuppressWarnings({ "rawtypes", "unchecked" }) - public void serialize(MethodParameter parameter, @Nullable Object value, Output output) { + public void serialize(MethodParameter parameter, @Nullable Object value, Writable writable) { ValueSerialization serialization = findSerialization(parameter.getParameterType()); - serialization.serialize(parameter, value, output); + serialization.serialize(parameter, value, writable); } @Nullable @Override - public Object deserialize(MethodParameter parameter, Input input) { + public Object deserialize(MethodParameter parameter, Readable readable) { var serialization = findSerialization(parameter.getParameterType()); - return serialization.deserialize(parameter, input); + return serialization.deserialize(parameter, readable); } @SuppressWarnings({ "rawtypes" }) diff --git a/today-service-api/src/main/java/infra/cloud/serialize/value/FuncValueSerialization.java b/today-service-api/src/main/java/infra/cloud/serialize/value/FuncValueSerialization.java index 66a7f1a..cc4b847 100644 --- a/today-service-api/src/main/java/infra/cloud/serialize/value/FuncValueSerialization.java +++ b/today-service-api/src/main/java/infra/cloud/serialize/value/FuncValueSerialization.java @@ -1,5 +1,5 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the original author or authors. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -20,8 +20,8 @@ import java.util.function.BiConsumer; import java.util.function.Function; -import infra.cloud.serialize.Input; -import infra.cloud.serialize.Output; +import infra.cloud.serialize.Readable; +import infra.cloud.serialize.Writable; import infra.cloud.serialize.SerializationException; import infra.core.MethodParameter; @@ -31,23 +31,23 @@ */ final class FuncValueSerialization implements ValueSerialization { - private final Function reader; + private final Function reader; - private final BiConsumer writer; + private final BiConsumer writer; - FuncValueSerialization(Function reader, BiConsumer writer) { + FuncValueSerialization(Function reader, BiConsumer writer) { this.reader = reader; this.writer = writer; } @Override - public void serialize(MethodParameter parameter, T value, Output payload) { + public void serialize(MethodParameter parameter, T value, Writable payload) { writer.accept(payload, value); } @Override - public T deserialize(MethodParameter parameter, Input input) throws SerializationException { - return reader.apply(input); + public T deserialize(MethodParameter parameter, Readable readable) throws SerializationException { + return reader.apply(readable); } } diff --git a/today-service-api/src/main/java/infra/cloud/serialize/value/ValueSerialization.java b/today-service-api/src/main/java/infra/cloud/serialize/value/ValueSerialization.java index 586a817..055bb29 100644 --- a/today-service-api/src/main/java/infra/cloud/serialize/value/ValueSerialization.java +++ b/today-service-api/src/main/java/infra/cloud/serialize/value/ValueSerialization.java @@ -1,5 +1,5 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the original author or authors. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -20,8 +20,8 @@ import java.util.function.BiConsumer; import java.util.function.Function; -import infra.cloud.serialize.Input; -import infra.cloud.serialize.Output; +import infra.cloud.serialize.Readable; +import infra.cloud.serialize.Writable; import infra.cloud.serialize.SerializationException; import infra.core.MethodParameter; import infra.lang.Assert; @@ -32,13 +32,13 @@ */ public interface ValueSerialization { - void serialize(MethodParameter parameter, T value, Output payload) + void serialize(MethodParameter parameter, T value, Writable payload) throws SerializationException; - T deserialize(MethodParameter parameter, Input payload) + T deserialize(MethodParameter parameter, Readable payload) throws SerializationException; - static ValueSerialization map(Function reader, BiConsumer writer) { + static ValueSerialization map(Function reader, BiConsumer writer) { Assert.notNull(reader, "reader Function is required"); Assert.notNull(writer, "writer BiConsumer is required"); return new FuncValueSerialization<>(reader, writer); diff --git a/today-service-client/src/main/java/infra/cloud/service/serialize/RequestSerializer.java b/today-service-client/src/main/java/infra/cloud/service/serialize/RequestSerializer.java index 6c371e9..f0200b7 100644 --- a/today-service-client/src/main/java/infra/cloud/service/serialize/RequestSerializer.java +++ b/today-service-client/src/main/java/infra/cloud/service/serialize/RequestSerializer.java @@ -1,5 +1,5 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the original author or authors. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -20,8 +20,8 @@ import java.util.List; import infra.cloud.RpcRequest; -import infra.cloud.serialize.MessagePackOutput; -import infra.cloud.serialize.Output; +import infra.cloud.serialize.MessagePackWriter; +import infra.cloud.serialize.Writable; import infra.cloud.serialize.RpcArgumentSerialization; import infra.cloud.service.ServiceMethod; import infra.core.MethodParameter; @@ -42,20 +42,20 @@ public RequestSerializer(List argumentSerializations) @SuppressWarnings("unchecked") public void serialize(RpcRequest request, ByteBuf payload) { - Output output = new MessagePackOutput(payload); - request.writeTo(output); + Writable writable = new MessagePackWriter(payload); + request.writeTo(writable); ServiceMethod method = request.getMethod(); int idx = 0; Object[] arguments = request.getArguments(); - beforeSerializeArguments(output, arguments); + beforeSerializeArguments(writable, arguments); for (MethodParameter parameter : method.getParameters()) { var serialization = findArgumentSerialization(parameter); - serialization.serialize(parameter, arguments[idx++], output); + serialization.serialize(parameter, arguments[idx++], writable); } - afterSerializeArguments(output, arguments); + afterSerializeArguments(writable, arguments); } private RpcArgumentSerialization findArgumentSerialization(MethodParameter parameter) { @@ -67,11 +67,11 @@ private RpcArgumentSerialization findArgumentSerialization(MethodParameter param throw new IllegalStateException("RpcArgumentSerialization for parameter %s not found".formatted(parameter)); } - protected void afterSerializeArguments(Output output, Object[] arguments) { + protected void afterSerializeArguments(Writable writable, Object[] arguments) { } - protected void beforeSerializeArguments(Output output, Object[] arguments) { + protected void beforeSerializeArguments(Writable writable, Object[] arguments) { } diff --git a/today-service-client/src/main/java/infra/cloud/service/serialize/ResponseDeserializer.java b/today-service-client/src/main/java/infra/cloud/service/serialize/ResponseDeserializer.java index 2fadb78..ba39f36 100644 --- a/today-service-client/src/main/java/infra/cloud/service/serialize/ResponseDeserializer.java +++ b/today-service-client/src/main/java/infra/cloud/service/serialize/ResponseDeserializer.java @@ -1,5 +1,5 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the original author or authors. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -20,7 +20,7 @@ import java.util.List; import infra.cloud.RpcResponse; -import infra.cloud.serialize.MessagePackInput; +import infra.cloud.serialize.MessagePackReader; import infra.cloud.serialize.ReturnValueDeserializer; import infra.cloud.serialize.SerializationException; import infra.cloud.serialize.ThrowableSerialization; @@ -45,7 +45,7 @@ public ResponseDeserializer(List serializations, Throwa } public RpcResponse deserialize(ServiceInterfaceMethod method, ByteBuf body) throws SerializationException { - MessagePackInput input = new MessagePackInput(body); + MessagePackReader input = new MessagePackReader(body); RpcResponse response = new RpcResponse(); response.setMethod(method); diff --git a/today-service-provider/src/main/java/infra/cloud/provider/ResponseSerializer.java b/today-service-provider/src/main/java/infra/cloud/provider/ResponseSerializer.java index 21491c8..5bc680b 100644 --- a/today-service-provider/src/main/java/infra/cloud/provider/ResponseSerializer.java +++ b/today-service-provider/src/main/java/infra/cloud/provider/ResponseSerializer.java @@ -1,5 +1,5 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the original author or authors. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,8 +21,8 @@ import java.util.List; -import infra.cloud.serialize.MessagePackOutput; -import infra.cloud.serialize.Output; +import infra.cloud.serialize.MessagePackWriter; +import infra.cloud.serialize.Writable; import infra.cloud.serialize.ReturnValueSerializer; import infra.cloud.service.ServiceMethod; import infra.remoting.Payload; @@ -48,9 +48,9 @@ public ResponseSerializer(List> returnValueSerializers) @SuppressWarnings({ "rawtypes", "unchecked" }) public Mono serialize(RemoteRequest request, @Nullable Object result) { ByteBuf buffer = allocator.ioBuffer(); - Output output = new MessagePackOutput(buffer); + Writable writable = new MessagePackWriter(buffer); - output.writeNullable(result, (out, v) -> { + writable.writeNullable(result, (out, v) -> { InvocableMethod invocableMethod = request.getMethod(); ReturnValueSerializer serializer = findSerializer(invocableMethod); serializer.serialize(invocableMethod, v, out); diff --git a/today-service-provider/src/main/java/infra/cloud/provider/RpcRequestDeserializer.java b/today-service-provider/src/main/java/infra/cloud/provider/RpcRequestDeserializer.java index 05dcd83..c68294b 100644 --- a/today-service-provider/src/main/java/infra/cloud/provider/RpcRequestDeserializer.java +++ b/today-service-provider/src/main/java/infra/cloud/provider/RpcRequestDeserializer.java @@ -1,5 +1,5 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the original author or authors. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -24,8 +24,8 @@ import java.util.Objects; import infra.cloud.RpcRequest; -import infra.cloud.serialize.Input; -import infra.cloud.serialize.MessagePackInput; +import infra.cloud.serialize.Readable; +import infra.cloud.serialize.MessagePackReader; import infra.cloud.serialize.RpcArgumentSerialization; import infra.cloud.serialize.SerializationException; import infra.cloud.service.ServiceInterfaceMetadata; @@ -60,13 +60,13 @@ public RpcRequestDeserializer(List argumentSerializati } public RemoteRequest deserialize(ByteBuf payload) throws SerializationException { - MessagePackInput input = new MessagePackInput(payload); + MessagePackReader input = new MessagePackReader(payload); RpcRequest request = new RpcRequest(); request.readFrom(input); String serviceClass = input.readString(); String methodName = input.readString(); - String[] paramTypes = input.read(String.class, Input::readString); + String[] paramTypes = input.read(String.class, Readable::readString); var serviceInterface = localServiceHolder.getServiceInterface(serviceClass); Assert.state(serviceInterface != null, "service interface not found"); diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/Deserializer.java b/today-service-serialization/src/main/java/infra/cloud/serialize/Deserializer.java index 4a83e70..7e6231a 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/Deserializer.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/Deserializer.java @@ -1,5 +1,5 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the original author or authors. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -31,6 +31,6 @@ public interface Deserializer { * @return the deserialized object * @throws IOException in case of errors reading from the stream */ - Object read(Input input) throws IOException; + Object read(Readable readable) throws IOException; } diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/Message.java b/today-service-serialization/src/main/java/infra/cloud/serialize/Message.java index 035e82b..2a3c22b 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/Message.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/Message.java @@ -1,5 +1,5 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the original author or authors. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -36,25 +36,48 @@ public interface Message { /** * The object implements the writeTo method to save its contents - * by calling the methods of {@link Output} for its primitive values or + * by calling the methods of {@link Writable} for its primitive values or * calling the write method of Output for objects, strings, * and arrays. * - * @param output the stream to write the object to + * @param writable the stream to write the object to * @throws SerializationException Serialization occur */ - void writeTo(Output output); + void writeTo(Writable writable); /** * The object implements the readFrom method to restore its - * contents by calling the methods of {@link Input} for primitive + * contents by calling the methods of {@link Readable} for primitive * types and read for objects, strings and arrays. The * readFrom method must read the values in the same sequence * and with the same types as were written by writeTo. * - * @param input the source to read data from in order to restore the object + * @param readable the source to read data from in order to restore the object * @throws SerializationException Serialization occur */ - void readFrom(Input input); + void readFrom(Readable readable); + + interface Factory { + + /** + * Create a new instance of the Message class, instantiating it + * from the given Input whose data had previously been written by + * {@link Message#writeTo Message.writeTo()}. + * + * @param source The Parcel to read the object's data from. + * @return Returns a new instance of the Message class. + * @throws SerializationException Serialization occur + */ + M create(Readable source); + + /** + * Create a new array of the Parcelable class. + * + * @param size Size of the array. + * @return Returns an array of the Parcelable class, with every entry + * initialized to null. + */ + M[] newArray(int size); + } } diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/Input.java b/today-service-serialization/src/main/java/infra/cloud/serialize/Readable.java similarity index 93% rename from today-service-serialization/src/main/java/infra/cloud/serialize/Input.java rename to today-service-serialization/src/main/java/infra/cloud/serialize/Readable.java index f7e1753..0959d4b 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/Input.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/Readable.java @@ -1,5 +1,5 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the original author or authors. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -32,7 +32,7 @@ * @see java.io.DataInput * @since 1.0 2025/8/16 16:59 */ -public interface Input { +public interface Readable { /** * Reads some bytes from an input @@ -179,7 +179,7 @@ public interface Input { void read(Message message); @Nullable - V readNullable(Function valueMapper); + V readNullable(Function valueMapper); /** * Reads a {@code array} value. @@ -187,7 +187,7 @@ public interface Input { * @return a array object. * @throws SerializationException if a serialization error occurs. */ - T[] read(Class type, Function mapper); + T[] read(Class type, Function mapper); /** * Reads a {@code array} value. @@ -203,7 +203,7 @@ public interface Input { * @return a List object. * @throws SerializationException if a serialization error occurs. */ - List read(Function mapper); + List read(Function mapper); /** * Reads a {@link List} value. @@ -219,6 +219,6 @@ public interface Input { * @return a Map object. * @throws SerializationException if a serialization error occurs. */ - Map read(Function keyMapper, Function valueMapper); + Map read(Function keyMapper, Function valueMapper); } diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/Serializer.java b/today-service-serialization/src/main/java/infra/cloud/serialize/Serializer.java index 3779555..0d98ece 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/Serializer.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/Serializer.java @@ -1,5 +1,5 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the original author or authors. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -29,9 +29,9 @@ public interface Serializer { * Write an object to the given Output. * * @param object the object to serialize - * @param output the output stream + * @param writable the output stream * @throws IOException in case of errors writing to the stream */ - void write(Object object, Output output) throws IOException; + void write(Object object, Writable writable) throws IOException; } diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/Output.java b/today-service-serialization/src/main/java/infra/cloud/serialize/Writable.java similarity index 92% rename from today-service-serialization/src/main/java/infra/cloud/serialize/Output.java rename to today-service-serialization/src/main/java/infra/cloud/serialize/Writable.java index e14e07d..ccb8c8d 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/Output.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/Writable.java @@ -1,5 +1,5 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the original author or authors. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -30,7 +30,7 @@ * @see java.io.DataOutput * @since 1.0 2025/8/16 16:58 */ -public interface Output { +public interface Writable { /** * Writes a byte array object to the output. @@ -39,7 +39,7 @@ public interface Output { * @throws SerializationException if a serialization error occurs. * @see #writeFully(byte[]) */ - void write(@Nullable byte[] b); + void write(byte @Nullable [] b); /** * Writes a byte array object to the output. @@ -163,7 +163,7 @@ public interface Output { * @param v the value to be written. * @throws SerializationException if a serialization error occurs. */ - void writeNullable(@Nullable V v, BiConsumer valueMapper); + void writeNullable(@Nullable V v, BiConsumer valueMapper); /** * Writes a {@code array} value. @@ -179,7 +179,7 @@ public interface Output { * @param v the array value to be written. * @throws SerializationException if a serialization error occurs. */ - void write(T[] v, BiConsumer mapper); + void write(T[] v, BiConsumer mapper); /** * Writes a {@code List} value. @@ -195,7 +195,7 @@ public interface Output { * @param v the List value to be written. * @throws SerializationException if a serialization error occurs. */ - void write(List v, BiConsumer mapper); + void write(List v, BiConsumer mapper); /** * Writes a {@code Map} value. @@ -211,6 +211,6 @@ public interface Output { * @param v the Map value to be written. * @throws SerializationException if a serialization error occurs. */ - void write(Map v, BiConsumer keyMapper, BiConsumer valueMapper); + void write(Map v, BiConsumer keyMapper, BiConsumer valueMapper); } diff --git a/today-service-serialization/src/test/java/infra/cloud/serialize/MessageTests.java b/today-service-serialization/src/test/java/infra/cloud/serialize/MessageTests.java index 1e66087..d7e4e0d 100644 --- a/today-service-serialization/src/test/java/infra/cloud/serialize/MessageTests.java +++ b/today-service-serialization/src/test/java/infra/cloud/serialize/MessageTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the original author or authors. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -65,15 +65,15 @@ public void setName(String name) { } @Override - public void writeTo(Output output) { - output.write(name); - output.write(age); + public void writeTo(Writable writable) { + writable.write(name); + writable.write(age); } @Override - public void readFrom(Input input) { - this.name = input.readString(); - this.age = input.readInt(); + public void readFrom(Readable readable) { + this.name = readable.readString(); + this.age = readable.readInt(); } } diff --git a/today-service-serialization/src/test/java/infra/cloud/serialize/InputTests.java b/today-service-serialization/src/test/java/infra/cloud/serialize/ReadableTests.java similarity index 79% rename from today-service-serialization/src/test/java/infra/cloud/serialize/InputTests.java rename to today-service-serialization/src/test/java/infra/cloud/serialize/ReadableTests.java index 7beea17..253af10 100644 --- a/today-service-serialization/src/test/java/infra/cloud/serialize/InputTests.java +++ b/today-service-serialization/src/test/java/infra/cloud/serialize/ReadableTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the original author or authors. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -30,22 +30,22 @@ * @author 海子 Yang * @since 1.0 2025/8/18 17:12 */ -class InputTests { +class ReadableTests { @ParameterizedTest @MethodSource("args") - void list(Input input) { - List list = input.read(Input::readInt); + void list(Readable readable) { + List list = readable.read(Readable::readInt); Random random = new Random(); - List read = input.read(() -> random.nextInt()); + List read = readable.read(() -> random.nextInt()); } @ParameterizedTest @MethodSource("args") - void map(Input input) { - Map map = input.read(Input::readString, Input::readString); + void map(Readable readable) { + Map map = readable.read(Readable::readString, Readable::readString); } From 1097f9ec1ce4863e0350665983c541629bd9c8f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Sat, 27 Dec 2025 18:27:51 +0800 Subject: [PATCH 063/104] =?UTF-8?q?:arrow=5Fup:=20=E6=9B=B4=E6=96=B0=20Gra?= =?UTF-8?q?dle=20=E7=89=88=E6=9C=AC=E5=B9=B6=E9=85=8D=E7=BD=AE=20Java=20?= =?UTF-8?q?=E7=BC=96=E8=AF=91=E5=B7=A5=E5=85=B7=E9=93=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将 Gradle 版本从 9.2.0 升级到 9.2.1 - 添加 .gitattributes 文件配置行结束符和二进制文件处理 - 更新基础架构版本号从 5.0-Draft.3 到 5.0-Draft.5 - 配置 Java 编译器工具链使用 Java 25 作为编译基线 - 设置编译字节码基线为 Java 17 并支持多版本 JAR - 重构 Java 编译约定应用逻辑并延迟执行配置 --- .gitattributes | 15 ++ buildSrc/gradle.properties | 2 +- .../java/infra/cloud/JavaConventions.java | 75 +++++-- gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew.bat | 186 +++++++++--------- 5 files changed, 169 insertions(+), 111 deletions(-) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..fb3dd3d --- /dev/null +++ b/.gitattributes @@ -0,0 +1,15 @@ +# Normalize line endings to LF. +* text eol=lf + +# Ensure that line endings for DOS batch files are not modified. +*.bat -text + +# Ensure the following are treated as binary. +*.gif binary +*.jar binary +*.jpeg binary +*.jpg binary +*.png binary +*.vsd binary +*.class binary +*.clazz binary diff --git a/buildSrc/gradle.properties b/buildSrc/gradle.properties index a49e315..9ec854a 100644 --- a/buildSrc/gradle.properties +++ b/buildSrc/gradle.properties @@ -1,3 +1,3 @@ org.gradle.caching=true -infraVersion=5.0-Draft.3-SNAPSHOT +infraVersion=5.0-Draft.5-SNAPSHOT diff --git a/buildSrc/src/main/java/infra/cloud/JavaConventions.java b/buildSrc/src/main/java/infra/cloud/JavaConventions.java index 65de80f..9b62015 100644 --- a/buildSrc/src/main/java/infra/cloud/JavaConventions.java +++ b/buildSrc/src/main/java/infra/cloud/JavaConventions.java @@ -50,6 +50,17 @@ public class JavaConventions { private static final List TEST_COMPILER_ARGS; + /** + * The Java version we should use as the JVM baseline for building the project + */ + private static final JavaLanguageVersion DEFAULT_LANGUAGE_VERSION = JavaLanguageVersion.of(25); + + /** + * The Java version we should use as the baseline for the compiled bytecode + * (the "-release" compiler argument). + */ + private static final JavaLanguageVersion DEFAULT_RELEASE_VERSION = JavaLanguageVersion.of(17); + static { List commonCompilerArgs = Arrays.asList( /*"-Xlint:serial",*/ "-Xlint:cast", "-Xlint:classfile",/* "-Xlint:dep-ann",*/ @@ -71,33 +82,65 @@ public class JavaConventions { public void apply(Project project) { project.getPlugins().withType(JavaBasePlugin.class, javaPlugin -> { + applyToolchainConventions(project); applyJavaCompileConventions(project); configureDependencyManagement(project); }); } /** - * Applies the common Java compiler options for main sources, test fixture sources, and + * Configure the Toolchain support for the project. + * + * @param project the current project + */ + private static void applyToolchainConventions(Project project) { + project.getExtensions().getByType(JavaPluginExtension.class).toolchain(toolchain -> { + toolchain.getLanguageVersion().set(DEFAULT_LANGUAGE_VERSION); + }); + } + + /** + * Apply the common Java compiler options for main sources, test fixture sources, and * test sources. * * @param project the current project */ private void applyJavaCompileConventions(Project project) { - project.getExtensions().getByType(JavaPluginExtension.class) - .getToolchain().getLanguageVersion().set(JavaLanguageVersion.of(17)); - project.getTasks().withType(JavaCompile.class) - .matching(compileTask -> compileTask.getName().equals(JavaPlugin.COMPILE_JAVA_TASK_NAME)) - .forEach(compileTask -> { - compileTask.getOptions().setCompilerArgs(COMPILER_ARGS); - compileTask.getOptions().setEncoding("UTF-8"); - }); - project.getTasks().withType(JavaCompile.class) - .matching(compileTask -> compileTask.getName().equals(JavaPlugin.COMPILE_TEST_JAVA_TASK_NAME) - || compileTask.getName().equals("compileTestFixturesJava")) - .forEach(compileTask -> { - compileTask.getOptions().setCompilerArgs(TEST_COMPILER_ARGS); - compileTask.getOptions().setEncoding("UTF-8"); - }); + project.afterEvaluate(p -> { + p.getTasks().withType(JavaCompile.class) + .matching(compileTask -> compileTask.getName().startsWith(JavaPlugin.COMPILE_JAVA_TASK_NAME)) + .forEach(compileTask -> { + compileTask.getOptions().setCompilerArgs(COMPILER_ARGS); + compileTask.getOptions().setEncoding("UTF-8"); + setJavaRelease(compileTask); + }); + p.getTasks().withType(JavaCompile.class) + .matching(compileTask -> compileTask.getName().startsWith(JavaPlugin.COMPILE_TEST_JAVA_TASK_NAME) + || compileTask.getName().equals("compileTestFixturesJava")) + .forEach(compileTask -> { + compileTask.getOptions().setCompilerArgs(TEST_COMPILER_ARGS); + compileTask.getOptions().setEncoding("UTF-8"); + setJavaRelease(compileTask); + }); + + }); + } + + /** + * We should pick the {@link #DEFAULT_RELEASE_VERSION} for all compiled classes, + * unless the current task is compiling multi-release JAR code with a higher version. + */ + private void setJavaRelease(JavaCompile task) { + int defaultVersion = DEFAULT_RELEASE_VERSION.asInt(); + int releaseVersion = defaultVersion; + int compilerVersion = task.getJavaCompiler().get().getMetadata().getLanguageVersion().asInt(); + for (int version = defaultVersion; version <= compilerVersion; version++) { + if (task.getName().contains("Java" + version)) { + releaseVersion = version; + break; + } + } + task.getOptions().getRelease().set(releaseVersion); } private void configureDependencyManagement(Project project) { diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index bad7c24..23449a2 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.0-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.1-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew.bat b/gradlew.bat index c4bdd3a..e509b2d 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -1,93 +1,93 @@ -@rem -@rem Copyright 2015 the original author or authors. -@rem -@rem Licensed under the Apache License, Version 2.0 (the "License"); -@rem you may not use this file except in compliance with the License. -@rem You may obtain a copy of the License at -@rem -@rem https://www.apache.org/licenses/LICENSE-2.0 -@rem -@rem Unless required by applicable law or agreed to in writing, software -@rem distributed under the License is distributed on an "AS IS" BASIS, -@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -@rem See the License for the specific language governing permissions and -@rem limitations under the License. -@rem -@rem SPDX-License-Identifier: Apache-2.0 -@rem - -@if "%DEBUG%"=="" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%"=="" set DIRNAME=. -@rem This is normally unused -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Resolve any "." and ".." in APP_HOME to make it shorter. -for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if %ERRORLEVEL% equ 0 goto execute - -echo. 1>&2 -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 -echo. 1>&2 -echo Please set the JAVA_HOME variable in your environment to match the 1>&2 -echo location of your Java installation. 1>&2 - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto execute - -echo. 1>&2 -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 -echo. 1>&2 -echo Please set the JAVA_HOME variable in your environment to match the 1>&2 -echo location of your Java installation. 1>&2 - -goto fail - -:execute -@rem Setup the command line - - - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* - -:end -@rem End local scope for the variables with windows NT shell -if %ERRORLEVEL% equ 0 goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -set EXIT_CODE=%ERRORLEVEL% -if %EXIT_CODE% equ 0 set EXIT_CODE=1 -if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% -exit /b %EXIT_CODE% - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:execute +@rem Setup the command line + + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega From f181d264c3cbcd6ae7b7653b685490f26a149c9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Fri, 30 Jan 2026 19:57:46 +0800 Subject: [PATCH 064/104] :arrow_up: ./gradlew wrapper --gradle-version=9.3.0 --- gradle/wrapper/gradle-wrapper.jar | Bin 45457 -> 46175 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 8bdaf60c75ab801e22807dde59e12a8735a34077..61285a659d17295f1de7c53e24fdf13ad755c379 100644 GIT binary patch delta 36855 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%0Aonjyf`q#Bg+;H(_UceX22V^ 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 Date: Fri, 30 Jan 2026 20:06:06 +0800 Subject: [PATCH 065/104] =?UTF-8?q?:sparkles:=20=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E6=9E=9A=E4=B8=BE=E5=BA=8F=E5=88=97=E5=8C=96=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在 MessagePackReader 中实现 readEnum 方法以读取枚举值 - 在 MessagePackWriter 中实现 write 方法以写入枚举值 - 更新 Readable 接口添加 readEnum 方法定义 - 更新 Writable 接口添加 write 枚举方法定义 - 修改 readNullable 和 readArray 方法的泛型约束 - 更新相关类导入 Enumerable 类型支持 --- .../cloud/serialize/MessagePackReader.java | 6 +++++ .../cloud/serialize/MessagePackWriter.java | 6 +++++ .../java/infra/cloud/serialize/Readable.java | 25 ++++++++++++++++--- .../java/infra/cloud/serialize/Writable.java | 10 ++++++++ 4 files changed, 43 insertions(+), 4 deletions(-) diff --git a/today-service-api/src/main/java/infra/cloud/serialize/MessagePackReader.java b/today-service-api/src/main/java/infra/cloud/serialize/MessagePackReader.java index ef3e147..e2c731d 100644 --- a/today-service-api/src/main/java/infra/cloud/serialize/MessagePackReader.java +++ b/today-service-api/src/main/java/infra/cloud/serialize/MessagePackReader.java @@ -41,6 +41,7 @@ import infra.cloud.serialize.format.MessageSizeException; import infra.cloud.serialize.format.MessageTypeException; import infra.lang.Constant; +import infra.lang.Enumerable; import infra.lang.TodayStrategies; import infra.util.CollectionUtils; import io.netty.buffer.ByteBuf; @@ -101,6 +102,11 @@ public void read(Message message) { message.readFrom(this); } + @Override + public > V readEnum(Class type) { + return Enumerable.of(type, readInt()); + } + @Nullable @Override public V readNullable(Function valueMapper) { diff --git a/today-service-api/src/main/java/infra/cloud/serialize/MessagePackWriter.java b/today-service-api/src/main/java/infra/cloud/serialize/MessagePackWriter.java index ee8321a..e9000f5 100644 --- a/today-service-api/src/main/java/infra/cloud/serialize/MessagePackWriter.java +++ b/today-service-api/src/main/java/infra/cloud/serialize/MessagePackWriter.java @@ -27,6 +27,7 @@ import java.util.function.Consumer; import infra.cloud.serialize.format.MessagePack; +import infra.lang.Enumerable; import io.netty.buffer.ByteBuf; import static infra.cloud.serialize.format.MessagePack.Code.ARRAY16; @@ -278,6 +279,11 @@ public void write(@Nullable String v) { } } + @Override + public void write(Enumerable v) { + write(v.getValue()); + } + @Override public void write(Instant v) { writeTimestamp(v.getEpochSecond(), v.getNano()); diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/Readable.java b/today-service-serialization/src/main/java/infra/cloud/serialize/Readable.java index 0959d4b..af032ee 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/Readable.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/Readable.java @@ -1,5 +1,5 @@ /* - * Copyright 2021 - 2026 the original author or authors. + * Copyright 2021 - 2024 the original author or authors. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -25,6 +25,8 @@ import java.util.function.Function; import java.util.function.Supplier; +import infra.lang.Enumerable; + /** * An Input lets an application read primitive data types and objects from a source of data. * @@ -178,8 +180,23 @@ public interface Readable { */ void read(Message message); - @Nullable - V readNullable(Function valueMapper); + /** + * Reads an enum value. + * + * @param type the enum class type. + * @return an enum value. + * @throws SerializationException if a serialization error occurs. + */ + > V readEnum(Class type); + + /** + * Reads a nullable value. + * + * @param valueMapper function to map the value from readable. + * @return a nullable value. + * @throws SerializationException if a serialization error occurs. + */ + V readNullable(Function valueMapper); /** * Reads a {@code array} value. @@ -187,7 +204,7 @@ public interface Readable { * @return a array object. * @throws SerializationException if a serialization error occurs. */ - T[] read(Class type, Function mapper); + T[] read(Class type, Function mapper); /** * Reads a {@code array} value. diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/Writable.java b/today-service-serialization/src/main/java/infra/cloud/serialize/Writable.java index ccb8c8d..ab73bdc 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/Writable.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/Writable.java @@ -25,6 +25,8 @@ import java.util.function.BiConsumer; import java.util.function.Consumer; +import infra.lang.Enumerable; + /** * @author 海子 Yang * @see java.io.DataOutput @@ -124,6 +126,14 @@ public interface Writable { */ void write(@Nullable String v); + /** + * Writes an {@code Enumerable} value. + * + * @param v the enumerable integer value to be written. + * @throws SerializationException if a serialization error occurs. + */ + void write(Enumerable v); + /** * Writes a Timestamp value. * From 48b29a3583c40a6384cbf0891297b1ea8f57aa9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Fri, 30 Jan 2026 20:28:59 +0800 Subject: [PATCH 066/104] :art: --- .../main/java/infra/cloud/serialize/MessagePackWriter.java | 6 +++++- .../src/main/java/infra/cloud/serialize/Readable.java | 5 +++-- .../src/main/java/infra/cloud/serialize/Writable.java | 3 +++ 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/today-service-api/src/main/java/infra/cloud/serialize/MessagePackWriter.java b/today-service-api/src/main/java/infra/cloud/serialize/MessagePackWriter.java index e9000f5..299308d 100644 --- a/today-service-api/src/main/java/infra/cloud/serialize/MessagePackWriter.java +++ b/today-service-api/src/main/java/infra/cloud/serialize/MessagePackWriter.java @@ -62,7 +62,11 @@ import static infra.cloud.serialize.format.MessagePack.Code.UINT8; /** - * @author 海子 Yang + * A writer for serializing data into MessagePack format. + * This class provides methods to write various data types according to the MessagePack specification, + * automatically choosing the most efficient encoding based on the value being written. + * + * @author TAKETODAY * @since 1.0 2025/8/18 17:50 */ public class MessagePackWriter implements Writable { diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/Readable.java b/today-service-serialization/src/main/java/infra/cloud/serialize/Readable.java index af032ee..8f2227c 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/Readable.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/Readable.java @@ -1,5 +1,5 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the original author or authors. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -28,7 +28,8 @@ import infra.lang.Enumerable; /** - * An Input lets an application read primitive data types and objects from a source of data. + * A readable interface that allows an application to read + * primitive data types and objects from a data source. * * @author 海子 Yang * @see java.io.DataInput diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/Writable.java b/today-service-serialization/src/main/java/infra/cloud/serialize/Writable.java index ab73bdc..1050dab 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/Writable.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/Writable.java @@ -28,6 +28,9 @@ import infra.lang.Enumerable; /** + * Interface for writing data to an output stream. + * Provides methods for writing various data types including primitives, arrays, collections, and objects. + * * @author 海子 Yang * @see java.io.DataOutput * @since 1.0 2025/8/16 16:58 From f6d5b872647e7e58af0f270c8ebb0f1541343c21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Fri, 30 Jan 2026 20:30:37 +0800 Subject: [PATCH 067/104] =?UTF-8?q?:arrow=5Fup:=20=E6=9B=B4=E6=96=B0?= =?UTF-8?q?=E5=9F=BA=E7=A1=80=E6=9E=B6=E6=9E=84=E7=89=88=E6=9C=AC=E5=8F=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将 infraVersion 从 5.0-Draft.5-SNAPSHOT 更新为 5.0-Draft.6-SNAPSHOT --- buildSrc/gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buildSrc/gradle.properties b/buildSrc/gradle.properties index 9ec854a..c36331c 100644 --- a/buildSrc/gradle.properties +++ b/buildSrc/gradle.properties @@ -1,3 +1,3 @@ org.gradle.caching=true -infraVersion=5.0-Draft.5-SNAPSHOT +infraVersion=5.0-Draft.6-SNAPSHOT From ea871ac6ace217772a18c54a3f4957984560a3e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Fri, 30 Jan 2026 20:30:44 +0800 Subject: [PATCH 068/104] :art: --- .../src/main/java/infra/cloud/serialize/MessagePackReader.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/today-service-api/src/main/java/infra/cloud/serialize/MessagePackReader.java b/today-service-api/src/main/java/infra/cloud/serialize/MessagePackReader.java index e2c731d..20da6ec 100644 --- a/today-service-api/src/main/java/infra/cloud/serialize/MessagePackReader.java +++ b/today-service-api/src/main/java/infra/cloud/serialize/MessagePackReader.java @@ -50,7 +50,7 @@ import static infra.cloud.serialize.format.MessagePack.Code.EXT_TIMESTAMP; /** - * Message pack specification input + * MessagePack specification reader implementation * * @author 海子 Yang * @since 1.0 2025/8/18 14:52 From a191a38c525082c21d6159405ceab3da37c96b99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Fri, 30 Jan 2026 20:46:13 +0800 Subject: [PATCH 069/104] :recycle: --- LICENSE | 876 ++++-------------- README.md | 2 +- build.gradle | 4 +- buildSrc/build.gradle | 23 +- .../java/infra/cloud/ConventionsPlugin.java | 21 +- .../java/infra/cloud/JavaConventions.java | 21 +- .../java/infra/cloud/TestConventions.java | 21 +- .../optional/OptionalDependenciesPlugin.java | 21 +- gradle.properties | 16 - gradle/cloud-module.gradle | 17 - gradle/publications.gradle | 4 +- today-cloud-config-server/build.gradle | 6 +- .../java/infra/config/DynamicProperty.java | 21 +- ...icPropertyDependencyResolvingStrategy.java | 21 +- today-cloud-core/build.gradle | 5 +- .../java/infra/cloud/RemotingException.java | 21 +- .../cloud/client/DefaultServiceInstance.java | 21 +- .../java/infra/cloud/client/Registration.java | 25 +- .../infra/cloud/client/ServiceInstance.java | 25 +- .../ConditionalOnDiscoveryEnabled.java | 21 +- .../main/java/infra/cloud/net/HostInfo.java | 21 +- .../net/HostInfoEnvironmentPostProcessor.java | 21 +- .../java/infra/cloud/net/InetProperties.java | 21 +- .../java/infra/cloud/net/InetService.java | 21 +- .../main/java/infra/cloud/package-info.java | 21 +- .../infra/cloud/net/InetServiceTests.java | 21 +- .../demo-tests/demo-registry/build.gradle | 25 +- .../taketoday/demo/RegistryApplication.java | 21 +- .../src/main/resources/logback-infra.xml | 16 - .../demo-tests/demo-user-api/build.gradle | 2 +- .../java/cn/taketoday/demo/model/User.java | 24 +- .../taketoday/demo/service/UserService.java | 21 +- .../src/main/resources/logback-infra.xml | 16 - .../demo-tests/demo-user-rest/build.gradle | 6 +- .../cn/taketoday/demo/ClientApplication.java | 21 +- .../cn/taketoday/demo/UserController.java | 21 +- .../src/main/resources/logback-infra.xml | 16 - .../demo-tests/demo-user-service/build.gradle | 6 +- .../demo/service/DefaultUserService.java | 21 +- .../demo/service/UserServiceApplication.java | 21 +- .../src/main/resources/logback-infra.xml | 16 - .../micrometer/MicrometerChannel.java | 21 +- .../MicrometerChannelDecorator.java | 21 +- .../micrometer/MicrometerConnection.java | 21 +- .../MicrometerConnectionDecorator.java | 21 +- .../observation/ChannelContext.java | 21 +- ...ChannelRequesterObservationConvention.java | 21 +- ...nelRequesterTracingObservationHandler.java | 21 +- ...ChannelResponderObservationConvention.java | 21 +- ...nelResponderTracingObservationHandler.java | 21 +- .../DefaultChannelObservationConvention.java | 21 +- ...ChannelRequesterObservationConvention.java | 21 +- ...ChannelResponderObservationConvention.java | 21 +- .../ObservationRequesterChannel.java | 21 +- .../ObservationResponderChannel.java | 21 +- .../micrometer/observation/PayloadUtils.java | 21 +- .../RemotingObservationDocumentation.java | 21 +- .../remoting/micrometer/package-info.java | 21 +- .../MicrometerChannelDecoratorTests.java | 21 +- .../micrometer/MicrometerChannelTests.java | 21 +- .../MicrometerConnectionDecoratorTests.java | 21 +- .../micrometer/MicrometerConnectionTests.java | 21 +- .../integration/IntegrationTests.java | 21 +- .../integration/InteractionsLoadTests.java | 21 +- .../integration/StreamingTests.java | 21 +- .../integration/TcpIntegrationTests.java | 21 +- .../observation/ByteBufGetter.java | 21 +- .../observation/ByteBufSetter.java | 21 +- .../ObservationIntegrationTests.java | 21 +- .../src/test/resources/logback-test.xml | 16 - .../transport/local/LocalClientTransport.java | 21 +- .../transport/local/LocalConnection.java | 21 +- .../transport/local/LocalServerTransport.java | 21 +- .../transport/local/LocalSocketAddress.java | 21 +- .../transport/local/package-info.java | 21 +- .../local/LocalClientTransportTests.java | 21 +- .../transport/local/LocalPingPong.java | 21 +- .../local/LocalResumableTransportTests.java | 21 +- ...umableWithFragmentationTransportTests.java | 21 +- .../local/LocalServerTransportTests.java | 21 +- .../local/LocalSocketAddressTests.java | 21 +- .../transport/local/LocalTransportTests.java | 21 +- .../LocalTransportWithFragmentationTests.java | 21 +- .../src/test/resources/logback-test.xml | 17 - .../netty/ProtocolFrameLengthCodec.java | 21 +- .../transport/netty/TcpConnection.java | 21 +- .../netty/client/TcpClientTransport.java | 21 +- .../transport/netty/client/package-info.java | 21 +- .../transport/netty/package-info.java | 21 +- .../netty/server/CloseableChannel.java | 21 +- .../netty/server/TcpServerTransport.java | 21 +- .../transport/netty/server/package-info.java | 21 +- .../transport/tcp/TCPServerTransport.java | 21 +- .../remoting/transport/tcp/package-info.java | 21 +- .../remoting/integration/FragmentTests.java | 21 +- .../remoting/integration/KeepaliveTests.java | 21 +- ...ctoryNettyTransportFragmentationTests.java | 21 +- .../netty/TcpFragmentationTransportTests.java | 21 +- .../transport/netty/TcpPingTests.java | 21 +- .../transport/netty/TcpPongServer.java | 21 +- .../netty/TcpResumableTransportTests.java | 21 +- ...umableWithFragmentationTransportTests.java | 21 +- .../netty/TcpSecureTransportTests.java | 21 +- .../transport/netty/TcpTransportTests.java | 21 +- .../netty/client/TcpClientTransportTests.java | 21 +- .../netty/server/CloseableChannelTests.java | 21 +- .../netty/server/TcpServerTransportTests.java | 21 +- .../src/test/resources/logback-test.xml | 17 - .../BaseWebsocketServerTransport.java | 21 +- .../transport/websocket/CloseableChannel.java | 21 +- .../websocket/WebsocketClientTransport.java | 21 +- .../websocket/WebsocketConnection.java | 21 +- .../websocket/WebsocketRouteTransport.java | 21 +- .../websocket/WebsocketServerTransport.java | 21 +- ...ctoryNettyTransportFragmentationTests.java | 21 +- .../websocket/SetupRejectionTests.java | 21 +- .../transport/websocket/WebSocketClient.java | 21 +- .../websocket/WebSocketClientHandler.java | 21 +- .../WebSocketTransportIntegrationTests.java | 21 +- .../WebsocketClientTransportTests.java | 21 +- .../transport/websocket/WebsocketPing.java | 21 +- .../WebsocketPingPongIntegrationTests.java | 21 +- .../websocket/WebsocketPongServer.java | 21 +- .../WebsocketResumableTransportTests.java | 21 +- ...umableWithFragmentationTransportTests.java | 21 +- .../WebsocketRouteTransportTests.java | 21 +- .../WebsocketSecureTransportTests.java | 21 +- .../WebsocketServerTransportTests.java | 21 +- .../websocket/WebsocketTransportTests.java | 21 +- today-remoting/build.gradle | 4 +- .../java/infra/remoting/Availability.java | 21 +- .../src/main/java/infra/remoting/Channel.java | 21 +- .../java/infra/remoting/ChannelAcceptor.java | 21 +- .../java/infra/remoting/ChannelAdapter.java | 21 +- .../java/infra/remoting/ChannelWrapper.java | 21 +- .../main/java/infra/remoting/Closeable.java | 21 +- .../main/java/infra/remoting/Connection.java | 21 +- .../remoting/ConnectionSetupPayload.java | 21 +- .../infra/remoting/ConnectionWrapper.java | 21 +- .../src/main/java/infra/remoting/Payload.java | 21 +- .../remoting/ProtocolErrorException.java | 21 +- .../infra/remoting/RemotingException.java | 21 +- .../infra/remoting/RemotingOperations.java | 21 +- .../infra/remoting/core/ChannelConnector.java | 21 +- .../infra/remoting/core/ChannelSupport.java | 21 +- .../core/ClientServerInputMultiplexer.java | 21 +- .../java/infra/remoting/core/ClientSetup.java | 21 +- .../core/DefaultConnectionSetupPayload.java | 21 +- .../remoting/core/DefaultRemotingClient.java | 21 +- .../core/FireAndForgetRequesterMono.java | 21 +- .../FireAndForgetResponderSubscriber.java | 21 +- .../remoting/core/FragmentationUtils.java | 21 +- .../infra/remoting/core/FrameHandler.java | 21 +- .../remoting/core/LeasePermitHandler.java | 21 +- .../java/infra/remoting/core/LeaseSpec.java | 21 +- .../remoting/core/LoggingConnection.java | 21 +- .../core/MetadataPushRequesterMono.java | 21 +- .../core/MetadataPushResponderSubscriber.java | 21 +- .../remoting/core/PayloadValidationUtils.java | 21 +- .../infra/remoting/core/ReassemblyUtils.java | 21 +- .../infra/remoting/core/ReconnectMono.java | 21 +- .../infra/remoting/core/RemotingClient.java | 21 +- .../remoting/core/RemotingClientAdapter.java | 21 +- .../infra/remoting/core/RemotingServer.java | 21 +- .../core/RequestChannelRequesterFlux.java | 21 +- .../RequestChannelResponderSubscriber.java | 21 +- .../core/RequestResponseRequesterMono.java | 21 +- .../RequestResponseResponderSubscriber.java | 21 +- .../core/RequestStreamRequesterFlux.java | 21 +- .../RequestStreamResponderSubscriber.java | 21 +- .../infra/remoting/core/RequesterChannel.java | 21 +- .../remoting/core/RequesterFrameHandler.java | 21 +- .../remoting/core/RequesterLeaseTracker.java | 21 +- .../remoting/core/ResolvingOperator.java | 21 +- .../infra/remoting/core/ResponderChannel.java | 21 +- .../remoting/core/ResponderFrameHandler.java | 21 +- .../remoting/core/ResponderLeaseTracker.java | 21 +- .../main/java/infra/remoting/core/Resume.java | 21 +- .../java/infra/remoting/core/SendUtils.java | 21 +- .../java/infra/remoting/core/ServerSetup.java | 21 +- .../core/SetupHandlingConnection.java | 21 +- .../core/SlowFireAndForgetRequesterMono.java | 21 +- .../java/infra/remoting/core/StateUtils.java | 21 +- .../infra/remoting/core/StreamIdProvider.java | 21 +- .../infra/remoting/core/package-info.java | 21 +- .../error/ApplicationErrorException.java | 21 +- .../remoting/error/CanceledException.java | 21 +- .../error/ConnectionCloseException.java | 21 +- .../error/ConnectionErrorException.java | 21 +- .../error/CustomProtocolException.java | 21 +- .../java/infra/remoting/error/Exceptions.java | 21 +- .../remoting/error/InvalidException.java | 21 +- .../remoting/error/InvalidSetupException.java | 21 +- .../remoting/error/RejectedException.java | 21 +- .../error/RejectedResumeException.java | 21 +- .../error/RejectedSetupException.java | 21 +- .../java/infra/remoting/error/Retryable.java | 21 +- .../infra/remoting/error/SetupException.java | 21 +- .../error/UnsupportedSetupException.java | 21 +- .../infra/remoting/error/package-info.java | 21 +- .../remoting/frame/CancelFrameCodec.java | 21 +- .../infra/remoting/frame/ErrorFrameCodec.java | 21 +- .../remoting/frame/ExtensionFrameCodec.java | 21 +- .../infra/remoting/frame/FrameBodyCodec.java | 21 +- .../remoting/frame/FrameHeaderCodec.java | 21 +- .../remoting/frame/FrameLengthCodec.java | 21 +- .../java/infra/remoting/frame/FrameType.java | 21 +- .../java/infra/remoting/frame/FrameUtil.java | 21 +- .../remoting/frame/GenericFrameCodec.java | 21 +- .../remoting/frame/KeepAliveFrameCodec.java | 21 +- .../infra/remoting/frame/LeaseFrameCodec.java | 21 +- .../frame/MetadataPushFrameCodec.java | 21 +- .../remoting/frame/PayloadFrameCodec.java | 21 +- .../frame/RequestChannelFrameCodec.java | 21 +- .../frame/RequestFireAndForgetFrameCodec.java | 21 +- .../remoting/frame/RequestNFrameCodec.java | 21 +- .../frame/RequestResponseFrameCodec.java | 21 +- .../frame/RequestStreamFrameCodec.java | 21 +- .../remoting/frame/ResumeFrameCodec.java | 21 +- .../remoting/frame/ResumeOkFrameCodec.java | 21 +- .../infra/remoting/frame/SetupFrameCodec.java | 21 +- .../infra/remoting/frame/VersionCodec.java | 21 +- .../frame/decoder/DefaultPayloadDecoder.java | 21 +- .../frame/decoder/PayloadDecoder.java | 21 +- .../frame/decoder/ZeroCopyPayloadDecoder.java | 21 +- .../remoting/frame/decoder/package-info.java | 21 +- .../infra/remoting/frame/package-info.java | 21 +- .../remoting/internal/BaseConnection.java | 21 +- .../remoting/internal/UnboundedProcessor.java | 21 +- .../jctools/queues/BaseLinkedQueue.java | 21 +- .../queues/BaseMpscLinkedArrayQueue.java | 21 +- .../jctools/queues/IndexedQueueSizeUtil.java | 21 +- .../jctools/queues/LinkedArrayQueueUtil.java | 21 +- .../jctools/queues/LinkedQueueNode.java | 21 +- .../jctools/queues/MessagePassingQueue.java | 21 +- .../queues/MessagePassingQueueUtil.java | 21 +- .../queues/MpscUnboundedArrayQueue.java | 21 +- .../jctools/queues/PortableJvmInfo.java | 21 +- .../internal/jctools/queues/Pow2.java | 21 +- .../queues/QueueProgressIndicators.java | 21 +- .../internal/jctools/queues/RangeUtil.java | 21 +- .../internal/jctools/queues/UnsafeAccess.java | 21 +- .../jctools/queues/UnsafeRefArrayAccess.java | 21 +- .../infra/remoting/internal/package-info.java | 21 +- .../keepalive/KeepAliveFramesAcceptor.java | 21 +- .../remoting/keepalive/KeepAliveHandler.java | 21 +- .../remoting/keepalive/KeepAliveSupport.java | 21 +- .../remoting/keepalive/package-info.java | 21 +- .../infra/remoting/lb/BaseWeightedStats.java | 21 +- .../java/infra/remoting/lb/ChannelPool.java | 21 +- .../lb/ClientLoadBalanceStrategy.java | 21 +- .../src/main/java/infra/remoting/lb/Ewma.java | 21 +- .../remoting/lb/FluxDeferredResolution.java | 21 +- .../infra/remoting/lb/FrugalQuantile.java | 21 +- .../infra/remoting/lb/Int2LongHashMap.java | 21 +- .../lb/LoadBalanceRemotingClient.java | 21 +- .../remoting/lb/LoadBalanceStrategy.java | 21 +- .../infra/remoting/lb/LoadBalanceTarget.java | 21 +- .../main/java/infra/remoting/lb/Median.java | 21 +- .../remoting/lb/MonoDeferredResolution.java | 21 +- .../java/infra/remoting/lb/PooledChannel.java | 21 +- .../main/java/infra/remoting/lb/Quantile.java | 21 +- .../infra/remoting/lb/ResolvingOperator.java | 21 +- .../lb/RoundRobinLoadBalanceStrategy.java | 21 +- .../lb/WeightedLoadBalanceStrategy.java | 21 +- .../java/infra/remoting/lb/WeightedStats.java | 21 +- .../remoting/lb/WeightedStatsChannel.java | 21 +- .../lb/WeightedStatsRequestInterceptor.java | 21 +- .../java/infra/remoting/lb/package-info.java | 21 +- .../main/java/infra/remoting/lease/Lease.java | 21 +- .../infra/remoting/lease/LeaseSender.java | 21 +- .../remoting/lease/MissingLeaseException.java | 21 +- .../remoting/lease/TrackingLeaseSender.java | 21 +- .../infra/remoting/lease/package-info.java | 21 +- .../java/infra/remoting/package-info.java | 21 +- .../plugins/ChannelAcceptorDecorator.java | 21 +- .../remoting/plugins/ChannelDecorator.java | 21 +- .../plugins/CompositeRequestInterceptor.java | 21 +- .../remoting/plugins/ConnectionDecorator.java | 21 +- .../InitializingInterceptorRegistry.java | 21 +- .../remoting/plugins/InterceptorRegistry.java | 21 +- .../remoting/plugins/RateLimitDecorator.java | 21 +- .../remoting/plugins/RequestInterceptor.java | 21 +- .../infra/remoting/plugins/package-info.java | 21 +- .../remoting/protocol/ProtocolFrame.java | 21 +- .../protocol/ProtocolParsingException.java | 21 +- .../infra/remoting/resume/ChannelSession.java | 21 +- .../remoting/resume/ClientChannelSession.java | 21 +- .../resume/InMemoryResumableFramesStore.java | 21 +- .../InMemoryResumableFramesStoreFactory.java | 21 +- .../RandomUUIDResumeTokenGenerator.java | 21 +- .../remoting/resume/ResumableConnection.java | 21 +- .../remoting/resume/ResumableFramesStore.java | 21 +- .../resume/ResumableFramesStoreFactory.java | 21 +- .../remoting/resume/ResumeStateException.java | 21 +- .../remoting/resume/ResumeStateHolder.java | 21 +- .../remoting/resume/ResumeTokenGenerator.java | 21 +- .../remoting/resume/ServerChannelSession.java | 21 +- .../infra/remoting/resume/SessionManager.java | 21 +- .../infra/remoting/resume/package-info.java | 21 +- .../remoting/transport/ClientTransport.java | 21 +- .../transport/ConnectionAcceptor.java | 21 +- .../remoting/transport/ServerTransport.java | 21 +- .../infra/remoting/transport/Transport.java | 21 +- .../remoting/transport/package-info.java | 21 +- .../infra/remoting/util/ByteBufPayload.java | 21 +- .../main/java/infra/remoting/util/Clock.java | 21 +- .../infra/remoting/util/DefaultPayload.java | 21 +- .../infra/remoting/util/EmptyPayload.java | 21 +- .../infra/remoting/util/PromiseAdapter.java | 21 +- .../infra/remoting/util/package-info.java | 21 +- .../test/java/infra/remoting/FrameAssert.java | 21 +- .../java/infra/remoting/PayloadAssert.java | 21 +- .../infra/remoting/RaceTestConstants.java | 21 +- .../java/infra/remoting/TestScheduler.java | 21 +- .../buffer/LeaksTrackingByteBufAllocator.java | 21 +- .../remoting/core/AbstractChannelRule.java | 21 +- .../remoting/core/ChannelConnectorTests.java | 21 +- .../remoting/core/ChannelLeaseTests.java | 21 +- .../remoting/core/ChannelReconnectTests.java | 21 +- .../infra/remoting/core/ChannelTests.java | 21 +- .../ClientServerInputMultiplexerTest.java | 21 +- .../core/ConnectionSetupPayloadTest.java | 21 +- .../core/DefaultChannelClientTests.java | 21 +- .../core/FireAndForgetRequesterMonoTests.java | 21 +- .../infra/remoting/core/KeepAliveTests.java | 21 +- .../core/PayloadValidationUtilsTests.java | 21 +- .../remoting/core/ReconnectMonoTests.java | 21 +- .../RemotingServerFragmentationTests.java | 21 +- .../remoting/core/RemotingServerTests.java | 21 +- .../RequestRequesterChannelFluxTests.java | 21 +- ...equestResponderChannelSubscriberTests.java | 21 +- .../RequestResponseRequesterMonoTests.java | 21 +- .../core/RequestStreamRequesterFluxTests.java | 21 +- .../RequesterChannelSubscribersTests.java | 21 +- .../RequesterChannelTerminationTests.java | 21 +- .../remoting/core/RequesterChannelTests.java | 21 +- .../core/RequesterOperatorsRacingTests.java | 21 +- .../remoting/core/ResolvingOperatorTests.java | 21 +- .../remoting/core/ResponderChannelTests.java | 21 +- .../core/ResponderOperatorsCommonTests.java | 21 +- .../infra/remoting/core/SendUtilsTests.java | 21 +- .../remoting/core/SetupRejectionTests.java | 21 +- .../infra/remoting/core/ShouldHaveFlag.java | 21 +- .../remoting/core/ShouldNotHaveFlag.java | 21 +- .../java/infra/remoting/core/StateAssert.java | 21 +- .../remoting/core/StreamIdProviderTest.java | 21 +- .../remoting/core/TestChannelSupport.java | 21 +- .../error/ApplicationErrorExceptionTests.java | 21 +- .../error/CanceledExceptionTests.java | 21 +- .../remoting/error/ChannelExceptionTests.java | 21 +- .../error/ConnectionCloseExceptionTests.java | 21 +- .../error/ConnectionErrorExceptionTests.java | 21 +- .../infra/remoting/error/ExceptionsTests.java | 21 +- .../remoting/error/InvalidExceptionTests.java | 21 +- .../error/InvalidSetupExceptionTests.java | 21 +- .../error/RejectedExceptionTests.java | 21 +- .../error/RejectedResumeExceptionTests.java | 21 +- .../error/RejectedSetupExceptionTests.java | 21 +- .../remoting/error/TestProtocolException.java | 21 +- .../error/UnsupportedSetupExceptionTests.java | 21 +- .../tcp/channel/ChannelEchoClient.java | 21 +- .../examples/tcp/client/ClientExample.java | 21 +- ...ingWithServerSideNotificationsExample.java | 21 +- .../lease/advanced/common/LeaseManager.java | 21 +- .../common/LimitBasedLeaseSender.java | 21 +- .../common/LimitBasedStatsCollector.java | 21 +- .../tcp/lease/advanced/controller/Task.java | 21 +- .../controller/TasksHandlingChannel.java | 21 +- .../invertmulticlient/RequestingServer.java | 21 +- .../invertmulticlient/RespondingClient.java | 21 +- .../multiclient/RequestingClient.java | 21 +- .../multiclient/RespondingServer.java | 21 +- .../tcp/lease/simple/LeaseExample.java | 21 +- .../RoundRobinLoadbalancerExample.java | 21 +- .../plugins/LimitRateInterceptorExample.java | 21 +- .../tcp/requestresponse/HelloWorldClient.java | 21 +- .../remoting/examples/tcp/resume/Files.java | 21 +- .../tcp/resume/ResumeFileTransfer.java | 21 +- .../tcp/stream/ClientStreamingToServer.java | 21 +- .../tcp/stream/ServerStreamingToClient.java | 21 +- .../ws/WebSocketAggregationSample.java | 21 +- .../examples/ws/WebSocketHeadersSample.java | 21 +- .../remoting/frame/ByteBufRepresentation.java | 21 +- .../remoting/frame/ErrorFrameCodecTests.java | 21 +- .../frame/ExtensionFrameCodecTests.java | 21 +- .../remoting/frame/FrameHeaderCodecTests.java | 21 +- .../frame/GenericFrameCodecTests.java | 21 +- .../frame/KeepaliveFrameFlyweightTests.java | 21 +- .../remoting/frame/LeaseFrameCodecTests.java | 21 +- .../remoting/frame/PayloadFlyweightTests.java | 21 +- .../frame/RequestNFrameCodecTests.java | 21 +- .../remoting/frame/ResumeFrameCodecTests.java | 21 +- .../frame/ResumeOkFrameCodecTests.java | 21 +- .../remoting/frame/SetupFrameCodecTests.java | 21 +- .../remoting/frame/VersionCodecTests.java | 21 +- .../remoting/internal/SchedulerUtils.java | 21 +- .../internal/UnboundedProcessorTests.java | 21 +- .../internal/subscriber/AssertSubscriber.java | 21 +- .../lb/LoadbalanceChannelClientTests.java | 21 +- .../infra/remoting/lb/LoadbalanceTests.java | 21 +- .../RoundRobinLoadBalanceStrategyTests.java | 21 +- .../lb/WeightedLoadBalanceStrategyTests.java | 21 +- .../infra/remoting/lease/LeaseImplTests.java | 21 +- .../plugins/RequestInterceptorTests.java | 21 +- .../plugins/TestRequestInterceptor.java | 21 +- .../remoting/protocol/MetadataTests.java | 21 +- .../resume/ClientChannelSessionTests.java | 21 +- .../resume/DisconnectableClientTransport.java | 21 +- .../resume/InMemoryResumeStoreTests.java | 21 +- .../resume/ResumeIntegrationTests.java | 21 +- .../resume/ServerChannelSessionTests.java | 21 +- .../remoting/test/util/ByteBufUtils.java | 21 +- .../remoting/test/util/LocalConnection.java | 21 +- .../infra/remoting/test/util/MockChannel.java | 21 +- .../infra/remoting/test/util/StringUtils.java | 21 +- .../test/util/TestClientTransport.java | 21 +- .../remoting/test/util/TestConnection.java | 21 +- .../test/util/TestLocalSocketAddress.java | 21 +- .../test/util/TestServerTransport.java | 21 +- .../remoting/test/util/TestSubscriber.java | 21 +- .../remoting/util/ByteBufPayloadTests.java | 21 +- .../remoting/util/DefaultPayloadTests.java | 21 +- .../src/test/resources/logback-test.xml | 16 - .../remoting/test/BaseClientServerTest.java | 21 +- .../remoting/test/ByteBufRepresentation.java | 21 +- .../infra/remoting/test/ClientSetupRule.java | 21 +- .../test/CountdownBaseSubscriber.java | 21 +- .../test/LeaksTrackingByteBufAllocator.java | 21 +- .../infra/remoting/test/PayloadPredicate.java | 21 +- .../java/infra/remoting/test/PerfTest.java | 21 +- .../java/infra/remoting/test/PingClient.java | 21 +- .../java/infra/remoting/test/PingHandler.java | 21 +- .../java/infra/remoting/test/SlowTest.java | 21 +- .../java/infra/remoting/test/TestChannel.java | 21 +- .../infra/remoting/test/TestConnection.java | 21 +- .../java/infra/remoting/test/TestFrames.java | 21 +- .../infra/remoting/test/TestSubscriber.java | 21 +- .../infra/remoting/test/TransportPair.java | 21 +- .../infra/remoting/test/TransportTest.java | 21 +- .../java/infra/remoting/test/TriFunction.java | 21 +- .../infra/remoting/test/package-info.java | 21 +- today-service-api/build.gradle | 4 +- .../src/main/java/infra/cloud/RpcRequest.java | 21 +- .../main/java/infra/cloud/RpcResponse.java | 21 +- .../cloud/serialize/MessagePackReader.java | 21 +- .../cloud/serialize/MessagePackWriter.java | 21 +- .../ProtobufArgumentSerialization.java | 21 +- .../serialize/ReturnValueDeserializer.java | 21 +- .../serialize/ReturnValueSerialization.java | 21 +- .../serialize/ReturnValueSerializer.java | 21 +- .../serialize/RpcArgumentSerialization.java | 21 +- .../SimpleValueArgumentSerialization.java | 21 +- .../serialize/ThrowableSerialization.java | 21 +- .../infra/cloud/serialize/package-info.java | 21 +- .../value/FuncValueSerialization.java | 21 +- .../serialize/value/ValueSerialization.java | 21 +- ...tractServiceInterfaceMetadataProvider.java | 21 +- .../infra/cloud/service/InvocationResult.java | 21 +- .../infra/cloud/service/InvocationType.java | 21 +- .../java/infra/cloud/service/Metadata.java | 21 +- .../cloud/service/MethodIdGenerator.java | 21 +- .../PackageInfoServiceMetadataProvider.java | 21 +- .../service/ServiceInterfaceMetadata.java | 21 +- .../ServiceInterfaceMetadataProvider.java | 21 +- .../infra/cloud/service/ServiceMetadata.java | 21 +- .../service/ServiceMetadataProvider.java | 21 +- .../infra/cloud/service/ServiceMethod.java | 21 +- .../service/config/ResumeProperties.java | 21 +- .../infra/cloud/service/package-info.java | 21 +- .../cloud/service/MethodIdGeneratorTests.java | 21 +- .../infra/cloud/ServiceTimeoutException.java | 21 +- .../ServiceDependencyResolvingStrategy.java | 21 +- .../client/annotation/ServiceReference.java | 21 +- .../ServiceClientAutoConfiguration.java | 21 +- .../service/AbstractInvocationResult.java | 21 +- .../cloud/service/ClientInterceptor.java | 21 +- .../DefaultRemotingOperationsProvider.java | 21 +- ...faultServiceInterfaceMetadataProvider.java | 21 +- .../service/DefaultServiceProxyFactory.java | 21 +- .../cloud/service/DuplexStreamingResult.java | 21 +- .../cloud/service/FireAndForgetResult.java | 21 +- .../service/MethodServiceInvocation.java | 21 +- .../service/RemotingOperationsProvider.java | 21 +- .../cloud/service/RequestResponseResult.java | 21 +- .../service/ResponseStreamingResult.java | 21 +- .../cloud/service/ReturnValueResolver.java | 21 +- .../cloud/service/ServiceInterfaceMethod.java | 21 +- .../cloud/service/ServiceInvocation.java | 21 +- .../infra/cloud/service/ServiceInvoker.java | 21 +- .../cloud/service/ServiceMethodInvoker.java | 21 +- .../infra/cloud/service/ServiceProvider.java | 21 +- .../cloud/service/ServiceProxyFactory.java | 21 +- .../service/serialize/RequestSerializer.java | 21 +- .../serialize/ResponseDeserializer.java | 21 +- .../main/resources/META-INF/today.strategies | 16 - .../ServiceClientAutoConfigurationTests.java | 21 +- ...ServiceInterfaceMetadataProviderTests.java | 21 +- .../service/ServiceInvokerFactoryTests.java | 21 +- .../cloud/service/TracingInterceptor.java | 21 +- today-service-discovery/build.gradle | 4 +- .../client/CompositeDiscoveryClient.java | 21 +- .../infra/cloud/client/DiscoveryClient.java | 21 +- .../DiscoveryClientAutoConfiguration.java | 21 +- .../client/simple/SimpleDiscoveryClient.java | 21 +- .../simple/SimpleDiscoveryProperties.java | 21 +- ...DiscoveryClientAutoConfigurationTests.java | 21 +- .../CompositeDiscoveryClientOrderTest.java | 21 +- .../client/CompositeDiscoveryClientTests.java | 21 +- .../CompositeDiscoveryClientTestsConfig.java | 21 +- .../CompositeDiscoveryClientUnitTests.java | 21 +- ...ryClientAutoConfigurationDefaultTests.java | 21 +- ...DiscoveryClientPropertiesMappingTests.java | 21 +- .../client/SimpleDiscoveryClientTests.java | 21 +- ...faultServiceInterfaceMetadataProvider.java | 21 +- .../infra/cloud/provider/InvocableMethod.java | 21 +- .../cloud/provider/LocalServiceHolder.java | 21 +- .../infra/cloud/provider/RemoteRequest.java | 21 +- .../cloud/provider/ResponseSerializer.java | 21 +- .../provider/RpcRequestDeserializer.java | 21 +- .../provider/ServerTransportFactory.java | 21 +- .../cloud/provider/ServiceChannelHandler.java | 21 +- .../infra/cloud/provider/ServiceObject.java | 21 +- .../cloud/provider/ServiceProviderServer.java | 21 +- .../provider/ServiceServerProperties.java | 27 +- .../cloud/provider/ServicesProvider.java | 21 +- .../provider/TcpServerTransportFactory.java | 21 +- .../ServiceProviderAutoConfiguration.java | 21 +- .../infra/cloud/provider/package-info.java | 21 +- .../provider/LocalServiceHolderTests.java | 21 +- today-service-registration/build.gradle | 4 +- .../AbstractAutoServiceRegistration.java | 21 +- .../registry/AutoServiceRegistration.java | 21 +- .../AutoServiceRegistrationProperties.java | 21 +- .../cloud/registry/RegistrationFactory.java | 21 +- .../cloud/registry/RegistrationLifecycle.java | 21 +- .../ServiceRegisterFailedException.java | 21 +- .../infra/cloud/registry/ServiceRegistry.java | 21 +- ...oServiceRegistrationAutoConfiguration.java | 21 +- .../AutoServiceRegistrationConfiguration.java | 27 +- .../event/InstancePreRegisteredEvent.java | 21 +- .../event/InstanceRegisteredEvent.java | 21 +- .../build.gradle | 4 +- .../registry/simple/HttpRegistration.java | 21 +- .../infra/cloud/registry/simple/Status.java | 21 +- .../api/SimpleHttpServiceRegistryAPI.java | 24 +- .../simple/config/SimpleHttpProperties.java | 21 +- ...tpServiceRegistryAPIAutoConfiguration.java | 27 +- .../build.gradle | 2 +- .../discovery/SimpleHttpDiscoveryClient.java | 21 +- ...eHttpDiscoveryClientAutoConfiguration.java | 21 +- .../build.gradle | 2 +- .../simple/HttpRegistrationFactory.java | 21 +- .../simple/SimpleAutoServiceRegistration.java | 21 +- .../simple/SimpleHttpServiceRegistry.java | 21 +- .../simple/SimpleRegistryProperties.java | 21 +- ...eHttpServiceRegistryAutoConfiguration.java | 21 +- .../build.gradle | 2 +- .../server/ServiceNotFoundException.java | 21 +- .../SimpleHttpServiceRegistryEndpoint.java | 21 +- ...erviceRegistryServerAutoConfiguration.java | 21 +- today-service-serialization/build.gradle | 2 +- .../infra/cloud/serialize/Deserializer.java | 21 +- .../java/infra/cloud/serialize/Message.java | 21 +- .../java/infra/cloud/serialize/Readable.java | 21 +- .../infra/cloud/serialize/Serialization.java | 21 +- .../serialize/SerializationException.java | 21 +- .../infra/cloud/serialize/Serializer.java | 21 +- .../java/infra/cloud/serialize/Writable.java | 21 +- .../serialize/format/ExtensionTypeHeader.java | 30 +- .../serialize/format/MessageBufferPacker.java | 21 +- .../cloud/serialize/format/MessageFormat.java | 21 +- .../format/MessageFormatException.java | 21 +- .../MessageInsufficientBufferException.java | 21 +- .../MessageIntegerOverflowException.java | 21 +- .../MessageNeverUsedFormatException.java | 21 +- .../cloud/serialize/format/MessagePack.java | 21 +- .../format/MessagePackException.java | 21 +- .../cloud/serialize/format/MessagePacker.java | 21 +- .../format/MessageSizeException.java | 21 +- .../format/MessageStringCodingException.java | 21 +- .../format/MessageTypeCastException.java | 21 +- .../format/MessageTypeException.java | 21 +- .../serialize/format/MessageUnpacker.java | 21 +- .../format/buffer/ArrayBufferInput.java | 21 +- .../format/buffer/ArrayBufferOutput.java | 21 +- .../format/buffer/ByteBufferInput.java | 21 +- .../format/buffer/ChannelBufferInput.java | 21 +- .../format/buffer/ChannelBufferOutput.java | 21 +- .../format/buffer/DirectBufferAccess.java | 21 +- .../format/buffer/InputStreamBufferInput.java | 21 +- .../format/buffer/MessageBuffer.java | 21 +- .../format/buffer/MessageBufferBE.java | 21 +- .../format/buffer/MessageBufferInput.java | 21 +- .../format/buffer/MessageBufferOutput.java | 21 +- .../format/buffer/MessageBufferU.java | 21 +- .../buffer/OutputStreamBufferOutput.java | 21 +- .../cloud/serialize/format/package-info.java | 21 +- .../serialize/format/value/ArrayValue.java | 21 +- .../serialize/format/value/BinaryValue.java | 21 +- .../serialize/format/value/BooleanValue.java | 21 +- .../format/value/ExtensionValue.java | 21 +- .../serialize/format/value/FloatValue.java | 21 +- .../format/value/ImmutableArrayValue.java | 21 +- .../format/value/ImmutableBinaryValue.java | 21 +- .../format/value/ImmutableBooleanValue.java | 21 +- .../format/value/ImmutableExtensionValue.java | 21 +- .../format/value/ImmutableFloatValue.java | 21 +- .../format/value/ImmutableIntegerValue.java | 21 +- .../format/value/ImmutableMapValue.java | 21 +- .../format/value/ImmutableNilValue.java | 21 +- .../format/value/ImmutableNumberValue.java | 21 +- .../format/value/ImmutableRawValue.java | 21 +- .../format/value/ImmutableStringValue.java | 21 +- .../format/value/ImmutableTimestampValue.java | 21 +- .../format/value/ImmutableValue.java | 21 +- .../serialize/format/value/IntegerValue.java | 21 +- .../serialize/format/value/MapValue.java | 21 +- .../serialize/format/value/NilValue.java | 21 +- .../serialize/format/value/NumberValue.java | 21 +- .../serialize/format/value/RawValue.java | 21 +- .../serialize/format/value/StringValue.java | 21 +- .../format/value/TimestampValue.java | 21 +- .../cloud/serialize/format/value/Value.java | 21 +- .../serialize/format/value/ValueFactory.java | 21 +- .../serialize/format/value/ValueType.java | 21 +- .../serialize/format/value/Variable.java | 21 +- .../value/impl/AbstractImmutableRawValue.java | 21 +- .../value/impl/AbstractImmutableValue.java | 21 +- .../value/impl/ImmutableArrayValueImpl.java | 21 +- .../impl/ImmutableBigIntegerValueImpl.java | 21 +- .../value/impl/ImmutableBinaryValueImpl.java | 21 +- .../value/impl/ImmutableBooleanValueImpl.java | 21 +- .../value/impl/ImmutableDoubleValueImpl.java | 21 +- .../impl/ImmutableExtensionValueImpl.java | 21 +- .../value/impl/ImmutableLongValueImpl.java | 21 +- .../value/impl/ImmutableMapValueImpl.java | 21 +- .../value/impl/ImmutableNilValueImpl.java | 21 +- .../value/impl/ImmutableStringValueImpl.java | 21 +- .../impl/ImmutableTimestampValueImpl.java | 21 +- .../infra/cloud/serialize/MessageTests.java | 21 +- .../infra/cloud/serialize/ReadableTests.java | 21 +- 642 files changed, 6381 insertions(+), 7657 deletions(-) diff --git a/LICENSE b/LICENSE index c59803d..261eeb9 100644 --- a/LICENSE +++ b/LICENSE @@ -1,675 +1,201 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright © TODAY & 2017 - 2019 All Rights Reserved. - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright © TODAY & 2021 All Rights Reserved. - - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. diff --git a/README.md b/README.md index f1dfefd..b8932ed 100644 --- a/README.md +++ b/README.md @@ -3,5 +3,5 @@ Study to create a microservices framework like Spring Cloud ![Java17](https://img.shields.io/badge/JDK-17+-success.svg) -[![GPLv3](https://img.shields.io/badge/License-GPLv3-blue.svg)](./LICENSE) +[![Apache License 2.0](https://img.shields.io/github/license/today-tech/today-cloud?color=blue)](./LICENSE) [![Author](https://img.shields.io/badge/Author-TODAY-blue.svg)](https://github.com/TAKETODAY) diff --git a/build.gradle b/build.gradle index b50a677..cf70453 100644 --- a/build.gradle +++ b/build.gradle @@ -49,8 +49,8 @@ configure(javaProjects) { testImplementation("org.mockito:mockito-core") testImplementation("org.mockito:mockito-junit-jupiter") testImplementation("org.assertj:assertj-core") - testImplementation("cn.taketoday:today-test") - testImplementation("cn.taketoday:today-test-support") + testImplementation("cn.taketoday:infra-test") + testImplementation("cn.taketoday:infra-test-support") testImplementation 'org.projectlombok:lombok' testAnnotationProcessor("org.projectlombok:lombok") diff --git a/buildSrc/build.gradle b/buildSrc/build.gradle index e540677..7980a3c 100644 --- a/buildSrc/build.gradle +++ b/buildSrc/build.gradle @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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. */ plugins { @@ -29,7 +28,7 @@ repositories { dependencies { implementation(platform("cn.taketoday:infra-bom:$infraVersion")) - implementation "cn.taketoday:today-core" + implementation "cn.taketoday:infra-core" implementation "cn.taketoday:infra-gradle-plugin" implementation "org.gradle:test-retry-gradle-plugin:1.4.1" } diff --git a/buildSrc/src/main/java/infra/cloud/ConventionsPlugin.java b/buildSrc/src/main/java/infra/cloud/ConventionsPlugin.java index 3610d1e..74e1952 100644 --- a/buildSrc/src/main/java/infra/cloud/ConventionsPlugin.java +++ b/buildSrc/src/main/java/infra/cloud/ConventionsPlugin.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud; diff --git a/buildSrc/src/main/java/infra/cloud/JavaConventions.java b/buildSrc/src/main/java/infra/cloud/JavaConventions.java index 9b62015..ce55a00 100644 --- a/buildSrc/src/main/java/infra/cloud/JavaConventions.java +++ b/buildSrc/src/main/java/infra/cloud/JavaConventions.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud; diff --git a/buildSrc/src/main/java/infra/cloud/TestConventions.java b/buildSrc/src/main/java/infra/cloud/TestConventions.java index 0f1e29a..2fdac73 100644 --- a/buildSrc/src/main/java/infra/cloud/TestConventions.java +++ b/buildSrc/src/main/java/infra/cloud/TestConventions.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud; diff --git a/buildSrc/src/main/java/infra/cloud/optional/OptionalDependenciesPlugin.java b/buildSrc/src/main/java/infra/cloud/optional/OptionalDependenciesPlugin.java index 6574724..3d96014 100644 --- a/buildSrc/src/main/java/infra/cloud/optional/OptionalDependenciesPlugin.java +++ b/buildSrc/src/main/java/infra/cloud/optional/OptionalDependenciesPlugin.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.optional; diff --git a/gradle.properties b/gradle.properties index 3521bff..4d42727 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,19 +1,3 @@ -# -# Copyright 2021 - 2024 the original author or authors. -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see [http://www.gnu.org/licenses/] -# version=1.0.0-Draft.1-SNAPSHOT diff --git a/gradle/cloud-module.gradle b/gradle/cloud-module.gradle index 1e35e96..b6baa89 100644 --- a/gradle/cloud-module.gradle +++ b/gradle/cloud-module.gradle @@ -1,20 +1,3 @@ -/* - * Copyright 2021 - 2024 the original author or authors. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] - */ - //file:noinspection ConfigurationAvoidance import java.time.LocalDateTime diff --git a/gradle/publications.gradle b/gradle/publications.gradle index b3c2b78..ed7fd9a 100644 --- a/gradle/publications.gradle +++ b/gradle/publications.gradle @@ -19,8 +19,8 @@ publishing { } licenses { license { - name = "GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007" - url = "https://www.gnu.org/licenses/gpl.txt" + name = 'The Apache License, Version 2.0' + url = 'https://www.apache.org/licenses/LICENSE-2.0.txt' distribution = "repo" } } diff --git a/today-cloud-config-server/build.gradle b/today-cloud-config-server/build.gradle index 4ed91bb..79fd520 100644 --- a/today-cloud-config-server/build.gradle +++ b/today-cloud-config-server/build.gradle @@ -1,10 +1,10 @@ description = "TODAY Cloud Config Server" dependencies { - implementation "cn.taketoday:today-core" - implementation 'cn.taketoday:today-framework' + implementation "cn.taketoday:infra-core" + implementation 'cn.taketoday:infra-app' - testImplementation "cn.taketoday:today-test" + testImplementation "cn.taketoday:infra-test" annotationProcessor 'cn.taketoday:infra-configuration-processor' } \ No newline at end of file diff --git a/today-cloud-config-server/src/main/java/infra/config/DynamicProperty.java b/today-cloud-config-server/src/main/java/infra/config/DynamicProperty.java index 80bd016..598f4ae 100644 --- a/today-cloud-config-server/src/main/java/infra/config/DynamicProperty.java +++ b/today-cloud-config-server/src/main/java/infra/config/DynamicProperty.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.config; diff --git a/today-cloud-config-server/src/main/java/infra/config/DynamicPropertyDependencyResolvingStrategy.java b/today-cloud-config-server/src/main/java/infra/config/DynamicPropertyDependencyResolvingStrategy.java index 2aab4f7..3f31492 100644 --- a/today-cloud-config-server/src/main/java/infra/config/DynamicPropertyDependencyResolvingStrategy.java +++ b/today-cloud-config-server/src/main/java/infra/config/DynamicPropertyDependencyResolvingStrategy.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.config; diff --git a/today-cloud-core/build.gradle b/today-cloud-core/build.gradle index 9497de9..9496335 100644 --- a/today-cloud-core/build.gradle +++ b/today-cloud-core/build.gradle @@ -1,10 +1,9 @@ description = "TODAY Cloud Core Technologies" dependencies { - api 'cn.taketoday:today-core' - api 'cn.taketoday:today-framework' + api 'cn.taketoday:infra-core' - implementation 'cn.taketoday:today-context' + implementation 'cn.taketoday:infra-context' annotationProcessor 'cn.taketoday:infra-configuration-processor' } \ No newline at end of file diff --git a/today-cloud-core/src/main/java/infra/cloud/RemotingException.java b/today-cloud-core/src/main/java/infra/cloud/RemotingException.java index 15be122..411c250 100644 --- a/today-cloud-core/src/main/java/infra/cloud/RemotingException.java +++ b/today-cloud-core/src/main/java/infra/cloud/RemotingException.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud; diff --git a/today-cloud-core/src/main/java/infra/cloud/client/DefaultServiceInstance.java b/today-cloud-core/src/main/java/infra/cloud/client/DefaultServiceInstance.java index 847759b..a32ca57 100644 --- a/today-cloud-core/src/main/java/infra/cloud/client/DefaultServiceInstance.java +++ b/today-cloud-core/src/main/java/infra/cloud/client/DefaultServiceInstance.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.client; diff --git a/today-cloud-core/src/main/java/infra/cloud/client/Registration.java b/today-cloud-core/src/main/java/infra/cloud/client/Registration.java index b1749cd..8b2bab9 100644 --- a/today-cloud-core/src/main/java/infra/cloud/client/Registration.java +++ b/today-cloud-core/src/main/java/infra/cloud/client/Registration.java @@ -1,23 +1,26 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.client; /** + * Represents a registration of a service instance in the cloud infrastructure. + * This interface extends {@link ServiceInstance} to provide additional capabilities + * related to service registration and management within a cloud environment. + * * @author Harry Yang * @since 1.0 2023/11/20 21:50 */ diff --git a/today-cloud-core/src/main/java/infra/cloud/client/ServiceInstance.java b/today-cloud-core/src/main/java/infra/cloud/client/ServiceInstance.java index 61ca598..b87e6f3 100644 --- a/today-cloud-core/src/main/java/infra/cloud/client/ServiceInstance.java +++ b/today-cloud-core/src/main/java/infra/cloud/client/ServiceInstance.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.client; @@ -21,7 +20,9 @@ import java.util.Map; /** - * Represents an instance of a service. + * Represents an instance of a service in the cloud infrastructure. + * This interface defines the contract for accessing information about + * a specific service instance including its identity, location, and metadata. * * @author Harry Yang * @since 1.0 2023/11/19 20:52 diff --git a/today-cloud-core/src/main/java/infra/cloud/client/annotation/ConditionalOnDiscoveryEnabled.java b/today-cloud-core/src/main/java/infra/cloud/client/annotation/ConditionalOnDiscoveryEnabled.java index 976d363..960d0bc 100644 --- a/today-cloud-core/src/main/java/infra/cloud/client/annotation/ConditionalOnDiscoveryEnabled.java +++ b/today-cloud-core/src/main/java/infra/cloud/client/annotation/ConditionalOnDiscoveryEnabled.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.client.annotation; diff --git a/today-cloud-core/src/main/java/infra/cloud/net/HostInfo.java b/today-cloud-core/src/main/java/infra/cloud/net/HostInfo.java index 9d22163..14b1919 100644 --- a/today-cloud-core/src/main/java/infra/cloud/net/HostInfo.java +++ b/today-cloud-core/src/main/java/infra/cloud/net/HostInfo.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.net; diff --git a/today-cloud-core/src/main/java/infra/cloud/net/HostInfoEnvironmentPostProcessor.java b/today-cloud-core/src/main/java/infra/cloud/net/HostInfoEnvironmentPostProcessor.java index 8108521..4536dec 100644 --- a/today-cloud-core/src/main/java/infra/cloud/net/HostInfoEnvironmentPostProcessor.java +++ b/today-cloud-core/src/main/java/infra/cloud/net/HostInfoEnvironmentPostProcessor.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.net; diff --git a/today-cloud-core/src/main/java/infra/cloud/net/InetProperties.java b/today-cloud-core/src/main/java/infra/cloud/net/InetProperties.java index ad9bf86..c36b1ff 100644 --- a/today-cloud-core/src/main/java/infra/cloud/net/InetProperties.java +++ b/today-cloud-core/src/main/java/infra/cloud/net/InetProperties.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.net; diff --git a/today-cloud-core/src/main/java/infra/cloud/net/InetService.java b/today-cloud-core/src/main/java/infra/cloud/net/InetService.java index c00adeb..66a9675 100644 --- a/today-cloud-core/src/main/java/infra/cloud/net/InetService.java +++ b/today-cloud-core/src/main/java/infra/cloud/net/InetService.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.net; diff --git a/today-cloud-core/src/main/java/infra/cloud/package-info.java b/today-cloud-core/src/main/java/infra/cloud/package-info.java index fa784e7..e911378 100644 --- a/today-cloud-core/src/main/java/infra/cloud/package-info.java +++ b/today-cloud-core/src/main/java/infra/cloud/package-info.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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. */ @NullMarked diff --git a/today-cloud-core/src/test/java/infra/cloud/net/InetServiceTests.java b/today-cloud-core/src/test/java/infra/cloud/net/InetServiceTests.java index fa88958..f87188e 100644 --- a/today-cloud-core/src/test/java/infra/cloud/net/InetServiceTests.java +++ b/today-cloud-core/src/test/java/infra/cloud/net/InetServiceTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.net; diff --git a/today-cloud-samples/demo-tests/demo-registry/build.gradle b/today-cloud-samples/demo-tests/demo-registry/build.gradle index 5a18c66..aeddd12 100644 --- a/today-cloud-samples/demo-tests/demo-registry/build.gradle +++ b/today-cloud-samples/demo-tests/demo-registry/build.gradle @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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. */ description = "Demo Service Registry" @@ -25,8 +24,8 @@ infraJar { dependencies { implementation project(":today-service-registry-simple-server") - implementation 'cn.taketoday:today-starter-web' - implementation 'cn.taketoday:today-starter-netty' + implementation 'cn.taketoday:infra-starter-web' + implementation 'cn.taketoday:infra-starter-netty-server' implementation 'ch.qos.logback:logback-classic' annotationProcessor 'cn.taketoday:infra-configuration-processor' diff --git a/today-cloud-samples/demo-tests/demo-registry/src/main/java/cn/taketoday/demo/RegistryApplication.java b/today-cloud-samples/demo-tests/demo-registry/src/main/java/cn/taketoday/demo/RegistryApplication.java index 049f516..c3703af 100644 --- a/today-cloud-samples/demo-tests/demo-registry/src/main/java/cn/taketoday/demo/RegistryApplication.java +++ b/today-cloud-samples/demo-tests/demo-registry/src/main/java/cn/taketoday/demo/RegistryApplication.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 cn.taketoday.demo; diff --git a/today-cloud-samples/demo-tests/demo-registry/src/main/resources/logback-infra.xml b/today-cloud-samples/demo-tests/demo-registry/src/main/resources/logback-infra.xml index 178ec19..dd1789f 100644 --- a/today-cloud-samples/demo-tests/demo-registry/src/main/resources/logback-infra.xml +++ b/today-cloud-samples/demo-tests/demo-registry/src/main/resources/logback-infra.xml @@ -1,20 +1,4 @@ - TODAY Cloud Demos diff --git a/today-cloud-samples/demo-tests/demo-user-api/build.gradle b/today-cloud-samples/demo-tests/demo-user-api/build.gradle index bb654be..d5e8a67 100644 --- a/today-cloud-samples/demo-tests/demo-user-api/build.gradle +++ b/today-cloud-samples/demo-tests/demo-user-api/build.gradle @@ -1,7 +1,7 @@ description = "Demo User API" dependencies { - implementation 'cn.taketoday:today-context' + implementation 'cn.taketoday:infra-context' compileOnly("org.projectlombok:lombok") annotationProcessor("org.projectlombok:lombok") diff --git a/today-cloud-samples/demo-tests/demo-user-api/src/main/java/cn/taketoday/demo/model/User.java b/today-cloud-samples/demo-tests/demo-user-api/src/main/java/cn/taketoday/demo/model/User.java index e7ed309..634279f 100644 --- a/today-cloud-samples/demo-tests/demo-user-api/src/main/java/cn/taketoday/demo/model/User.java +++ b/today-cloud-samples/demo-tests/demo-user-api/src/main/java/cn/taketoday/demo/model/User.java @@ -1,21 +1,17 @@ /* - * Original Author -> 杨海健 (taketoday@foxmail.com) https://taketoday.cn - * Copyright © TODAY & 2021 All Rights Reserved. + * Copyright 2021 - 2026 the TODAY authors * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER + * 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 * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * https://www.apache.org/licenses/LICENSE-2.0 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 cn.taketoday.demo.model; diff --git a/today-cloud-samples/demo-tests/demo-user-api/src/main/java/cn/taketoday/demo/service/UserService.java b/today-cloud-samples/demo-tests/demo-user-api/src/main/java/cn/taketoday/demo/service/UserService.java index 3349920..5364016 100644 --- a/today-cloud-samples/demo-tests/demo-user-api/src/main/java/cn/taketoday/demo/service/UserService.java +++ b/today-cloud-samples/demo-tests/demo-user-api/src/main/java/cn/taketoday/demo/service/UserService.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 cn.taketoday.demo.service; diff --git a/today-cloud-samples/demo-tests/demo-user-api/src/main/resources/logback-infra.xml b/today-cloud-samples/demo-tests/demo-user-api/src/main/resources/logback-infra.xml index 178ec19..dd1789f 100644 --- a/today-cloud-samples/demo-tests/demo-user-api/src/main/resources/logback-infra.xml +++ b/today-cloud-samples/demo-tests/demo-user-api/src/main/resources/logback-infra.xml @@ -1,20 +1,4 @@ - TODAY Cloud Demos diff --git a/today-cloud-samples/demo-tests/demo-user-rest/build.gradle b/today-cloud-samples/demo-tests/demo-user-rest/build.gradle index ae64e51..4e331f3 100644 --- a/today-cloud-samples/demo-tests/demo-user-rest/build.gradle +++ b/today-cloud-samples/demo-tests/demo-user-rest/build.gradle @@ -5,9 +5,9 @@ dependencies { implementation project(":today-service-client") implementation project(":today-cloud-samples:demo-tests:demo-user-api") - implementation 'cn.taketoday:today-starter-web' - implementation 'cn.taketoday:today-starter-json' - implementation 'cn.taketoday:today-starter-netty' + implementation 'cn.taketoday:infra-starter-web' + implementation 'cn.taketoday:infra-starter-json' + implementation 'cn.taketoday:infra-starter-netty-server' implementation 'ch.qos.logback:logback-classic' implementation "com.google.protobuf:protobuf-java" diff --git a/today-cloud-samples/demo-tests/demo-user-rest/src/main/java/cn/taketoday/demo/ClientApplication.java b/today-cloud-samples/demo-tests/demo-user-rest/src/main/java/cn/taketoday/demo/ClientApplication.java index 4b84588..b0cc347 100644 --- a/today-cloud-samples/demo-tests/demo-user-rest/src/main/java/cn/taketoday/demo/ClientApplication.java +++ b/today-cloud-samples/demo-tests/demo-user-rest/src/main/java/cn/taketoday/demo/ClientApplication.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 cn.taketoday.demo; diff --git a/today-cloud-samples/demo-tests/demo-user-rest/src/main/java/cn/taketoday/demo/UserController.java b/today-cloud-samples/demo-tests/demo-user-rest/src/main/java/cn/taketoday/demo/UserController.java index 655d857..4934cb1 100644 --- a/today-cloud-samples/demo-tests/demo-user-rest/src/main/java/cn/taketoday/demo/UserController.java +++ b/today-cloud-samples/demo-tests/demo-user-rest/src/main/java/cn/taketoday/demo/UserController.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 cn.taketoday.demo; diff --git a/today-cloud-samples/demo-tests/demo-user-rest/src/main/resources/logback-infra.xml b/today-cloud-samples/demo-tests/demo-user-rest/src/main/resources/logback-infra.xml index 08d899a..c551468 100644 --- a/today-cloud-samples/demo-tests/demo-user-rest/src/main/resources/logback-infra.xml +++ b/today-cloud-samples/demo-tests/demo-user-rest/src/main/resources/logback-infra.xml @@ -1,20 +1,4 @@ - TODAY Cloud Client Demos diff --git a/today-cloud-samples/demo-tests/demo-user-service/build.gradle b/today-cloud-samples/demo-tests/demo-user-service/build.gradle index 12906ea..4acc4df 100644 --- a/today-cloud-samples/demo-tests/demo-user-service/build.gradle +++ b/today-cloud-samples/demo-tests/demo-user-service/build.gradle @@ -6,9 +6,9 @@ dependencies { implementation project(":today-service-provider") implementation project(":today-service-registry-simple-registration") -// implementation 'cn.taketoday:today-starter-web' -// implementation 'cn.taketoday:today-starter-netty' - implementation 'cn.taketoday:today-starter-logback' +// implementation 'cn.taketoday:infra-starter-web' +// implementation 'cn.taketoday:infra-starter-netty' + implementation 'cn.taketoday:infra-starter-logback' // implementation "com.google.protobuf:protobuf-java" diff --git a/today-cloud-samples/demo-tests/demo-user-service/src/main/java/cn/taketoday/demo/service/DefaultUserService.java b/today-cloud-samples/demo-tests/demo-user-service/src/main/java/cn/taketoday/demo/service/DefaultUserService.java index c020f9f..3dc9420 100644 --- a/today-cloud-samples/demo-tests/demo-user-service/src/main/java/cn/taketoday/demo/service/DefaultUserService.java +++ b/today-cloud-samples/demo-tests/demo-user-service/src/main/java/cn/taketoday/demo/service/DefaultUserService.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 cn.taketoday.demo.service; diff --git a/today-cloud-samples/demo-tests/demo-user-service/src/main/java/cn/taketoday/demo/service/UserServiceApplication.java b/today-cloud-samples/demo-tests/demo-user-service/src/main/java/cn/taketoday/demo/service/UserServiceApplication.java index 8cc21ca..61ddc51 100644 --- a/today-cloud-samples/demo-tests/demo-user-service/src/main/java/cn/taketoday/demo/service/UserServiceApplication.java +++ b/today-cloud-samples/demo-tests/demo-user-service/src/main/java/cn/taketoday/demo/service/UserServiceApplication.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 cn.taketoday.demo.service; diff --git a/today-cloud-samples/demo-tests/demo-user-service/src/main/resources/logback-infra.xml b/today-cloud-samples/demo-tests/demo-user-service/src/main/resources/logback-infra.xml index 3a96f13..6c55836 100644 --- a/today-cloud-samples/demo-tests/demo-user-service/src/main/resources/logback-infra.xml +++ b/today-cloud-samples/demo-tests/demo-user-service/src/main/resources/logback-infra.xml @@ -1,20 +1,4 @@ - TODAY Cloud Demos diff --git a/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/MicrometerChannel.java b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/MicrometerChannel.java index 78f31b3..f74254e 100644 --- a/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/MicrometerChannel.java +++ b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/MicrometerChannel.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.micrometer; diff --git a/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/MicrometerChannelDecorator.java b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/MicrometerChannelDecorator.java index 0c69c34..477e104 100644 --- a/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/MicrometerChannelDecorator.java +++ b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/MicrometerChannelDecorator.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.micrometer; diff --git a/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/MicrometerConnection.java b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/MicrometerConnection.java index d0b5d0c..29edc9d 100644 --- a/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/MicrometerConnection.java +++ b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/MicrometerConnection.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.micrometer; diff --git a/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/MicrometerConnectionDecorator.java b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/MicrometerConnectionDecorator.java index 55f0654..d2a609a 100644 --- a/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/MicrometerConnectionDecorator.java +++ b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/MicrometerConnectionDecorator.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.micrometer; diff --git a/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/ChannelContext.java b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/ChannelContext.java index 7d77d40..3195843 100644 --- a/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/ChannelContext.java +++ b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/ChannelContext.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.micrometer.observation; diff --git a/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/ChannelRequesterObservationConvention.java b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/ChannelRequesterObservationConvention.java index 9f47ef5..16732ed 100644 --- a/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/ChannelRequesterObservationConvention.java +++ b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/ChannelRequesterObservationConvention.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.micrometer.observation; diff --git a/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/ChannelRequesterTracingObservationHandler.java b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/ChannelRequesterTracingObservationHandler.java index 1d8d5ba..c006644 100644 --- a/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/ChannelRequesterTracingObservationHandler.java +++ b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/ChannelRequesterTracingObservationHandler.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.micrometer.observation; diff --git a/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/ChannelResponderObservationConvention.java b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/ChannelResponderObservationConvention.java index fc1d41f..541ab3b 100644 --- a/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/ChannelResponderObservationConvention.java +++ b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/ChannelResponderObservationConvention.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.micrometer.observation; diff --git a/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/ChannelResponderTracingObservationHandler.java b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/ChannelResponderTracingObservationHandler.java index 1e0c745..fa6cb7d 100644 --- a/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/ChannelResponderTracingObservationHandler.java +++ b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/ChannelResponderTracingObservationHandler.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.micrometer.observation; diff --git a/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/DefaultChannelObservationConvention.java b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/DefaultChannelObservationConvention.java index a6eebe6..0c67c5e 100644 --- a/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/DefaultChannelObservationConvention.java +++ b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/DefaultChannelObservationConvention.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.micrometer.observation; diff --git a/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/DefaultChannelRequesterObservationConvention.java b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/DefaultChannelRequesterObservationConvention.java index 2b874cb..3755076 100644 --- a/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/DefaultChannelRequesterObservationConvention.java +++ b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/DefaultChannelRequesterObservationConvention.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.micrometer.observation; diff --git a/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/DefaultChannelResponderObservationConvention.java b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/DefaultChannelResponderObservationConvention.java index 76ee3b1..e07f09d 100644 --- a/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/DefaultChannelResponderObservationConvention.java +++ b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/DefaultChannelResponderObservationConvention.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.micrometer.observation; diff --git a/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/ObservationRequesterChannel.java b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/ObservationRequesterChannel.java index b0ae526..492a90c 100644 --- a/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/ObservationRequesterChannel.java +++ b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/ObservationRequesterChannel.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.micrometer.observation; diff --git a/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/ObservationResponderChannel.java b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/ObservationResponderChannel.java index c196e91..8014962 100644 --- a/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/ObservationResponderChannel.java +++ b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/ObservationResponderChannel.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.micrometer.observation; diff --git a/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/PayloadUtils.java b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/PayloadUtils.java index 71aa552..71a6757 100644 --- a/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/PayloadUtils.java +++ b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/PayloadUtils.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.micrometer.observation; diff --git a/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/RemotingObservationDocumentation.java b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/RemotingObservationDocumentation.java index 2727cf9..cf467de 100644 --- a/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/RemotingObservationDocumentation.java +++ b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/RemotingObservationDocumentation.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.micrometer.observation; diff --git a/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/package-info.java b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/package-info.java index 16603bc..ee55704 100644 --- a/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/package-info.java +++ b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/package-info.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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. */ /** diff --git a/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/MicrometerChannelDecoratorTests.java b/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/MicrometerChannelDecoratorTests.java index d4b21ab..8d97b7d 100644 --- a/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/MicrometerChannelDecoratorTests.java +++ b/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/MicrometerChannelDecoratorTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.micrometer; diff --git a/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/MicrometerChannelTests.java b/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/MicrometerChannelTests.java index ca0d53c..1068a2e 100644 --- a/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/MicrometerChannelTests.java +++ b/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/MicrometerChannelTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.micrometer; diff --git a/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/MicrometerConnectionDecoratorTests.java b/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/MicrometerConnectionDecoratorTests.java index 4e164f9..73d3f9c 100644 --- a/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/MicrometerConnectionDecoratorTests.java +++ b/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/MicrometerConnectionDecoratorTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.micrometer; diff --git a/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/MicrometerConnectionTests.java b/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/MicrometerConnectionTests.java index f27e327..4dd6dad 100644 --- a/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/MicrometerConnectionTests.java +++ b/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/MicrometerConnectionTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.micrometer; diff --git a/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/IntegrationTests.java b/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/IntegrationTests.java index 8ae45e0..466b13b 100644 --- a/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/IntegrationTests.java +++ b/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/IntegrationTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.micrometer.integration; diff --git a/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/InteractionsLoadTests.java b/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/InteractionsLoadTests.java index 2be1db5..12a4bed 100644 --- a/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/InteractionsLoadTests.java +++ b/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/InteractionsLoadTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.micrometer.integration; diff --git a/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/StreamingTests.java b/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/StreamingTests.java index f372712..870fa68 100644 --- a/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/StreamingTests.java +++ b/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/StreamingTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.micrometer.integration; diff --git a/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/TcpIntegrationTests.java b/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/TcpIntegrationTests.java index 2a7bb7a..15ffaa9 100644 --- a/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/TcpIntegrationTests.java +++ b/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/TcpIntegrationTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.micrometer.integration; diff --git a/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/observation/ByteBufGetter.java b/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/observation/ByteBufGetter.java index f2536f2..3b8ce33 100644 --- a/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/observation/ByteBufGetter.java +++ b/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/observation/ByteBufGetter.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.micrometer.integration.observation; diff --git a/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/observation/ByteBufSetter.java b/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/observation/ByteBufSetter.java index 6223e5d..90ceed7 100644 --- a/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/observation/ByteBufSetter.java +++ b/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/observation/ByteBufSetter.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.micrometer.integration.observation; diff --git a/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/observation/ObservationIntegrationTests.java b/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/observation/ObservationIntegrationTests.java index f52119b..26e2c36 100644 --- a/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/observation/ObservationIntegrationTests.java +++ b/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/observation/ObservationIntegrationTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.micrometer.integration.observation; diff --git a/today-remoting-micrometer/src/test/resources/logback-test.xml b/today-remoting-micrometer/src/test/resources/logback-test.xml index 2cc1ec3..2a208a6 100644 --- a/today-remoting-micrometer/src/test/resources/logback-test.xml +++ b/today-remoting-micrometer/src/test/resources/logback-test.xml @@ -1,20 +1,4 @@ - diff --git a/today-remoting-transport-local/src/main/java/infra/remoting/transport/local/LocalClientTransport.java b/today-remoting-transport-local/src/main/java/infra/remoting/transport/local/LocalClientTransport.java index 786a470..dca4c21 100644 --- a/today-remoting-transport-local/src/main/java/infra/remoting/transport/local/LocalClientTransport.java +++ b/today-remoting-transport-local/src/main/java/infra/remoting/transport/local/LocalClientTransport.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.transport.local; diff --git a/today-remoting-transport-local/src/main/java/infra/remoting/transport/local/LocalConnection.java b/today-remoting-transport-local/src/main/java/infra/remoting/transport/local/LocalConnection.java index aa21578..cabc322 100644 --- a/today-remoting-transport-local/src/main/java/infra/remoting/transport/local/LocalConnection.java +++ b/today-remoting-transport-local/src/main/java/infra/remoting/transport/local/LocalConnection.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.transport.local; diff --git a/today-remoting-transport-local/src/main/java/infra/remoting/transport/local/LocalServerTransport.java b/today-remoting-transport-local/src/main/java/infra/remoting/transport/local/LocalServerTransport.java index 50d0330..2ef33be 100644 --- a/today-remoting-transport-local/src/main/java/infra/remoting/transport/local/LocalServerTransport.java +++ b/today-remoting-transport-local/src/main/java/infra/remoting/transport/local/LocalServerTransport.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.transport.local; diff --git a/today-remoting-transport-local/src/main/java/infra/remoting/transport/local/LocalSocketAddress.java b/today-remoting-transport-local/src/main/java/infra/remoting/transport/local/LocalSocketAddress.java index 9aa5098..902afd7 100644 --- a/today-remoting-transport-local/src/main/java/infra/remoting/transport/local/LocalSocketAddress.java +++ b/today-remoting-transport-local/src/main/java/infra/remoting/transport/local/LocalSocketAddress.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.transport.local; diff --git a/today-remoting-transport-local/src/main/java/infra/remoting/transport/local/package-info.java b/today-remoting-transport-local/src/main/java/infra/remoting/transport/local/package-info.java index 0566d12..8c33711 100644 --- a/today-remoting-transport-local/src/main/java/infra/remoting/transport/local/package-info.java +++ b/today-remoting-transport-local/src/main/java/infra/remoting/transport/local/package-info.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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. */ /** diff --git a/today-remoting-transport-local/src/test/java/infra/remoting/transport/local/LocalClientTransportTests.java b/today-remoting-transport-local/src/test/java/infra/remoting/transport/local/LocalClientTransportTests.java index 7f02ea4..da37baf 100644 --- a/today-remoting-transport-local/src/test/java/infra/remoting/transport/local/LocalClientTransportTests.java +++ b/today-remoting-transport-local/src/test/java/infra/remoting/transport/local/LocalClientTransportTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.transport.local; diff --git a/today-remoting-transport-local/src/test/java/infra/remoting/transport/local/LocalPingPong.java b/today-remoting-transport-local/src/test/java/infra/remoting/transport/local/LocalPingPong.java index 22b0279..20a56a4 100644 --- a/today-remoting-transport-local/src/test/java/infra/remoting/transport/local/LocalPingPong.java +++ b/today-remoting-transport-local/src/test/java/infra/remoting/transport/local/LocalPingPong.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.transport.local; diff --git a/today-remoting-transport-local/src/test/java/infra/remoting/transport/local/LocalResumableTransportTests.java b/today-remoting-transport-local/src/test/java/infra/remoting/transport/local/LocalResumableTransportTests.java index ca8444b..f2bd5f5 100644 --- a/today-remoting-transport-local/src/test/java/infra/remoting/transport/local/LocalResumableTransportTests.java +++ b/today-remoting-transport-local/src/test/java/infra/remoting/transport/local/LocalResumableTransportTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.transport.local; diff --git a/today-remoting-transport-local/src/test/java/infra/remoting/transport/local/LocalResumableWithFragmentationTransportTests.java b/today-remoting-transport-local/src/test/java/infra/remoting/transport/local/LocalResumableWithFragmentationTransportTests.java index f478b34..0a59c4f 100644 --- a/today-remoting-transport-local/src/test/java/infra/remoting/transport/local/LocalResumableWithFragmentationTransportTests.java +++ b/today-remoting-transport-local/src/test/java/infra/remoting/transport/local/LocalResumableWithFragmentationTransportTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.transport.local; diff --git a/today-remoting-transport-local/src/test/java/infra/remoting/transport/local/LocalServerTransportTests.java b/today-remoting-transport-local/src/test/java/infra/remoting/transport/local/LocalServerTransportTests.java index b713b86..3d6cf53 100644 --- a/today-remoting-transport-local/src/test/java/infra/remoting/transport/local/LocalServerTransportTests.java +++ b/today-remoting-transport-local/src/test/java/infra/remoting/transport/local/LocalServerTransportTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.transport.local; diff --git a/today-remoting-transport-local/src/test/java/infra/remoting/transport/local/LocalSocketAddressTests.java b/today-remoting-transport-local/src/test/java/infra/remoting/transport/local/LocalSocketAddressTests.java index fde758f..9a3ea3a 100644 --- a/today-remoting-transport-local/src/test/java/infra/remoting/transport/local/LocalSocketAddressTests.java +++ b/today-remoting-transport-local/src/test/java/infra/remoting/transport/local/LocalSocketAddressTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.transport.local; diff --git a/today-remoting-transport-local/src/test/java/infra/remoting/transport/local/LocalTransportTests.java b/today-remoting-transport-local/src/test/java/infra/remoting/transport/local/LocalTransportTests.java index 623ef52..27d0253 100644 --- a/today-remoting-transport-local/src/test/java/infra/remoting/transport/local/LocalTransportTests.java +++ b/today-remoting-transport-local/src/test/java/infra/remoting/transport/local/LocalTransportTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.transport.local; diff --git a/today-remoting-transport-local/src/test/java/infra/remoting/transport/local/LocalTransportWithFragmentationTests.java b/today-remoting-transport-local/src/test/java/infra/remoting/transport/local/LocalTransportWithFragmentationTests.java index aed5c90..1fe2311 100644 --- a/today-remoting-transport-local/src/test/java/infra/remoting/transport/local/LocalTransportWithFragmentationTests.java +++ b/today-remoting-transport-local/src/test/java/infra/remoting/transport/local/LocalTransportWithFragmentationTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.transport.local; diff --git a/today-remoting-transport-local/src/test/resources/logback-test.xml b/today-remoting-transport-local/src/test/resources/logback-test.xml index 04b396a..0cea20c 100644 --- a/today-remoting-transport-local/src/test/resources/logback-test.xml +++ b/today-remoting-transport-local/src/test/resources/logback-test.xml @@ -1,21 +1,4 @@ - - diff --git a/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/ProtocolFrameLengthCodec.java b/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/ProtocolFrameLengthCodec.java index eff6036..eab2ccf 100644 --- a/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/ProtocolFrameLengthCodec.java +++ b/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/ProtocolFrameLengthCodec.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.transport.netty; diff --git a/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/TcpConnection.java b/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/TcpConnection.java index 63d2bc0..1ebe582 100644 --- a/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/TcpConnection.java +++ b/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/TcpConnection.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.transport.netty; diff --git a/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/client/TcpClientTransport.java b/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/client/TcpClientTransport.java index 694db0c..61430f9 100644 --- a/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/client/TcpClientTransport.java +++ b/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/client/TcpClientTransport.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.transport.netty.client; diff --git a/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/client/package-info.java b/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/client/package-info.java index dae3f34..f1bebbd 100644 --- a/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/client/package-info.java +++ b/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/client/package-info.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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. */ /** The Netty-based client transport implementations. */ diff --git a/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/package-info.java b/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/package-info.java index 59ff962..70c5ee2 100644 --- a/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/package-info.java +++ b/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/package-info.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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. */ /** diff --git a/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/server/CloseableChannel.java b/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/server/CloseableChannel.java index 7bf2cd4..a03d349 100644 --- a/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/server/CloseableChannel.java +++ b/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/server/CloseableChannel.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.transport.netty.server; diff --git a/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/server/TcpServerTransport.java b/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/server/TcpServerTransport.java index bdba76b..3f0aca8 100644 --- a/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/server/TcpServerTransport.java +++ b/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/server/TcpServerTransport.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.transport.netty.server; diff --git a/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/server/package-info.java b/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/server/package-info.java index d40bed1..bead30e 100644 --- a/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/server/package-info.java +++ b/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/netty/server/package-info.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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. */ /** The Netty-based server transport implementations. */ diff --git a/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/tcp/TCPServerTransport.java b/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/tcp/TCPServerTransport.java index 6948686..119f884 100644 --- a/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/tcp/TCPServerTransport.java +++ b/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/tcp/TCPServerTransport.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.transport.tcp; diff --git a/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/tcp/package-info.java b/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/tcp/package-info.java index 50e7ebe..ac3b380 100644 --- a/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/tcp/package-info.java +++ b/today-remoting-transport-tcp/src/main/java/infra/remoting/transport/tcp/package-info.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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. */ /** diff --git a/today-remoting-transport-tcp/src/test/java/infra/remoting/integration/FragmentTests.java b/today-remoting-transport-tcp/src/test/java/infra/remoting/integration/FragmentTests.java index e0be1aa..df9aae4 100644 --- a/today-remoting-transport-tcp/src/test/java/infra/remoting/integration/FragmentTests.java +++ b/today-remoting-transport-tcp/src/test/java/infra/remoting/integration/FragmentTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.integration; diff --git a/today-remoting-transport-tcp/src/test/java/infra/remoting/integration/KeepaliveTests.java b/today-remoting-transport-tcp/src/test/java/infra/remoting/integration/KeepaliveTests.java index 0a22525..9397a06 100644 --- a/today-remoting-transport-tcp/src/test/java/infra/remoting/integration/KeepaliveTests.java +++ b/today-remoting-transport-tcp/src/test/java/infra/remoting/integration/KeepaliveTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.integration; diff --git a/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/ChannelFactoryNettyTransportFragmentationTests.java b/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/ChannelFactoryNettyTransportFragmentationTests.java index 762a1db..cca0964 100644 --- a/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/ChannelFactoryNettyTransportFragmentationTests.java +++ b/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/ChannelFactoryNettyTransportFragmentationTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.transport.netty; diff --git a/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/TcpFragmentationTransportTests.java b/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/TcpFragmentationTransportTests.java index e050f0a..9511411 100644 --- a/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/TcpFragmentationTransportTests.java +++ b/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/TcpFragmentationTransportTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.transport.netty; diff --git a/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/TcpPingTests.java b/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/TcpPingTests.java index 4c274e8..51ee0b3 100644 --- a/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/TcpPingTests.java +++ b/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/TcpPingTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.transport.netty; diff --git a/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/TcpPongServer.java b/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/TcpPongServer.java index 97ab50d..20d4327 100644 --- a/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/TcpPongServer.java +++ b/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/TcpPongServer.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.transport.netty; diff --git a/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/TcpResumableTransportTests.java b/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/TcpResumableTransportTests.java index 19cbfd9..54dc18e 100644 --- a/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/TcpResumableTransportTests.java +++ b/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/TcpResumableTransportTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.transport.netty; diff --git a/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/TcpResumableWithFragmentationTransportTests.java b/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/TcpResumableWithFragmentationTransportTests.java index e237a7e..d683f97 100644 --- a/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/TcpResumableWithFragmentationTransportTests.java +++ b/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/TcpResumableWithFragmentationTransportTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.transport.netty; diff --git a/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/TcpSecureTransportTests.java b/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/TcpSecureTransportTests.java index 91dde2f..b119251 100644 --- a/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/TcpSecureTransportTests.java +++ b/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/TcpSecureTransportTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.transport.netty; diff --git a/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/TcpTransportTests.java b/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/TcpTransportTests.java index e0cdf18..fbbe0cd 100644 --- a/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/TcpTransportTests.java +++ b/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/TcpTransportTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.transport.netty; diff --git a/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/client/TcpClientTransportTests.java b/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/client/TcpClientTransportTests.java index 2e3c26c..da489f4 100644 --- a/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/client/TcpClientTransportTests.java +++ b/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/client/TcpClientTransportTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.transport.netty.client; diff --git a/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/server/CloseableChannelTests.java b/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/server/CloseableChannelTests.java index 54bc5a1..15d54c7 100644 --- a/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/server/CloseableChannelTests.java +++ b/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/server/CloseableChannelTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.transport.netty.server; diff --git a/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/server/TcpServerTransportTests.java b/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/server/TcpServerTransportTests.java index 9f2fea2..3e7c8e5 100644 --- a/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/server/TcpServerTransportTests.java +++ b/today-remoting-transport-tcp/src/test/java/infra/remoting/transport/netty/server/TcpServerTransportTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.transport.netty.server; diff --git a/today-remoting-transport-tcp/src/test/resources/logback-test.xml b/today-remoting-transport-tcp/src/test/resources/logback-test.xml index 8918d37..7022e97 100644 --- a/today-remoting-transport-tcp/src/test/resources/logback-test.xml +++ b/today-remoting-transport-tcp/src/test/resources/logback-test.xml @@ -1,21 +1,4 @@ - - diff --git a/today-remoting-transport-websocket/src/main/java/infra/remoting/transport/websocket/BaseWebsocketServerTransport.java b/today-remoting-transport-websocket/src/main/java/infra/remoting/transport/websocket/BaseWebsocketServerTransport.java index d8a10fc..80f3697 100644 --- a/today-remoting-transport-websocket/src/main/java/infra/remoting/transport/websocket/BaseWebsocketServerTransport.java +++ b/today-remoting-transport-websocket/src/main/java/infra/remoting/transport/websocket/BaseWebsocketServerTransport.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.transport.websocket; diff --git a/today-remoting-transport-websocket/src/main/java/infra/remoting/transport/websocket/CloseableChannel.java b/today-remoting-transport-websocket/src/main/java/infra/remoting/transport/websocket/CloseableChannel.java index c2c0e29..2cd4edf 100644 --- a/today-remoting-transport-websocket/src/main/java/infra/remoting/transport/websocket/CloseableChannel.java +++ b/today-remoting-transport-websocket/src/main/java/infra/remoting/transport/websocket/CloseableChannel.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.transport.websocket; diff --git a/today-remoting-transport-websocket/src/main/java/infra/remoting/transport/websocket/WebsocketClientTransport.java b/today-remoting-transport-websocket/src/main/java/infra/remoting/transport/websocket/WebsocketClientTransport.java index 1bc9cb5..c14c173 100644 --- a/today-remoting-transport-websocket/src/main/java/infra/remoting/transport/websocket/WebsocketClientTransport.java +++ b/today-remoting-transport-websocket/src/main/java/infra/remoting/transport/websocket/WebsocketClientTransport.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.transport.websocket; diff --git a/today-remoting-transport-websocket/src/main/java/infra/remoting/transport/websocket/WebsocketConnection.java b/today-remoting-transport-websocket/src/main/java/infra/remoting/transport/websocket/WebsocketConnection.java index b6ff46e..1e9d289 100644 --- a/today-remoting-transport-websocket/src/main/java/infra/remoting/transport/websocket/WebsocketConnection.java +++ b/today-remoting-transport-websocket/src/main/java/infra/remoting/transport/websocket/WebsocketConnection.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.transport.websocket; diff --git a/today-remoting-transport-websocket/src/main/java/infra/remoting/transport/websocket/WebsocketRouteTransport.java b/today-remoting-transport-websocket/src/main/java/infra/remoting/transport/websocket/WebsocketRouteTransport.java index e506939..5c4cc9e 100644 --- a/today-remoting-transport-websocket/src/main/java/infra/remoting/transport/websocket/WebsocketRouteTransport.java +++ b/today-remoting-transport-websocket/src/main/java/infra/remoting/transport/websocket/WebsocketRouteTransport.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.transport.websocket; diff --git a/today-remoting-transport-websocket/src/main/java/infra/remoting/transport/websocket/WebsocketServerTransport.java b/today-remoting-transport-websocket/src/main/java/infra/remoting/transport/websocket/WebsocketServerTransport.java index 8c8cda2..9f0aecd 100644 --- a/today-remoting-transport-websocket/src/main/java/infra/remoting/transport/websocket/WebsocketServerTransport.java +++ b/today-remoting-transport-websocket/src/main/java/infra/remoting/transport/websocket/WebsocketServerTransport.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.transport.websocket; diff --git a/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/ChannelFactoryNettyTransportFragmentationTests.java b/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/ChannelFactoryNettyTransportFragmentationTests.java index 2cc5354..dbc2632 100644 --- a/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/ChannelFactoryNettyTransportFragmentationTests.java +++ b/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/ChannelFactoryNettyTransportFragmentationTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.transport.websocket; diff --git a/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/SetupRejectionTests.java b/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/SetupRejectionTests.java index 972f52a..59feb7d 100644 --- a/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/SetupRejectionTests.java +++ b/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/SetupRejectionTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.transport.websocket; diff --git a/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/WebSocketClient.java b/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/WebSocketClient.java index a0d27ea..b95d701 100644 --- a/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/WebSocketClient.java +++ b/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/WebSocketClient.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.transport.websocket; diff --git a/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/WebSocketClientHandler.java b/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/WebSocketClientHandler.java index 1bf23cc..2946450 100644 --- a/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/WebSocketClientHandler.java +++ b/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/WebSocketClientHandler.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.transport.websocket; diff --git a/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/WebSocketTransportIntegrationTests.java b/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/WebSocketTransportIntegrationTests.java index 10b555e..ede85ed 100644 --- a/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/WebSocketTransportIntegrationTests.java +++ b/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/WebSocketTransportIntegrationTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.transport.websocket; diff --git a/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/WebsocketClientTransportTests.java b/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/WebsocketClientTransportTests.java index ecc5efc..214778f 100644 --- a/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/WebsocketClientTransportTests.java +++ b/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/WebsocketClientTransportTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.transport.websocket; diff --git a/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/WebsocketPing.java b/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/WebsocketPing.java index dcb8e14..5e976a0 100644 --- a/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/WebsocketPing.java +++ b/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/WebsocketPing.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.transport.websocket; diff --git a/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/WebsocketPingPongIntegrationTests.java b/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/WebsocketPingPongIntegrationTests.java index 3b901b6..4a8a638 100644 --- a/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/WebsocketPingPongIntegrationTests.java +++ b/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/WebsocketPingPongIntegrationTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.transport.websocket; diff --git a/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/WebsocketPongServer.java b/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/WebsocketPongServer.java index 6d3efba..2b9f8a7 100644 --- a/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/WebsocketPongServer.java +++ b/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/WebsocketPongServer.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.transport.websocket; diff --git a/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/WebsocketResumableTransportTests.java b/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/WebsocketResumableTransportTests.java index fe1ccf1..ddbfa53 100644 --- a/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/WebsocketResumableTransportTests.java +++ b/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/WebsocketResumableTransportTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.transport.websocket; diff --git a/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/WebsocketResumableWithFragmentationTransportTests.java b/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/WebsocketResumableWithFragmentationTransportTests.java index 9eb1ef8..80480c5 100644 --- a/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/WebsocketResumableWithFragmentationTransportTests.java +++ b/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/WebsocketResumableWithFragmentationTransportTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.transport.websocket; diff --git a/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/WebsocketRouteTransportTests.java b/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/WebsocketRouteTransportTests.java index 6873f44..4386c08 100644 --- a/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/WebsocketRouteTransportTests.java +++ b/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/WebsocketRouteTransportTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.transport.websocket; diff --git a/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/WebsocketSecureTransportTests.java b/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/WebsocketSecureTransportTests.java index e5d4794..762b387 100644 --- a/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/WebsocketSecureTransportTests.java +++ b/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/WebsocketSecureTransportTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.transport.websocket; diff --git a/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/WebsocketServerTransportTests.java b/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/WebsocketServerTransportTests.java index f756913..df729f3 100644 --- a/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/WebsocketServerTransportTests.java +++ b/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/WebsocketServerTransportTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.transport.websocket; diff --git a/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/WebsocketTransportTests.java b/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/WebsocketTransportTests.java index 25f5923..6af6f55 100644 --- a/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/WebsocketTransportTests.java +++ b/today-remoting-transport-websocket/src/test/java/infra/remoting/transport/websocket/WebsocketTransportTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.transport.websocket; diff --git a/today-remoting/build.gradle b/today-remoting/build.gradle index 2bc4f5e..e47998d 100644 --- a/today-remoting/build.gradle +++ b/today-remoting/build.gradle @@ -4,7 +4,7 @@ description = "TODAY Cloud Remoting" dependencies { - api "cn.taketoday:today-core" + api "cn.taketoday:infra-core" api 'io.netty:netty-buffer' api 'io.projectreactor:reactor-core' @@ -19,7 +19,7 @@ dependencies { testRuntimeOnly 'ch.qos.logback:logback-classic' - testFixturesApi "cn.taketoday:today-core" + testFixturesApi "cn.taketoday:infra-core" testFixturesApi 'org.assertj:assertj-core' testFixturesApi 'org.junit.jupiter:junit-jupiter-api' testFixturesApi 'org.junit.jupiter:junit-jupiter-params' diff --git a/today-remoting/src/main/java/infra/remoting/Availability.java b/today-remoting/src/main/java/infra/remoting/Availability.java index 44e5dc7..d8fba94 100644 --- a/today-remoting/src/main/java/infra/remoting/Availability.java +++ b/today-remoting/src/main/java/infra/remoting/Availability.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting; diff --git a/today-remoting/src/main/java/infra/remoting/Channel.java b/today-remoting/src/main/java/infra/remoting/Channel.java index 583c54b..01e9222 100644 --- a/today-remoting/src/main/java/infra/remoting/Channel.java +++ b/today-remoting/src/main/java/infra/remoting/Channel.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting; diff --git a/today-remoting/src/main/java/infra/remoting/ChannelAcceptor.java b/today-remoting/src/main/java/infra/remoting/ChannelAcceptor.java index 308b4ee..33c3b0f 100644 --- a/today-remoting/src/main/java/infra/remoting/ChannelAcceptor.java +++ b/today-remoting/src/main/java/infra/remoting/ChannelAcceptor.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting; diff --git a/today-remoting/src/main/java/infra/remoting/ChannelAdapter.java b/today-remoting/src/main/java/infra/remoting/ChannelAdapter.java index 98e8f3f..4c3ed49 100644 --- a/today-remoting/src/main/java/infra/remoting/ChannelAdapter.java +++ b/today-remoting/src/main/java/infra/remoting/ChannelAdapter.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting; diff --git a/today-remoting/src/main/java/infra/remoting/ChannelWrapper.java b/today-remoting/src/main/java/infra/remoting/ChannelWrapper.java index f4b9a51..f17099e 100644 --- a/today-remoting/src/main/java/infra/remoting/ChannelWrapper.java +++ b/today-remoting/src/main/java/infra/remoting/ChannelWrapper.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting; diff --git a/today-remoting/src/main/java/infra/remoting/Closeable.java b/today-remoting/src/main/java/infra/remoting/Closeable.java index 7aa98a4..147d778 100644 --- a/today-remoting/src/main/java/infra/remoting/Closeable.java +++ b/today-remoting/src/main/java/infra/remoting/Closeable.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting; diff --git a/today-remoting/src/main/java/infra/remoting/Connection.java b/today-remoting/src/main/java/infra/remoting/Connection.java index 9f6c678..54175fa 100644 --- a/today-remoting/src/main/java/infra/remoting/Connection.java +++ b/today-remoting/src/main/java/infra/remoting/Connection.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting; diff --git a/today-remoting/src/main/java/infra/remoting/ConnectionSetupPayload.java b/today-remoting/src/main/java/infra/remoting/ConnectionSetupPayload.java index c1118b4..f6765bf 100644 --- a/today-remoting/src/main/java/infra/remoting/ConnectionSetupPayload.java +++ b/today-remoting/src/main/java/infra/remoting/ConnectionSetupPayload.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting; diff --git a/today-remoting/src/main/java/infra/remoting/ConnectionWrapper.java b/today-remoting/src/main/java/infra/remoting/ConnectionWrapper.java index feb3737..36aa832 100644 --- a/today-remoting/src/main/java/infra/remoting/ConnectionWrapper.java +++ b/today-remoting/src/main/java/infra/remoting/ConnectionWrapper.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting; diff --git a/today-remoting/src/main/java/infra/remoting/Payload.java b/today-remoting/src/main/java/infra/remoting/Payload.java index 02f7008..c30533f 100644 --- a/today-remoting/src/main/java/infra/remoting/Payload.java +++ b/today-remoting/src/main/java/infra/remoting/Payload.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting; diff --git a/today-remoting/src/main/java/infra/remoting/ProtocolErrorException.java b/today-remoting/src/main/java/infra/remoting/ProtocolErrorException.java index 4ac39f9..b2df2a7 100644 --- a/today-remoting/src/main/java/infra/remoting/ProtocolErrorException.java +++ b/today-remoting/src/main/java/infra/remoting/ProtocolErrorException.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting; diff --git a/today-remoting/src/main/java/infra/remoting/RemotingException.java b/today-remoting/src/main/java/infra/remoting/RemotingException.java index 21bb0fc..f53cfc7 100644 --- a/today-remoting/src/main/java/infra/remoting/RemotingException.java +++ b/today-remoting/src/main/java/infra/remoting/RemotingException.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting; diff --git a/today-remoting/src/main/java/infra/remoting/RemotingOperations.java b/today-remoting/src/main/java/infra/remoting/RemotingOperations.java index f28934c..863549a 100644 --- a/today-remoting/src/main/java/infra/remoting/RemotingOperations.java +++ b/today-remoting/src/main/java/infra/remoting/RemotingOperations.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting; diff --git a/today-remoting/src/main/java/infra/remoting/core/ChannelConnector.java b/today-remoting/src/main/java/infra/remoting/core/ChannelConnector.java index 41317c7..e557de7 100644 --- a/today-remoting/src/main/java/infra/remoting/core/ChannelConnector.java +++ b/today-remoting/src/main/java/infra/remoting/core/ChannelConnector.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.core; diff --git a/today-remoting/src/main/java/infra/remoting/core/ChannelSupport.java b/today-remoting/src/main/java/infra/remoting/core/ChannelSupport.java index 2e45432..ddfeafc 100644 --- a/today-remoting/src/main/java/infra/remoting/core/ChannelSupport.java +++ b/today-remoting/src/main/java/infra/remoting/core/ChannelSupport.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.core; diff --git a/today-remoting/src/main/java/infra/remoting/core/ClientServerInputMultiplexer.java b/today-remoting/src/main/java/infra/remoting/core/ClientServerInputMultiplexer.java index 701d3d0..fdbd4a8 100644 --- a/today-remoting/src/main/java/infra/remoting/core/ClientServerInputMultiplexer.java +++ b/today-remoting/src/main/java/infra/remoting/core/ClientServerInputMultiplexer.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.core; diff --git a/today-remoting/src/main/java/infra/remoting/core/ClientSetup.java b/today-remoting/src/main/java/infra/remoting/core/ClientSetup.java index 2e79ad6..32623a4 100644 --- a/today-remoting/src/main/java/infra/remoting/core/ClientSetup.java +++ b/today-remoting/src/main/java/infra/remoting/core/ClientSetup.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.core; diff --git a/today-remoting/src/main/java/infra/remoting/core/DefaultConnectionSetupPayload.java b/today-remoting/src/main/java/infra/remoting/core/DefaultConnectionSetupPayload.java index 76f4b34..d1c4fbd 100644 --- a/today-remoting/src/main/java/infra/remoting/core/DefaultConnectionSetupPayload.java +++ b/today-remoting/src/main/java/infra/remoting/core/DefaultConnectionSetupPayload.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.core; diff --git a/today-remoting/src/main/java/infra/remoting/core/DefaultRemotingClient.java b/today-remoting/src/main/java/infra/remoting/core/DefaultRemotingClient.java index 209fa96..ba347a4 100644 --- a/today-remoting/src/main/java/infra/remoting/core/DefaultRemotingClient.java +++ b/today-remoting/src/main/java/infra/remoting/core/DefaultRemotingClient.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.core; diff --git a/today-remoting/src/main/java/infra/remoting/core/FireAndForgetRequesterMono.java b/today-remoting/src/main/java/infra/remoting/core/FireAndForgetRequesterMono.java index 5f693fe..b6eee67 100644 --- a/today-remoting/src/main/java/infra/remoting/core/FireAndForgetRequesterMono.java +++ b/today-remoting/src/main/java/infra/remoting/core/FireAndForgetRequesterMono.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.core; diff --git a/today-remoting/src/main/java/infra/remoting/core/FireAndForgetResponderSubscriber.java b/today-remoting/src/main/java/infra/remoting/core/FireAndForgetResponderSubscriber.java index 70d601b..24462aa 100644 --- a/today-remoting/src/main/java/infra/remoting/core/FireAndForgetResponderSubscriber.java +++ b/today-remoting/src/main/java/infra/remoting/core/FireAndForgetResponderSubscriber.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.core; diff --git a/today-remoting/src/main/java/infra/remoting/core/FragmentationUtils.java b/today-remoting/src/main/java/infra/remoting/core/FragmentationUtils.java index 893b687..4a0873c 100644 --- a/today-remoting/src/main/java/infra/remoting/core/FragmentationUtils.java +++ b/today-remoting/src/main/java/infra/remoting/core/FragmentationUtils.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.core; diff --git a/today-remoting/src/main/java/infra/remoting/core/FrameHandler.java b/today-remoting/src/main/java/infra/remoting/core/FrameHandler.java index 5dd0d06..1e060b1 100644 --- a/today-remoting/src/main/java/infra/remoting/core/FrameHandler.java +++ b/today-remoting/src/main/java/infra/remoting/core/FrameHandler.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.core; diff --git a/today-remoting/src/main/java/infra/remoting/core/LeasePermitHandler.java b/today-remoting/src/main/java/infra/remoting/core/LeasePermitHandler.java index 56f81b2..66ba671 100644 --- a/today-remoting/src/main/java/infra/remoting/core/LeasePermitHandler.java +++ b/today-remoting/src/main/java/infra/remoting/core/LeasePermitHandler.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.core; diff --git a/today-remoting/src/main/java/infra/remoting/core/LeaseSpec.java b/today-remoting/src/main/java/infra/remoting/core/LeaseSpec.java index a56dafc..edb59eb 100644 --- a/today-remoting/src/main/java/infra/remoting/core/LeaseSpec.java +++ b/today-remoting/src/main/java/infra/remoting/core/LeaseSpec.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.core; diff --git a/today-remoting/src/main/java/infra/remoting/core/LoggingConnection.java b/today-remoting/src/main/java/infra/remoting/core/LoggingConnection.java index 790003d..e7284c3 100644 --- a/today-remoting/src/main/java/infra/remoting/core/LoggingConnection.java +++ b/today-remoting/src/main/java/infra/remoting/core/LoggingConnection.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.core; diff --git a/today-remoting/src/main/java/infra/remoting/core/MetadataPushRequesterMono.java b/today-remoting/src/main/java/infra/remoting/core/MetadataPushRequesterMono.java index 67f861d..39c914b 100644 --- a/today-remoting/src/main/java/infra/remoting/core/MetadataPushRequesterMono.java +++ b/today-remoting/src/main/java/infra/remoting/core/MetadataPushRequesterMono.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.core; diff --git a/today-remoting/src/main/java/infra/remoting/core/MetadataPushResponderSubscriber.java b/today-remoting/src/main/java/infra/remoting/core/MetadataPushResponderSubscriber.java index a0e9c0f..a3b9149 100644 --- a/today-remoting/src/main/java/infra/remoting/core/MetadataPushResponderSubscriber.java +++ b/today-remoting/src/main/java/infra/remoting/core/MetadataPushResponderSubscriber.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.core; diff --git a/today-remoting/src/main/java/infra/remoting/core/PayloadValidationUtils.java b/today-remoting/src/main/java/infra/remoting/core/PayloadValidationUtils.java index fdeba96..56926dd 100644 --- a/today-remoting/src/main/java/infra/remoting/core/PayloadValidationUtils.java +++ b/today-remoting/src/main/java/infra/remoting/core/PayloadValidationUtils.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.core; diff --git a/today-remoting/src/main/java/infra/remoting/core/ReassemblyUtils.java b/today-remoting/src/main/java/infra/remoting/core/ReassemblyUtils.java index a994999..25e5a6e 100644 --- a/today-remoting/src/main/java/infra/remoting/core/ReassemblyUtils.java +++ b/today-remoting/src/main/java/infra/remoting/core/ReassemblyUtils.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.core; diff --git a/today-remoting/src/main/java/infra/remoting/core/ReconnectMono.java b/today-remoting/src/main/java/infra/remoting/core/ReconnectMono.java index dc56388..15896c2 100644 --- a/today-remoting/src/main/java/infra/remoting/core/ReconnectMono.java +++ b/today-remoting/src/main/java/infra/remoting/core/ReconnectMono.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.core; diff --git a/today-remoting/src/main/java/infra/remoting/core/RemotingClient.java b/today-remoting/src/main/java/infra/remoting/core/RemotingClient.java index 3d3ff95..574b41e 100644 --- a/today-remoting/src/main/java/infra/remoting/core/RemotingClient.java +++ b/today-remoting/src/main/java/infra/remoting/core/RemotingClient.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.core; diff --git a/today-remoting/src/main/java/infra/remoting/core/RemotingClientAdapter.java b/today-remoting/src/main/java/infra/remoting/core/RemotingClientAdapter.java index 540ac7b..ee05c37 100644 --- a/today-remoting/src/main/java/infra/remoting/core/RemotingClientAdapter.java +++ b/today-remoting/src/main/java/infra/remoting/core/RemotingClientAdapter.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.core; diff --git a/today-remoting/src/main/java/infra/remoting/core/RemotingServer.java b/today-remoting/src/main/java/infra/remoting/core/RemotingServer.java index 825a951..0bc128c 100644 --- a/today-remoting/src/main/java/infra/remoting/core/RemotingServer.java +++ b/today-remoting/src/main/java/infra/remoting/core/RemotingServer.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.core; diff --git a/today-remoting/src/main/java/infra/remoting/core/RequestChannelRequesterFlux.java b/today-remoting/src/main/java/infra/remoting/core/RequestChannelRequesterFlux.java index 9a04a0b..d493b31 100644 --- a/today-remoting/src/main/java/infra/remoting/core/RequestChannelRequesterFlux.java +++ b/today-remoting/src/main/java/infra/remoting/core/RequestChannelRequesterFlux.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.core; diff --git a/today-remoting/src/main/java/infra/remoting/core/RequestChannelResponderSubscriber.java b/today-remoting/src/main/java/infra/remoting/core/RequestChannelResponderSubscriber.java index 37111b4..790c10c 100644 --- a/today-remoting/src/main/java/infra/remoting/core/RequestChannelResponderSubscriber.java +++ b/today-remoting/src/main/java/infra/remoting/core/RequestChannelResponderSubscriber.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.core; diff --git a/today-remoting/src/main/java/infra/remoting/core/RequestResponseRequesterMono.java b/today-remoting/src/main/java/infra/remoting/core/RequestResponseRequesterMono.java index fd6993d..83d6256 100644 --- a/today-remoting/src/main/java/infra/remoting/core/RequestResponseRequesterMono.java +++ b/today-remoting/src/main/java/infra/remoting/core/RequestResponseRequesterMono.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.core; diff --git a/today-remoting/src/main/java/infra/remoting/core/RequestResponseResponderSubscriber.java b/today-remoting/src/main/java/infra/remoting/core/RequestResponseResponderSubscriber.java index 0abc442..4d30603 100644 --- a/today-remoting/src/main/java/infra/remoting/core/RequestResponseResponderSubscriber.java +++ b/today-remoting/src/main/java/infra/remoting/core/RequestResponseResponderSubscriber.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.core; diff --git a/today-remoting/src/main/java/infra/remoting/core/RequestStreamRequesterFlux.java b/today-remoting/src/main/java/infra/remoting/core/RequestStreamRequesterFlux.java index c3cb528..d7346a9 100644 --- a/today-remoting/src/main/java/infra/remoting/core/RequestStreamRequesterFlux.java +++ b/today-remoting/src/main/java/infra/remoting/core/RequestStreamRequesterFlux.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.core; diff --git a/today-remoting/src/main/java/infra/remoting/core/RequestStreamResponderSubscriber.java b/today-remoting/src/main/java/infra/remoting/core/RequestStreamResponderSubscriber.java index f66ca84..f765138 100644 --- a/today-remoting/src/main/java/infra/remoting/core/RequestStreamResponderSubscriber.java +++ b/today-remoting/src/main/java/infra/remoting/core/RequestStreamResponderSubscriber.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.core; diff --git a/today-remoting/src/main/java/infra/remoting/core/RequesterChannel.java b/today-remoting/src/main/java/infra/remoting/core/RequesterChannel.java index 1aaf938..6990f55 100644 --- a/today-remoting/src/main/java/infra/remoting/core/RequesterChannel.java +++ b/today-remoting/src/main/java/infra/remoting/core/RequesterChannel.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.core; diff --git a/today-remoting/src/main/java/infra/remoting/core/RequesterFrameHandler.java b/today-remoting/src/main/java/infra/remoting/core/RequesterFrameHandler.java index 4a8f869..a1e6f8c 100644 --- a/today-remoting/src/main/java/infra/remoting/core/RequesterFrameHandler.java +++ b/today-remoting/src/main/java/infra/remoting/core/RequesterFrameHandler.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.core; diff --git a/today-remoting/src/main/java/infra/remoting/core/RequesterLeaseTracker.java b/today-remoting/src/main/java/infra/remoting/core/RequesterLeaseTracker.java index ede9ac0..0b3fbe4 100644 --- a/today-remoting/src/main/java/infra/remoting/core/RequesterLeaseTracker.java +++ b/today-remoting/src/main/java/infra/remoting/core/RequesterLeaseTracker.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.core; diff --git a/today-remoting/src/main/java/infra/remoting/core/ResolvingOperator.java b/today-remoting/src/main/java/infra/remoting/core/ResolvingOperator.java index 21ff44d..c164b15 100644 --- a/today-remoting/src/main/java/infra/remoting/core/ResolvingOperator.java +++ b/today-remoting/src/main/java/infra/remoting/core/ResolvingOperator.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.core; diff --git a/today-remoting/src/main/java/infra/remoting/core/ResponderChannel.java b/today-remoting/src/main/java/infra/remoting/core/ResponderChannel.java index 6e37116..bd031d4 100644 --- a/today-remoting/src/main/java/infra/remoting/core/ResponderChannel.java +++ b/today-remoting/src/main/java/infra/remoting/core/ResponderChannel.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.core; diff --git a/today-remoting/src/main/java/infra/remoting/core/ResponderFrameHandler.java b/today-remoting/src/main/java/infra/remoting/core/ResponderFrameHandler.java index 2b21cad..242f89e 100644 --- a/today-remoting/src/main/java/infra/remoting/core/ResponderFrameHandler.java +++ b/today-remoting/src/main/java/infra/remoting/core/ResponderFrameHandler.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.core; diff --git a/today-remoting/src/main/java/infra/remoting/core/ResponderLeaseTracker.java b/today-remoting/src/main/java/infra/remoting/core/ResponderLeaseTracker.java index a673d03..3e88a93 100644 --- a/today-remoting/src/main/java/infra/remoting/core/ResponderLeaseTracker.java +++ b/today-remoting/src/main/java/infra/remoting/core/ResponderLeaseTracker.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.core; diff --git a/today-remoting/src/main/java/infra/remoting/core/Resume.java b/today-remoting/src/main/java/infra/remoting/core/Resume.java index 29e79bf..94ec566 100644 --- a/today-remoting/src/main/java/infra/remoting/core/Resume.java +++ b/today-remoting/src/main/java/infra/remoting/core/Resume.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.core; diff --git a/today-remoting/src/main/java/infra/remoting/core/SendUtils.java b/today-remoting/src/main/java/infra/remoting/core/SendUtils.java index e7a9475..ef1e653 100644 --- a/today-remoting/src/main/java/infra/remoting/core/SendUtils.java +++ b/today-remoting/src/main/java/infra/remoting/core/SendUtils.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.core; diff --git a/today-remoting/src/main/java/infra/remoting/core/ServerSetup.java b/today-remoting/src/main/java/infra/remoting/core/ServerSetup.java index c1e3cc6..04ebf42 100644 --- a/today-remoting/src/main/java/infra/remoting/core/ServerSetup.java +++ b/today-remoting/src/main/java/infra/remoting/core/ServerSetup.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.core; diff --git a/today-remoting/src/main/java/infra/remoting/core/SetupHandlingConnection.java b/today-remoting/src/main/java/infra/remoting/core/SetupHandlingConnection.java index 18e8789..5fb5048 100644 --- a/today-remoting/src/main/java/infra/remoting/core/SetupHandlingConnection.java +++ b/today-remoting/src/main/java/infra/remoting/core/SetupHandlingConnection.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.core; diff --git a/today-remoting/src/main/java/infra/remoting/core/SlowFireAndForgetRequesterMono.java b/today-remoting/src/main/java/infra/remoting/core/SlowFireAndForgetRequesterMono.java index 59f5efb..b28e1cf 100644 --- a/today-remoting/src/main/java/infra/remoting/core/SlowFireAndForgetRequesterMono.java +++ b/today-remoting/src/main/java/infra/remoting/core/SlowFireAndForgetRequesterMono.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.core; diff --git a/today-remoting/src/main/java/infra/remoting/core/StateUtils.java b/today-remoting/src/main/java/infra/remoting/core/StateUtils.java index 79a3624..e826236 100644 --- a/today-remoting/src/main/java/infra/remoting/core/StateUtils.java +++ b/today-remoting/src/main/java/infra/remoting/core/StateUtils.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.core; diff --git a/today-remoting/src/main/java/infra/remoting/core/StreamIdProvider.java b/today-remoting/src/main/java/infra/remoting/core/StreamIdProvider.java index b6c2780..338bc38 100644 --- a/today-remoting/src/main/java/infra/remoting/core/StreamIdProvider.java +++ b/today-remoting/src/main/java/infra/remoting/core/StreamIdProvider.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.core; diff --git a/today-remoting/src/main/java/infra/remoting/core/package-info.java b/today-remoting/src/main/java/infra/remoting/core/package-info.java index 6b8f77e..054fe0b 100644 --- a/today-remoting/src/main/java/infra/remoting/core/package-info.java +++ b/today-remoting/src/main/java/infra/remoting/core/package-info.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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. */ /** diff --git a/today-remoting/src/main/java/infra/remoting/error/ApplicationErrorException.java b/today-remoting/src/main/java/infra/remoting/error/ApplicationErrorException.java index de3ee80..8977782 100644 --- a/today-remoting/src/main/java/infra/remoting/error/ApplicationErrorException.java +++ b/today-remoting/src/main/java/infra/remoting/error/ApplicationErrorException.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.error; diff --git a/today-remoting/src/main/java/infra/remoting/error/CanceledException.java b/today-remoting/src/main/java/infra/remoting/error/CanceledException.java index f61eca8..8d7a40d 100644 --- a/today-remoting/src/main/java/infra/remoting/error/CanceledException.java +++ b/today-remoting/src/main/java/infra/remoting/error/CanceledException.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.error; diff --git a/today-remoting/src/main/java/infra/remoting/error/ConnectionCloseException.java b/today-remoting/src/main/java/infra/remoting/error/ConnectionCloseException.java index fbc1f29..9bd9605 100644 --- a/today-remoting/src/main/java/infra/remoting/error/ConnectionCloseException.java +++ b/today-remoting/src/main/java/infra/remoting/error/ConnectionCloseException.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.error; diff --git a/today-remoting/src/main/java/infra/remoting/error/ConnectionErrorException.java b/today-remoting/src/main/java/infra/remoting/error/ConnectionErrorException.java index a107a1a..a37bc7d 100644 --- a/today-remoting/src/main/java/infra/remoting/error/ConnectionErrorException.java +++ b/today-remoting/src/main/java/infra/remoting/error/ConnectionErrorException.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.error; diff --git a/today-remoting/src/main/java/infra/remoting/error/CustomProtocolException.java b/today-remoting/src/main/java/infra/remoting/error/CustomProtocolException.java index bacbc40..503f8bd 100644 --- a/today-remoting/src/main/java/infra/remoting/error/CustomProtocolException.java +++ b/today-remoting/src/main/java/infra/remoting/error/CustomProtocolException.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.error; diff --git a/today-remoting/src/main/java/infra/remoting/error/Exceptions.java b/today-remoting/src/main/java/infra/remoting/error/Exceptions.java index 8c45af3..c5a46de 100644 --- a/today-remoting/src/main/java/infra/remoting/error/Exceptions.java +++ b/today-remoting/src/main/java/infra/remoting/error/Exceptions.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.error; diff --git a/today-remoting/src/main/java/infra/remoting/error/InvalidException.java b/today-remoting/src/main/java/infra/remoting/error/InvalidException.java index 7fb7195..059c4d9 100644 --- a/today-remoting/src/main/java/infra/remoting/error/InvalidException.java +++ b/today-remoting/src/main/java/infra/remoting/error/InvalidException.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.error; diff --git a/today-remoting/src/main/java/infra/remoting/error/InvalidSetupException.java b/today-remoting/src/main/java/infra/remoting/error/InvalidSetupException.java index da4c9f0..9e53dff 100644 --- a/today-remoting/src/main/java/infra/remoting/error/InvalidSetupException.java +++ b/today-remoting/src/main/java/infra/remoting/error/InvalidSetupException.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.error; diff --git a/today-remoting/src/main/java/infra/remoting/error/RejectedException.java b/today-remoting/src/main/java/infra/remoting/error/RejectedException.java index 2d96c73..323dbd3 100644 --- a/today-remoting/src/main/java/infra/remoting/error/RejectedException.java +++ b/today-remoting/src/main/java/infra/remoting/error/RejectedException.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.error; diff --git a/today-remoting/src/main/java/infra/remoting/error/RejectedResumeException.java b/today-remoting/src/main/java/infra/remoting/error/RejectedResumeException.java index 07f77d9..c8a26ed 100644 --- a/today-remoting/src/main/java/infra/remoting/error/RejectedResumeException.java +++ b/today-remoting/src/main/java/infra/remoting/error/RejectedResumeException.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.error; diff --git a/today-remoting/src/main/java/infra/remoting/error/RejectedSetupException.java b/today-remoting/src/main/java/infra/remoting/error/RejectedSetupException.java index 27b5805..b6b2839 100644 --- a/today-remoting/src/main/java/infra/remoting/error/RejectedSetupException.java +++ b/today-remoting/src/main/java/infra/remoting/error/RejectedSetupException.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.error; diff --git a/today-remoting/src/main/java/infra/remoting/error/Retryable.java b/today-remoting/src/main/java/infra/remoting/error/Retryable.java index 9e8c960..39d3002 100644 --- a/today-remoting/src/main/java/infra/remoting/error/Retryable.java +++ b/today-remoting/src/main/java/infra/remoting/error/Retryable.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.error; diff --git a/today-remoting/src/main/java/infra/remoting/error/SetupException.java b/today-remoting/src/main/java/infra/remoting/error/SetupException.java index c816b92..3e654a6 100644 --- a/today-remoting/src/main/java/infra/remoting/error/SetupException.java +++ b/today-remoting/src/main/java/infra/remoting/error/SetupException.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.error; diff --git a/today-remoting/src/main/java/infra/remoting/error/UnsupportedSetupException.java b/today-remoting/src/main/java/infra/remoting/error/UnsupportedSetupException.java index 95186c1..409da10 100644 --- a/today-remoting/src/main/java/infra/remoting/error/UnsupportedSetupException.java +++ b/today-remoting/src/main/java/infra/remoting/error/UnsupportedSetupException.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.error; diff --git a/today-remoting/src/main/java/infra/remoting/error/package-info.java b/today-remoting/src/main/java/infra/remoting/error/package-info.java index f719d7e..9c63461 100644 --- a/today-remoting/src/main/java/infra/remoting/error/package-info.java +++ b/today-remoting/src/main/java/infra/remoting/error/package-info.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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. */ /** diff --git a/today-remoting/src/main/java/infra/remoting/frame/CancelFrameCodec.java b/today-remoting/src/main/java/infra/remoting/frame/CancelFrameCodec.java index 4ee059c..16f72ac 100644 --- a/today-remoting/src/main/java/infra/remoting/frame/CancelFrameCodec.java +++ b/today-remoting/src/main/java/infra/remoting/frame/CancelFrameCodec.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.frame; diff --git a/today-remoting/src/main/java/infra/remoting/frame/ErrorFrameCodec.java b/today-remoting/src/main/java/infra/remoting/frame/ErrorFrameCodec.java index ff84222..b67cbdf 100644 --- a/today-remoting/src/main/java/infra/remoting/frame/ErrorFrameCodec.java +++ b/today-remoting/src/main/java/infra/remoting/frame/ErrorFrameCodec.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.frame; diff --git a/today-remoting/src/main/java/infra/remoting/frame/ExtensionFrameCodec.java b/today-remoting/src/main/java/infra/remoting/frame/ExtensionFrameCodec.java index 1860ad6..78dd1ed 100644 --- a/today-remoting/src/main/java/infra/remoting/frame/ExtensionFrameCodec.java +++ b/today-remoting/src/main/java/infra/remoting/frame/ExtensionFrameCodec.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.frame; diff --git a/today-remoting/src/main/java/infra/remoting/frame/FrameBodyCodec.java b/today-remoting/src/main/java/infra/remoting/frame/FrameBodyCodec.java index a2a16cc..ca0b2a2 100644 --- a/today-remoting/src/main/java/infra/remoting/frame/FrameBodyCodec.java +++ b/today-remoting/src/main/java/infra/remoting/frame/FrameBodyCodec.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.frame; diff --git a/today-remoting/src/main/java/infra/remoting/frame/FrameHeaderCodec.java b/today-remoting/src/main/java/infra/remoting/frame/FrameHeaderCodec.java index e2750a7..ddbc2a2 100644 --- a/today-remoting/src/main/java/infra/remoting/frame/FrameHeaderCodec.java +++ b/today-remoting/src/main/java/infra/remoting/frame/FrameHeaderCodec.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.frame; diff --git a/today-remoting/src/main/java/infra/remoting/frame/FrameLengthCodec.java b/today-remoting/src/main/java/infra/remoting/frame/FrameLengthCodec.java index 7560ec3..1259a24 100644 --- a/today-remoting/src/main/java/infra/remoting/frame/FrameLengthCodec.java +++ b/today-remoting/src/main/java/infra/remoting/frame/FrameLengthCodec.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.frame; diff --git a/today-remoting/src/main/java/infra/remoting/frame/FrameType.java b/today-remoting/src/main/java/infra/remoting/frame/FrameType.java index 714d0e2..de71673 100644 --- a/today-remoting/src/main/java/infra/remoting/frame/FrameType.java +++ b/today-remoting/src/main/java/infra/remoting/frame/FrameType.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.frame; diff --git a/today-remoting/src/main/java/infra/remoting/frame/FrameUtil.java b/today-remoting/src/main/java/infra/remoting/frame/FrameUtil.java index 1355d4c..055b423 100644 --- a/today-remoting/src/main/java/infra/remoting/frame/FrameUtil.java +++ b/today-remoting/src/main/java/infra/remoting/frame/FrameUtil.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.frame; diff --git a/today-remoting/src/main/java/infra/remoting/frame/GenericFrameCodec.java b/today-remoting/src/main/java/infra/remoting/frame/GenericFrameCodec.java index 17c9611..514b76e 100644 --- a/today-remoting/src/main/java/infra/remoting/frame/GenericFrameCodec.java +++ b/today-remoting/src/main/java/infra/remoting/frame/GenericFrameCodec.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.frame; diff --git a/today-remoting/src/main/java/infra/remoting/frame/KeepAliveFrameCodec.java b/today-remoting/src/main/java/infra/remoting/frame/KeepAliveFrameCodec.java index 40a1045..f1162c1 100644 --- a/today-remoting/src/main/java/infra/remoting/frame/KeepAliveFrameCodec.java +++ b/today-remoting/src/main/java/infra/remoting/frame/KeepAliveFrameCodec.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.frame; diff --git a/today-remoting/src/main/java/infra/remoting/frame/LeaseFrameCodec.java b/today-remoting/src/main/java/infra/remoting/frame/LeaseFrameCodec.java index c5c74d5..ab2e8ef 100644 --- a/today-remoting/src/main/java/infra/remoting/frame/LeaseFrameCodec.java +++ b/today-remoting/src/main/java/infra/remoting/frame/LeaseFrameCodec.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.frame; diff --git a/today-remoting/src/main/java/infra/remoting/frame/MetadataPushFrameCodec.java b/today-remoting/src/main/java/infra/remoting/frame/MetadataPushFrameCodec.java index d3cad41..d2e6496 100644 --- a/today-remoting/src/main/java/infra/remoting/frame/MetadataPushFrameCodec.java +++ b/today-remoting/src/main/java/infra/remoting/frame/MetadataPushFrameCodec.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.frame; diff --git a/today-remoting/src/main/java/infra/remoting/frame/PayloadFrameCodec.java b/today-remoting/src/main/java/infra/remoting/frame/PayloadFrameCodec.java index 41e4b9b..d1124c8 100644 --- a/today-remoting/src/main/java/infra/remoting/frame/PayloadFrameCodec.java +++ b/today-remoting/src/main/java/infra/remoting/frame/PayloadFrameCodec.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.frame; diff --git a/today-remoting/src/main/java/infra/remoting/frame/RequestChannelFrameCodec.java b/today-remoting/src/main/java/infra/remoting/frame/RequestChannelFrameCodec.java index ccf5e4c..cf1ad75 100644 --- a/today-remoting/src/main/java/infra/remoting/frame/RequestChannelFrameCodec.java +++ b/today-remoting/src/main/java/infra/remoting/frame/RequestChannelFrameCodec.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.frame; diff --git a/today-remoting/src/main/java/infra/remoting/frame/RequestFireAndForgetFrameCodec.java b/today-remoting/src/main/java/infra/remoting/frame/RequestFireAndForgetFrameCodec.java index 122f545..709747b 100644 --- a/today-remoting/src/main/java/infra/remoting/frame/RequestFireAndForgetFrameCodec.java +++ b/today-remoting/src/main/java/infra/remoting/frame/RequestFireAndForgetFrameCodec.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.frame; diff --git a/today-remoting/src/main/java/infra/remoting/frame/RequestNFrameCodec.java b/today-remoting/src/main/java/infra/remoting/frame/RequestNFrameCodec.java index a7d01f2..3b3dffc 100644 --- a/today-remoting/src/main/java/infra/remoting/frame/RequestNFrameCodec.java +++ b/today-remoting/src/main/java/infra/remoting/frame/RequestNFrameCodec.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.frame; diff --git a/today-remoting/src/main/java/infra/remoting/frame/RequestResponseFrameCodec.java b/today-remoting/src/main/java/infra/remoting/frame/RequestResponseFrameCodec.java index 75b040b..9814fab 100644 --- a/today-remoting/src/main/java/infra/remoting/frame/RequestResponseFrameCodec.java +++ b/today-remoting/src/main/java/infra/remoting/frame/RequestResponseFrameCodec.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.frame; diff --git a/today-remoting/src/main/java/infra/remoting/frame/RequestStreamFrameCodec.java b/today-remoting/src/main/java/infra/remoting/frame/RequestStreamFrameCodec.java index 6a6d8cd..7d771dd 100644 --- a/today-remoting/src/main/java/infra/remoting/frame/RequestStreamFrameCodec.java +++ b/today-remoting/src/main/java/infra/remoting/frame/RequestStreamFrameCodec.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.frame; diff --git a/today-remoting/src/main/java/infra/remoting/frame/ResumeFrameCodec.java b/today-remoting/src/main/java/infra/remoting/frame/ResumeFrameCodec.java index 76c0bb4..cd84eea 100644 --- a/today-remoting/src/main/java/infra/remoting/frame/ResumeFrameCodec.java +++ b/today-remoting/src/main/java/infra/remoting/frame/ResumeFrameCodec.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.frame; diff --git a/today-remoting/src/main/java/infra/remoting/frame/ResumeOkFrameCodec.java b/today-remoting/src/main/java/infra/remoting/frame/ResumeOkFrameCodec.java index 644dc83..00d1af7 100644 --- a/today-remoting/src/main/java/infra/remoting/frame/ResumeOkFrameCodec.java +++ b/today-remoting/src/main/java/infra/remoting/frame/ResumeOkFrameCodec.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.frame; diff --git a/today-remoting/src/main/java/infra/remoting/frame/SetupFrameCodec.java b/today-remoting/src/main/java/infra/remoting/frame/SetupFrameCodec.java index d6dc1fe..818b2d1 100644 --- a/today-remoting/src/main/java/infra/remoting/frame/SetupFrameCodec.java +++ b/today-remoting/src/main/java/infra/remoting/frame/SetupFrameCodec.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.frame; diff --git a/today-remoting/src/main/java/infra/remoting/frame/VersionCodec.java b/today-remoting/src/main/java/infra/remoting/frame/VersionCodec.java index 039b177..fae411b 100644 --- a/today-remoting/src/main/java/infra/remoting/frame/VersionCodec.java +++ b/today-remoting/src/main/java/infra/remoting/frame/VersionCodec.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.frame; diff --git a/today-remoting/src/main/java/infra/remoting/frame/decoder/DefaultPayloadDecoder.java b/today-remoting/src/main/java/infra/remoting/frame/decoder/DefaultPayloadDecoder.java index a853af6..9781717 100644 --- a/today-remoting/src/main/java/infra/remoting/frame/decoder/DefaultPayloadDecoder.java +++ b/today-remoting/src/main/java/infra/remoting/frame/decoder/DefaultPayloadDecoder.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.frame.decoder; diff --git a/today-remoting/src/main/java/infra/remoting/frame/decoder/PayloadDecoder.java b/today-remoting/src/main/java/infra/remoting/frame/decoder/PayloadDecoder.java index d2e4717..8b3eb24 100644 --- a/today-remoting/src/main/java/infra/remoting/frame/decoder/PayloadDecoder.java +++ b/today-remoting/src/main/java/infra/remoting/frame/decoder/PayloadDecoder.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.frame.decoder; diff --git a/today-remoting/src/main/java/infra/remoting/frame/decoder/ZeroCopyPayloadDecoder.java b/today-remoting/src/main/java/infra/remoting/frame/decoder/ZeroCopyPayloadDecoder.java index 7733b8d..86fd1d4 100644 --- a/today-remoting/src/main/java/infra/remoting/frame/decoder/ZeroCopyPayloadDecoder.java +++ b/today-remoting/src/main/java/infra/remoting/frame/decoder/ZeroCopyPayloadDecoder.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.frame.decoder; diff --git a/today-remoting/src/main/java/infra/remoting/frame/decoder/package-info.java b/today-remoting/src/main/java/infra/remoting/frame/decoder/package-info.java index 8f767df..14bd32a 100644 --- a/today-remoting/src/main/java/infra/remoting/frame/decoder/package-info.java +++ b/today-remoting/src/main/java/infra/remoting/frame/decoder/package-info.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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. */ /** diff --git a/today-remoting/src/main/java/infra/remoting/frame/package-info.java b/today-remoting/src/main/java/infra/remoting/frame/package-info.java index 1aee553..51715a5 100644 --- a/today-remoting/src/main/java/infra/remoting/frame/package-info.java +++ b/today-remoting/src/main/java/infra/remoting/frame/package-info.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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. */ /** diff --git a/today-remoting/src/main/java/infra/remoting/internal/BaseConnection.java b/today-remoting/src/main/java/infra/remoting/internal/BaseConnection.java index d41871b..181013e 100644 --- a/today-remoting/src/main/java/infra/remoting/internal/BaseConnection.java +++ b/today-remoting/src/main/java/infra/remoting/internal/BaseConnection.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.internal; diff --git a/today-remoting/src/main/java/infra/remoting/internal/UnboundedProcessor.java b/today-remoting/src/main/java/infra/remoting/internal/UnboundedProcessor.java index 24fc0d4..3c7d820 100644 --- a/today-remoting/src/main/java/infra/remoting/internal/UnboundedProcessor.java +++ b/today-remoting/src/main/java/infra/remoting/internal/UnboundedProcessor.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.internal; diff --git a/today-remoting/src/main/java/infra/remoting/internal/jctools/queues/BaseLinkedQueue.java b/today-remoting/src/main/java/infra/remoting/internal/jctools/queues/BaseLinkedQueue.java index ef88f3b..00287c3 100644 --- a/today-remoting/src/main/java/infra/remoting/internal/jctools/queues/BaseLinkedQueue.java +++ b/today-remoting/src/main/java/infra/remoting/internal/jctools/queues/BaseLinkedQueue.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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. */ /* diff --git a/today-remoting/src/main/java/infra/remoting/internal/jctools/queues/BaseMpscLinkedArrayQueue.java b/today-remoting/src/main/java/infra/remoting/internal/jctools/queues/BaseMpscLinkedArrayQueue.java index 1b5987c..593ae36 100644 --- a/today-remoting/src/main/java/infra/remoting/internal/jctools/queues/BaseMpscLinkedArrayQueue.java +++ b/today-remoting/src/main/java/infra/remoting/internal/jctools/queues/BaseMpscLinkedArrayQueue.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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. */ /* diff --git a/today-remoting/src/main/java/infra/remoting/internal/jctools/queues/IndexedQueueSizeUtil.java b/today-remoting/src/main/java/infra/remoting/internal/jctools/queues/IndexedQueueSizeUtil.java index 014567b..f078f60 100644 --- a/today-remoting/src/main/java/infra/remoting/internal/jctools/queues/IndexedQueueSizeUtil.java +++ b/today-remoting/src/main/java/infra/remoting/internal/jctools/queues/IndexedQueueSizeUtil.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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. */ /* diff --git a/today-remoting/src/main/java/infra/remoting/internal/jctools/queues/LinkedArrayQueueUtil.java b/today-remoting/src/main/java/infra/remoting/internal/jctools/queues/LinkedArrayQueueUtil.java index 57c32c4..065f83d 100644 --- a/today-remoting/src/main/java/infra/remoting/internal/jctools/queues/LinkedArrayQueueUtil.java +++ b/today-remoting/src/main/java/infra/remoting/internal/jctools/queues/LinkedArrayQueueUtil.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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. */ /* diff --git a/today-remoting/src/main/java/infra/remoting/internal/jctools/queues/LinkedQueueNode.java b/today-remoting/src/main/java/infra/remoting/internal/jctools/queues/LinkedQueueNode.java index b56a3ec..1e58bb8 100644 --- a/today-remoting/src/main/java/infra/remoting/internal/jctools/queues/LinkedQueueNode.java +++ b/today-remoting/src/main/java/infra/remoting/internal/jctools/queues/LinkedQueueNode.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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. */ /* diff --git a/today-remoting/src/main/java/infra/remoting/internal/jctools/queues/MessagePassingQueue.java b/today-remoting/src/main/java/infra/remoting/internal/jctools/queues/MessagePassingQueue.java index d6954bf..3f0690a 100644 --- a/today-remoting/src/main/java/infra/remoting/internal/jctools/queues/MessagePassingQueue.java +++ b/today-remoting/src/main/java/infra/remoting/internal/jctools/queues/MessagePassingQueue.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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. */ /* diff --git a/today-remoting/src/main/java/infra/remoting/internal/jctools/queues/MessagePassingQueueUtil.java b/today-remoting/src/main/java/infra/remoting/internal/jctools/queues/MessagePassingQueueUtil.java index c36a5fa..b97b548 100644 --- a/today-remoting/src/main/java/infra/remoting/internal/jctools/queues/MessagePassingQueueUtil.java +++ b/today-remoting/src/main/java/infra/remoting/internal/jctools/queues/MessagePassingQueueUtil.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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. */ /* diff --git a/today-remoting/src/main/java/infra/remoting/internal/jctools/queues/MpscUnboundedArrayQueue.java b/today-remoting/src/main/java/infra/remoting/internal/jctools/queues/MpscUnboundedArrayQueue.java index c2a3413..8e1f4ae 100644 --- a/today-remoting/src/main/java/infra/remoting/internal/jctools/queues/MpscUnboundedArrayQueue.java +++ b/today-remoting/src/main/java/infra/remoting/internal/jctools/queues/MpscUnboundedArrayQueue.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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. */ /* diff --git a/today-remoting/src/main/java/infra/remoting/internal/jctools/queues/PortableJvmInfo.java b/today-remoting/src/main/java/infra/remoting/internal/jctools/queues/PortableJvmInfo.java index 1c17ee7..ea425b8 100644 --- a/today-remoting/src/main/java/infra/remoting/internal/jctools/queues/PortableJvmInfo.java +++ b/today-remoting/src/main/java/infra/remoting/internal/jctools/queues/PortableJvmInfo.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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. */ /* diff --git a/today-remoting/src/main/java/infra/remoting/internal/jctools/queues/Pow2.java b/today-remoting/src/main/java/infra/remoting/internal/jctools/queues/Pow2.java index 17bc5a6..cb27084 100644 --- a/today-remoting/src/main/java/infra/remoting/internal/jctools/queues/Pow2.java +++ b/today-remoting/src/main/java/infra/remoting/internal/jctools/queues/Pow2.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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. */ /* diff --git a/today-remoting/src/main/java/infra/remoting/internal/jctools/queues/QueueProgressIndicators.java b/today-remoting/src/main/java/infra/remoting/internal/jctools/queues/QueueProgressIndicators.java index e5683eb..f0a9ac0 100644 --- a/today-remoting/src/main/java/infra/remoting/internal/jctools/queues/QueueProgressIndicators.java +++ b/today-remoting/src/main/java/infra/remoting/internal/jctools/queues/QueueProgressIndicators.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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. */ /* diff --git a/today-remoting/src/main/java/infra/remoting/internal/jctools/queues/RangeUtil.java b/today-remoting/src/main/java/infra/remoting/internal/jctools/queues/RangeUtil.java index 371970b..2161cfa 100644 --- a/today-remoting/src/main/java/infra/remoting/internal/jctools/queues/RangeUtil.java +++ b/today-remoting/src/main/java/infra/remoting/internal/jctools/queues/RangeUtil.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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. */ /* diff --git a/today-remoting/src/main/java/infra/remoting/internal/jctools/queues/UnsafeAccess.java b/today-remoting/src/main/java/infra/remoting/internal/jctools/queues/UnsafeAccess.java index a425706..b377728 100644 --- a/today-remoting/src/main/java/infra/remoting/internal/jctools/queues/UnsafeAccess.java +++ b/today-remoting/src/main/java/infra/remoting/internal/jctools/queues/UnsafeAccess.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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. */ /* diff --git a/today-remoting/src/main/java/infra/remoting/internal/jctools/queues/UnsafeRefArrayAccess.java b/today-remoting/src/main/java/infra/remoting/internal/jctools/queues/UnsafeRefArrayAccess.java index 2bfca17..d790a44 100644 --- a/today-remoting/src/main/java/infra/remoting/internal/jctools/queues/UnsafeRefArrayAccess.java +++ b/today-remoting/src/main/java/infra/remoting/internal/jctools/queues/UnsafeRefArrayAccess.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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. */ /* diff --git a/today-remoting/src/main/java/infra/remoting/internal/package-info.java b/today-remoting/src/main/java/infra/remoting/internal/package-info.java index f9c6ebb..3eee235 100644 --- a/today-remoting/src/main/java/infra/remoting/internal/package-info.java +++ b/today-remoting/src/main/java/infra/remoting/internal/package-info.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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. */ /** diff --git a/today-remoting/src/main/java/infra/remoting/keepalive/KeepAliveFramesAcceptor.java b/today-remoting/src/main/java/infra/remoting/keepalive/KeepAliveFramesAcceptor.java index bf6cad9..08481a3 100644 --- a/today-remoting/src/main/java/infra/remoting/keepalive/KeepAliveFramesAcceptor.java +++ b/today-remoting/src/main/java/infra/remoting/keepalive/KeepAliveFramesAcceptor.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.keepalive; diff --git a/today-remoting/src/main/java/infra/remoting/keepalive/KeepAliveHandler.java b/today-remoting/src/main/java/infra/remoting/keepalive/KeepAliveHandler.java index 9cd0658..04744ba 100644 --- a/today-remoting/src/main/java/infra/remoting/keepalive/KeepAliveHandler.java +++ b/today-remoting/src/main/java/infra/remoting/keepalive/KeepAliveHandler.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.keepalive; diff --git a/today-remoting/src/main/java/infra/remoting/keepalive/KeepAliveSupport.java b/today-remoting/src/main/java/infra/remoting/keepalive/KeepAliveSupport.java index 7642c44..db1e899 100644 --- a/today-remoting/src/main/java/infra/remoting/keepalive/KeepAliveSupport.java +++ b/today-remoting/src/main/java/infra/remoting/keepalive/KeepAliveSupport.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.keepalive; diff --git a/today-remoting/src/main/java/infra/remoting/keepalive/package-info.java b/today-remoting/src/main/java/infra/remoting/keepalive/package-info.java index a5424f9..6f94811 100644 --- a/today-remoting/src/main/java/infra/remoting/keepalive/package-info.java +++ b/today-remoting/src/main/java/infra/remoting/keepalive/package-info.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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. */ /** diff --git a/today-remoting/src/main/java/infra/remoting/lb/BaseWeightedStats.java b/today-remoting/src/main/java/infra/remoting/lb/BaseWeightedStats.java index 95dae53..335242d 100644 --- a/today-remoting/src/main/java/infra/remoting/lb/BaseWeightedStats.java +++ b/today-remoting/src/main/java/infra/remoting/lb/BaseWeightedStats.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.lb; diff --git a/today-remoting/src/main/java/infra/remoting/lb/ChannelPool.java b/today-remoting/src/main/java/infra/remoting/lb/ChannelPool.java index df3773b..1b786ce 100644 --- a/today-remoting/src/main/java/infra/remoting/lb/ChannelPool.java +++ b/today-remoting/src/main/java/infra/remoting/lb/ChannelPool.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.lb; diff --git a/today-remoting/src/main/java/infra/remoting/lb/ClientLoadBalanceStrategy.java b/today-remoting/src/main/java/infra/remoting/lb/ClientLoadBalanceStrategy.java index 41d8cd5..bc4b8c4 100644 --- a/today-remoting/src/main/java/infra/remoting/lb/ClientLoadBalanceStrategy.java +++ b/today-remoting/src/main/java/infra/remoting/lb/ClientLoadBalanceStrategy.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.lb; diff --git a/today-remoting/src/main/java/infra/remoting/lb/Ewma.java b/today-remoting/src/main/java/infra/remoting/lb/Ewma.java index ccf5764..a50df86 100644 --- a/today-remoting/src/main/java/infra/remoting/lb/Ewma.java +++ b/today-remoting/src/main/java/infra/remoting/lb/Ewma.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.lb; diff --git a/today-remoting/src/main/java/infra/remoting/lb/FluxDeferredResolution.java b/today-remoting/src/main/java/infra/remoting/lb/FluxDeferredResolution.java index 326b586..430ae65 100644 --- a/today-remoting/src/main/java/infra/remoting/lb/FluxDeferredResolution.java +++ b/today-remoting/src/main/java/infra/remoting/lb/FluxDeferredResolution.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.lb; diff --git a/today-remoting/src/main/java/infra/remoting/lb/FrugalQuantile.java b/today-remoting/src/main/java/infra/remoting/lb/FrugalQuantile.java index 3f5b4a7..57c9ce2 100644 --- a/today-remoting/src/main/java/infra/remoting/lb/FrugalQuantile.java +++ b/today-remoting/src/main/java/infra/remoting/lb/FrugalQuantile.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.lb; diff --git a/today-remoting/src/main/java/infra/remoting/lb/Int2LongHashMap.java b/today-remoting/src/main/java/infra/remoting/lb/Int2LongHashMap.java index 93cf409..16dbb23 100644 --- a/today-remoting/src/main/java/infra/remoting/lb/Int2LongHashMap.java +++ b/today-remoting/src/main/java/infra/remoting/lb/Int2LongHashMap.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.lb; diff --git a/today-remoting/src/main/java/infra/remoting/lb/LoadBalanceRemotingClient.java b/today-remoting/src/main/java/infra/remoting/lb/LoadBalanceRemotingClient.java index e3bf720..d8b9022 100644 --- a/today-remoting/src/main/java/infra/remoting/lb/LoadBalanceRemotingClient.java +++ b/today-remoting/src/main/java/infra/remoting/lb/LoadBalanceRemotingClient.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.lb; diff --git a/today-remoting/src/main/java/infra/remoting/lb/LoadBalanceStrategy.java b/today-remoting/src/main/java/infra/remoting/lb/LoadBalanceStrategy.java index 010ece7..16606f6 100644 --- a/today-remoting/src/main/java/infra/remoting/lb/LoadBalanceStrategy.java +++ b/today-remoting/src/main/java/infra/remoting/lb/LoadBalanceStrategy.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.lb; diff --git a/today-remoting/src/main/java/infra/remoting/lb/LoadBalanceTarget.java b/today-remoting/src/main/java/infra/remoting/lb/LoadBalanceTarget.java index 3e6fc5f..18630fb 100644 --- a/today-remoting/src/main/java/infra/remoting/lb/LoadBalanceTarget.java +++ b/today-remoting/src/main/java/infra/remoting/lb/LoadBalanceTarget.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.lb; diff --git a/today-remoting/src/main/java/infra/remoting/lb/Median.java b/today-remoting/src/main/java/infra/remoting/lb/Median.java index 2fa9db8..7920b22 100644 --- a/today-remoting/src/main/java/infra/remoting/lb/Median.java +++ b/today-remoting/src/main/java/infra/remoting/lb/Median.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.lb; diff --git a/today-remoting/src/main/java/infra/remoting/lb/MonoDeferredResolution.java b/today-remoting/src/main/java/infra/remoting/lb/MonoDeferredResolution.java index 2bfed3b..99d13b9 100644 --- a/today-remoting/src/main/java/infra/remoting/lb/MonoDeferredResolution.java +++ b/today-remoting/src/main/java/infra/remoting/lb/MonoDeferredResolution.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.lb; diff --git a/today-remoting/src/main/java/infra/remoting/lb/PooledChannel.java b/today-remoting/src/main/java/infra/remoting/lb/PooledChannel.java index 867f287..c6665f6 100644 --- a/today-remoting/src/main/java/infra/remoting/lb/PooledChannel.java +++ b/today-remoting/src/main/java/infra/remoting/lb/PooledChannel.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.lb; diff --git a/today-remoting/src/main/java/infra/remoting/lb/Quantile.java b/today-remoting/src/main/java/infra/remoting/lb/Quantile.java index 85144a0..6097cbc 100644 --- a/today-remoting/src/main/java/infra/remoting/lb/Quantile.java +++ b/today-remoting/src/main/java/infra/remoting/lb/Quantile.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.lb; diff --git a/today-remoting/src/main/java/infra/remoting/lb/ResolvingOperator.java b/today-remoting/src/main/java/infra/remoting/lb/ResolvingOperator.java index 2848112..b12e6f1 100644 --- a/today-remoting/src/main/java/infra/remoting/lb/ResolvingOperator.java +++ b/today-remoting/src/main/java/infra/remoting/lb/ResolvingOperator.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.lb; diff --git a/today-remoting/src/main/java/infra/remoting/lb/RoundRobinLoadBalanceStrategy.java b/today-remoting/src/main/java/infra/remoting/lb/RoundRobinLoadBalanceStrategy.java index 3a24553..9a67552 100644 --- a/today-remoting/src/main/java/infra/remoting/lb/RoundRobinLoadBalanceStrategy.java +++ b/today-remoting/src/main/java/infra/remoting/lb/RoundRobinLoadBalanceStrategy.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.lb; diff --git a/today-remoting/src/main/java/infra/remoting/lb/WeightedLoadBalanceStrategy.java b/today-remoting/src/main/java/infra/remoting/lb/WeightedLoadBalanceStrategy.java index da2aee3..ff6d465 100644 --- a/today-remoting/src/main/java/infra/remoting/lb/WeightedLoadBalanceStrategy.java +++ b/today-remoting/src/main/java/infra/remoting/lb/WeightedLoadBalanceStrategy.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.lb; diff --git a/today-remoting/src/main/java/infra/remoting/lb/WeightedStats.java b/today-remoting/src/main/java/infra/remoting/lb/WeightedStats.java index b6730a7..818a297 100644 --- a/today-remoting/src/main/java/infra/remoting/lb/WeightedStats.java +++ b/today-remoting/src/main/java/infra/remoting/lb/WeightedStats.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.lb; diff --git a/today-remoting/src/main/java/infra/remoting/lb/WeightedStatsChannel.java b/today-remoting/src/main/java/infra/remoting/lb/WeightedStatsChannel.java index d8aa384..ad57e83 100644 --- a/today-remoting/src/main/java/infra/remoting/lb/WeightedStatsChannel.java +++ b/today-remoting/src/main/java/infra/remoting/lb/WeightedStatsChannel.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.lb; diff --git a/today-remoting/src/main/java/infra/remoting/lb/WeightedStatsRequestInterceptor.java b/today-remoting/src/main/java/infra/remoting/lb/WeightedStatsRequestInterceptor.java index fbbc0d3..891a219 100644 --- a/today-remoting/src/main/java/infra/remoting/lb/WeightedStatsRequestInterceptor.java +++ b/today-remoting/src/main/java/infra/remoting/lb/WeightedStatsRequestInterceptor.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.lb; diff --git a/today-remoting/src/main/java/infra/remoting/lb/package-info.java b/today-remoting/src/main/java/infra/remoting/lb/package-info.java index 6efed23..b4dbb9a 100644 --- a/today-remoting/src/main/java/infra/remoting/lb/package-info.java +++ b/today-remoting/src/main/java/infra/remoting/lb/package-info.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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. */ /** diff --git a/today-remoting/src/main/java/infra/remoting/lease/Lease.java b/today-remoting/src/main/java/infra/remoting/lease/Lease.java index 4da350e..7dc0fb3 100644 --- a/today-remoting/src/main/java/infra/remoting/lease/Lease.java +++ b/today-remoting/src/main/java/infra/remoting/lease/Lease.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.lease; diff --git a/today-remoting/src/main/java/infra/remoting/lease/LeaseSender.java b/today-remoting/src/main/java/infra/remoting/lease/LeaseSender.java index 7699534..4555168 100644 --- a/today-remoting/src/main/java/infra/remoting/lease/LeaseSender.java +++ b/today-remoting/src/main/java/infra/remoting/lease/LeaseSender.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.lease; diff --git a/today-remoting/src/main/java/infra/remoting/lease/MissingLeaseException.java b/today-remoting/src/main/java/infra/remoting/lease/MissingLeaseException.java index 3709aa7..2cb9e4a 100644 --- a/today-remoting/src/main/java/infra/remoting/lease/MissingLeaseException.java +++ b/today-remoting/src/main/java/infra/remoting/lease/MissingLeaseException.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.lease; diff --git a/today-remoting/src/main/java/infra/remoting/lease/TrackingLeaseSender.java b/today-remoting/src/main/java/infra/remoting/lease/TrackingLeaseSender.java index 5218270..e112e94 100644 --- a/today-remoting/src/main/java/infra/remoting/lease/TrackingLeaseSender.java +++ b/today-remoting/src/main/java/infra/remoting/lease/TrackingLeaseSender.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.lease; diff --git a/today-remoting/src/main/java/infra/remoting/lease/package-info.java b/today-remoting/src/main/java/infra/remoting/lease/package-info.java index 9126f5e..9205044 100644 --- a/today-remoting/src/main/java/infra/remoting/lease/package-info.java +++ b/today-remoting/src/main/java/infra/remoting/lease/package-info.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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. */ /** diff --git a/today-remoting/src/main/java/infra/remoting/package-info.java b/today-remoting/src/main/java/infra/remoting/package-info.java index 4315062..8935386 100644 --- a/today-remoting/src/main/java/infra/remoting/package-info.java +++ b/today-remoting/src/main/java/infra/remoting/package-info.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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. */ @NullMarked diff --git a/today-remoting/src/main/java/infra/remoting/plugins/ChannelAcceptorDecorator.java b/today-remoting/src/main/java/infra/remoting/plugins/ChannelAcceptorDecorator.java index 23e82b7..8ad47fe 100644 --- a/today-remoting/src/main/java/infra/remoting/plugins/ChannelAcceptorDecorator.java +++ b/today-remoting/src/main/java/infra/remoting/plugins/ChannelAcceptorDecorator.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.plugins; diff --git a/today-remoting/src/main/java/infra/remoting/plugins/ChannelDecorator.java b/today-remoting/src/main/java/infra/remoting/plugins/ChannelDecorator.java index f2249ec..d4b3458 100644 --- a/today-remoting/src/main/java/infra/remoting/plugins/ChannelDecorator.java +++ b/today-remoting/src/main/java/infra/remoting/plugins/ChannelDecorator.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.plugins; diff --git a/today-remoting/src/main/java/infra/remoting/plugins/CompositeRequestInterceptor.java b/today-remoting/src/main/java/infra/remoting/plugins/CompositeRequestInterceptor.java index 719fb64..fbb3cb5 100644 --- a/today-remoting/src/main/java/infra/remoting/plugins/CompositeRequestInterceptor.java +++ b/today-remoting/src/main/java/infra/remoting/plugins/CompositeRequestInterceptor.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.plugins; diff --git a/today-remoting/src/main/java/infra/remoting/plugins/ConnectionDecorator.java b/today-remoting/src/main/java/infra/remoting/plugins/ConnectionDecorator.java index 83fb404..80244cc 100644 --- a/today-remoting/src/main/java/infra/remoting/plugins/ConnectionDecorator.java +++ b/today-remoting/src/main/java/infra/remoting/plugins/ConnectionDecorator.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.plugins; diff --git a/today-remoting/src/main/java/infra/remoting/plugins/InitializingInterceptorRegistry.java b/today-remoting/src/main/java/infra/remoting/plugins/InitializingInterceptorRegistry.java index 12e7921..c82670d 100644 --- a/today-remoting/src/main/java/infra/remoting/plugins/InitializingInterceptorRegistry.java +++ b/today-remoting/src/main/java/infra/remoting/plugins/InitializingInterceptorRegistry.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.plugins; diff --git a/today-remoting/src/main/java/infra/remoting/plugins/InterceptorRegistry.java b/today-remoting/src/main/java/infra/remoting/plugins/InterceptorRegistry.java index 4bf9615..e877765 100644 --- a/today-remoting/src/main/java/infra/remoting/plugins/InterceptorRegistry.java +++ b/today-remoting/src/main/java/infra/remoting/plugins/InterceptorRegistry.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.plugins; diff --git a/today-remoting/src/main/java/infra/remoting/plugins/RateLimitDecorator.java b/today-remoting/src/main/java/infra/remoting/plugins/RateLimitDecorator.java index ee57119..0a51c21 100644 --- a/today-remoting/src/main/java/infra/remoting/plugins/RateLimitDecorator.java +++ b/today-remoting/src/main/java/infra/remoting/plugins/RateLimitDecorator.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.plugins; diff --git a/today-remoting/src/main/java/infra/remoting/plugins/RequestInterceptor.java b/today-remoting/src/main/java/infra/remoting/plugins/RequestInterceptor.java index a6778e7..bfa09e1 100644 --- a/today-remoting/src/main/java/infra/remoting/plugins/RequestInterceptor.java +++ b/today-remoting/src/main/java/infra/remoting/plugins/RequestInterceptor.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.plugins; diff --git a/today-remoting/src/main/java/infra/remoting/plugins/package-info.java b/today-remoting/src/main/java/infra/remoting/plugins/package-info.java index 836c1d4..a86e4e3 100644 --- a/today-remoting/src/main/java/infra/remoting/plugins/package-info.java +++ b/today-remoting/src/main/java/infra/remoting/plugins/package-info.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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. */ /** Contracts for interception of transports, connections, and requests. */ diff --git a/today-remoting/src/main/java/infra/remoting/protocol/ProtocolFrame.java b/today-remoting/src/main/java/infra/remoting/protocol/ProtocolFrame.java index f7861b6..2bc3244 100644 --- a/today-remoting/src/main/java/infra/remoting/protocol/ProtocolFrame.java +++ b/today-remoting/src/main/java/infra/remoting/protocol/ProtocolFrame.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.protocol; diff --git a/today-remoting/src/main/java/infra/remoting/protocol/ProtocolParsingException.java b/today-remoting/src/main/java/infra/remoting/protocol/ProtocolParsingException.java index d1e7c77..c3a2fef 100644 --- a/today-remoting/src/main/java/infra/remoting/protocol/ProtocolParsingException.java +++ b/today-remoting/src/main/java/infra/remoting/protocol/ProtocolParsingException.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.protocol; diff --git a/today-remoting/src/main/java/infra/remoting/resume/ChannelSession.java b/today-remoting/src/main/java/infra/remoting/resume/ChannelSession.java index e4628e1..76bb5a5 100644 --- a/today-remoting/src/main/java/infra/remoting/resume/ChannelSession.java +++ b/today-remoting/src/main/java/infra/remoting/resume/ChannelSession.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.resume; diff --git a/today-remoting/src/main/java/infra/remoting/resume/ClientChannelSession.java b/today-remoting/src/main/java/infra/remoting/resume/ClientChannelSession.java index abcbfae..1bc1008 100644 --- a/today-remoting/src/main/java/infra/remoting/resume/ClientChannelSession.java +++ b/today-remoting/src/main/java/infra/remoting/resume/ClientChannelSession.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.resume; diff --git a/today-remoting/src/main/java/infra/remoting/resume/InMemoryResumableFramesStore.java b/today-remoting/src/main/java/infra/remoting/resume/InMemoryResumableFramesStore.java index c28c771..812e382 100644 --- a/today-remoting/src/main/java/infra/remoting/resume/InMemoryResumableFramesStore.java +++ b/today-remoting/src/main/java/infra/remoting/resume/InMemoryResumableFramesStore.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.resume; diff --git a/today-remoting/src/main/java/infra/remoting/resume/InMemoryResumableFramesStoreFactory.java b/today-remoting/src/main/java/infra/remoting/resume/InMemoryResumableFramesStoreFactory.java index e10c060..5e53e0c 100644 --- a/today-remoting/src/main/java/infra/remoting/resume/InMemoryResumableFramesStoreFactory.java +++ b/today-remoting/src/main/java/infra/remoting/resume/InMemoryResumableFramesStoreFactory.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.resume; diff --git a/today-remoting/src/main/java/infra/remoting/resume/RandomUUIDResumeTokenGenerator.java b/today-remoting/src/main/java/infra/remoting/resume/RandomUUIDResumeTokenGenerator.java index 9716904..1e6a8ee 100644 --- a/today-remoting/src/main/java/infra/remoting/resume/RandomUUIDResumeTokenGenerator.java +++ b/today-remoting/src/main/java/infra/remoting/resume/RandomUUIDResumeTokenGenerator.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.resume; diff --git a/today-remoting/src/main/java/infra/remoting/resume/ResumableConnection.java b/today-remoting/src/main/java/infra/remoting/resume/ResumableConnection.java index 7b44db5..ef3370c 100644 --- a/today-remoting/src/main/java/infra/remoting/resume/ResumableConnection.java +++ b/today-remoting/src/main/java/infra/remoting/resume/ResumableConnection.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.resume; diff --git a/today-remoting/src/main/java/infra/remoting/resume/ResumableFramesStore.java b/today-remoting/src/main/java/infra/remoting/resume/ResumableFramesStore.java index 82be602..fab3b9e 100644 --- a/today-remoting/src/main/java/infra/remoting/resume/ResumableFramesStore.java +++ b/today-remoting/src/main/java/infra/remoting/resume/ResumableFramesStore.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.resume; diff --git a/today-remoting/src/main/java/infra/remoting/resume/ResumableFramesStoreFactory.java b/today-remoting/src/main/java/infra/remoting/resume/ResumableFramesStoreFactory.java index 7c61442..8c4394b 100644 --- a/today-remoting/src/main/java/infra/remoting/resume/ResumableFramesStoreFactory.java +++ b/today-remoting/src/main/java/infra/remoting/resume/ResumableFramesStoreFactory.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.resume; diff --git a/today-remoting/src/main/java/infra/remoting/resume/ResumeStateException.java b/today-remoting/src/main/java/infra/remoting/resume/ResumeStateException.java index 311d87b..a1e938c 100644 --- a/today-remoting/src/main/java/infra/remoting/resume/ResumeStateException.java +++ b/today-remoting/src/main/java/infra/remoting/resume/ResumeStateException.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.resume; diff --git a/today-remoting/src/main/java/infra/remoting/resume/ResumeStateHolder.java b/today-remoting/src/main/java/infra/remoting/resume/ResumeStateHolder.java index d40d2b3..c217aeb 100644 --- a/today-remoting/src/main/java/infra/remoting/resume/ResumeStateHolder.java +++ b/today-remoting/src/main/java/infra/remoting/resume/ResumeStateHolder.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.resume; diff --git a/today-remoting/src/main/java/infra/remoting/resume/ResumeTokenGenerator.java b/today-remoting/src/main/java/infra/remoting/resume/ResumeTokenGenerator.java index 787139a..99aee1c 100644 --- a/today-remoting/src/main/java/infra/remoting/resume/ResumeTokenGenerator.java +++ b/today-remoting/src/main/java/infra/remoting/resume/ResumeTokenGenerator.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.resume; diff --git a/today-remoting/src/main/java/infra/remoting/resume/ServerChannelSession.java b/today-remoting/src/main/java/infra/remoting/resume/ServerChannelSession.java index d15917f..b01abf1 100644 --- a/today-remoting/src/main/java/infra/remoting/resume/ServerChannelSession.java +++ b/today-remoting/src/main/java/infra/remoting/resume/ServerChannelSession.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.resume; diff --git a/today-remoting/src/main/java/infra/remoting/resume/SessionManager.java b/today-remoting/src/main/java/infra/remoting/resume/SessionManager.java index d72c80c..b95402a 100644 --- a/today-remoting/src/main/java/infra/remoting/resume/SessionManager.java +++ b/today-remoting/src/main/java/infra/remoting/resume/SessionManager.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.resume; diff --git a/today-remoting/src/main/java/infra/remoting/resume/package-info.java b/today-remoting/src/main/java/infra/remoting/resume/package-info.java index 2435b1d..bd3d0f7 100644 --- a/today-remoting/src/main/java/infra/remoting/resume/package-info.java +++ b/today-remoting/src/main/java/infra/remoting/resume/package-info.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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. */ /** diff --git a/today-remoting/src/main/java/infra/remoting/transport/ClientTransport.java b/today-remoting/src/main/java/infra/remoting/transport/ClientTransport.java index 2514397..fcfcea2 100644 --- a/today-remoting/src/main/java/infra/remoting/transport/ClientTransport.java +++ b/today-remoting/src/main/java/infra/remoting/transport/ClientTransport.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.transport; diff --git a/today-remoting/src/main/java/infra/remoting/transport/ConnectionAcceptor.java b/today-remoting/src/main/java/infra/remoting/transport/ConnectionAcceptor.java index 52af3ef..de1710a 100644 --- a/today-remoting/src/main/java/infra/remoting/transport/ConnectionAcceptor.java +++ b/today-remoting/src/main/java/infra/remoting/transport/ConnectionAcceptor.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.transport; diff --git a/today-remoting/src/main/java/infra/remoting/transport/ServerTransport.java b/today-remoting/src/main/java/infra/remoting/transport/ServerTransport.java index a3cef49..7f32948 100644 --- a/today-remoting/src/main/java/infra/remoting/transport/ServerTransport.java +++ b/today-remoting/src/main/java/infra/remoting/transport/ServerTransport.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.transport; diff --git a/today-remoting/src/main/java/infra/remoting/transport/Transport.java b/today-remoting/src/main/java/infra/remoting/transport/Transport.java index f79bf60..5ceb258 100644 --- a/today-remoting/src/main/java/infra/remoting/transport/Transport.java +++ b/today-remoting/src/main/java/infra/remoting/transport/Transport.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.transport; diff --git a/today-remoting/src/main/java/infra/remoting/transport/package-info.java b/today-remoting/src/main/java/infra/remoting/transport/package-info.java index d7878b8..2268e63 100644 --- a/today-remoting/src/main/java/infra/remoting/transport/package-info.java +++ b/today-remoting/src/main/java/infra/remoting/transport/package-info.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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. */ /** Client and server transport contracts for pluggable transports. */ diff --git a/today-remoting/src/main/java/infra/remoting/util/ByteBufPayload.java b/today-remoting/src/main/java/infra/remoting/util/ByteBufPayload.java index 8f2422b..dad4284 100644 --- a/today-remoting/src/main/java/infra/remoting/util/ByteBufPayload.java +++ b/today-remoting/src/main/java/infra/remoting/util/ByteBufPayload.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.util; diff --git a/today-remoting/src/main/java/infra/remoting/util/Clock.java b/today-remoting/src/main/java/infra/remoting/util/Clock.java index dd9c1c7..2b65ed8 100644 --- a/today-remoting/src/main/java/infra/remoting/util/Clock.java +++ b/today-remoting/src/main/java/infra/remoting/util/Clock.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.util; diff --git a/today-remoting/src/main/java/infra/remoting/util/DefaultPayload.java b/today-remoting/src/main/java/infra/remoting/util/DefaultPayload.java index 53011a5..ecc8f82 100644 --- a/today-remoting/src/main/java/infra/remoting/util/DefaultPayload.java +++ b/today-remoting/src/main/java/infra/remoting/util/DefaultPayload.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.util; diff --git a/today-remoting/src/main/java/infra/remoting/util/EmptyPayload.java b/today-remoting/src/main/java/infra/remoting/util/EmptyPayload.java index 8d8fe1e..b1aad4e 100644 --- a/today-remoting/src/main/java/infra/remoting/util/EmptyPayload.java +++ b/today-remoting/src/main/java/infra/remoting/util/EmptyPayload.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.util; diff --git a/today-remoting/src/main/java/infra/remoting/util/PromiseAdapter.java b/today-remoting/src/main/java/infra/remoting/util/PromiseAdapter.java index b9d83c2..a4a0bdb 100644 --- a/today-remoting/src/main/java/infra/remoting/util/PromiseAdapter.java +++ b/today-remoting/src/main/java/infra/remoting/util/PromiseAdapter.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.util; diff --git a/today-remoting/src/main/java/infra/remoting/util/package-info.java b/today-remoting/src/main/java/infra/remoting/util/package-info.java index 70e446b..6757960 100644 --- a/today-remoting/src/main/java/infra/remoting/util/package-info.java +++ b/today-remoting/src/main/java/infra/remoting/util/package-info.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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. */ /** Shared utility classes and {@link infra.remoting.Payload} implementations. */ diff --git a/today-remoting/src/test/java/infra/remoting/FrameAssert.java b/today-remoting/src/test/java/infra/remoting/FrameAssert.java index f270a52..19137d5 100644 --- a/today-remoting/src/test/java/infra/remoting/FrameAssert.java +++ b/today-remoting/src/test/java/infra/remoting/FrameAssert.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting; diff --git a/today-remoting/src/test/java/infra/remoting/PayloadAssert.java b/today-remoting/src/test/java/infra/remoting/PayloadAssert.java index f558abb..be0c3e3 100755 --- a/today-remoting/src/test/java/infra/remoting/PayloadAssert.java +++ b/today-remoting/src/test/java/infra/remoting/PayloadAssert.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting; diff --git a/today-remoting/src/test/java/infra/remoting/RaceTestConstants.java b/today-remoting/src/test/java/infra/remoting/RaceTestConstants.java index e058926..e234e24 100644 --- a/today-remoting/src/test/java/infra/remoting/RaceTestConstants.java +++ b/today-remoting/src/test/java/infra/remoting/RaceTestConstants.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting; diff --git a/today-remoting/src/test/java/infra/remoting/TestScheduler.java b/today-remoting/src/test/java/infra/remoting/TestScheduler.java index 7e8236e..c38c7ab 100644 --- a/today-remoting/src/test/java/infra/remoting/TestScheduler.java +++ b/today-remoting/src/test/java/infra/remoting/TestScheduler.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting; diff --git a/today-remoting/src/test/java/infra/remoting/buffer/LeaksTrackingByteBufAllocator.java b/today-remoting/src/test/java/infra/remoting/buffer/LeaksTrackingByteBufAllocator.java index f12047e..a4fd883 100644 --- a/today-remoting/src/test/java/infra/remoting/buffer/LeaksTrackingByteBufAllocator.java +++ b/today-remoting/src/test/java/infra/remoting/buffer/LeaksTrackingByteBufAllocator.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.buffer; diff --git a/today-remoting/src/test/java/infra/remoting/core/AbstractChannelRule.java b/today-remoting/src/test/java/infra/remoting/core/AbstractChannelRule.java index 58abace..2473508 100644 --- a/today-remoting/src/test/java/infra/remoting/core/AbstractChannelRule.java +++ b/today-remoting/src/test/java/infra/remoting/core/AbstractChannelRule.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.core; diff --git a/today-remoting/src/test/java/infra/remoting/core/ChannelConnectorTests.java b/today-remoting/src/test/java/infra/remoting/core/ChannelConnectorTests.java index 2a1716a..aa85c60 100644 --- a/today-remoting/src/test/java/infra/remoting/core/ChannelConnectorTests.java +++ b/today-remoting/src/test/java/infra/remoting/core/ChannelConnectorTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.core; diff --git a/today-remoting/src/test/java/infra/remoting/core/ChannelLeaseTests.java b/today-remoting/src/test/java/infra/remoting/core/ChannelLeaseTests.java index 7e98a4e..e3f0c0f 100644 --- a/today-remoting/src/test/java/infra/remoting/core/ChannelLeaseTests.java +++ b/today-remoting/src/test/java/infra/remoting/core/ChannelLeaseTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.core; diff --git a/today-remoting/src/test/java/infra/remoting/core/ChannelReconnectTests.java b/today-remoting/src/test/java/infra/remoting/core/ChannelReconnectTests.java index 2a4feed..85cd1ce 100644 --- a/today-remoting/src/test/java/infra/remoting/core/ChannelReconnectTests.java +++ b/today-remoting/src/test/java/infra/remoting/core/ChannelReconnectTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.core; diff --git a/today-remoting/src/test/java/infra/remoting/core/ChannelTests.java b/today-remoting/src/test/java/infra/remoting/core/ChannelTests.java index c190e36..020c2b9 100644 --- a/today-remoting/src/test/java/infra/remoting/core/ChannelTests.java +++ b/today-remoting/src/test/java/infra/remoting/core/ChannelTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.core; diff --git a/today-remoting/src/test/java/infra/remoting/core/ClientServerInputMultiplexerTest.java b/today-remoting/src/test/java/infra/remoting/core/ClientServerInputMultiplexerTest.java index fbf074e..816ea11 100644 --- a/today-remoting/src/test/java/infra/remoting/core/ClientServerInputMultiplexerTest.java +++ b/today-remoting/src/test/java/infra/remoting/core/ClientServerInputMultiplexerTest.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.core; diff --git a/today-remoting/src/test/java/infra/remoting/core/ConnectionSetupPayloadTest.java b/today-remoting/src/test/java/infra/remoting/core/ConnectionSetupPayloadTest.java index bb3eae3..1f3ee27 100644 --- a/today-remoting/src/test/java/infra/remoting/core/ConnectionSetupPayloadTest.java +++ b/today-remoting/src/test/java/infra/remoting/core/ConnectionSetupPayloadTest.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.core; diff --git a/today-remoting/src/test/java/infra/remoting/core/DefaultChannelClientTests.java b/today-remoting/src/test/java/infra/remoting/core/DefaultChannelClientTests.java index 067fd29..1992ab3 100644 --- a/today-remoting/src/test/java/infra/remoting/core/DefaultChannelClientTests.java +++ b/today-remoting/src/test/java/infra/remoting/core/DefaultChannelClientTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.core; diff --git a/today-remoting/src/test/java/infra/remoting/core/FireAndForgetRequesterMonoTests.java b/today-remoting/src/test/java/infra/remoting/core/FireAndForgetRequesterMonoTests.java index 6dbdf02..aa73ad1 100644 --- a/today-remoting/src/test/java/infra/remoting/core/FireAndForgetRequesterMonoTests.java +++ b/today-remoting/src/test/java/infra/remoting/core/FireAndForgetRequesterMonoTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.core; diff --git a/today-remoting/src/test/java/infra/remoting/core/KeepAliveTests.java b/today-remoting/src/test/java/infra/remoting/core/KeepAliveTests.java index 048b1f9..cd63412 100644 --- a/today-remoting/src/test/java/infra/remoting/core/KeepAliveTests.java +++ b/today-remoting/src/test/java/infra/remoting/core/KeepAliveTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.core; diff --git a/today-remoting/src/test/java/infra/remoting/core/PayloadValidationUtilsTests.java b/today-remoting/src/test/java/infra/remoting/core/PayloadValidationUtilsTests.java index 853c3ad..71538b3 100644 --- a/today-remoting/src/test/java/infra/remoting/core/PayloadValidationUtilsTests.java +++ b/today-remoting/src/test/java/infra/remoting/core/PayloadValidationUtilsTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.core; diff --git a/today-remoting/src/test/java/infra/remoting/core/ReconnectMonoTests.java b/today-remoting/src/test/java/infra/remoting/core/ReconnectMonoTests.java index d3387ac..ec7d608 100644 --- a/today-remoting/src/test/java/infra/remoting/core/ReconnectMonoTests.java +++ b/today-remoting/src/test/java/infra/remoting/core/ReconnectMonoTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.core; diff --git a/today-remoting/src/test/java/infra/remoting/core/RemotingServerFragmentationTests.java b/today-remoting/src/test/java/infra/remoting/core/RemotingServerFragmentationTests.java index 5e474b7..5435e4a 100644 --- a/today-remoting/src/test/java/infra/remoting/core/RemotingServerFragmentationTests.java +++ b/today-remoting/src/test/java/infra/remoting/core/RemotingServerFragmentationTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.core; diff --git a/today-remoting/src/test/java/infra/remoting/core/RemotingServerTests.java b/today-remoting/src/test/java/infra/remoting/core/RemotingServerTests.java index 1b4f51a..5b85a6c 100644 --- a/today-remoting/src/test/java/infra/remoting/core/RemotingServerTests.java +++ b/today-remoting/src/test/java/infra/remoting/core/RemotingServerTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.core; diff --git a/today-remoting/src/test/java/infra/remoting/core/RequestRequesterChannelFluxTests.java b/today-remoting/src/test/java/infra/remoting/core/RequestRequesterChannelFluxTests.java index c81c4e2..0d39b87 100644 --- a/today-remoting/src/test/java/infra/remoting/core/RequestRequesterChannelFluxTests.java +++ b/today-remoting/src/test/java/infra/remoting/core/RequestRequesterChannelFluxTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.core; diff --git a/today-remoting/src/test/java/infra/remoting/core/RequestResponderChannelSubscriberTests.java b/today-remoting/src/test/java/infra/remoting/core/RequestResponderChannelSubscriberTests.java index c3ab10e..6659f3f 100644 --- a/today-remoting/src/test/java/infra/remoting/core/RequestResponderChannelSubscriberTests.java +++ b/today-remoting/src/test/java/infra/remoting/core/RequestResponderChannelSubscriberTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.core; diff --git a/today-remoting/src/test/java/infra/remoting/core/RequestResponseRequesterMonoTests.java b/today-remoting/src/test/java/infra/remoting/core/RequestResponseRequesterMonoTests.java index cd9c5c6..f7d6490 100644 --- a/today-remoting/src/test/java/infra/remoting/core/RequestResponseRequesterMonoTests.java +++ b/today-remoting/src/test/java/infra/remoting/core/RequestResponseRequesterMonoTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.core; diff --git a/today-remoting/src/test/java/infra/remoting/core/RequestStreamRequesterFluxTests.java b/today-remoting/src/test/java/infra/remoting/core/RequestStreamRequesterFluxTests.java index 307aaeb..77a0586 100644 --- a/today-remoting/src/test/java/infra/remoting/core/RequestStreamRequesterFluxTests.java +++ b/today-remoting/src/test/java/infra/remoting/core/RequestStreamRequesterFluxTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.core; diff --git a/today-remoting/src/test/java/infra/remoting/core/RequesterChannelSubscribersTests.java b/today-remoting/src/test/java/infra/remoting/core/RequesterChannelSubscribersTests.java index 908cf87..d89e122 100644 --- a/today-remoting/src/test/java/infra/remoting/core/RequesterChannelSubscribersTests.java +++ b/today-remoting/src/test/java/infra/remoting/core/RequesterChannelSubscribersTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.core; diff --git a/today-remoting/src/test/java/infra/remoting/core/RequesterChannelTerminationTests.java b/today-remoting/src/test/java/infra/remoting/core/RequesterChannelTerminationTests.java index 253a353..0172b7f 100644 --- a/today-remoting/src/test/java/infra/remoting/core/RequesterChannelTerminationTests.java +++ b/today-remoting/src/test/java/infra/remoting/core/RequesterChannelTerminationTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.core; diff --git a/today-remoting/src/test/java/infra/remoting/core/RequesterChannelTests.java b/today-remoting/src/test/java/infra/remoting/core/RequesterChannelTests.java index 839d150..9694d11 100644 --- a/today-remoting/src/test/java/infra/remoting/core/RequesterChannelTests.java +++ b/today-remoting/src/test/java/infra/remoting/core/RequesterChannelTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.core; diff --git a/today-remoting/src/test/java/infra/remoting/core/RequesterOperatorsRacingTests.java b/today-remoting/src/test/java/infra/remoting/core/RequesterOperatorsRacingTests.java index 39b26e4..0203de5 100644 --- a/today-remoting/src/test/java/infra/remoting/core/RequesterOperatorsRacingTests.java +++ b/today-remoting/src/test/java/infra/remoting/core/RequesterOperatorsRacingTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.core; diff --git a/today-remoting/src/test/java/infra/remoting/core/ResolvingOperatorTests.java b/today-remoting/src/test/java/infra/remoting/core/ResolvingOperatorTests.java index 59d6c70..a177c9c 100644 --- a/today-remoting/src/test/java/infra/remoting/core/ResolvingOperatorTests.java +++ b/today-remoting/src/test/java/infra/remoting/core/ResolvingOperatorTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.core; diff --git a/today-remoting/src/test/java/infra/remoting/core/ResponderChannelTests.java b/today-remoting/src/test/java/infra/remoting/core/ResponderChannelTests.java index 6051aad..27349dd 100644 --- a/today-remoting/src/test/java/infra/remoting/core/ResponderChannelTests.java +++ b/today-remoting/src/test/java/infra/remoting/core/ResponderChannelTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.core; diff --git a/today-remoting/src/test/java/infra/remoting/core/ResponderOperatorsCommonTests.java b/today-remoting/src/test/java/infra/remoting/core/ResponderOperatorsCommonTests.java index 34e0121..dd8cb21 100755 --- a/today-remoting/src/test/java/infra/remoting/core/ResponderOperatorsCommonTests.java +++ b/today-remoting/src/test/java/infra/remoting/core/ResponderOperatorsCommonTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.core; diff --git a/today-remoting/src/test/java/infra/remoting/core/SendUtilsTests.java b/today-remoting/src/test/java/infra/remoting/core/SendUtilsTests.java index 7b8e2d6..78bf185 100644 --- a/today-remoting/src/test/java/infra/remoting/core/SendUtilsTests.java +++ b/today-remoting/src/test/java/infra/remoting/core/SendUtilsTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.core; diff --git a/today-remoting/src/test/java/infra/remoting/core/SetupRejectionTests.java b/today-remoting/src/test/java/infra/remoting/core/SetupRejectionTests.java index 2e9d08b..5837216 100644 --- a/today-remoting/src/test/java/infra/remoting/core/SetupRejectionTests.java +++ b/today-remoting/src/test/java/infra/remoting/core/SetupRejectionTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.core; diff --git a/today-remoting/src/test/java/infra/remoting/core/ShouldHaveFlag.java b/today-remoting/src/test/java/infra/remoting/core/ShouldHaveFlag.java index 78ac868..3097f2f 100644 --- a/today-remoting/src/test/java/infra/remoting/core/ShouldHaveFlag.java +++ b/today-remoting/src/test/java/infra/remoting/core/ShouldHaveFlag.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.core; diff --git a/today-remoting/src/test/java/infra/remoting/core/ShouldNotHaveFlag.java b/today-remoting/src/test/java/infra/remoting/core/ShouldNotHaveFlag.java index aba2c84..db11b63 100644 --- a/today-remoting/src/test/java/infra/remoting/core/ShouldNotHaveFlag.java +++ b/today-remoting/src/test/java/infra/remoting/core/ShouldNotHaveFlag.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.core; diff --git a/today-remoting/src/test/java/infra/remoting/core/StateAssert.java b/today-remoting/src/test/java/infra/remoting/core/StateAssert.java index 60e7b8d..1fabd5b 100644 --- a/today-remoting/src/test/java/infra/remoting/core/StateAssert.java +++ b/today-remoting/src/test/java/infra/remoting/core/StateAssert.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.core; diff --git a/today-remoting/src/test/java/infra/remoting/core/StreamIdProviderTest.java b/today-remoting/src/test/java/infra/remoting/core/StreamIdProviderTest.java index 8599227..e3c45b1 100644 --- a/today-remoting/src/test/java/infra/remoting/core/StreamIdProviderTest.java +++ b/today-remoting/src/test/java/infra/remoting/core/StreamIdProviderTest.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.core; diff --git a/today-remoting/src/test/java/infra/remoting/core/TestChannelSupport.java b/today-remoting/src/test/java/infra/remoting/core/TestChannelSupport.java index 92884f7..f1bb0b9 100644 --- a/today-remoting/src/test/java/infra/remoting/core/TestChannelSupport.java +++ b/today-remoting/src/test/java/infra/remoting/core/TestChannelSupport.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.core; diff --git a/today-remoting/src/test/java/infra/remoting/error/ApplicationErrorExceptionTests.java b/today-remoting/src/test/java/infra/remoting/error/ApplicationErrorExceptionTests.java index 50a94bf..27f9f5a 100644 --- a/today-remoting/src/test/java/infra/remoting/error/ApplicationErrorExceptionTests.java +++ b/today-remoting/src/test/java/infra/remoting/error/ApplicationErrorExceptionTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.error; diff --git a/today-remoting/src/test/java/infra/remoting/error/CanceledExceptionTests.java b/today-remoting/src/test/java/infra/remoting/error/CanceledExceptionTests.java index e8a2c18..0683954 100644 --- a/today-remoting/src/test/java/infra/remoting/error/CanceledExceptionTests.java +++ b/today-remoting/src/test/java/infra/remoting/error/CanceledExceptionTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.error; diff --git a/today-remoting/src/test/java/infra/remoting/error/ChannelExceptionTests.java b/today-remoting/src/test/java/infra/remoting/error/ChannelExceptionTests.java index eff3082..7f927cc 100644 --- a/today-remoting/src/test/java/infra/remoting/error/ChannelExceptionTests.java +++ b/today-remoting/src/test/java/infra/remoting/error/ChannelExceptionTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.error; diff --git a/today-remoting/src/test/java/infra/remoting/error/ConnectionCloseExceptionTests.java b/today-remoting/src/test/java/infra/remoting/error/ConnectionCloseExceptionTests.java index e4aecb8..bb2de45 100644 --- a/today-remoting/src/test/java/infra/remoting/error/ConnectionCloseExceptionTests.java +++ b/today-remoting/src/test/java/infra/remoting/error/ConnectionCloseExceptionTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.error; diff --git a/today-remoting/src/test/java/infra/remoting/error/ConnectionErrorExceptionTests.java b/today-remoting/src/test/java/infra/remoting/error/ConnectionErrorExceptionTests.java index 20ae2dc..2ec7e49 100644 --- a/today-remoting/src/test/java/infra/remoting/error/ConnectionErrorExceptionTests.java +++ b/today-remoting/src/test/java/infra/remoting/error/ConnectionErrorExceptionTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.error; diff --git a/today-remoting/src/test/java/infra/remoting/error/ExceptionsTests.java b/today-remoting/src/test/java/infra/remoting/error/ExceptionsTests.java index 3880ba4..5117009 100644 --- a/today-remoting/src/test/java/infra/remoting/error/ExceptionsTests.java +++ b/today-remoting/src/test/java/infra/remoting/error/ExceptionsTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.error; diff --git a/today-remoting/src/test/java/infra/remoting/error/InvalidExceptionTests.java b/today-remoting/src/test/java/infra/remoting/error/InvalidExceptionTests.java index 0b107c0..80478d7 100644 --- a/today-remoting/src/test/java/infra/remoting/error/InvalidExceptionTests.java +++ b/today-remoting/src/test/java/infra/remoting/error/InvalidExceptionTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.error; diff --git a/today-remoting/src/test/java/infra/remoting/error/InvalidSetupExceptionTests.java b/today-remoting/src/test/java/infra/remoting/error/InvalidSetupExceptionTests.java index 5e9497b..99db7f5 100644 --- a/today-remoting/src/test/java/infra/remoting/error/InvalidSetupExceptionTests.java +++ b/today-remoting/src/test/java/infra/remoting/error/InvalidSetupExceptionTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.error; diff --git a/today-remoting/src/test/java/infra/remoting/error/RejectedExceptionTests.java b/today-remoting/src/test/java/infra/remoting/error/RejectedExceptionTests.java index d768dd9..652313a 100644 --- a/today-remoting/src/test/java/infra/remoting/error/RejectedExceptionTests.java +++ b/today-remoting/src/test/java/infra/remoting/error/RejectedExceptionTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.error; diff --git a/today-remoting/src/test/java/infra/remoting/error/RejectedResumeExceptionTests.java b/today-remoting/src/test/java/infra/remoting/error/RejectedResumeExceptionTests.java index f88af45..62053e5 100644 --- a/today-remoting/src/test/java/infra/remoting/error/RejectedResumeExceptionTests.java +++ b/today-remoting/src/test/java/infra/remoting/error/RejectedResumeExceptionTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.error; diff --git a/today-remoting/src/test/java/infra/remoting/error/RejectedSetupExceptionTests.java b/today-remoting/src/test/java/infra/remoting/error/RejectedSetupExceptionTests.java index 3dd674e..f99ebcf 100644 --- a/today-remoting/src/test/java/infra/remoting/error/RejectedSetupExceptionTests.java +++ b/today-remoting/src/test/java/infra/remoting/error/RejectedSetupExceptionTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.error; diff --git a/today-remoting/src/test/java/infra/remoting/error/TestProtocolException.java b/today-remoting/src/test/java/infra/remoting/error/TestProtocolException.java index badf646..6e2442a 100644 --- a/today-remoting/src/test/java/infra/remoting/error/TestProtocolException.java +++ b/today-remoting/src/test/java/infra/remoting/error/TestProtocolException.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.error; diff --git a/today-remoting/src/test/java/infra/remoting/error/UnsupportedSetupExceptionTests.java b/today-remoting/src/test/java/infra/remoting/error/UnsupportedSetupExceptionTests.java index 45ef572..5a0cb08 100644 --- a/today-remoting/src/test/java/infra/remoting/error/UnsupportedSetupExceptionTests.java +++ b/today-remoting/src/test/java/infra/remoting/error/UnsupportedSetupExceptionTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.error; diff --git a/today-remoting/src/test/java/infra/remoting/examples/tcp/channel/ChannelEchoClient.java b/today-remoting/src/test/java/infra/remoting/examples/tcp/channel/ChannelEchoClient.java index 8a8b6a0..042db28 100644 --- a/today-remoting/src/test/java/infra/remoting/examples/tcp/channel/ChannelEchoClient.java +++ b/today-remoting/src/test/java/infra/remoting/examples/tcp/channel/ChannelEchoClient.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.examples.tcp.channel; diff --git a/today-remoting/src/test/java/infra/remoting/examples/tcp/client/ClientExample.java b/today-remoting/src/test/java/infra/remoting/examples/tcp/client/ClientExample.java index fbea922..3f32884 100644 --- a/today-remoting/src/test/java/infra/remoting/examples/tcp/client/ClientExample.java +++ b/today-remoting/src/test/java/infra/remoting/examples/tcp/client/ClientExample.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.examples.tcp.client; diff --git a/today-remoting/src/test/java/infra/remoting/examples/tcp/fnf/TaskProcessingWithServerSideNotificationsExample.java b/today-remoting/src/test/java/infra/remoting/examples/tcp/fnf/TaskProcessingWithServerSideNotificationsExample.java index 8fb1ffa..442026e 100644 --- a/today-remoting/src/test/java/infra/remoting/examples/tcp/fnf/TaskProcessingWithServerSideNotificationsExample.java +++ b/today-remoting/src/test/java/infra/remoting/examples/tcp/fnf/TaskProcessingWithServerSideNotificationsExample.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.examples.tcp.fnf; diff --git a/today-remoting/src/test/java/infra/remoting/examples/tcp/lease/advanced/common/LeaseManager.java b/today-remoting/src/test/java/infra/remoting/examples/tcp/lease/advanced/common/LeaseManager.java index 1454664..f81b8d1 100644 --- a/today-remoting/src/test/java/infra/remoting/examples/tcp/lease/advanced/common/LeaseManager.java +++ b/today-remoting/src/test/java/infra/remoting/examples/tcp/lease/advanced/common/LeaseManager.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.examples.tcp.lease.advanced.common; diff --git a/today-remoting/src/test/java/infra/remoting/examples/tcp/lease/advanced/common/LimitBasedLeaseSender.java b/today-remoting/src/test/java/infra/remoting/examples/tcp/lease/advanced/common/LimitBasedLeaseSender.java index 2b6fa27..3f1f51a 100644 --- a/today-remoting/src/test/java/infra/remoting/examples/tcp/lease/advanced/common/LimitBasedLeaseSender.java +++ b/today-remoting/src/test/java/infra/remoting/examples/tcp/lease/advanced/common/LimitBasedLeaseSender.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.examples.tcp.lease.advanced.common; diff --git a/today-remoting/src/test/java/infra/remoting/examples/tcp/lease/advanced/common/LimitBasedStatsCollector.java b/today-remoting/src/test/java/infra/remoting/examples/tcp/lease/advanced/common/LimitBasedStatsCollector.java index a353e5f..1fba2b9 100644 --- a/today-remoting/src/test/java/infra/remoting/examples/tcp/lease/advanced/common/LimitBasedStatsCollector.java +++ b/today-remoting/src/test/java/infra/remoting/examples/tcp/lease/advanced/common/LimitBasedStatsCollector.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.examples.tcp.lease.advanced.common; diff --git a/today-remoting/src/test/java/infra/remoting/examples/tcp/lease/advanced/controller/Task.java b/today-remoting/src/test/java/infra/remoting/examples/tcp/lease/advanced/controller/Task.java index 1b5ebea..5a05569 100644 --- a/today-remoting/src/test/java/infra/remoting/examples/tcp/lease/advanced/controller/Task.java +++ b/today-remoting/src/test/java/infra/remoting/examples/tcp/lease/advanced/controller/Task.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.examples.tcp.lease.advanced.controller; diff --git a/today-remoting/src/test/java/infra/remoting/examples/tcp/lease/advanced/controller/TasksHandlingChannel.java b/today-remoting/src/test/java/infra/remoting/examples/tcp/lease/advanced/controller/TasksHandlingChannel.java index 20f5cd3..3c07ffe 100644 --- a/today-remoting/src/test/java/infra/remoting/examples/tcp/lease/advanced/controller/TasksHandlingChannel.java +++ b/today-remoting/src/test/java/infra/remoting/examples/tcp/lease/advanced/controller/TasksHandlingChannel.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.examples.tcp.lease.advanced.controller; diff --git a/today-remoting/src/test/java/infra/remoting/examples/tcp/lease/advanced/invertmulticlient/RequestingServer.java b/today-remoting/src/test/java/infra/remoting/examples/tcp/lease/advanced/invertmulticlient/RequestingServer.java index 458c2db..a537b3b 100644 --- a/today-remoting/src/test/java/infra/remoting/examples/tcp/lease/advanced/invertmulticlient/RequestingServer.java +++ b/today-remoting/src/test/java/infra/remoting/examples/tcp/lease/advanced/invertmulticlient/RequestingServer.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.examples.tcp.lease.advanced.invertmulticlient; diff --git a/today-remoting/src/test/java/infra/remoting/examples/tcp/lease/advanced/invertmulticlient/RespondingClient.java b/today-remoting/src/test/java/infra/remoting/examples/tcp/lease/advanced/invertmulticlient/RespondingClient.java index 847d03c..2826179 100644 --- a/today-remoting/src/test/java/infra/remoting/examples/tcp/lease/advanced/invertmulticlient/RespondingClient.java +++ b/today-remoting/src/test/java/infra/remoting/examples/tcp/lease/advanced/invertmulticlient/RespondingClient.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.examples.tcp.lease.advanced.invertmulticlient; diff --git a/today-remoting/src/test/java/infra/remoting/examples/tcp/lease/advanced/multiclient/RequestingClient.java b/today-remoting/src/test/java/infra/remoting/examples/tcp/lease/advanced/multiclient/RequestingClient.java index 6a236eb..42a15b6 100644 --- a/today-remoting/src/test/java/infra/remoting/examples/tcp/lease/advanced/multiclient/RequestingClient.java +++ b/today-remoting/src/test/java/infra/remoting/examples/tcp/lease/advanced/multiclient/RequestingClient.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.examples.tcp.lease.advanced.multiclient; diff --git a/today-remoting/src/test/java/infra/remoting/examples/tcp/lease/advanced/multiclient/RespondingServer.java b/today-remoting/src/test/java/infra/remoting/examples/tcp/lease/advanced/multiclient/RespondingServer.java index f490c40..4258ba8 100644 --- a/today-remoting/src/test/java/infra/remoting/examples/tcp/lease/advanced/multiclient/RespondingServer.java +++ b/today-remoting/src/test/java/infra/remoting/examples/tcp/lease/advanced/multiclient/RespondingServer.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.examples.tcp.lease.advanced.multiclient; diff --git a/today-remoting/src/test/java/infra/remoting/examples/tcp/lease/simple/LeaseExample.java b/today-remoting/src/test/java/infra/remoting/examples/tcp/lease/simple/LeaseExample.java index 7e2dd45..607ac57 100644 --- a/today-remoting/src/test/java/infra/remoting/examples/tcp/lease/simple/LeaseExample.java +++ b/today-remoting/src/test/java/infra/remoting/examples/tcp/lease/simple/LeaseExample.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.examples.tcp.lease.simple; diff --git a/today-remoting/src/test/java/infra/remoting/examples/tcp/loadbalancer/RoundRobinLoadbalancerExample.java b/today-remoting/src/test/java/infra/remoting/examples/tcp/loadbalancer/RoundRobinLoadbalancerExample.java index d676762..a5e4602 100644 --- a/today-remoting/src/test/java/infra/remoting/examples/tcp/loadbalancer/RoundRobinLoadbalancerExample.java +++ b/today-remoting/src/test/java/infra/remoting/examples/tcp/loadbalancer/RoundRobinLoadbalancerExample.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.examples.tcp.loadbalancer; diff --git a/today-remoting/src/test/java/infra/remoting/examples/tcp/plugins/LimitRateInterceptorExample.java b/today-remoting/src/test/java/infra/remoting/examples/tcp/plugins/LimitRateInterceptorExample.java index 3092118..d0e4f2a 100644 --- a/today-remoting/src/test/java/infra/remoting/examples/tcp/plugins/LimitRateInterceptorExample.java +++ b/today-remoting/src/test/java/infra/remoting/examples/tcp/plugins/LimitRateInterceptorExample.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.examples.tcp.plugins; diff --git a/today-remoting/src/test/java/infra/remoting/examples/tcp/requestresponse/HelloWorldClient.java b/today-remoting/src/test/java/infra/remoting/examples/tcp/requestresponse/HelloWorldClient.java index e775a44..975594e 100644 --- a/today-remoting/src/test/java/infra/remoting/examples/tcp/requestresponse/HelloWorldClient.java +++ b/today-remoting/src/test/java/infra/remoting/examples/tcp/requestresponse/HelloWorldClient.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.examples.tcp.requestresponse; diff --git a/today-remoting/src/test/java/infra/remoting/examples/tcp/resume/Files.java b/today-remoting/src/test/java/infra/remoting/examples/tcp/resume/Files.java index ce2e17d..325f688 100644 --- a/today-remoting/src/test/java/infra/remoting/examples/tcp/resume/Files.java +++ b/today-remoting/src/test/java/infra/remoting/examples/tcp/resume/Files.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.examples.tcp.resume; diff --git a/today-remoting/src/test/java/infra/remoting/examples/tcp/resume/ResumeFileTransfer.java b/today-remoting/src/test/java/infra/remoting/examples/tcp/resume/ResumeFileTransfer.java index 0d2a673..60dc6f8 100644 --- a/today-remoting/src/test/java/infra/remoting/examples/tcp/resume/ResumeFileTransfer.java +++ b/today-remoting/src/test/java/infra/remoting/examples/tcp/resume/ResumeFileTransfer.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.examples.tcp.resume; diff --git a/today-remoting/src/test/java/infra/remoting/examples/tcp/stream/ClientStreamingToServer.java b/today-remoting/src/test/java/infra/remoting/examples/tcp/stream/ClientStreamingToServer.java index 2fa29d6..36b0557 100644 --- a/today-remoting/src/test/java/infra/remoting/examples/tcp/stream/ClientStreamingToServer.java +++ b/today-remoting/src/test/java/infra/remoting/examples/tcp/stream/ClientStreamingToServer.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.examples.tcp.stream; diff --git a/today-remoting/src/test/java/infra/remoting/examples/tcp/stream/ServerStreamingToClient.java b/today-remoting/src/test/java/infra/remoting/examples/tcp/stream/ServerStreamingToClient.java index f5c421f..66b4dbe 100644 --- a/today-remoting/src/test/java/infra/remoting/examples/tcp/stream/ServerStreamingToClient.java +++ b/today-remoting/src/test/java/infra/remoting/examples/tcp/stream/ServerStreamingToClient.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.examples.tcp.stream; diff --git a/today-remoting/src/test/java/infra/remoting/examples/ws/WebSocketAggregationSample.java b/today-remoting/src/test/java/infra/remoting/examples/ws/WebSocketAggregationSample.java index b214abb..2913855 100644 --- a/today-remoting/src/test/java/infra/remoting/examples/ws/WebSocketAggregationSample.java +++ b/today-remoting/src/test/java/infra/remoting/examples/ws/WebSocketAggregationSample.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.examples.ws; diff --git a/today-remoting/src/test/java/infra/remoting/examples/ws/WebSocketHeadersSample.java b/today-remoting/src/test/java/infra/remoting/examples/ws/WebSocketHeadersSample.java index 65f5a82..c2cc321 100644 --- a/today-remoting/src/test/java/infra/remoting/examples/ws/WebSocketHeadersSample.java +++ b/today-remoting/src/test/java/infra/remoting/examples/ws/WebSocketHeadersSample.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.examples.ws; diff --git a/today-remoting/src/test/java/infra/remoting/frame/ByteBufRepresentation.java b/today-remoting/src/test/java/infra/remoting/frame/ByteBufRepresentation.java index 3dab653..0ebb92e 100644 --- a/today-remoting/src/test/java/infra/remoting/frame/ByteBufRepresentation.java +++ b/today-remoting/src/test/java/infra/remoting/frame/ByteBufRepresentation.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.frame; diff --git a/today-remoting/src/test/java/infra/remoting/frame/ErrorFrameCodecTests.java b/today-remoting/src/test/java/infra/remoting/frame/ErrorFrameCodecTests.java index 3e95887..07c833e 100644 --- a/today-remoting/src/test/java/infra/remoting/frame/ErrorFrameCodecTests.java +++ b/today-remoting/src/test/java/infra/remoting/frame/ErrorFrameCodecTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.frame; diff --git a/today-remoting/src/test/java/infra/remoting/frame/ExtensionFrameCodecTests.java b/today-remoting/src/test/java/infra/remoting/frame/ExtensionFrameCodecTests.java index df8d25a..ffa468a 100644 --- a/today-remoting/src/test/java/infra/remoting/frame/ExtensionFrameCodecTests.java +++ b/today-remoting/src/test/java/infra/remoting/frame/ExtensionFrameCodecTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.frame; diff --git a/today-remoting/src/test/java/infra/remoting/frame/FrameHeaderCodecTests.java b/today-remoting/src/test/java/infra/remoting/frame/FrameHeaderCodecTests.java index 56fde1b..16f5cbb 100644 --- a/today-remoting/src/test/java/infra/remoting/frame/FrameHeaderCodecTests.java +++ b/today-remoting/src/test/java/infra/remoting/frame/FrameHeaderCodecTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.frame; diff --git a/today-remoting/src/test/java/infra/remoting/frame/GenericFrameCodecTests.java b/today-remoting/src/test/java/infra/remoting/frame/GenericFrameCodecTests.java index 028f8b8..0a72669 100644 --- a/today-remoting/src/test/java/infra/remoting/frame/GenericFrameCodecTests.java +++ b/today-remoting/src/test/java/infra/remoting/frame/GenericFrameCodecTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.frame; diff --git a/today-remoting/src/test/java/infra/remoting/frame/KeepaliveFrameFlyweightTests.java b/today-remoting/src/test/java/infra/remoting/frame/KeepaliveFrameFlyweightTests.java index 6ad7371..83f1953 100644 --- a/today-remoting/src/test/java/infra/remoting/frame/KeepaliveFrameFlyweightTests.java +++ b/today-remoting/src/test/java/infra/remoting/frame/KeepaliveFrameFlyweightTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.frame; diff --git a/today-remoting/src/test/java/infra/remoting/frame/LeaseFrameCodecTests.java b/today-remoting/src/test/java/infra/remoting/frame/LeaseFrameCodecTests.java index 4e87866..da4a07e 100644 --- a/today-remoting/src/test/java/infra/remoting/frame/LeaseFrameCodecTests.java +++ b/today-remoting/src/test/java/infra/remoting/frame/LeaseFrameCodecTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.frame; diff --git a/today-remoting/src/test/java/infra/remoting/frame/PayloadFlyweightTests.java b/today-remoting/src/test/java/infra/remoting/frame/PayloadFlyweightTests.java index 9096d25..45122d3 100644 --- a/today-remoting/src/test/java/infra/remoting/frame/PayloadFlyweightTests.java +++ b/today-remoting/src/test/java/infra/remoting/frame/PayloadFlyweightTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.frame; diff --git a/today-remoting/src/test/java/infra/remoting/frame/RequestNFrameCodecTests.java b/today-remoting/src/test/java/infra/remoting/frame/RequestNFrameCodecTests.java index 5146a4f..275187b 100644 --- a/today-remoting/src/test/java/infra/remoting/frame/RequestNFrameCodecTests.java +++ b/today-remoting/src/test/java/infra/remoting/frame/RequestNFrameCodecTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.frame; diff --git a/today-remoting/src/test/java/infra/remoting/frame/ResumeFrameCodecTests.java b/today-remoting/src/test/java/infra/remoting/frame/ResumeFrameCodecTests.java index 9e691cd..2ebc72b 100644 --- a/today-remoting/src/test/java/infra/remoting/frame/ResumeFrameCodecTests.java +++ b/today-remoting/src/test/java/infra/remoting/frame/ResumeFrameCodecTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.frame; diff --git a/today-remoting/src/test/java/infra/remoting/frame/ResumeOkFrameCodecTests.java b/today-remoting/src/test/java/infra/remoting/frame/ResumeOkFrameCodecTests.java index 6f1811f..6b6a3ad 100644 --- a/today-remoting/src/test/java/infra/remoting/frame/ResumeOkFrameCodecTests.java +++ b/today-remoting/src/test/java/infra/remoting/frame/ResumeOkFrameCodecTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.frame; diff --git a/today-remoting/src/test/java/infra/remoting/frame/SetupFrameCodecTests.java b/today-remoting/src/test/java/infra/remoting/frame/SetupFrameCodecTests.java index 399be94..099c9b6 100644 --- a/today-remoting/src/test/java/infra/remoting/frame/SetupFrameCodecTests.java +++ b/today-remoting/src/test/java/infra/remoting/frame/SetupFrameCodecTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.frame; diff --git a/today-remoting/src/test/java/infra/remoting/frame/VersionCodecTests.java b/today-remoting/src/test/java/infra/remoting/frame/VersionCodecTests.java index fecc14f..95ebc0f 100644 --- a/today-remoting/src/test/java/infra/remoting/frame/VersionCodecTests.java +++ b/today-remoting/src/test/java/infra/remoting/frame/VersionCodecTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.frame; diff --git a/today-remoting/src/test/java/infra/remoting/internal/SchedulerUtils.java b/today-remoting/src/test/java/infra/remoting/internal/SchedulerUtils.java index 90e9945..856beda 100644 --- a/today-remoting/src/test/java/infra/remoting/internal/SchedulerUtils.java +++ b/today-remoting/src/test/java/infra/remoting/internal/SchedulerUtils.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.internal; diff --git a/today-remoting/src/test/java/infra/remoting/internal/UnboundedProcessorTests.java b/today-remoting/src/test/java/infra/remoting/internal/UnboundedProcessorTests.java index 5407f5a..c2ac2a5 100644 --- a/today-remoting/src/test/java/infra/remoting/internal/UnboundedProcessorTests.java +++ b/today-remoting/src/test/java/infra/remoting/internal/UnboundedProcessorTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.internal; diff --git a/today-remoting/src/test/java/infra/remoting/internal/subscriber/AssertSubscriber.java b/today-remoting/src/test/java/infra/remoting/internal/subscriber/AssertSubscriber.java index 608ec80..e8c50e5 100644 --- a/today-remoting/src/test/java/infra/remoting/internal/subscriber/AssertSubscriber.java +++ b/today-remoting/src/test/java/infra/remoting/internal/subscriber/AssertSubscriber.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.internal.subscriber; diff --git a/today-remoting/src/test/java/infra/remoting/lb/LoadbalanceChannelClientTests.java b/today-remoting/src/test/java/infra/remoting/lb/LoadbalanceChannelClientTests.java index 4b9b80c..16de46a 100644 --- a/today-remoting/src/test/java/infra/remoting/lb/LoadbalanceChannelClientTests.java +++ b/today-remoting/src/test/java/infra/remoting/lb/LoadbalanceChannelClientTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.lb; diff --git a/today-remoting/src/test/java/infra/remoting/lb/LoadbalanceTests.java b/today-remoting/src/test/java/infra/remoting/lb/LoadbalanceTests.java index 8b6da30..1f726ce 100644 --- a/today-remoting/src/test/java/infra/remoting/lb/LoadbalanceTests.java +++ b/today-remoting/src/test/java/infra/remoting/lb/LoadbalanceTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.lb; diff --git a/today-remoting/src/test/java/infra/remoting/lb/RoundRobinLoadBalanceStrategyTests.java b/today-remoting/src/test/java/infra/remoting/lb/RoundRobinLoadBalanceStrategyTests.java index 9e1159a..bf8b518 100644 --- a/today-remoting/src/test/java/infra/remoting/lb/RoundRobinLoadBalanceStrategyTests.java +++ b/today-remoting/src/test/java/infra/remoting/lb/RoundRobinLoadBalanceStrategyTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.lb; diff --git a/today-remoting/src/test/java/infra/remoting/lb/WeightedLoadBalanceStrategyTests.java b/today-remoting/src/test/java/infra/remoting/lb/WeightedLoadBalanceStrategyTests.java index dfe336e..173f98d 100644 --- a/today-remoting/src/test/java/infra/remoting/lb/WeightedLoadBalanceStrategyTests.java +++ b/today-remoting/src/test/java/infra/remoting/lb/WeightedLoadBalanceStrategyTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.lb; diff --git a/today-remoting/src/test/java/infra/remoting/lease/LeaseImplTests.java b/today-remoting/src/test/java/infra/remoting/lease/LeaseImplTests.java index e879920..b7e7a73 100644 --- a/today-remoting/src/test/java/infra/remoting/lease/LeaseImplTests.java +++ b/today-remoting/src/test/java/infra/remoting/lease/LeaseImplTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.lease; diff --git a/today-remoting/src/test/java/infra/remoting/plugins/RequestInterceptorTests.java b/today-remoting/src/test/java/infra/remoting/plugins/RequestInterceptorTests.java index af653b7..3ccf358 100644 --- a/today-remoting/src/test/java/infra/remoting/plugins/RequestInterceptorTests.java +++ b/today-remoting/src/test/java/infra/remoting/plugins/RequestInterceptorTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.plugins; diff --git a/today-remoting/src/test/java/infra/remoting/plugins/TestRequestInterceptor.java b/today-remoting/src/test/java/infra/remoting/plugins/TestRequestInterceptor.java index 826fd1e..6d5b9ab 100644 --- a/today-remoting/src/test/java/infra/remoting/plugins/TestRequestInterceptor.java +++ b/today-remoting/src/test/java/infra/remoting/plugins/TestRequestInterceptor.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.plugins; diff --git a/today-remoting/src/test/java/infra/remoting/protocol/MetadataTests.java b/today-remoting/src/test/java/infra/remoting/protocol/MetadataTests.java index a772c2d..a157a8d 100644 --- a/today-remoting/src/test/java/infra/remoting/protocol/MetadataTests.java +++ b/today-remoting/src/test/java/infra/remoting/protocol/MetadataTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.protocol; diff --git a/today-remoting/src/test/java/infra/remoting/resume/ClientChannelSessionTests.java b/today-remoting/src/test/java/infra/remoting/resume/ClientChannelSessionTests.java index fdb4afa..e0bf3f5 100644 --- a/today-remoting/src/test/java/infra/remoting/resume/ClientChannelSessionTests.java +++ b/today-remoting/src/test/java/infra/remoting/resume/ClientChannelSessionTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.resume; diff --git a/today-remoting/src/test/java/infra/remoting/resume/DisconnectableClientTransport.java b/today-remoting/src/test/java/infra/remoting/resume/DisconnectableClientTransport.java index e104d3f..444729e 100644 --- a/today-remoting/src/test/java/infra/remoting/resume/DisconnectableClientTransport.java +++ b/today-remoting/src/test/java/infra/remoting/resume/DisconnectableClientTransport.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.resume; diff --git a/today-remoting/src/test/java/infra/remoting/resume/InMemoryResumeStoreTests.java b/today-remoting/src/test/java/infra/remoting/resume/InMemoryResumeStoreTests.java index 5023403..8dcf9aa 100644 --- a/today-remoting/src/test/java/infra/remoting/resume/InMemoryResumeStoreTests.java +++ b/today-remoting/src/test/java/infra/remoting/resume/InMemoryResumeStoreTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.resume; diff --git a/today-remoting/src/test/java/infra/remoting/resume/ResumeIntegrationTests.java b/today-remoting/src/test/java/infra/remoting/resume/ResumeIntegrationTests.java index 2a1f1ad..d358c25 100644 --- a/today-remoting/src/test/java/infra/remoting/resume/ResumeIntegrationTests.java +++ b/today-remoting/src/test/java/infra/remoting/resume/ResumeIntegrationTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.resume; diff --git a/today-remoting/src/test/java/infra/remoting/resume/ServerChannelSessionTests.java b/today-remoting/src/test/java/infra/remoting/resume/ServerChannelSessionTests.java index 03e320e..3123b83 100644 --- a/today-remoting/src/test/java/infra/remoting/resume/ServerChannelSessionTests.java +++ b/today-remoting/src/test/java/infra/remoting/resume/ServerChannelSessionTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.resume; diff --git a/today-remoting/src/test/java/infra/remoting/test/util/ByteBufUtils.java b/today-remoting/src/test/java/infra/remoting/test/util/ByteBufUtils.java index 11cf136..413b54a 100644 --- a/today-remoting/src/test/java/infra/remoting/test/util/ByteBufUtils.java +++ b/today-remoting/src/test/java/infra/remoting/test/util/ByteBufUtils.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.test.util; diff --git a/today-remoting/src/test/java/infra/remoting/test/util/LocalConnection.java b/today-remoting/src/test/java/infra/remoting/test/util/LocalConnection.java index 26d4623..3c4b6b8 100644 --- a/today-remoting/src/test/java/infra/remoting/test/util/LocalConnection.java +++ b/today-remoting/src/test/java/infra/remoting/test/util/LocalConnection.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.test.util; diff --git a/today-remoting/src/test/java/infra/remoting/test/util/MockChannel.java b/today-remoting/src/test/java/infra/remoting/test/util/MockChannel.java index 39bd36f..93a08a4 100644 --- a/today-remoting/src/test/java/infra/remoting/test/util/MockChannel.java +++ b/today-remoting/src/test/java/infra/remoting/test/util/MockChannel.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.test.util; diff --git a/today-remoting/src/test/java/infra/remoting/test/util/StringUtils.java b/today-remoting/src/test/java/infra/remoting/test/util/StringUtils.java index 14242d1..8c20318 100644 --- a/today-remoting/src/test/java/infra/remoting/test/util/StringUtils.java +++ b/today-remoting/src/test/java/infra/remoting/test/util/StringUtils.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.test.util; diff --git a/today-remoting/src/test/java/infra/remoting/test/util/TestClientTransport.java b/today-remoting/src/test/java/infra/remoting/test/util/TestClientTransport.java index b0d9314..dac86e4 100644 --- a/today-remoting/src/test/java/infra/remoting/test/util/TestClientTransport.java +++ b/today-remoting/src/test/java/infra/remoting/test/util/TestClientTransport.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.test.util; diff --git a/today-remoting/src/test/java/infra/remoting/test/util/TestConnection.java b/today-remoting/src/test/java/infra/remoting/test/util/TestConnection.java index e1ccb05..b906b61 100644 --- a/today-remoting/src/test/java/infra/remoting/test/util/TestConnection.java +++ b/today-remoting/src/test/java/infra/remoting/test/util/TestConnection.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.test.util; diff --git a/today-remoting/src/test/java/infra/remoting/test/util/TestLocalSocketAddress.java b/today-remoting/src/test/java/infra/remoting/test/util/TestLocalSocketAddress.java index 1b08dae..d41d36e 100644 --- a/today-remoting/src/test/java/infra/remoting/test/util/TestLocalSocketAddress.java +++ b/today-remoting/src/test/java/infra/remoting/test/util/TestLocalSocketAddress.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.test.util; diff --git a/today-remoting/src/test/java/infra/remoting/test/util/TestServerTransport.java b/today-remoting/src/test/java/infra/remoting/test/util/TestServerTransport.java index a166fe0..36dd226 100644 --- a/today-remoting/src/test/java/infra/remoting/test/util/TestServerTransport.java +++ b/today-remoting/src/test/java/infra/remoting/test/util/TestServerTransport.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.test.util; diff --git a/today-remoting/src/test/java/infra/remoting/test/util/TestSubscriber.java b/today-remoting/src/test/java/infra/remoting/test/util/TestSubscriber.java index df46bac..237c049 100644 --- a/today-remoting/src/test/java/infra/remoting/test/util/TestSubscriber.java +++ b/today-remoting/src/test/java/infra/remoting/test/util/TestSubscriber.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.test.util; diff --git a/today-remoting/src/test/java/infra/remoting/util/ByteBufPayloadTests.java b/today-remoting/src/test/java/infra/remoting/util/ByteBufPayloadTests.java index f7891fd..5cfdd7d 100644 --- a/today-remoting/src/test/java/infra/remoting/util/ByteBufPayloadTests.java +++ b/today-remoting/src/test/java/infra/remoting/util/ByteBufPayloadTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.util; diff --git a/today-remoting/src/test/java/infra/remoting/util/DefaultPayloadTests.java b/today-remoting/src/test/java/infra/remoting/util/DefaultPayloadTests.java index 4b7dc3a..ff4d06f 100644 --- a/today-remoting/src/test/java/infra/remoting/util/DefaultPayloadTests.java +++ b/today-remoting/src/test/java/infra/remoting/util/DefaultPayloadTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.util; diff --git a/today-remoting/src/test/resources/logback-test.xml b/today-remoting/src/test/resources/logback-test.xml index a380c54..dd39c4a 100644 --- a/today-remoting/src/test/resources/logback-test.xml +++ b/today-remoting/src/test/resources/logback-test.xml @@ -1,20 +1,4 @@ - diff --git a/today-remoting/src/testFixtures/java/infra/remoting/test/BaseClientServerTest.java b/today-remoting/src/testFixtures/java/infra/remoting/test/BaseClientServerTest.java index e0853e6..1c926ae 100644 --- a/today-remoting/src/testFixtures/java/infra/remoting/test/BaseClientServerTest.java +++ b/today-remoting/src/testFixtures/java/infra/remoting/test/BaseClientServerTest.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.test; diff --git a/today-remoting/src/testFixtures/java/infra/remoting/test/ByteBufRepresentation.java b/today-remoting/src/testFixtures/java/infra/remoting/test/ByteBufRepresentation.java index 2f6e203..562b545 100644 --- a/today-remoting/src/testFixtures/java/infra/remoting/test/ByteBufRepresentation.java +++ b/today-remoting/src/testFixtures/java/infra/remoting/test/ByteBufRepresentation.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.test; diff --git a/today-remoting/src/testFixtures/java/infra/remoting/test/ClientSetupRule.java b/today-remoting/src/testFixtures/java/infra/remoting/test/ClientSetupRule.java index 5131f04..cfddf80 100644 --- a/today-remoting/src/testFixtures/java/infra/remoting/test/ClientSetupRule.java +++ b/today-remoting/src/testFixtures/java/infra/remoting/test/ClientSetupRule.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.test; diff --git a/today-remoting/src/testFixtures/java/infra/remoting/test/CountdownBaseSubscriber.java b/today-remoting/src/testFixtures/java/infra/remoting/test/CountdownBaseSubscriber.java index 4edbb62..4a22d3d 100644 --- a/today-remoting/src/testFixtures/java/infra/remoting/test/CountdownBaseSubscriber.java +++ b/today-remoting/src/testFixtures/java/infra/remoting/test/CountdownBaseSubscriber.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.test; diff --git a/today-remoting/src/testFixtures/java/infra/remoting/test/LeaksTrackingByteBufAllocator.java b/today-remoting/src/testFixtures/java/infra/remoting/test/LeaksTrackingByteBufAllocator.java index d26120a..89da69b 100644 --- a/today-remoting/src/testFixtures/java/infra/remoting/test/LeaksTrackingByteBufAllocator.java +++ b/today-remoting/src/testFixtures/java/infra/remoting/test/LeaksTrackingByteBufAllocator.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.test; diff --git a/today-remoting/src/testFixtures/java/infra/remoting/test/PayloadPredicate.java b/today-remoting/src/testFixtures/java/infra/remoting/test/PayloadPredicate.java index 5c39624..62f3bbe 100644 --- a/today-remoting/src/testFixtures/java/infra/remoting/test/PayloadPredicate.java +++ b/today-remoting/src/testFixtures/java/infra/remoting/test/PayloadPredicate.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.test; diff --git a/today-remoting/src/testFixtures/java/infra/remoting/test/PerfTest.java b/today-remoting/src/testFixtures/java/infra/remoting/test/PerfTest.java index c1edf50..8942577 100644 --- a/today-remoting/src/testFixtures/java/infra/remoting/test/PerfTest.java +++ b/today-remoting/src/testFixtures/java/infra/remoting/test/PerfTest.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.test; diff --git a/today-remoting/src/testFixtures/java/infra/remoting/test/PingClient.java b/today-remoting/src/testFixtures/java/infra/remoting/test/PingClient.java index 7c4abc6..c65ec60 100644 --- a/today-remoting/src/testFixtures/java/infra/remoting/test/PingClient.java +++ b/today-remoting/src/testFixtures/java/infra/remoting/test/PingClient.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.test; diff --git a/today-remoting/src/testFixtures/java/infra/remoting/test/PingHandler.java b/today-remoting/src/testFixtures/java/infra/remoting/test/PingHandler.java index 3e584dc..e2c3436 100644 --- a/today-remoting/src/testFixtures/java/infra/remoting/test/PingHandler.java +++ b/today-remoting/src/testFixtures/java/infra/remoting/test/PingHandler.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.test; diff --git a/today-remoting/src/testFixtures/java/infra/remoting/test/SlowTest.java b/today-remoting/src/testFixtures/java/infra/remoting/test/SlowTest.java index c0040d5..5ffd1bf 100644 --- a/today-remoting/src/testFixtures/java/infra/remoting/test/SlowTest.java +++ b/today-remoting/src/testFixtures/java/infra/remoting/test/SlowTest.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.test; diff --git a/today-remoting/src/testFixtures/java/infra/remoting/test/TestChannel.java b/today-remoting/src/testFixtures/java/infra/remoting/test/TestChannel.java index 8160b25..875871f 100644 --- a/today-remoting/src/testFixtures/java/infra/remoting/test/TestChannel.java +++ b/today-remoting/src/testFixtures/java/infra/remoting/test/TestChannel.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.test; diff --git a/today-remoting/src/testFixtures/java/infra/remoting/test/TestConnection.java b/today-remoting/src/testFixtures/java/infra/remoting/test/TestConnection.java index de4def8..b240122 100644 --- a/today-remoting/src/testFixtures/java/infra/remoting/test/TestConnection.java +++ b/today-remoting/src/testFixtures/java/infra/remoting/test/TestConnection.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.test; diff --git a/today-remoting/src/testFixtures/java/infra/remoting/test/TestFrames.java b/today-remoting/src/testFixtures/java/infra/remoting/test/TestFrames.java index 4dbf700..da98e9b 100644 --- a/today-remoting/src/testFixtures/java/infra/remoting/test/TestFrames.java +++ b/today-remoting/src/testFixtures/java/infra/remoting/test/TestFrames.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.test; diff --git a/today-remoting/src/testFixtures/java/infra/remoting/test/TestSubscriber.java b/today-remoting/src/testFixtures/java/infra/remoting/test/TestSubscriber.java index 3ab3be1..336e6d2 100644 --- a/today-remoting/src/testFixtures/java/infra/remoting/test/TestSubscriber.java +++ b/today-remoting/src/testFixtures/java/infra/remoting/test/TestSubscriber.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.test; diff --git a/today-remoting/src/testFixtures/java/infra/remoting/test/TransportPair.java b/today-remoting/src/testFixtures/java/infra/remoting/test/TransportPair.java index 11baa1e..25541f5 100644 --- a/today-remoting/src/testFixtures/java/infra/remoting/test/TransportPair.java +++ b/today-remoting/src/testFixtures/java/infra/remoting/test/TransportPair.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.test; diff --git a/today-remoting/src/testFixtures/java/infra/remoting/test/TransportTest.java b/today-remoting/src/testFixtures/java/infra/remoting/test/TransportTest.java index 3cde207..04fbebd 100644 --- a/today-remoting/src/testFixtures/java/infra/remoting/test/TransportTest.java +++ b/today-remoting/src/testFixtures/java/infra/remoting/test/TransportTest.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.test; diff --git a/today-remoting/src/testFixtures/java/infra/remoting/test/TriFunction.java b/today-remoting/src/testFixtures/java/infra/remoting/test/TriFunction.java index bfee944..e2ddda7 100644 --- a/today-remoting/src/testFixtures/java/infra/remoting/test/TriFunction.java +++ b/today-remoting/src/testFixtures/java/infra/remoting/test/TriFunction.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.remoting.test; diff --git a/today-remoting/src/testFixtures/java/infra/remoting/test/package-info.java b/today-remoting/src/testFixtures/java/infra/remoting/test/package-info.java index c69a2e3..c19fc14 100644 --- a/today-remoting/src/testFixtures/java/infra/remoting/test/package-info.java +++ b/today-remoting/src/testFixtures/java/infra/remoting/test/package-info.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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. */ /** Utilities for testing components. */ diff --git a/today-service-api/build.gradle b/today-service-api/build.gradle index 0a791a3..62d881a 100644 --- a/today-service-api/build.gradle +++ b/today-service-api/build.gradle @@ -6,8 +6,8 @@ dependencies { api project(":today-cloud-core") api project(":today-service-serialization") - implementation 'cn.taketoday:today-beans' - implementation 'cn.taketoday:today-context' + implementation 'cn.taketoday:infra-beans' + implementation 'cn.taketoday:infra-context' optional "com.google.protobuf:protobuf-java" diff --git a/today-service-api/src/main/java/infra/cloud/RpcRequest.java b/today-service-api/src/main/java/infra/cloud/RpcRequest.java index d29921d..487bd89 100644 --- a/today-service-api/src/main/java/infra/cloud/RpcRequest.java +++ b/today-service-api/src/main/java/infra/cloud/RpcRequest.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2026 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud; diff --git a/today-service-api/src/main/java/infra/cloud/RpcResponse.java b/today-service-api/src/main/java/infra/cloud/RpcResponse.java index 4e58c14..61f1dda 100644 --- a/today-service-api/src/main/java/infra/cloud/RpcResponse.java +++ b/today-service-api/src/main/java/infra/cloud/RpcResponse.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud; diff --git a/today-service-api/src/main/java/infra/cloud/serialize/MessagePackReader.java b/today-service-api/src/main/java/infra/cloud/serialize/MessagePackReader.java index 20da6ec..c921667 100644 --- a/today-service-api/src/main/java/infra/cloud/serialize/MessagePackReader.java +++ b/today-service-api/src/main/java/infra/cloud/serialize/MessagePackReader.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2026 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.serialize; diff --git a/today-service-api/src/main/java/infra/cloud/serialize/MessagePackWriter.java b/today-service-api/src/main/java/infra/cloud/serialize/MessagePackWriter.java index 299308d..f6181e8 100644 --- a/today-service-api/src/main/java/infra/cloud/serialize/MessagePackWriter.java +++ b/today-service-api/src/main/java/infra/cloud/serialize/MessagePackWriter.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2026 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.serialize; diff --git a/today-service-api/src/main/java/infra/cloud/serialize/ProtobufArgumentSerialization.java b/today-service-api/src/main/java/infra/cloud/serialize/ProtobufArgumentSerialization.java index 9df78ad..daad002 100644 --- a/today-service-api/src/main/java/infra/cloud/serialize/ProtobufArgumentSerialization.java +++ b/today-service-api/src/main/java/infra/cloud/serialize/ProtobufArgumentSerialization.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2026 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.serialize; diff --git a/today-service-api/src/main/java/infra/cloud/serialize/ReturnValueDeserializer.java b/today-service-api/src/main/java/infra/cloud/serialize/ReturnValueDeserializer.java index 2e44386..14b0713 100644 --- a/today-service-api/src/main/java/infra/cloud/serialize/ReturnValueDeserializer.java +++ b/today-service-api/src/main/java/infra/cloud/serialize/ReturnValueDeserializer.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2026 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.serialize; diff --git a/today-service-api/src/main/java/infra/cloud/serialize/ReturnValueSerialization.java b/today-service-api/src/main/java/infra/cloud/serialize/ReturnValueSerialization.java index aae43ac..204ab77 100644 --- a/today-service-api/src/main/java/infra/cloud/serialize/ReturnValueSerialization.java +++ b/today-service-api/src/main/java/infra/cloud/serialize/ReturnValueSerialization.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.serialize; diff --git a/today-service-api/src/main/java/infra/cloud/serialize/ReturnValueSerializer.java b/today-service-api/src/main/java/infra/cloud/serialize/ReturnValueSerializer.java index 6192b0c..84bd4cb 100644 --- a/today-service-api/src/main/java/infra/cloud/serialize/ReturnValueSerializer.java +++ b/today-service-api/src/main/java/infra/cloud/serialize/ReturnValueSerializer.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2026 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.serialize; diff --git a/today-service-api/src/main/java/infra/cloud/serialize/RpcArgumentSerialization.java b/today-service-api/src/main/java/infra/cloud/serialize/RpcArgumentSerialization.java index 0378556..8b5cd77 100644 --- a/today-service-api/src/main/java/infra/cloud/serialize/RpcArgumentSerialization.java +++ b/today-service-api/src/main/java/infra/cloud/serialize/RpcArgumentSerialization.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2026 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.serialize; diff --git a/today-service-api/src/main/java/infra/cloud/serialize/SimpleValueArgumentSerialization.java b/today-service-api/src/main/java/infra/cloud/serialize/SimpleValueArgumentSerialization.java index 1c150b0..2b3df42 100644 --- a/today-service-api/src/main/java/infra/cloud/serialize/SimpleValueArgumentSerialization.java +++ b/today-service-api/src/main/java/infra/cloud/serialize/SimpleValueArgumentSerialization.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2026 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.serialize; diff --git a/today-service-api/src/main/java/infra/cloud/serialize/ThrowableSerialization.java b/today-service-api/src/main/java/infra/cloud/serialize/ThrowableSerialization.java index 5bf0e81..a8eabd0 100644 --- a/today-service-api/src/main/java/infra/cloud/serialize/ThrowableSerialization.java +++ b/today-service-api/src/main/java/infra/cloud/serialize/ThrowableSerialization.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.serialize; diff --git a/today-service-api/src/main/java/infra/cloud/serialize/package-info.java b/today-service-api/src/main/java/infra/cloud/serialize/package-info.java index 17b26a5..5b28edc 100644 --- a/today-service-api/src/main/java/infra/cloud/serialize/package-info.java +++ b/today-service-api/src/main/java/infra/cloud/serialize/package-info.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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. */ /** diff --git a/today-service-api/src/main/java/infra/cloud/serialize/value/FuncValueSerialization.java b/today-service-api/src/main/java/infra/cloud/serialize/value/FuncValueSerialization.java index cc4b847..ab2c1f2 100644 --- a/today-service-api/src/main/java/infra/cloud/serialize/value/FuncValueSerialization.java +++ b/today-service-api/src/main/java/infra/cloud/serialize/value/FuncValueSerialization.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2026 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.serialize.value; diff --git a/today-service-api/src/main/java/infra/cloud/serialize/value/ValueSerialization.java b/today-service-api/src/main/java/infra/cloud/serialize/value/ValueSerialization.java index 055bb29..1bc3f3f 100644 --- a/today-service-api/src/main/java/infra/cloud/serialize/value/ValueSerialization.java +++ b/today-service-api/src/main/java/infra/cloud/serialize/value/ValueSerialization.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2026 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.serialize.value; diff --git a/today-service-api/src/main/java/infra/cloud/service/AbstractServiceInterfaceMetadataProvider.java b/today-service-api/src/main/java/infra/cloud/service/AbstractServiceInterfaceMetadataProvider.java index 5e5a20a..9aa86d5 100644 --- a/today-service-api/src/main/java/infra/cloud/service/AbstractServiceInterfaceMetadataProvider.java +++ b/today-service-api/src/main/java/infra/cloud/service/AbstractServiceInterfaceMetadataProvider.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.service; diff --git a/today-service-api/src/main/java/infra/cloud/service/InvocationResult.java b/today-service-api/src/main/java/infra/cloud/service/InvocationResult.java index 1a3649f..1f71bb5 100644 --- a/today-service-api/src/main/java/infra/cloud/service/InvocationResult.java +++ b/today-service-api/src/main/java/infra/cloud/service/InvocationResult.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.service; diff --git a/today-service-api/src/main/java/infra/cloud/service/InvocationType.java b/today-service-api/src/main/java/infra/cloud/service/InvocationType.java index 0adead5..8fba7b6 100644 --- a/today-service-api/src/main/java/infra/cloud/service/InvocationType.java +++ b/today-service-api/src/main/java/infra/cloud/service/InvocationType.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.service; diff --git a/today-service-api/src/main/java/infra/cloud/service/Metadata.java b/today-service-api/src/main/java/infra/cloud/service/Metadata.java index ac1f436..f2362ad 100644 --- a/today-service-api/src/main/java/infra/cloud/service/Metadata.java +++ b/today-service-api/src/main/java/infra/cloud/service/Metadata.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.service; diff --git a/today-service-api/src/main/java/infra/cloud/service/MethodIdGenerator.java b/today-service-api/src/main/java/infra/cloud/service/MethodIdGenerator.java index 974e926..cfcaf6e 100644 --- a/today-service-api/src/main/java/infra/cloud/service/MethodIdGenerator.java +++ b/today-service-api/src/main/java/infra/cloud/service/MethodIdGenerator.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.service; diff --git a/today-service-api/src/main/java/infra/cloud/service/PackageInfoServiceMetadataProvider.java b/today-service-api/src/main/java/infra/cloud/service/PackageInfoServiceMetadataProvider.java index 8d9d23a..78642b2 100644 --- a/today-service-api/src/main/java/infra/cloud/service/PackageInfoServiceMetadataProvider.java +++ b/today-service-api/src/main/java/infra/cloud/service/PackageInfoServiceMetadataProvider.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.service; diff --git a/today-service-api/src/main/java/infra/cloud/service/ServiceInterfaceMetadata.java b/today-service-api/src/main/java/infra/cloud/service/ServiceInterfaceMetadata.java index bb2ee7d..4763628 100644 --- a/today-service-api/src/main/java/infra/cloud/service/ServiceInterfaceMetadata.java +++ b/today-service-api/src/main/java/infra/cloud/service/ServiceInterfaceMetadata.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.service; diff --git a/today-service-api/src/main/java/infra/cloud/service/ServiceInterfaceMetadataProvider.java b/today-service-api/src/main/java/infra/cloud/service/ServiceInterfaceMetadataProvider.java index d122129..d96330a 100644 --- a/today-service-api/src/main/java/infra/cloud/service/ServiceInterfaceMetadataProvider.java +++ b/today-service-api/src/main/java/infra/cloud/service/ServiceInterfaceMetadataProvider.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.service; diff --git a/today-service-api/src/main/java/infra/cloud/service/ServiceMetadata.java b/today-service-api/src/main/java/infra/cloud/service/ServiceMetadata.java index 8be5af1..ba9e7cb 100644 --- a/today-service-api/src/main/java/infra/cloud/service/ServiceMetadata.java +++ b/today-service-api/src/main/java/infra/cloud/service/ServiceMetadata.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.service; diff --git a/today-service-api/src/main/java/infra/cloud/service/ServiceMetadataProvider.java b/today-service-api/src/main/java/infra/cloud/service/ServiceMetadataProvider.java index 65db170..e974c71 100644 --- a/today-service-api/src/main/java/infra/cloud/service/ServiceMetadataProvider.java +++ b/today-service-api/src/main/java/infra/cloud/service/ServiceMetadataProvider.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.service; diff --git a/today-service-api/src/main/java/infra/cloud/service/ServiceMethod.java b/today-service-api/src/main/java/infra/cloud/service/ServiceMethod.java index 82aef4a..6ba4227 100644 --- a/today-service-api/src/main/java/infra/cloud/service/ServiceMethod.java +++ b/today-service-api/src/main/java/infra/cloud/service/ServiceMethod.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.service; diff --git a/today-service-api/src/main/java/infra/cloud/service/config/ResumeProperties.java b/today-service-api/src/main/java/infra/cloud/service/config/ResumeProperties.java index 4270618..6b32701 100644 --- a/today-service-api/src/main/java/infra/cloud/service/config/ResumeProperties.java +++ b/today-service-api/src/main/java/infra/cloud/service/config/ResumeProperties.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.service.config; diff --git a/today-service-api/src/main/java/infra/cloud/service/package-info.java b/today-service-api/src/main/java/infra/cloud/service/package-info.java index 4fd4b46..22ef3b6 100644 --- a/today-service-api/src/main/java/infra/cloud/service/package-info.java +++ b/today-service-api/src/main/java/infra/cloud/service/package-info.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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. */ @NullMarked diff --git a/today-service-api/src/test/java/infra/cloud/service/MethodIdGeneratorTests.java b/today-service-api/src/test/java/infra/cloud/service/MethodIdGeneratorTests.java index aee4cab..cffb62f 100644 --- a/today-service-api/src/test/java/infra/cloud/service/MethodIdGeneratorTests.java +++ b/today-service-api/src/test/java/infra/cloud/service/MethodIdGeneratorTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.service; diff --git a/today-service-client/src/main/java/infra/cloud/ServiceTimeoutException.java b/today-service-client/src/main/java/infra/cloud/ServiceTimeoutException.java index b740ef6..17aed48 100644 --- a/today-service-client/src/main/java/infra/cloud/ServiceTimeoutException.java +++ b/today-service-client/src/main/java/infra/cloud/ServiceTimeoutException.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud; diff --git a/today-service-client/src/main/java/infra/cloud/client/annotation/ServiceDependencyResolvingStrategy.java b/today-service-client/src/main/java/infra/cloud/client/annotation/ServiceDependencyResolvingStrategy.java index bd20fc2..bd2ce40 100644 --- a/today-service-client/src/main/java/infra/cloud/client/annotation/ServiceDependencyResolvingStrategy.java +++ b/today-service-client/src/main/java/infra/cloud/client/annotation/ServiceDependencyResolvingStrategy.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.client.annotation; diff --git a/today-service-client/src/main/java/infra/cloud/client/annotation/ServiceReference.java b/today-service-client/src/main/java/infra/cloud/client/annotation/ServiceReference.java index eac080e..232d22b 100644 --- a/today-service-client/src/main/java/infra/cloud/client/annotation/ServiceReference.java +++ b/today-service-client/src/main/java/infra/cloud/client/annotation/ServiceReference.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.client.annotation; diff --git a/today-service-client/src/main/java/infra/cloud/client/annotation/config/ServiceClientAutoConfiguration.java b/today-service-client/src/main/java/infra/cloud/client/annotation/config/ServiceClientAutoConfiguration.java index e603913..10ccb64 100644 --- a/today-service-client/src/main/java/infra/cloud/client/annotation/config/ServiceClientAutoConfiguration.java +++ b/today-service-client/src/main/java/infra/cloud/client/annotation/config/ServiceClientAutoConfiguration.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.client.annotation.config; diff --git a/today-service-client/src/main/java/infra/cloud/service/AbstractInvocationResult.java b/today-service-client/src/main/java/infra/cloud/service/AbstractInvocationResult.java index 7092f17..dc9ee25 100644 --- a/today-service-client/src/main/java/infra/cloud/service/AbstractInvocationResult.java +++ b/today-service-client/src/main/java/infra/cloud/service/AbstractInvocationResult.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.service; diff --git a/today-service-client/src/main/java/infra/cloud/service/ClientInterceptor.java b/today-service-client/src/main/java/infra/cloud/service/ClientInterceptor.java index 61b16ef..d2d1556 100644 --- a/today-service-client/src/main/java/infra/cloud/service/ClientInterceptor.java +++ b/today-service-client/src/main/java/infra/cloud/service/ClientInterceptor.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.service; diff --git a/today-service-client/src/main/java/infra/cloud/service/DefaultRemotingOperationsProvider.java b/today-service-client/src/main/java/infra/cloud/service/DefaultRemotingOperationsProvider.java index cf47df6..0d025c5 100644 --- a/today-service-client/src/main/java/infra/cloud/service/DefaultRemotingOperationsProvider.java +++ b/today-service-client/src/main/java/infra/cloud/service/DefaultRemotingOperationsProvider.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.service; diff --git a/today-service-client/src/main/java/infra/cloud/service/DefaultServiceInterfaceMetadataProvider.java b/today-service-client/src/main/java/infra/cloud/service/DefaultServiceInterfaceMetadataProvider.java index 2ea27f5..91c6625 100644 --- a/today-service-client/src/main/java/infra/cloud/service/DefaultServiceInterfaceMetadataProvider.java +++ b/today-service-client/src/main/java/infra/cloud/service/DefaultServiceInterfaceMetadataProvider.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.service; diff --git a/today-service-client/src/main/java/infra/cloud/service/DefaultServiceProxyFactory.java b/today-service-client/src/main/java/infra/cloud/service/DefaultServiceProxyFactory.java index d9d2bb2..aba24b0 100644 --- a/today-service-client/src/main/java/infra/cloud/service/DefaultServiceProxyFactory.java +++ b/today-service-client/src/main/java/infra/cloud/service/DefaultServiceProxyFactory.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.service; diff --git a/today-service-client/src/main/java/infra/cloud/service/DuplexStreamingResult.java b/today-service-client/src/main/java/infra/cloud/service/DuplexStreamingResult.java index c1cfae4..5d550a0 100644 --- a/today-service-client/src/main/java/infra/cloud/service/DuplexStreamingResult.java +++ b/today-service-client/src/main/java/infra/cloud/service/DuplexStreamingResult.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.service; diff --git a/today-service-client/src/main/java/infra/cloud/service/FireAndForgetResult.java b/today-service-client/src/main/java/infra/cloud/service/FireAndForgetResult.java index 662103d..dcd02e4 100644 --- a/today-service-client/src/main/java/infra/cloud/service/FireAndForgetResult.java +++ b/today-service-client/src/main/java/infra/cloud/service/FireAndForgetResult.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.service; diff --git a/today-service-client/src/main/java/infra/cloud/service/MethodServiceInvocation.java b/today-service-client/src/main/java/infra/cloud/service/MethodServiceInvocation.java index efadfdf..101c74b 100644 --- a/today-service-client/src/main/java/infra/cloud/service/MethodServiceInvocation.java +++ b/today-service-client/src/main/java/infra/cloud/service/MethodServiceInvocation.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.service; diff --git a/today-service-client/src/main/java/infra/cloud/service/RemotingOperationsProvider.java b/today-service-client/src/main/java/infra/cloud/service/RemotingOperationsProvider.java index 330362d..f159278 100644 --- a/today-service-client/src/main/java/infra/cloud/service/RemotingOperationsProvider.java +++ b/today-service-client/src/main/java/infra/cloud/service/RemotingOperationsProvider.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.service; diff --git a/today-service-client/src/main/java/infra/cloud/service/RequestResponseResult.java b/today-service-client/src/main/java/infra/cloud/service/RequestResponseResult.java index c634c73..d44b76e 100644 --- a/today-service-client/src/main/java/infra/cloud/service/RequestResponseResult.java +++ b/today-service-client/src/main/java/infra/cloud/service/RequestResponseResult.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.service; diff --git a/today-service-client/src/main/java/infra/cloud/service/ResponseStreamingResult.java b/today-service-client/src/main/java/infra/cloud/service/ResponseStreamingResult.java index 4c22f99..be02e73 100644 --- a/today-service-client/src/main/java/infra/cloud/service/ResponseStreamingResult.java +++ b/today-service-client/src/main/java/infra/cloud/service/ResponseStreamingResult.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.service; diff --git a/today-service-client/src/main/java/infra/cloud/service/ReturnValueResolver.java b/today-service-client/src/main/java/infra/cloud/service/ReturnValueResolver.java index 94eed9a..a8b6b55 100644 --- a/today-service-client/src/main/java/infra/cloud/service/ReturnValueResolver.java +++ b/today-service-client/src/main/java/infra/cloud/service/ReturnValueResolver.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.service; diff --git a/today-service-client/src/main/java/infra/cloud/service/ServiceInterfaceMethod.java b/today-service-client/src/main/java/infra/cloud/service/ServiceInterfaceMethod.java index a6f6cac..03012d2 100644 --- a/today-service-client/src/main/java/infra/cloud/service/ServiceInterfaceMethod.java +++ b/today-service-client/src/main/java/infra/cloud/service/ServiceInterfaceMethod.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.service; diff --git a/today-service-client/src/main/java/infra/cloud/service/ServiceInvocation.java b/today-service-client/src/main/java/infra/cloud/service/ServiceInvocation.java index 93b14ea..91dcc2c 100644 --- a/today-service-client/src/main/java/infra/cloud/service/ServiceInvocation.java +++ b/today-service-client/src/main/java/infra/cloud/service/ServiceInvocation.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.service; diff --git a/today-service-client/src/main/java/infra/cloud/service/ServiceInvoker.java b/today-service-client/src/main/java/infra/cloud/service/ServiceInvoker.java index 457a865..b6cbd3d 100644 --- a/today-service-client/src/main/java/infra/cloud/service/ServiceInvoker.java +++ b/today-service-client/src/main/java/infra/cloud/service/ServiceInvoker.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.service; diff --git a/today-service-client/src/main/java/infra/cloud/service/ServiceMethodInvoker.java b/today-service-client/src/main/java/infra/cloud/service/ServiceMethodInvoker.java index 68e21b0..abbe50a 100644 --- a/today-service-client/src/main/java/infra/cloud/service/ServiceMethodInvoker.java +++ b/today-service-client/src/main/java/infra/cloud/service/ServiceMethodInvoker.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.service; diff --git a/today-service-client/src/main/java/infra/cloud/service/ServiceProvider.java b/today-service-client/src/main/java/infra/cloud/service/ServiceProvider.java index 6542cb0..42e6055 100644 --- a/today-service-client/src/main/java/infra/cloud/service/ServiceProvider.java +++ b/today-service-client/src/main/java/infra/cloud/service/ServiceProvider.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.service; diff --git a/today-service-client/src/main/java/infra/cloud/service/ServiceProxyFactory.java b/today-service-client/src/main/java/infra/cloud/service/ServiceProxyFactory.java index 0e48838..ae260f3 100644 --- a/today-service-client/src/main/java/infra/cloud/service/ServiceProxyFactory.java +++ b/today-service-client/src/main/java/infra/cloud/service/ServiceProxyFactory.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.service; diff --git a/today-service-client/src/main/java/infra/cloud/service/serialize/RequestSerializer.java b/today-service-client/src/main/java/infra/cloud/service/serialize/RequestSerializer.java index f0200b7..bc726c1 100644 --- a/today-service-client/src/main/java/infra/cloud/service/serialize/RequestSerializer.java +++ b/today-service-client/src/main/java/infra/cloud/service/serialize/RequestSerializer.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2026 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.service.serialize; diff --git a/today-service-client/src/main/java/infra/cloud/service/serialize/ResponseDeserializer.java b/today-service-client/src/main/java/infra/cloud/service/serialize/ResponseDeserializer.java index ba39f36..4837ec2 100644 --- a/today-service-client/src/main/java/infra/cloud/service/serialize/ResponseDeserializer.java +++ b/today-service-client/src/main/java/infra/cloud/service/serialize/ResponseDeserializer.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2026 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.service.serialize; diff --git a/today-service-client/src/main/resources/META-INF/today.strategies b/today-service-client/src/main/resources/META-INF/today.strategies index 43e4be3..1aef7d7 100644 --- a/today-service-client/src/main/resources/META-INF/today.strategies +++ b/today-service-client/src/main/resources/META-INF/today.strategies @@ -1,19 +1,3 @@ -# -# Copyright 2021 - 2024 the original author or authors. -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see [http://www.gnu.org/licenses/] -# infra.beans.factory.support.DependencyResolvingStrategy=\ infra.cloud.client.annotation.ServiceDependencyResolvingStrategy diff --git a/today-service-client/src/test/java/infra/cloud/client/annotation/config/ServiceClientAutoConfigurationTests.java b/today-service-client/src/test/java/infra/cloud/client/annotation/config/ServiceClientAutoConfigurationTests.java index e73d5dc..adf2faf 100644 --- a/today-service-client/src/test/java/infra/cloud/client/annotation/config/ServiceClientAutoConfigurationTests.java +++ b/today-service-client/src/test/java/infra/cloud/client/annotation/config/ServiceClientAutoConfigurationTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.client.annotation.config; diff --git a/today-service-client/src/test/java/infra/cloud/service/DefaultServiceInterfaceMetadataProviderTests.java b/today-service-client/src/test/java/infra/cloud/service/DefaultServiceInterfaceMetadataProviderTests.java index 2164968..2e84707 100644 --- a/today-service-client/src/test/java/infra/cloud/service/DefaultServiceInterfaceMetadataProviderTests.java +++ b/today-service-client/src/test/java/infra/cloud/service/DefaultServiceInterfaceMetadataProviderTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.service; diff --git a/today-service-client/src/test/java/infra/cloud/service/ServiceInvokerFactoryTests.java b/today-service-client/src/test/java/infra/cloud/service/ServiceInvokerFactoryTests.java index 2b96802..0c31a7e 100644 --- a/today-service-client/src/test/java/infra/cloud/service/ServiceInvokerFactoryTests.java +++ b/today-service-client/src/test/java/infra/cloud/service/ServiceInvokerFactoryTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.service; diff --git a/today-service-client/src/test/java/infra/cloud/service/TracingInterceptor.java b/today-service-client/src/test/java/infra/cloud/service/TracingInterceptor.java index d33222d..0c3fb49 100644 --- a/today-service-client/src/test/java/infra/cloud/service/TracingInterceptor.java +++ b/today-service-client/src/test/java/infra/cloud/service/TracingInterceptor.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.service; diff --git a/today-service-discovery/build.gradle b/today-service-discovery/build.gradle index afa2a2c..0c0fd7f 100644 --- a/today-service-discovery/build.gradle +++ b/today-service-discovery/build.gradle @@ -3,8 +3,8 @@ description = "TODAY Service discovery client" dependencies { api project(":today-cloud-core") - implementation 'cn.taketoday:today-beans' - implementation 'cn.taketoday:today-context' + implementation 'cn.taketoday:infra-beans' + implementation 'cn.taketoday:infra-context' testImplementation project(":today-cloud-samples:demo-tests:demo-user-api") diff --git a/today-service-discovery/src/main/java/infra/cloud/client/CompositeDiscoveryClient.java b/today-service-discovery/src/main/java/infra/cloud/client/CompositeDiscoveryClient.java index 8be803b..0119855 100644 --- a/today-service-discovery/src/main/java/infra/cloud/client/CompositeDiscoveryClient.java +++ b/today-service-discovery/src/main/java/infra/cloud/client/CompositeDiscoveryClient.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.client; diff --git a/today-service-discovery/src/main/java/infra/cloud/client/DiscoveryClient.java b/today-service-discovery/src/main/java/infra/cloud/client/DiscoveryClient.java index 15336a0..908cc5a 100644 --- a/today-service-discovery/src/main/java/infra/cloud/client/DiscoveryClient.java +++ b/today-service-discovery/src/main/java/infra/cloud/client/DiscoveryClient.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.client; diff --git a/today-service-discovery/src/main/java/infra/cloud/client/config/DiscoveryClientAutoConfiguration.java b/today-service-discovery/src/main/java/infra/cloud/client/config/DiscoveryClientAutoConfiguration.java index 9aaf3e3..aa7ed2e 100644 --- a/today-service-discovery/src/main/java/infra/cloud/client/config/DiscoveryClientAutoConfiguration.java +++ b/today-service-discovery/src/main/java/infra/cloud/client/config/DiscoveryClientAutoConfiguration.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.client.config; diff --git a/today-service-discovery/src/main/java/infra/cloud/client/simple/SimpleDiscoveryClient.java b/today-service-discovery/src/main/java/infra/cloud/client/simple/SimpleDiscoveryClient.java index 48c4b3c..d70a6fb 100644 --- a/today-service-discovery/src/main/java/infra/cloud/client/simple/SimpleDiscoveryClient.java +++ b/today-service-discovery/src/main/java/infra/cloud/client/simple/SimpleDiscoveryClient.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.client.simple; diff --git a/today-service-discovery/src/main/java/infra/cloud/client/simple/SimpleDiscoveryProperties.java b/today-service-discovery/src/main/java/infra/cloud/client/simple/SimpleDiscoveryProperties.java index 4afd661..8727b3a 100644 --- a/today-service-discovery/src/main/java/infra/cloud/client/simple/SimpleDiscoveryProperties.java +++ b/today-service-discovery/src/main/java/infra/cloud/client/simple/SimpleDiscoveryProperties.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.client.simple; diff --git a/today-service-discovery/src/test/java/infra/cloud/client/CompositeDiscoveryClientAutoConfigurationTests.java b/today-service-discovery/src/test/java/infra/cloud/client/CompositeDiscoveryClientAutoConfigurationTests.java index dfb5faa..1ef5a88 100644 --- a/today-service-discovery/src/test/java/infra/cloud/client/CompositeDiscoveryClientAutoConfigurationTests.java +++ b/today-service-discovery/src/test/java/infra/cloud/client/CompositeDiscoveryClientAutoConfigurationTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.client; diff --git a/today-service-discovery/src/test/java/infra/cloud/client/CompositeDiscoveryClientOrderTest.java b/today-service-discovery/src/test/java/infra/cloud/client/CompositeDiscoveryClientOrderTest.java index c5709be..59fa14c 100644 --- a/today-service-discovery/src/test/java/infra/cloud/client/CompositeDiscoveryClientOrderTest.java +++ b/today-service-discovery/src/test/java/infra/cloud/client/CompositeDiscoveryClientOrderTest.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.client; diff --git a/today-service-discovery/src/test/java/infra/cloud/client/CompositeDiscoveryClientTests.java b/today-service-discovery/src/test/java/infra/cloud/client/CompositeDiscoveryClientTests.java index 1b140ce..a0e1dd9 100644 --- a/today-service-discovery/src/test/java/infra/cloud/client/CompositeDiscoveryClientTests.java +++ b/today-service-discovery/src/test/java/infra/cloud/client/CompositeDiscoveryClientTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.client; diff --git a/today-service-discovery/src/test/java/infra/cloud/client/CompositeDiscoveryClientTestsConfig.java b/today-service-discovery/src/test/java/infra/cloud/client/CompositeDiscoveryClientTestsConfig.java index 5053004..572244a 100644 --- a/today-service-discovery/src/test/java/infra/cloud/client/CompositeDiscoveryClientTestsConfig.java +++ b/today-service-discovery/src/test/java/infra/cloud/client/CompositeDiscoveryClientTestsConfig.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.client; diff --git a/today-service-discovery/src/test/java/infra/cloud/client/CompositeDiscoveryClientUnitTests.java b/today-service-discovery/src/test/java/infra/cloud/client/CompositeDiscoveryClientUnitTests.java index 81166c4..1e1d376 100644 --- a/today-service-discovery/src/test/java/infra/cloud/client/CompositeDiscoveryClientUnitTests.java +++ b/today-service-discovery/src/test/java/infra/cloud/client/CompositeDiscoveryClientUnitTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.client; diff --git a/today-service-discovery/src/test/java/infra/cloud/client/DiscoveryClientAutoConfigurationDefaultTests.java b/today-service-discovery/src/test/java/infra/cloud/client/DiscoveryClientAutoConfigurationDefaultTests.java index 54bf0b0..b202dfd 100644 --- a/today-service-discovery/src/test/java/infra/cloud/client/DiscoveryClientAutoConfigurationDefaultTests.java +++ b/today-service-discovery/src/test/java/infra/cloud/client/DiscoveryClientAutoConfigurationDefaultTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.client; diff --git a/today-service-discovery/src/test/java/infra/cloud/client/SimpleDiscoveryClientPropertiesMappingTests.java b/today-service-discovery/src/test/java/infra/cloud/client/SimpleDiscoveryClientPropertiesMappingTests.java index cbc9c82..f145c3f 100644 --- a/today-service-discovery/src/test/java/infra/cloud/client/SimpleDiscoveryClientPropertiesMappingTests.java +++ b/today-service-discovery/src/test/java/infra/cloud/client/SimpleDiscoveryClientPropertiesMappingTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.client; diff --git a/today-service-discovery/src/test/java/infra/cloud/client/SimpleDiscoveryClientTests.java b/today-service-discovery/src/test/java/infra/cloud/client/SimpleDiscoveryClientTests.java index 0fb5bce..cdcef57 100644 --- a/today-service-discovery/src/test/java/infra/cloud/client/SimpleDiscoveryClientTests.java +++ b/today-service-discovery/src/test/java/infra/cloud/client/SimpleDiscoveryClientTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.client; diff --git a/today-service-provider/src/main/java/infra/cloud/provider/DefaultServiceInterfaceMetadataProvider.java b/today-service-provider/src/main/java/infra/cloud/provider/DefaultServiceInterfaceMetadataProvider.java index 97c60f3..3eb5c1e 100644 --- a/today-service-provider/src/main/java/infra/cloud/provider/DefaultServiceInterfaceMetadataProvider.java +++ b/today-service-provider/src/main/java/infra/cloud/provider/DefaultServiceInterfaceMetadataProvider.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.provider; diff --git a/today-service-provider/src/main/java/infra/cloud/provider/InvocableMethod.java b/today-service-provider/src/main/java/infra/cloud/provider/InvocableMethod.java index 7ad4c37..bc0414c 100644 --- a/today-service-provider/src/main/java/infra/cloud/provider/InvocableMethod.java +++ b/today-service-provider/src/main/java/infra/cloud/provider/InvocableMethod.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.provider; diff --git a/today-service-provider/src/main/java/infra/cloud/provider/LocalServiceHolder.java b/today-service-provider/src/main/java/infra/cloud/provider/LocalServiceHolder.java index c4c27cb..64140c9 100644 --- a/today-service-provider/src/main/java/infra/cloud/provider/LocalServiceHolder.java +++ b/today-service-provider/src/main/java/infra/cloud/provider/LocalServiceHolder.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.provider; diff --git a/today-service-provider/src/main/java/infra/cloud/provider/RemoteRequest.java b/today-service-provider/src/main/java/infra/cloud/provider/RemoteRequest.java index 6dda81f..e308282 100644 --- a/today-service-provider/src/main/java/infra/cloud/provider/RemoteRequest.java +++ b/today-service-provider/src/main/java/infra/cloud/provider/RemoteRequest.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.provider; diff --git a/today-service-provider/src/main/java/infra/cloud/provider/ResponseSerializer.java b/today-service-provider/src/main/java/infra/cloud/provider/ResponseSerializer.java index 5bc680b..7618ab9 100644 --- a/today-service-provider/src/main/java/infra/cloud/provider/ResponseSerializer.java +++ b/today-service-provider/src/main/java/infra/cloud/provider/ResponseSerializer.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2026 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.provider; diff --git a/today-service-provider/src/main/java/infra/cloud/provider/RpcRequestDeserializer.java b/today-service-provider/src/main/java/infra/cloud/provider/RpcRequestDeserializer.java index c68294b..94a591c 100644 --- a/today-service-provider/src/main/java/infra/cloud/provider/RpcRequestDeserializer.java +++ b/today-service-provider/src/main/java/infra/cloud/provider/RpcRequestDeserializer.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2026 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.provider; diff --git a/today-service-provider/src/main/java/infra/cloud/provider/ServerTransportFactory.java b/today-service-provider/src/main/java/infra/cloud/provider/ServerTransportFactory.java index 4364a45..44117e0 100644 --- a/today-service-provider/src/main/java/infra/cloud/provider/ServerTransportFactory.java +++ b/today-service-provider/src/main/java/infra/cloud/provider/ServerTransportFactory.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.provider; diff --git a/today-service-provider/src/main/java/infra/cloud/provider/ServiceChannelHandler.java b/today-service-provider/src/main/java/infra/cloud/provider/ServiceChannelHandler.java index d84b24d..739f748 100644 --- a/today-service-provider/src/main/java/infra/cloud/provider/ServiceChannelHandler.java +++ b/today-service-provider/src/main/java/infra/cloud/provider/ServiceChannelHandler.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.provider; diff --git a/today-service-provider/src/main/java/infra/cloud/provider/ServiceObject.java b/today-service-provider/src/main/java/infra/cloud/provider/ServiceObject.java index b25e93f..26c9beb 100644 --- a/today-service-provider/src/main/java/infra/cloud/provider/ServiceObject.java +++ b/today-service-provider/src/main/java/infra/cloud/provider/ServiceObject.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.provider; diff --git a/today-service-provider/src/main/java/infra/cloud/provider/ServiceProviderServer.java b/today-service-provider/src/main/java/infra/cloud/provider/ServiceProviderServer.java index 60e5586..0ef539c 100644 --- a/today-service-provider/src/main/java/infra/cloud/provider/ServiceProviderServer.java +++ b/today-service-provider/src/main/java/infra/cloud/provider/ServiceProviderServer.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.provider; diff --git a/today-service-provider/src/main/java/infra/cloud/provider/ServiceServerProperties.java b/today-service-provider/src/main/java/infra/cloud/provider/ServiceServerProperties.java index 00a634b..025a41c 100644 --- a/today-service-provider/src/main/java/infra/cloud/provider/ServiceServerProperties.java +++ b/today-service-provider/src/main/java/infra/cloud/provider/ServiceServerProperties.java @@ -1,26 +1,19 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.provider; - -import org.jspecify.annotations.Nullable; - -import java.time.Duration; - import infra.cloud.service.config.ResumeProperties; import infra.context.properties.ConfigurationProperties; import infra.context.properties.NestedConfigurationProperty; diff --git a/today-service-provider/src/main/java/infra/cloud/provider/ServicesProvider.java b/today-service-provider/src/main/java/infra/cloud/provider/ServicesProvider.java index 5d145ec..45bc361 100644 --- a/today-service-provider/src/main/java/infra/cloud/provider/ServicesProvider.java +++ b/today-service-provider/src/main/java/infra/cloud/provider/ServicesProvider.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.provider; diff --git a/today-service-provider/src/main/java/infra/cloud/provider/TcpServerTransportFactory.java b/today-service-provider/src/main/java/infra/cloud/provider/TcpServerTransportFactory.java index 95e6ac9..bf42c7c 100644 --- a/today-service-provider/src/main/java/infra/cloud/provider/TcpServerTransportFactory.java +++ b/today-service-provider/src/main/java/infra/cloud/provider/TcpServerTransportFactory.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.provider; diff --git a/today-service-provider/src/main/java/infra/cloud/provider/annotation/config/ServiceProviderAutoConfiguration.java b/today-service-provider/src/main/java/infra/cloud/provider/annotation/config/ServiceProviderAutoConfiguration.java index 890be98..dec990d 100644 --- a/today-service-provider/src/main/java/infra/cloud/provider/annotation/config/ServiceProviderAutoConfiguration.java +++ b/today-service-provider/src/main/java/infra/cloud/provider/annotation/config/ServiceProviderAutoConfiguration.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.provider.annotation.config; diff --git a/today-service-provider/src/main/java/infra/cloud/provider/package-info.java b/today-service-provider/src/main/java/infra/cloud/provider/package-info.java index f17060e..dc2acfb 100644 --- a/today-service-provider/src/main/java/infra/cloud/provider/package-info.java +++ b/today-service-provider/src/main/java/infra/cloud/provider/package-info.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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. */ @NullMarked diff --git a/today-service-provider/src/test/java/infra/cloud/provider/LocalServiceHolderTests.java b/today-service-provider/src/test/java/infra/cloud/provider/LocalServiceHolderTests.java index efcd0a4..c95526b 100644 --- a/today-service-provider/src/test/java/infra/cloud/provider/LocalServiceHolderTests.java +++ b/today-service-provider/src/test/java/infra/cloud/provider/LocalServiceHolderTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.provider; diff --git a/today-service-registration/build.gradle b/today-service-registration/build.gradle index 130edc1..73f548d 100644 --- a/today-service-registration/build.gradle +++ b/today-service-registration/build.gradle @@ -4,8 +4,8 @@ dependencies { api project(":today-cloud-core") api project(":today-service-provider") - api 'cn.taketoday:today-core' - api 'cn.taketoday:today-context' + api 'cn.taketoday:infra-core' + api 'cn.taketoday:infra-context' annotationProcessor 'cn.taketoday:infra-configuration-processor' diff --git a/today-service-registration/src/main/java/infra/cloud/registry/AbstractAutoServiceRegistration.java b/today-service-registration/src/main/java/infra/cloud/registry/AbstractAutoServiceRegistration.java index d8b3e05..4109447 100644 --- a/today-service-registration/src/main/java/infra/cloud/registry/AbstractAutoServiceRegistration.java +++ b/today-service-registration/src/main/java/infra/cloud/registry/AbstractAutoServiceRegistration.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.registry; diff --git a/today-service-registration/src/main/java/infra/cloud/registry/AutoServiceRegistration.java b/today-service-registration/src/main/java/infra/cloud/registry/AutoServiceRegistration.java index 1eaf3c7..07d40d2 100644 --- a/today-service-registration/src/main/java/infra/cloud/registry/AutoServiceRegistration.java +++ b/today-service-registration/src/main/java/infra/cloud/registry/AutoServiceRegistration.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.registry; diff --git a/today-service-registration/src/main/java/infra/cloud/registry/AutoServiceRegistrationProperties.java b/today-service-registration/src/main/java/infra/cloud/registry/AutoServiceRegistrationProperties.java index ba63dc4..801d7b0 100644 --- a/today-service-registration/src/main/java/infra/cloud/registry/AutoServiceRegistrationProperties.java +++ b/today-service-registration/src/main/java/infra/cloud/registry/AutoServiceRegistrationProperties.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.registry; diff --git a/today-service-registration/src/main/java/infra/cloud/registry/RegistrationFactory.java b/today-service-registration/src/main/java/infra/cloud/registry/RegistrationFactory.java index 8462907..743f03d 100644 --- a/today-service-registration/src/main/java/infra/cloud/registry/RegistrationFactory.java +++ b/today-service-registration/src/main/java/infra/cloud/registry/RegistrationFactory.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.registry; diff --git a/today-service-registration/src/main/java/infra/cloud/registry/RegistrationLifecycle.java b/today-service-registration/src/main/java/infra/cloud/registry/RegistrationLifecycle.java index 82eacb7..1d813a7 100644 --- a/today-service-registration/src/main/java/infra/cloud/registry/RegistrationLifecycle.java +++ b/today-service-registration/src/main/java/infra/cloud/registry/RegistrationLifecycle.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.registry; diff --git a/today-service-registration/src/main/java/infra/cloud/registry/ServiceRegisterFailedException.java b/today-service-registration/src/main/java/infra/cloud/registry/ServiceRegisterFailedException.java index ad43fcc..b254676 100644 --- a/today-service-registration/src/main/java/infra/cloud/registry/ServiceRegisterFailedException.java +++ b/today-service-registration/src/main/java/infra/cloud/registry/ServiceRegisterFailedException.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.registry; diff --git a/today-service-registration/src/main/java/infra/cloud/registry/ServiceRegistry.java b/today-service-registration/src/main/java/infra/cloud/registry/ServiceRegistry.java index b916188..4f2e427 100644 --- a/today-service-registration/src/main/java/infra/cloud/registry/ServiceRegistry.java +++ b/today-service-registration/src/main/java/infra/cloud/registry/ServiceRegistry.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.registry; diff --git a/today-service-registration/src/main/java/infra/cloud/registry/annotation/config/AutoServiceRegistrationAutoConfiguration.java b/today-service-registration/src/main/java/infra/cloud/registry/annotation/config/AutoServiceRegistrationAutoConfiguration.java index 4e36cd6..798182b 100644 --- a/today-service-registration/src/main/java/infra/cloud/registry/annotation/config/AutoServiceRegistrationAutoConfiguration.java +++ b/today-service-registration/src/main/java/infra/cloud/registry/annotation/config/AutoServiceRegistrationAutoConfiguration.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.registry.annotation.config; diff --git a/today-service-registration/src/main/java/infra/cloud/registry/annotation/config/AutoServiceRegistrationConfiguration.java b/today-service-registration/src/main/java/infra/cloud/registry/annotation/config/AutoServiceRegistrationConfiguration.java index 8501c4a..aa41517 100644 --- a/today-service-registration/src/main/java/infra/cloud/registry/annotation/config/AutoServiceRegistrationConfiguration.java +++ b/today-service-registration/src/main/java/infra/cloud/registry/annotation/config/AutoServiceRegistrationConfiguration.java @@ -1,23 +1,18 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] - */ - -package infra.cloud.registry.annotation.config; - -import infra.cloud.registry.AutoServiceRegistrationProperties; + * 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. + */Properties; import infra.context.annotation.Configuration; import infra.context.condition.ConditionalOnProperty; import infra.context.properties.EnableConfigurationProperties; diff --git a/today-service-registration/src/main/java/infra/cloud/registry/event/InstancePreRegisteredEvent.java b/today-service-registration/src/main/java/infra/cloud/registry/event/InstancePreRegisteredEvent.java index 6bcf899..e41b367 100644 --- a/today-service-registration/src/main/java/infra/cloud/registry/event/InstancePreRegisteredEvent.java +++ b/today-service-registration/src/main/java/infra/cloud/registry/event/InstancePreRegisteredEvent.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.registry.event; diff --git a/today-service-registration/src/main/java/infra/cloud/registry/event/InstanceRegisteredEvent.java b/today-service-registration/src/main/java/infra/cloud/registry/event/InstanceRegisteredEvent.java index f6d4c3d..c59889a 100644 --- a/today-service-registration/src/main/java/infra/cloud/registry/event/InstanceRegisteredEvent.java +++ b/today-service-registration/src/main/java/infra/cloud/registry/event/InstanceRegisteredEvent.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.registry.event; diff --git a/today-service-registry-simple-api/build.gradle b/today-service-registry-simple-api/build.gradle index f75fa37..53ed243 100644 --- a/today-service-registry-simple-api/build.gradle +++ b/today-service-registry-simple-api/build.gradle @@ -3,7 +3,9 @@ description = "TODAY Service Simple Registry API" dependencies { implementation project(":today-cloud-core") - implementation 'cn.taketoday:today-starter-web' + implementation 'cn.taketoday:infra-starter-web' + implementation 'cn.taketoday:infra-starter-http-service' + implementation 'cn.taketoday:infra-starter-restclient' annotationProcessor 'cn.taketoday:infra-configuration-processor' } \ No newline at end of file diff --git a/today-service-registry-simple-api/src/main/java/infra/cloud/registry/simple/HttpRegistration.java b/today-service-registry-simple-api/src/main/java/infra/cloud/registry/simple/HttpRegistration.java index bea730b..ac79349 100644 --- a/today-service-registry-simple-api/src/main/java/infra/cloud/registry/simple/HttpRegistration.java +++ b/today-service-registry-simple-api/src/main/java/infra/cloud/registry/simple/HttpRegistration.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.registry.simple; diff --git a/today-service-registry-simple-api/src/main/java/infra/cloud/registry/simple/Status.java b/today-service-registry-simple-api/src/main/java/infra/cloud/registry/simple/Status.java index 611a04a..c325f07 100644 --- a/today-service-registry-simple-api/src/main/java/infra/cloud/registry/simple/Status.java +++ b/today-service-registry-simple-api/src/main/java/infra/cloud/registry/simple/Status.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.registry.simple; diff --git a/today-service-registry-simple-api/src/main/java/infra/cloud/registry/simple/api/SimpleHttpServiceRegistryAPI.java b/today-service-registry-simple-api/src/main/java/infra/cloud/registry/simple/api/SimpleHttpServiceRegistryAPI.java index de54e1e..9880b11 100644 --- a/today-service-registry-simple-api/src/main/java/infra/cloud/registry/simple/api/SimpleHttpServiceRegistryAPI.java +++ b/today-service-registry-simple-api/src/main/java/infra/cloud/registry/simple/api/SimpleHttpServiceRegistryAPI.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.registry.simple.api; @@ -31,6 +30,9 @@ import infra.web.annotation.RequestMapping; /** + * HTTP API interface for simple service registry operations. + * Provides methods for registering, unregistering, updating and looking up services. + * * @author 海子 Yang * @since 1.0 2025/8/8 11:18 */ diff --git a/today-service-registry-simple-api/src/main/java/infra/cloud/registry/simple/config/SimpleHttpProperties.java b/today-service-registry-simple-api/src/main/java/infra/cloud/registry/simple/config/SimpleHttpProperties.java index ca07d47..b88eb61 100644 --- a/today-service-registry-simple-api/src/main/java/infra/cloud/registry/simple/config/SimpleHttpProperties.java +++ b/today-service-registry-simple-api/src/main/java/infra/cloud/registry/simple/config/SimpleHttpProperties.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.registry.simple.config; diff --git a/today-service-registry-simple-api/src/main/java/infra/cloud/registry/simple/config/SimpleHttpServiceRegistryAPIAutoConfiguration.java b/today-service-registry-simple-api/src/main/java/infra/cloud/registry/simple/config/SimpleHttpServiceRegistryAPIAutoConfiguration.java index 6f1357e..afdd60b 100644 --- a/today-service-registry-simple-api/src/main/java/infra/cloud/registry/simple/config/SimpleHttpServiceRegistryAPIAutoConfiguration.java +++ b/today-service-registry-simple-api/src/main/java/infra/cloud/registry/simple/config/SimpleHttpServiceRegistryAPIAutoConfiguration.java @@ -1,23 +1,21 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.registry.simple.config; -import infra.annotation.config.web.client.RestClientAutoConfiguration; import infra.beans.factory.config.ConfigurableBeanFactory; import infra.beans.factory.config.EmbeddedValueResolver; import infra.cloud.client.annotation.ConditionalOnDiscoveryEnabled; @@ -25,10 +23,11 @@ import infra.context.annotation.config.DisableDIAutoConfiguration; import infra.context.condition.ConditionalOnMissingBean; import infra.context.properties.EnableConfigurationProperties; +import infra.http.service.invoker.HttpServiceProxyFactory; +import infra.http.service.support.RestClientAdapter; import infra.stereotype.Component; import infra.web.client.RestClient; -import infra.web.client.support.RestClientAdapter; -import infra.web.service.invoker.HttpServiceProxyFactory; +import infra.web.client.config.RestClientAutoConfiguration; /** * @author 海子 Yang diff --git a/today-service-registry-simple-discovery/build.gradle b/today-service-registry-simple-discovery/build.gradle index d0fd860..e8c396f 100644 --- a/today-service-registry-simple-discovery/build.gradle +++ b/today-service-registry-simple-discovery/build.gradle @@ -5,7 +5,7 @@ dependencies { api project(":today-service-discovery") api project(":today-service-registry-simple-api") - implementation 'cn.taketoday:today-starter-web' + implementation 'cn.taketoday:infra-starter-web' annotationProcessor 'cn.taketoday:infra-configuration-processor' } \ No newline at end of file diff --git a/today-service-registry-simple-discovery/src/main/java/infra/cloud/registry/simple/discovery/SimpleHttpDiscoveryClient.java b/today-service-registry-simple-discovery/src/main/java/infra/cloud/registry/simple/discovery/SimpleHttpDiscoveryClient.java index c3c526d..7028a42 100644 --- a/today-service-registry-simple-discovery/src/main/java/infra/cloud/registry/simple/discovery/SimpleHttpDiscoveryClient.java +++ b/today-service-registry-simple-discovery/src/main/java/infra/cloud/registry/simple/discovery/SimpleHttpDiscoveryClient.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.registry.simple.discovery; diff --git a/today-service-registry-simple-discovery/src/main/java/infra/cloud/registry/simple/discovery/SimpleHttpDiscoveryClientAutoConfiguration.java b/today-service-registry-simple-discovery/src/main/java/infra/cloud/registry/simple/discovery/SimpleHttpDiscoveryClientAutoConfiguration.java index 20225d8..d5e3b0c 100644 --- a/today-service-registry-simple-discovery/src/main/java/infra/cloud/registry/simple/discovery/SimpleHttpDiscoveryClientAutoConfiguration.java +++ b/today-service-registry-simple-discovery/src/main/java/infra/cloud/registry/simple/discovery/SimpleHttpDiscoveryClientAutoConfiguration.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.registry.simple.discovery; diff --git a/today-service-registry-simple-registration/build.gradle b/today-service-registry-simple-registration/build.gradle index 2856b4a..c708e43 100644 --- a/today-service-registry-simple-registration/build.gradle +++ b/today-service-registry-simple-registration/build.gradle @@ -5,7 +5,7 @@ dependencies { api project(":today-service-registration") api project(":today-service-registry-simple-api") - implementation 'cn.taketoday:today-starter-web' + implementation 'cn.taketoday:infra-starter-web' annotationProcessor 'cn.taketoday:infra-configuration-processor' } \ No newline at end of file diff --git a/today-service-registry-simple-registration/src/main/java/infra/cloud/registry/simple/HttpRegistrationFactory.java b/today-service-registry-simple-registration/src/main/java/infra/cloud/registry/simple/HttpRegistrationFactory.java index 04292cb..13cac02 100644 --- a/today-service-registry-simple-registration/src/main/java/infra/cloud/registry/simple/HttpRegistrationFactory.java +++ b/today-service-registry-simple-registration/src/main/java/infra/cloud/registry/simple/HttpRegistrationFactory.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.registry.simple; diff --git a/today-service-registry-simple-registration/src/main/java/infra/cloud/registry/simple/SimpleAutoServiceRegistration.java b/today-service-registry-simple-registration/src/main/java/infra/cloud/registry/simple/SimpleAutoServiceRegistration.java index 6526658..012dff2 100644 --- a/today-service-registry-simple-registration/src/main/java/infra/cloud/registry/simple/SimpleAutoServiceRegistration.java +++ b/today-service-registry-simple-registration/src/main/java/infra/cloud/registry/simple/SimpleAutoServiceRegistration.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.registry.simple; diff --git a/today-service-registry-simple-registration/src/main/java/infra/cloud/registry/simple/SimpleHttpServiceRegistry.java b/today-service-registry-simple-registration/src/main/java/infra/cloud/registry/simple/SimpleHttpServiceRegistry.java index fc842b4..85da7b2 100644 --- a/today-service-registry-simple-registration/src/main/java/infra/cloud/registry/simple/SimpleHttpServiceRegistry.java +++ b/today-service-registry-simple-registration/src/main/java/infra/cloud/registry/simple/SimpleHttpServiceRegistry.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.registry.simple; diff --git a/today-service-registry-simple-registration/src/main/java/infra/cloud/registry/simple/SimpleRegistryProperties.java b/today-service-registry-simple-registration/src/main/java/infra/cloud/registry/simple/SimpleRegistryProperties.java index d73705f..1a5bb54 100644 --- a/today-service-registry-simple-registration/src/main/java/infra/cloud/registry/simple/SimpleRegistryProperties.java +++ b/today-service-registry-simple-registration/src/main/java/infra/cloud/registry/simple/SimpleRegistryProperties.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.registry.simple; diff --git a/today-service-registry-simple-registration/src/main/java/infra/cloud/registry/simple/annotation/config/SimpleHttpServiceRegistryAutoConfiguration.java b/today-service-registry-simple-registration/src/main/java/infra/cloud/registry/simple/annotation/config/SimpleHttpServiceRegistryAutoConfiguration.java index 17d5ca1..6ea40c5 100644 --- a/today-service-registry-simple-registration/src/main/java/infra/cloud/registry/simple/annotation/config/SimpleHttpServiceRegistryAutoConfiguration.java +++ b/today-service-registry-simple-registration/src/main/java/infra/cloud/registry/simple/annotation/config/SimpleHttpServiceRegistryAutoConfiguration.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.registry.simple.annotation.config; diff --git a/today-service-registry-simple-server/build.gradle b/today-service-registry-simple-server/build.gradle index 3392cc9..e58c017 100644 --- a/today-service-registry-simple-server/build.gradle +++ b/today-service-registry-simple-server/build.gradle @@ -5,7 +5,7 @@ dependencies { api project(":today-cloud-core") api project(":today-service-registry-simple-api") - implementation 'cn.taketoday:today-starter-web' + implementation 'cn.taketoday:infra-starter-web' annotationProcessor 'cn.taketoday:infra-configuration-processor' } \ No newline at end of file diff --git a/today-service-registry-simple-server/src/main/java/infra/cloud/registry/simple/server/ServiceNotFoundException.java b/today-service-registry-simple-server/src/main/java/infra/cloud/registry/simple/server/ServiceNotFoundException.java index c058fe2..f741ef1 100644 --- a/today-service-registry-simple-server/src/main/java/infra/cloud/registry/simple/server/ServiceNotFoundException.java +++ b/today-service-registry-simple-server/src/main/java/infra/cloud/registry/simple/server/ServiceNotFoundException.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.registry.simple.server; diff --git a/today-service-registry-simple-server/src/main/java/infra/cloud/registry/simple/server/SimpleHttpServiceRegistryEndpoint.java b/today-service-registry-simple-server/src/main/java/infra/cloud/registry/simple/server/SimpleHttpServiceRegistryEndpoint.java index 7bd3f9e..8929bdf 100644 --- a/today-service-registry-simple-server/src/main/java/infra/cloud/registry/simple/server/SimpleHttpServiceRegistryEndpoint.java +++ b/today-service-registry-simple-server/src/main/java/infra/cloud/registry/simple/server/SimpleHttpServiceRegistryEndpoint.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.registry.simple.server; diff --git a/today-service-registry-simple-server/src/main/java/infra/cloud/registry/simple/server/SimpleHttpServiceRegistryServerAutoConfiguration.java b/today-service-registry-simple-server/src/main/java/infra/cloud/registry/simple/server/SimpleHttpServiceRegistryServerAutoConfiguration.java index ba8e146..85045c1 100644 --- a/today-service-registry-simple-server/src/main/java/infra/cloud/registry/simple/server/SimpleHttpServiceRegistryServerAutoConfiguration.java +++ b/today-service-registry-simple-server/src/main/java/infra/cloud/registry/simple/server/SimpleHttpServiceRegistryServerAutoConfiguration.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.registry.simple.server; diff --git a/today-service-serialization/build.gradle b/today-service-serialization/build.gradle index b7382ea..aba27f8 100644 --- a/today-service-serialization/build.gradle +++ b/today-service-serialization/build.gradle @@ -1,7 +1,7 @@ description = "TODAY Service serialization API and default format based on msgpack specification" dependencies { - api "cn.taketoday:today-core" + api "cn.taketoday:infra-core" } diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/Deserializer.java b/today-service-serialization/src/main/java/infra/cloud/serialize/Deserializer.java index 7e6231a..f180cba 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/Deserializer.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/Deserializer.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2026 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.serialize; diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/Message.java b/today-service-serialization/src/main/java/infra/cloud/serialize/Message.java index 2a3c22b..9a25043 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/Message.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/Message.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2026 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.serialize; diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/Readable.java b/today-service-serialization/src/main/java/infra/cloud/serialize/Readable.java index 8f2227c..b9e2396 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/Readable.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/Readable.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2026 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.serialize; diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/Serialization.java b/today-service-serialization/src/main/java/infra/cloud/serialize/Serialization.java index d741da5..2b0ee90 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/Serialization.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/Serialization.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.serialize; diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/SerializationException.java b/today-service-serialization/src/main/java/infra/cloud/serialize/SerializationException.java index a9af766..9e02605 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/SerializationException.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/SerializationException.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.serialize; diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/Serializer.java b/today-service-serialization/src/main/java/infra/cloud/serialize/Serializer.java index 0d98ece..fec3514 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/Serializer.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/Serializer.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2026 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.serialize; diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/Writable.java b/today-service-serialization/src/main/java/infra/cloud/serialize/Writable.java index 1050dab..0d6dc23 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/Writable.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/Writable.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2026 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.serialize; diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/ExtensionTypeHeader.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/ExtensionTypeHeader.java index 23af74e..a3ac1cc 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/ExtensionTypeHeader.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/ExtensionTypeHeader.java @@ -1,26 +1,18 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] - */ - -package infra.cloud.serialize.format; - -import infra.lang.Assert; - -/** - * Header of the Extension types + * 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. + */es */ public class ExtensionTypeHeader { private final byte type; diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageBufferPacker.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageBufferPacker.java index 97eb415..dfe1ecf 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageBufferPacker.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageBufferPacker.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.serialize.format; diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageFormat.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageFormat.java index fd25c00..daba74b 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageFormat.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageFormat.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.serialize.format; diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageFormatException.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageFormatException.java index ce99b6f..6f4bb86 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageFormatException.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageFormatException.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.serialize.format; diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageInsufficientBufferException.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageInsufficientBufferException.java index 601cc31..a3b05bb 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageInsufficientBufferException.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageInsufficientBufferException.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.serialize.format; diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageIntegerOverflowException.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageIntegerOverflowException.java index 2f3a618..7ca917b 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageIntegerOverflowException.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageIntegerOverflowException.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.serialize.format; diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageNeverUsedFormatException.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageNeverUsedFormatException.java index da9745c..cb3251e 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageNeverUsedFormatException.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageNeverUsedFormatException.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.serialize.format; diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessagePack.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessagePack.java index 7c4de6a..5f7fad6 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessagePack.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessagePack.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.serialize.format; diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessagePackException.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessagePackException.java index 7069879..3cd235e 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessagePackException.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessagePackException.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.serialize.format; diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessagePacker.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessagePacker.java index 8bcc8c9..7d1d4c1 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessagePacker.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessagePacker.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.serialize.format; diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageSizeException.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageSizeException.java index f6d1888..5ac9d92 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageSizeException.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageSizeException.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.serialize.format; diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageStringCodingException.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageStringCodingException.java index 2b390a1..f4a5de7 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageStringCodingException.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageStringCodingException.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.serialize.format; diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageTypeCastException.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageTypeCastException.java index 2d87a81..4c3ba0b 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageTypeCastException.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageTypeCastException.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.serialize.format; diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageTypeException.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageTypeException.java index 5b4968f..b1fa3fc 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageTypeException.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageTypeException.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.serialize.format; diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageUnpacker.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageUnpacker.java index ed4f815..0fa2dbc 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageUnpacker.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageUnpacker.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.serialize.format; diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/ArrayBufferInput.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/ArrayBufferInput.java index c7314a6..5cc42c5 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/ArrayBufferInput.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/ArrayBufferInput.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.serialize.format.buffer; diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/ArrayBufferOutput.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/ArrayBufferOutput.java index c5830de..c7941fe 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/ArrayBufferOutput.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/ArrayBufferOutput.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.serialize.format.buffer; diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/ByteBufferInput.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/ByteBufferInput.java index 06d06c2..03af151 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/ByteBufferInput.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/ByteBufferInput.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.serialize.format.buffer; diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/ChannelBufferInput.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/ChannelBufferInput.java index d83f929..912cc7b 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/ChannelBufferInput.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/ChannelBufferInput.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.serialize.format.buffer; diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/ChannelBufferOutput.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/ChannelBufferOutput.java index 77e0d29..5844c27 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/ChannelBufferOutput.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/ChannelBufferOutput.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.serialize.format.buffer; diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/DirectBufferAccess.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/DirectBufferAccess.java index b9953a2..a13756d 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/DirectBufferAccess.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/DirectBufferAccess.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.serialize.format.buffer; diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/InputStreamBufferInput.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/InputStreamBufferInput.java index eb4d84b..c9c0bb2 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/InputStreamBufferInput.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/InputStreamBufferInput.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.serialize.format.buffer; diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/MessageBuffer.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/MessageBuffer.java index c57ad83..5849859 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/MessageBuffer.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/MessageBuffer.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.serialize.format.buffer; diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/MessageBufferBE.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/MessageBufferBE.java index 1464edf..3c5bbd5 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/MessageBufferBE.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/MessageBufferBE.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.serialize.format.buffer; diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/MessageBufferInput.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/MessageBufferInput.java index 6d0108c..23dc526 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/MessageBufferInput.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/MessageBufferInput.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.serialize.format.buffer; diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/MessageBufferOutput.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/MessageBufferOutput.java index 26557c7..4826849 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/MessageBufferOutput.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/MessageBufferOutput.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.serialize.format.buffer; diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/MessageBufferU.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/MessageBufferU.java index b3a02ca..6f3b143 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/MessageBufferU.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/MessageBufferU.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.serialize.format.buffer; diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/OutputStreamBufferOutput.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/OutputStreamBufferOutput.java index 73491bf..713d387 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/OutputStreamBufferOutput.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/OutputStreamBufferOutput.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.serialize.format.buffer; diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/package-info.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/package-info.java index 74cb601..c66fad4 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/package-info.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/package-info.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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. */ /** diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ArrayValue.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ArrayValue.java index 6eb813a..d21a0d0 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ArrayValue.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ArrayValue.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.serialize.format.value; diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/BinaryValue.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/BinaryValue.java index 28ebd75..b914b32 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/BinaryValue.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/BinaryValue.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.serialize.format.value; diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/BooleanValue.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/BooleanValue.java index a588f4d..cd61b36 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/BooleanValue.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/BooleanValue.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.serialize.format.value; diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ExtensionValue.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ExtensionValue.java index 7bca8b5..3bed4c7 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ExtensionValue.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ExtensionValue.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.serialize.format.value; diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/FloatValue.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/FloatValue.java index d7d6922..c9c9039 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/FloatValue.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/FloatValue.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.serialize.format.value; diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableArrayValue.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableArrayValue.java index 83c9156..07a0c71 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableArrayValue.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableArrayValue.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.serialize.format.value; diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableBinaryValue.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableBinaryValue.java index 1a7c1ad..76743c0 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableBinaryValue.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableBinaryValue.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.serialize.format.value; diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableBooleanValue.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableBooleanValue.java index 48ea26e..47735f1 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableBooleanValue.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableBooleanValue.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.serialize.format.value; diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableExtensionValue.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableExtensionValue.java index 6caa006..a094055 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableExtensionValue.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableExtensionValue.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.serialize.format.value; diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableFloatValue.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableFloatValue.java index f216837..17850b6 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableFloatValue.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableFloatValue.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.serialize.format.value; diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableIntegerValue.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableIntegerValue.java index ded546a..3541c8e 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableIntegerValue.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableIntegerValue.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.serialize.format.value; diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableMapValue.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableMapValue.java index 2177a1e..949402a 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableMapValue.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableMapValue.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.serialize.format.value; diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableNilValue.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableNilValue.java index 642d11e..d488fb8 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableNilValue.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableNilValue.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.serialize.format.value; diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableNumberValue.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableNumberValue.java index 0508517..a85d3dc 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableNumberValue.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableNumberValue.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.serialize.format.value; diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableRawValue.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableRawValue.java index 1a00b74..5ff67cd 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableRawValue.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableRawValue.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.serialize.format.value; diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableStringValue.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableStringValue.java index 6abced0..0a0e092 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableStringValue.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableStringValue.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.serialize.format.value; diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableTimestampValue.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableTimestampValue.java index eb5702f..82f1903 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableTimestampValue.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableTimestampValue.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.serialize.format.value; diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableValue.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableValue.java index 2c6de33..3776fca 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableValue.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableValue.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.serialize.format.value; diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/IntegerValue.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/IntegerValue.java index 57a1bc8..3644159 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/IntegerValue.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/IntegerValue.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.serialize.format.value; diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/MapValue.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/MapValue.java index 05818fa..7082342 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/MapValue.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/MapValue.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.serialize.format.value; diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/NilValue.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/NilValue.java index 2fcad8c..d598e20 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/NilValue.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/NilValue.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.serialize.format.value; diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/NumberValue.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/NumberValue.java index 75eabe1..cf85e9c 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/NumberValue.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/NumberValue.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.serialize.format.value; diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/RawValue.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/RawValue.java index 589a0fc..1a8f7a4 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/RawValue.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/RawValue.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.serialize.format.value; diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/StringValue.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/StringValue.java index 3d535ed..f080ea6 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/StringValue.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/StringValue.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.serialize.format.value; diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/TimestampValue.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/TimestampValue.java index fd753b3..b38c4c0 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/TimestampValue.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/TimestampValue.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.serialize.format.value; diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/Value.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/Value.java index 68f1cc9..bbb5982 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/Value.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/Value.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.serialize.format.value; diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ValueFactory.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ValueFactory.java index 85f8992..a51fa4f 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ValueFactory.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ValueFactory.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.serialize.format.value; diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ValueType.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ValueType.java index 6ace9b8..89be1a1 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ValueType.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ValueType.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.serialize.format.value; diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/Variable.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/Variable.java index 6c3ed59..be02bdc 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/Variable.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/Variable.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.serialize.format.value; diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/AbstractImmutableRawValue.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/AbstractImmutableRawValue.java index 9adcb85..941341d 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/AbstractImmutableRawValue.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/AbstractImmutableRawValue.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.serialize.format.value.impl; diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/AbstractImmutableValue.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/AbstractImmutableValue.java index 88814d8..50c1643 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/AbstractImmutableValue.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/AbstractImmutableValue.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.serialize.format.value.impl; diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableArrayValueImpl.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableArrayValueImpl.java index 0732f7e..93cc5e2 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableArrayValueImpl.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableArrayValueImpl.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.serialize.format.value.impl; diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableBigIntegerValueImpl.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableBigIntegerValueImpl.java index 3cf0f6c..aef31f8 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableBigIntegerValueImpl.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableBigIntegerValueImpl.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.serialize.format.value.impl; diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableBinaryValueImpl.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableBinaryValueImpl.java index c36cedf..a085523 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableBinaryValueImpl.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableBinaryValueImpl.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.serialize.format.value.impl; diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableBooleanValueImpl.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableBooleanValueImpl.java index ed4e4e3..5f2c257 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableBooleanValueImpl.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableBooleanValueImpl.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.serialize.format.value.impl; diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableDoubleValueImpl.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableDoubleValueImpl.java index f54015f..97fdc5e 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableDoubleValueImpl.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableDoubleValueImpl.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.serialize.format.value.impl; diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableExtensionValueImpl.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableExtensionValueImpl.java index c361f18..3a5aac5 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableExtensionValueImpl.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableExtensionValueImpl.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.serialize.format.value.impl; diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableLongValueImpl.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableLongValueImpl.java index ceadc61..aa50f4a 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableLongValueImpl.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableLongValueImpl.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.serialize.format.value.impl; diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableMapValueImpl.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableMapValueImpl.java index 2c073a3..1e65f9b 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableMapValueImpl.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableMapValueImpl.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.serialize.format.value.impl; diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableNilValueImpl.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableNilValueImpl.java index c13a2f7..3714d29 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableNilValueImpl.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableNilValueImpl.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.serialize.format.value.impl; diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableStringValueImpl.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableStringValueImpl.java index 483baeb..8acd0df 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableStringValueImpl.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableStringValueImpl.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.serialize.format.value.impl; diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableTimestampValueImpl.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableTimestampValueImpl.java index 3d66eaa..eb2838c 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableTimestampValueImpl.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableTimestampValueImpl.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2024 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.serialize.format.value.impl; diff --git a/today-service-serialization/src/test/java/infra/cloud/serialize/MessageTests.java b/today-service-serialization/src/test/java/infra/cloud/serialize/MessageTests.java index d7e4e0d..3149d3e 100644 --- a/today-service-serialization/src/test/java/infra/cloud/serialize/MessageTests.java +++ b/today-service-serialization/src/test/java/infra/cloud/serialize/MessageTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2026 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.serialize; diff --git a/today-service-serialization/src/test/java/infra/cloud/serialize/ReadableTests.java b/today-service-serialization/src/test/java/infra/cloud/serialize/ReadableTests.java index 253af10..f400d89 100644 --- a/today-service-serialization/src/test/java/infra/cloud/serialize/ReadableTests.java +++ b/today-service-serialization/src/test/java/infra/cloud/serialize/ReadableTests.java @@ -1,18 +1,17 @@ /* - * Copyright 2021 - 2026 the original author or authors. + * Copyright 2021 - 2026 the TODAY authors * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * https://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/] + * 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 infra.cloud.serialize; From 286f131498d478ce99ad4ba5add5231693176cd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Fri, 30 Jan 2026 22:10:13 +0800 Subject: [PATCH 070/104] =?UTF-8?q?:recycle:=20=E9=87=8D=E6=9E=84=E6=B6=88?= =?UTF-8?q?=E6=81=AF=E5=BA=8F=E5=88=97=E5=8C=96=E5=92=8C=E9=98=9F=E5=88=97?= =?UTF-8?q?=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 移除 UnsafeAccess 中的冗余常量检查支持 - 删除 RangeUtil 中的验证方法以简化实现 - 从 MessagePackReader 和 Writer 中移除旧的 Code 引用 - 使用新的 MessagePackCode 常量替换原有引用 - 简化类型检查逻辑并统一代码风格 --- .run/publishToMavenLocal.run.xml | 27 + today-cloud-core/build.gradle | 2 + .../demo-tests/demo-registry/build.gradle | 1 + .../demo-tests/demo-user-rest/build.gradle | 1 + .../cn/taketoday/demo/ClientApplication.java | 2 +- .../demo-tests/demo-user-service/build.gradle | 1 + today-remoting/build.gradle | 1 - .../internal/jctools/queues/RangeUtil.java | 24 - .../internal/jctools/queues/UnsafeAccess.java | 37 - .../infra/remoting/lb/Int2LongHashMap.java | 1 - .../lb/WeightedLoadBalanceStrategy.java | 2 +- .../cloud/serialize/MessagePackReader.java | 172 +- .../cloud/serialize/MessagePackWriter.java | 65 +- today-service-client/build.gradle | 2 + today-service-discovery/build.gradle | 2 +- today-service-provider/build.gradle | 1 + .../provider/ServiceServerProperties.java | 6 + .../AutoServiceRegistrationConfiguration.java | 6 +- today-service-serialization/build.gradle | 7 - .../serialize/format/ExtensionTypeHeader.java | 10 +- .../serialize/format/MessageBufferPacker.java | 123 -- .../cloud/serialize/format/MessageFormat.java | 72 +- .../cloud/serialize/format/MessagePack.java | 699 ------- .../serialize/format/MessagePackCode.java | 103 ++ .../cloud/serialize/format/MessagePacker.java | 1093 ----------- .../format/MessageStringCodingException.java | 34 - .../format/MessageTypeCastException.java | 25 - .../serialize/format/MessageUnpacker.java | 1638 ----------------- .../format/{value => }/ValueType.java | 43 +- .../format/buffer/ArrayBufferInput.java | 78 - .../format/buffer/ArrayBufferOutput.java | 160 -- .../format/buffer/ByteBufferInput.java | 62 - .../format/buffer/ChannelBufferInput.java | 72 - .../format/buffer/ChannelBufferOutput.java | 92 - .../format/buffer/DirectBufferAccess.java | 174 -- .../format/buffer/InputStreamBufferInput.java | 82 - .../format/buffer/MessageBuffer.java | 573 ------ .../format/buffer/MessageBufferBE.java | 97 - .../format/buffer/MessageBufferInput.java | 59 - .../format/buffer/MessageBufferOutput.java | 81 - .../format/buffer/MessageBufferU.java | 243 --- .../buffer/OutputStreamBufferOutput.java | 85 - .../serialize/format/value/ArrayValue.java | 57 - .../serialize/format/value/BinaryValue.java | 28 - .../serialize/format/value/BooleanValue.java | 30 - .../format/value/ExtensionValue.java | 32 - .../serialize/format/value/FloatValue.java | 28 - .../format/value/ImmutableArrayValue.java | 40 - .../format/value/ImmutableBinaryValue.java | 28 - .../format/value/ImmutableBooleanValue.java | 26 - .../format/value/ImmutableExtensionValue.java | 26 - .../format/value/ImmutableFloatValue.java | 28 - .../format/value/ImmutableIntegerValue.java | 26 - .../format/value/ImmutableMapValue.java | 26 - .../format/value/ImmutableNilValue.java | 24 - .../format/value/ImmutableNumberValue.java | 27 - .../format/value/ImmutableRawValue.java | 29 - .../format/value/ImmutableStringValue.java | 27 - .../format/value/ImmutableTimestampValue.java | 26 - .../format/value/ImmutableValue.java | 53 - .../serialize/format/value/IntegerValue.java | 90 - .../serialize/format/value/MapValue.java | 55 - .../serialize/format/value/NilValue.java | 24 - .../serialize/format/value/NumberValue.java | 65 - .../serialize/format/value/RawValue.java | 63 - .../serialize/format/value/StringValue.java | 30 - .../format/value/TimestampValue.java | 33 - .../cloud/serialize/format/value/Value.java | 331 ---- .../serialize/format/value/ValueFactory.java | 274 --- .../serialize/format/value/Variable.java | 1163 ------------ .../value/impl/AbstractImmutableRawValue.java | 174 -- .../value/impl/AbstractImmutableValue.java | 155 -- .../value/impl/ImmutableArrayValueImpl.java | 239 --- .../impl/ImmutableBigIntegerValueImpl.java | 232 --- .../value/impl/ImmutableBinaryValueImpl.java | 89 - .../value/impl/ImmutableBooleanValueImpl.java | 107 -- .../value/impl/ImmutableDoubleValueImpl.java | 140 -- .../impl/ImmutableExtensionValueImpl.java | 127 -- .../value/impl/ImmutableLongValueImpl.java | 211 --- .../value/impl/ImmutableMapValueImpl.java | 330 ---- .../value/impl/ImmutableNilValueImpl.java | 91 - .../value/impl/ImmutableStringValueImpl.java | 93 - .../impl/ImmutableTimestampValueImpl.java | 181 -- 83 files changed, 332 insertions(+), 10584 deletions(-) create mode 100644 .run/publishToMavenLocal.run.xml delete mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageBufferPacker.java delete mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/MessagePack.java create mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/MessagePackCode.java delete mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/MessagePacker.java delete mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageStringCodingException.java delete mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageTypeCastException.java delete mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageUnpacker.java rename today-service-serialization/src/main/java/infra/cloud/serialize/format/{value => }/ValueType.java (69%) delete mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/ArrayBufferInput.java delete mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/ArrayBufferOutput.java delete mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/ByteBufferInput.java delete mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/ChannelBufferInput.java delete mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/ChannelBufferOutput.java delete mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/DirectBufferAccess.java delete mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/InputStreamBufferInput.java delete mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/MessageBuffer.java delete mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/MessageBufferBE.java delete mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/MessageBufferInput.java delete mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/MessageBufferOutput.java delete mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/MessageBufferU.java delete mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/OutputStreamBufferOutput.java delete mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ArrayValue.java delete mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/value/BinaryValue.java delete mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/value/BooleanValue.java delete mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ExtensionValue.java delete mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/value/FloatValue.java delete mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableArrayValue.java delete mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableBinaryValue.java delete mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableBooleanValue.java delete mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableExtensionValue.java delete mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableFloatValue.java delete mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableIntegerValue.java delete mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableMapValue.java delete mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableNilValue.java delete mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableNumberValue.java delete mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableRawValue.java delete mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableStringValue.java delete mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableTimestampValue.java delete mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableValue.java delete mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/value/IntegerValue.java delete mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/value/MapValue.java delete mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/value/NilValue.java delete mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/value/NumberValue.java delete mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/value/RawValue.java delete mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/value/StringValue.java delete mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/value/TimestampValue.java delete mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/value/Value.java delete mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ValueFactory.java delete mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/value/Variable.java delete mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/AbstractImmutableRawValue.java delete mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/AbstractImmutableValue.java delete mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableArrayValueImpl.java delete mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableBigIntegerValueImpl.java delete mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableBinaryValueImpl.java delete mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableBooleanValueImpl.java delete mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableDoubleValueImpl.java delete mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableExtensionValueImpl.java delete mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableLongValueImpl.java delete mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableMapValueImpl.java delete mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableNilValueImpl.java delete mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableStringValueImpl.java delete mode 100644 today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableTimestampValueImpl.java diff --git a/.run/publishToMavenLocal.run.xml b/.run/publishToMavenLocal.run.xml new file mode 100644 index 0000000..cf8c4aa --- /dev/null +++ b/.run/publishToMavenLocal.run.xml @@ -0,0 +1,27 @@ + + + + + + + true + true + false + false + false + false + false + + + \ No newline at end of file diff --git a/today-cloud-core/build.gradle b/today-cloud-core/build.gradle index 9496335..793a138 100644 --- a/today-cloud-core/build.gradle +++ b/today-cloud-core/build.gradle @@ -3,6 +3,8 @@ description = "TODAY Cloud Core Technologies" dependencies { api 'cn.taketoday:infra-core' + optional 'cn.taketoday:infra-app' + implementation 'cn.taketoday:infra-context' annotationProcessor 'cn.taketoday:infra-configuration-processor' diff --git a/today-cloud-samples/demo-tests/demo-registry/build.gradle b/today-cloud-samples/demo-tests/demo-registry/build.gradle index aeddd12..56b821b 100644 --- a/today-cloud-samples/demo-tests/demo-registry/build.gradle +++ b/today-cloud-samples/demo-tests/demo-registry/build.gradle @@ -26,6 +26,7 @@ dependencies { implementation 'cn.taketoday:infra-starter-web' implementation 'cn.taketoday:infra-starter-netty-server' + implementation 'cn.taketoday:infra-starter-application' implementation 'ch.qos.logback:logback-classic' annotationProcessor 'cn.taketoday:infra-configuration-processor' diff --git a/today-cloud-samples/demo-tests/demo-user-rest/build.gradle b/today-cloud-samples/demo-tests/demo-user-rest/build.gradle index 4e331f3..8eb7d3f 100644 --- a/today-cloud-samples/demo-tests/demo-user-rest/build.gradle +++ b/today-cloud-samples/demo-tests/demo-user-rest/build.gradle @@ -6,6 +6,7 @@ dependencies { implementation project(":today-cloud-samples:demo-tests:demo-user-api") implementation 'cn.taketoday:infra-starter-web' + implementation 'cn.taketoday:infra-starter-application' implementation 'cn.taketoday:infra-starter-json' implementation 'cn.taketoday:infra-starter-netty-server' implementation 'ch.qos.logback:logback-classic' diff --git a/today-cloud-samples/demo-tests/demo-user-rest/src/main/java/cn/taketoday/demo/ClientApplication.java b/today-cloud-samples/demo-tests/demo-user-rest/src/main/java/cn/taketoday/demo/ClientApplication.java index b0cc347..090bf98 100644 --- a/today-cloud-samples/demo-tests/demo-user-rest/src/main/java/cn/taketoday/demo/ClientApplication.java +++ b/today-cloud-samples/demo-tests/demo-user-rest/src/main/java/cn/taketoday/demo/ClientApplication.java @@ -29,7 +29,7 @@ public class ClientApplication { public static void main(String[] args) { ApplicationBuilder.forSources(ClientApplication.class) - .type(ApplicationType.NETTY_WEB) + .type(ApplicationType.WEB) .run(args); } diff --git a/today-cloud-samples/demo-tests/demo-user-service/build.gradle b/today-cloud-samples/demo-tests/demo-user-service/build.gradle index 4acc4df..bfd71d8 100644 --- a/today-cloud-samples/demo-tests/demo-user-service/build.gradle +++ b/today-cloud-samples/demo-tests/demo-user-service/build.gradle @@ -9,6 +9,7 @@ dependencies { // implementation 'cn.taketoday:infra-starter-web' // implementation 'cn.taketoday:infra-starter-netty' implementation 'cn.taketoday:infra-starter-logback' + implementation 'cn.taketoday:infra-starter-application' // implementation "com.google.protobuf:protobuf-java" diff --git a/today-remoting/build.gradle b/today-remoting/build.gradle index e47998d..34cc56b 100644 --- a/today-remoting/build.gradle +++ b/today-remoting/build.gradle @@ -28,5 +28,4 @@ dependencies { testFixturesApi 'org.hdrhistogram:HdrHistogram:2.1.12' - } diff --git a/today-remoting/src/main/java/infra/remoting/internal/jctools/queues/RangeUtil.java b/today-remoting/src/main/java/infra/remoting/internal/jctools/queues/RangeUtil.java index 2161cfa..2ee9495 100644 --- a/today-remoting/src/main/java/infra/remoting/internal/jctools/queues/RangeUtil.java +++ b/today-remoting/src/main/java/infra/remoting/internal/jctools/queues/RangeUtil.java @@ -38,30 +38,6 @@ public static long checkPositive(long n, String name) { return n; } - public static int checkPositiveOrZero(int n, String name) { - if (n < 0) { - throw new IllegalArgumentException(name + ": " + n + " (expected: >= 0)"); - } - - return n; - } - - public static int checkLessThan(int n, int expected, String name) { - if (n >= expected) { - throw new IllegalArgumentException(name + ": " + n + " (expected: < " + expected + ')'); - } - - return n; - } - - public static int checkLessThanOrEqual(int n, long expected, String name) { - if (n > expected) { - throw new IllegalArgumentException(name + ": " + n + " (expected: <= " + expected + ')'); - } - - return n; - } - public static int checkGreaterThanOrEqual(int n, int expected, String name) { if (n < expected) { throw new IllegalArgumentException(name + ": " + n + " (expected: >= " + expected + ')'); diff --git a/today-remoting/src/main/java/infra/remoting/internal/jctools/queues/UnsafeAccess.java b/today-remoting/src/main/java/infra/remoting/internal/jctools/queues/UnsafeAccess.java index b377728..48d2e52 100644 --- a/today-remoting/src/main/java/infra/remoting/internal/jctools/queues/UnsafeAccess.java +++ b/today-remoting/src/main/java/infra/remoting/internal/jctools/queues/UnsafeAccess.java @@ -14,19 +14,6 @@ * limitations under the License. */ -/* - * 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 infra.remoting.internal.jctools.queues; import java.lang.reflect.Constructor; @@ -51,14 +38,10 @@ * @author nitsanw */ class UnsafeAccess { - public static final boolean SUPPORTS_GET_AND_SET_REF; - public static final boolean SUPPORTS_GET_AND_ADD_LONG; public static final Unsafe UNSAFE; static { UNSAFE = getUnsafe(); - SUPPORTS_GET_AND_SET_REF = hasGetAndSetSupport(); - SUPPORTS_GET_AND_ADD_LONG = hasGetAndAddLongSupport(); } private static Unsafe getUnsafe() { @@ -86,26 +69,6 @@ private static Unsafe getUnsafe() { return instance; } - private static boolean hasGetAndSetSupport() { - try { - Unsafe.class.getMethod("getAndSetObject", Object.class, Long.TYPE, Object.class); - return true; - } - catch (Exception ignored) { - } - return false; - } - - private static boolean hasGetAndAddLongSupport() { - try { - Unsafe.class.getMethod("getAndAddLong", Object.class, Long.TYPE, Long.TYPE); - return true; - } - catch (Exception ignored) { - } - return false; - } - public static long fieldOffset(Class clz, String fieldName) throws RuntimeException { try { return UNSAFE.objectFieldOffset(clz.getDeclaredField(fieldName)); diff --git a/today-remoting/src/main/java/infra/remoting/lb/Int2LongHashMap.java b/today-remoting/src/main/java/infra/remoting/lb/Int2LongHashMap.java index 16dbb23..e495c39 100644 --- a/today-remoting/src/main/java/infra/remoting/lb/Int2LongHashMap.java +++ b/today-remoting/src/main/java/infra/remoting/lb/Int2LongHashMap.java @@ -635,7 +635,6 @@ protected final void findNext() { throw new IllegalStateException(); } - /** {@inheritDoc} */ public void remove() { if (isPositionValid) { final int position = keyPosition(); diff --git a/today-remoting/src/main/java/infra/remoting/lb/WeightedLoadBalanceStrategy.java b/today-remoting/src/main/java/infra/remoting/lb/WeightedLoadBalanceStrategy.java index ff6d465..27d6ba5 100644 --- a/today-remoting/src/main/java/infra/remoting/lb/WeightedLoadBalanceStrategy.java +++ b/today-remoting/src/main/java/infra/remoting/lb/WeightedLoadBalanceStrategy.java @@ -34,7 +34,7 @@ *

          Use {@link #create()} or a {@link #builder() Builder} to create an instance. * * @see Predictive Load-Balancing: Unfair but - * Faster & more Robust + * Faster and more Robust * @see WeightedStatsRequestInterceptor */ public class WeightedLoadBalanceStrategy implements ClientLoadBalanceStrategy { diff --git a/today-service-api/src/main/java/infra/cloud/serialize/MessagePackReader.java b/today-service-api/src/main/java/infra/cloud/serialize/MessagePackReader.java index c921667..9df5249 100644 --- a/today-service-api/src/main/java/infra/cloud/serialize/MessagePackReader.java +++ b/today-service-api/src/main/java/infra/cloud/serialize/MessagePackReader.java @@ -35,7 +35,6 @@ import infra.cloud.serialize.format.MessageInsufficientBufferException; import infra.cloud.serialize.format.MessageIntegerOverflowException; import infra.cloud.serialize.format.MessageNeverUsedFormatException; -import infra.cloud.serialize.format.MessagePack.Code; import infra.cloud.serialize.format.MessagePackException; import infra.cloud.serialize.format.MessageSizeException; import infra.cloud.serialize.format.MessageTypeException; @@ -46,7 +45,42 @@ import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; -import static infra.cloud.serialize.format.MessagePack.Code.EXT_TIMESTAMP; +import static infra.cloud.serialize.format.MessagePackCode.ARRAY16; +import static infra.cloud.serialize.format.MessagePackCode.ARRAY32; +import static infra.cloud.serialize.format.MessagePackCode.BIN16; +import static infra.cloud.serialize.format.MessagePackCode.BIN32; +import static infra.cloud.serialize.format.MessagePackCode.BIN8; +import static infra.cloud.serialize.format.MessagePackCode.EXT16; +import static infra.cloud.serialize.format.MessagePackCode.EXT32; +import static infra.cloud.serialize.format.MessagePackCode.EXT8; +import static infra.cloud.serialize.format.MessagePackCode.EXT_TIMESTAMP; +import static infra.cloud.serialize.format.MessagePackCode.FALSE; +import static infra.cloud.serialize.format.MessagePackCode.FIXEXT1; +import static infra.cloud.serialize.format.MessagePackCode.FIXEXT16; +import static infra.cloud.serialize.format.MessagePackCode.FIXEXT2; +import static infra.cloud.serialize.format.MessagePackCode.FIXEXT4; +import static infra.cloud.serialize.format.MessagePackCode.FIXEXT8; +import static infra.cloud.serialize.format.MessagePackCode.FLOAT32; +import static infra.cloud.serialize.format.MessagePackCode.FLOAT64; +import static infra.cloud.serialize.format.MessagePackCode.INT16; +import static infra.cloud.serialize.format.MessagePackCode.INT32; +import static infra.cloud.serialize.format.MessagePackCode.INT64; +import static infra.cloud.serialize.format.MessagePackCode.INT8; +import static infra.cloud.serialize.format.MessagePackCode.MAP16; +import static infra.cloud.serialize.format.MessagePackCode.MAP32; +import static infra.cloud.serialize.format.MessagePackCode.NIL; +import static infra.cloud.serialize.format.MessagePackCode.STR16; +import static infra.cloud.serialize.format.MessagePackCode.STR32; +import static infra.cloud.serialize.format.MessagePackCode.STR8; +import static infra.cloud.serialize.format.MessagePackCode.TRUE; +import static infra.cloud.serialize.format.MessagePackCode.UINT16; +import static infra.cloud.serialize.format.MessagePackCode.UINT32; +import static infra.cloud.serialize.format.MessagePackCode.UINT64; +import static infra.cloud.serialize.format.MessagePackCode.UINT8; +import static infra.cloud.serialize.format.MessagePackCode.isFixInt; +import static infra.cloud.serialize.format.MessagePackCode.isFixedArray; +import static infra.cloud.serialize.format.MessagePackCode.isFixedMap; +import static infra.cloud.serialize.format.MessagePackCode.isFixedRaw; /** * MessagePack specification reader implementation @@ -125,10 +159,10 @@ public int skipBytes(int n) { @Override public boolean readBoolean() { byte b = buffer.readByte(); - if (b == Code.FALSE) { + if (b == FALSE) { return false; } - else if (b == Code.TRUE) { + else if (b == TRUE) { return true; } throw unexpected("boolean", b); @@ -137,49 +171,49 @@ else if (b == Code.TRUE) { @Override public byte readByte() { byte b = readInt8(); - if (Code.isFixInt(b)) { + if (isFixInt(b)) { return b; } switch (b) { - case Code.UINT8: // unsigned int 8 + case UINT8: // unsigned int 8 byte u8 = readInt8(); if (u8 < (byte) 0) { throw overflowU8(u8); } return u8; - case Code.UINT16: // unsigned int 16 + case UINT16: // unsigned int 16 short u16 = readInt16(); if (u16 < 0 || u16 > Byte.MAX_VALUE) { throw overflowU16(u16); } return (byte) u16; - case Code.UINT32: // unsigned int 32 + case UINT32: // unsigned int 32 int u32 = readInt32(); if (u32 < 0 || u32 > Byte.MAX_VALUE) { throw overflowU32(u32); } return (byte) u32; - case Code.UINT64: // unsigned int 64 + case UINT64: // unsigned int 64 long u64 = readInt64(); if (u64 < 0L || u64 > Byte.MAX_VALUE) { throw overflowU64(u64); } return (byte) u64; - case Code.INT8: // signed int 8 + case INT8: // signed int 8 return readInt8(); - case Code.INT16: // signed int 16 + case INT16: // signed int 16 short i16 = readInt16(); if (i16 < Byte.MIN_VALUE || i16 > Byte.MAX_VALUE) { throw overflowI16(i16); } return (byte) i16; - case Code.INT32: // signed int 32 + case INT32: // signed int 32 int i32 = readInt32(); if (i32 < Byte.MIN_VALUE || i32 > Byte.MAX_VALUE) { throw overflowI32(i32); } return (byte) i32; - case Code.INT64: // signed int 64 + case INT64: // signed int 64 long i64 = readInt64(); if (i64 < Byte.MIN_VALUE || i64 > Byte.MAX_VALUE) { throw overflowI64(i64); @@ -197,42 +231,42 @@ public int readUnsignedByte() { @Override public short readShort() { byte b = readInt8(); - if (Code.isFixInt(b)) { + if (isFixInt(b)) { return b; } switch (b) { - case Code.UINT8: // unsigned int 8 + case UINT8: // unsigned int 8 byte u8 = readInt8(); return (short) (u8 & 0xff); - case Code.UINT16: // unsigned int 16 + case UINT16: // unsigned int 16 short u16 = readInt16(); if (u16 < (short) 0) { throw overflowU16(u16); } return u16; - case Code.UINT32: // unsigned int 32 + case UINT32: // unsigned int 32 int u32 = readInt32(); if (u32 < 0 || u32 > Short.MAX_VALUE) { throw overflowU32(u32); } return (short) u32; - case Code.UINT64: // unsigned int 64 + case UINT64: // unsigned int 64 long u64 = readInt64(); if (u64 < 0L || u64 > Short.MAX_VALUE) { throw overflowU64(u64); } return (short) u64; - case Code.INT8: // signed int 8 + case INT8: // signed int 8 return readInt8(); - case Code.INT16: // signed int 16 + case INT16: // signed int 16 return readInt16(); - case Code.INT32: // signed int 32 + case INT32: // signed int 32 int i32 = readInt32(); if (i32 < Short.MIN_VALUE || i32 > Short.MAX_VALUE) { throw overflowI32(i32); } return (short) i32; - case Code.INT64: // signed int 64 + case INT64: // signed int 64 long i64 = readInt64(); if (i64 < Short.MIN_VALUE || i64 > Short.MAX_VALUE) { throw overflowI64(i64); @@ -250,35 +284,35 @@ public int readUnsignedShort() { @Override public int readInt() { byte b = readInt8(); - if (Code.isFixInt(b)) { + if (isFixInt(b)) { return b; } switch (b) { - case Code.UINT8: // unsigned int 8 + case UINT8: // unsigned int 8 byte u8 = readInt8(); return u8 & 0xff; - case Code.UINT16: // unsigned int 16 + case UINT16: // unsigned int 16 short u16 = readInt16(); return u16 & 0xffff; - case Code.UINT32: // unsigned int 32 + case UINT32: // unsigned int 32 int u32 = readInt32(); if (u32 < 0) { throw overflowU32(u32); } return u32; - case Code.UINT64: // unsigned int 64 + case UINT64: // unsigned int 64 long u64 = readInt64(); if (u64 < 0L || u64 > (long) Integer.MAX_VALUE) { throw overflowU64(u64); } return (int) u64; - case Code.INT8: // signed int 8 + case INT8: // signed int 8 return readInt8(); - case Code.INT16: // signed int 16 + case INT16: // signed int 16 return readInt16(); - case Code.INT32: // signed int 32 + case INT32: // signed int 32 return readInt32(); - case Code.INT64: // signed int 64 + case INT64: // signed int 64 long i64 = readInt64(); if (i64 < (long) Integer.MIN_VALUE || i64 > (long) Integer.MAX_VALUE) { throw overflowI64(i64); @@ -291,17 +325,17 @@ public int readInt() { @Override public long readLong() { byte b = readInt8(); - if (Code.isFixInt(b)) { + if (isFixInt(b)) { return b; } switch (b) { - case Code.UINT8: // unsigned int 8 + case UINT8: // unsigned int 8 byte u8 = readInt8(); return u8 & 0xff; - case Code.UINT16: // unsigned int 16 + case UINT16: // unsigned int 16 short u16 = readInt16(); return u16 & 0xffff; - case Code.UINT32: // unsigned int 32 + case UINT32: // unsigned int 32 int u32 = readInt32(); if (u32 < 0) { return (long) (u32 & 0x7fffffff) + 0x80000000L; @@ -309,19 +343,19 @@ public long readLong() { else { return u32; } - case Code.UINT64: // unsigned int 64 + case UINT64: // unsigned int 64 long u64 = readInt64(); if (u64 < 0L) { throw overflowU64(u64); } return u64; - case Code.INT8: // signed int 8 + case INT8: // signed int 8 return readInt8(); - case Code.INT16: // signed int 16 + case INT16: // signed int 16 return readInt16(); - case Code.INT32: // signed int 32 + case INT32: // signed int 32 return readInt32(); - case Code.INT64: // signed int 64 + case INT64: // signed int 64 return readInt64(); } throw unexpected("Integer", b); @@ -331,8 +365,8 @@ public long readLong() { public float readFloat() { byte b = readInt8(); return switch (b) { - case Code.FLOAT32 -> readFloat32(); - case Code.FLOAT64 -> (float) readFloat64(); + case FLOAT32 -> readFloat32(); + case FLOAT64 -> (float) readFloat64(); default -> throw unexpected("Float", b); }; } @@ -341,8 +375,8 @@ public float readFloat() { public double readDouble() { byte b = readInt8(); return switch (b) { - case Code.FLOAT32 -> readFloat32(); - case Code.FLOAT64 -> readFloat64(); + case FLOAT32 -> readFloat32(); + case FLOAT64 -> readFloat64(); default -> throw unexpected("Float", b); }; } @@ -455,14 +489,14 @@ public Map read(Function keyMapper, Function readNextLength16(); + case ARRAY16 -> readNextLength16(); // array 32 - case Code.ARRAY32 -> readNextLength32(); + case ARRAY32 -> readNextLength32(); default -> throw unexpected("Array", b); }; } @@ -481,12 +515,12 @@ public int readArrayHeader() { */ public int readMapHeader() { byte b = readInt8(); - if (Code.isFixedMap(b)) { // fixmap + if (isFixedMap(b)) { // fixmap return b & 0x0f; } return switch (b) { - case Code.MAP16 -> readNextLength16();// map 16 - case Code.MAP32 -> readNextLength32();// map 32 + case MAP16 -> readNextLength16();// map 16 + case MAP32 -> readNextLength32();// map 32 default -> throw unexpected("Map", b); }; } @@ -494,37 +528,37 @@ public int readMapHeader() { public ExtensionTypeHeader readExtensionTypeHeader() { byte b = readInt8(); switch (b) { - case Code.FIXEXT1: { + case FIXEXT1: { byte type = readInt8(); return new ExtensionTypeHeader(type, 1); } - case Code.FIXEXT2: { + case FIXEXT2: { byte type = readInt8(); return new ExtensionTypeHeader(type, 2); } - case Code.FIXEXT4: { + case FIXEXT4: { byte type = readInt8(); return new ExtensionTypeHeader(type, 4); } - case Code.FIXEXT8: { + case FIXEXT8: { byte type = readInt8(); return new ExtensionTypeHeader(type, 8); } - case Code.FIXEXT16: { + case FIXEXT16: { byte type = readInt8(); return new ExtensionTypeHeader(type, 16); } - case Code.EXT8: { + case EXT8: { int length = readNextLength8(); byte type = readInt8(); return new ExtensionTypeHeader(type, length); } - case Code.EXT16: { + case EXT16: { int length = readNextLength16(); byte type = readInt8(); return new ExtensionTypeHeader(type, length); } - case Code.EXT32: { + case EXT32: { int length = readNextLength32(); byte type = readInt8(); return new ExtensionTypeHeader(type, length); @@ -581,25 +615,25 @@ private int readNextLength32() { private int tryReadStringHeader(byte b) { return switch (b) { - case Code.STR8 -> readNextLength8(); // str 8 - case Code.STR16 -> readNextLength16(); // str 16 - case Code.STR32 -> readNextLength32(); // str 32 + case STR8 -> readNextLength8(); // str 8 + case STR16 -> readNextLength16(); // str 16 + case STR32 -> readNextLength32(); // str 32 default -> -1; }; } private int tryReadBinaryHeader(byte b) { return switch (b) { - case Code.BIN8 -> readNextLength8(); // bin 8 - case Code.BIN16 -> readNextLength16(); // bin 16 - case Code.BIN32 -> readNextLength32(); // bin 32 + case BIN8 -> readNextLength8(); // bin 8 + case BIN16 -> readNextLength16(); // bin 16 + case BIN32 -> readNextLength32(); // bin 32 default -> -1; }; } public int readStringHeader() { byte b = readInt8(); - if (Code.isFixedRaw(b)) { // FixRaw + if (isFixedRaw(b)) { // FixRaw return b & 0x1f; } int len = tryReadStringHeader(b); @@ -624,11 +658,11 @@ public int readStringHeader() { * @return the size of the map to be read * @throws MessageTypeException when value is not MessagePack Map type * @throws MessageSizeException when size of the map is larger than 2^31 - 1 - * @ when underlying input + * when underlying input */ public int readBinaryHeader() { byte b = readInt8(); - if (Code.isFixedRaw(b)) { // FixRaw + if (isFixedRaw(b)) { // FixRaw return b & 0x1f; } int len = tryReadBinaryHeader(b); @@ -646,7 +680,7 @@ public int readBinaryHeader() { */ public void readNull() { byte b = readInt8(); - if (b == Code.NIL) { + if (b == NIL) { return; } throw unexpected("Nil", b); @@ -669,7 +703,7 @@ public boolean tryReadNull() { } int index = buffer.readerIndex(); byte b = buffer.getByte(index); - if (b == Code.NIL) { + if (b == NIL) { buffer.readerIndex(index + 1); return true; } diff --git a/today-service-api/src/main/java/infra/cloud/serialize/MessagePackWriter.java b/today-service-api/src/main/java/infra/cloud/serialize/MessagePackWriter.java index f6181e8..d597f39 100644 --- a/today-service-api/src/main/java/infra/cloud/serialize/MessagePackWriter.java +++ b/today-service-api/src/main/java/infra/cloud/serialize/MessagePackWriter.java @@ -25,40 +25,39 @@ import java.util.function.BiConsumer; import java.util.function.Consumer; -import infra.cloud.serialize.format.MessagePack; import infra.lang.Enumerable; import io.netty.buffer.ByteBuf; -import static infra.cloud.serialize.format.MessagePack.Code.ARRAY16; -import static infra.cloud.serialize.format.MessagePack.Code.ARRAY32; -import static infra.cloud.serialize.format.MessagePack.Code.BIN16; -import static infra.cloud.serialize.format.MessagePack.Code.BIN32; -import static infra.cloud.serialize.format.MessagePack.Code.BIN8; -import static infra.cloud.serialize.format.MessagePack.Code.EXT8; -import static infra.cloud.serialize.format.MessagePack.Code.EXT_TIMESTAMP; -import static infra.cloud.serialize.format.MessagePack.Code.FALSE; -import static infra.cloud.serialize.format.MessagePack.Code.FIXARRAY_PREFIX; -import static infra.cloud.serialize.format.MessagePack.Code.FIXEXT4; -import static infra.cloud.serialize.format.MessagePack.Code.FIXEXT8; -import static infra.cloud.serialize.format.MessagePack.Code.FIXMAP_PREFIX; -import static infra.cloud.serialize.format.MessagePack.Code.FIXSTR_PREFIX; -import static infra.cloud.serialize.format.MessagePack.Code.FLOAT32; -import static infra.cloud.serialize.format.MessagePack.Code.FLOAT64; -import static infra.cloud.serialize.format.MessagePack.Code.INT16; -import static infra.cloud.serialize.format.MessagePack.Code.INT32; -import static infra.cloud.serialize.format.MessagePack.Code.INT64; -import static infra.cloud.serialize.format.MessagePack.Code.INT8; -import static infra.cloud.serialize.format.MessagePack.Code.MAP16; -import static infra.cloud.serialize.format.MessagePack.Code.MAP32; -import static infra.cloud.serialize.format.MessagePack.Code.NIL; -import static infra.cloud.serialize.format.MessagePack.Code.STR16; -import static infra.cloud.serialize.format.MessagePack.Code.STR32; -import static infra.cloud.serialize.format.MessagePack.Code.STR8; -import static infra.cloud.serialize.format.MessagePack.Code.TRUE; -import static infra.cloud.serialize.format.MessagePack.Code.UINT16; -import static infra.cloud.serialize.format.MessagePack.Code.UINT32; -import static infra.cloud.serialize.format.MessagePack.Code.UINT64; -import static infra.cloud.serialize.format.MessagePack.Code.UINT8; +import static infra.cloud.serialize.format.MessagePackCode.ARRAY16; +import static infra.cloud.serialize.format.MessagePackCode.ARRAY32; +import static infra.cloud.serialize.format.MessagePackCode.BIN16; +import static infra.cloud.serialize.format.MessagePackCode.BIN32; +import static infra.cloud.serialize.format.MessagePackCode.BIN8; +import static infra.cloud.serialize.format.MessagePackCode.EXT8; +import static infra.cloud.serialize.format.MessagePackCode.EXT_TIMESTAMP; +import static infra.cloud.serialize.format.MessagePackCode.FALSE; +import static infra.cloud.serialize.format.MessagePackCode.FIXARRAY_PREFIX; +import static infra.cloud.serialize.format.MessagePackCode.FIXEXT4; +import static infra.cloud.serialize.format.MessagePackCode.FIXEXT8; +import static infra.cloud.serialize.format.MessagePackCode.FIXMAP_PREFIX; +import static infra.cloud.serialize.format.MessagePackCode.FIXSTR_PREFIX; +import static infra.cloud.serialize.format.MessagePackCode.FLOAT32; +import static infra.cloud.serialize.format.MessagePackCode.FLOAT64; +import static infra.cloud.serialize.format.MessagePackCode.INT16; +import static infra.cloud.serialize.format.MessagePackCode.INT32; +import static infra.cloud.serialize.format.MessagePackCode.INT64; +import static infra.cloud.serialize.format.MessagePackCode.INT8; +import static infra.cloud.serialize.format.MessagePackCode.MAP16; +import static infra.cloud.serialize.format.MessagePackCode.MAP32; +import static infra.cloud.serialize.format.MessagePackCode.NIL; +import static infra.cloud.serialize.format.MessagePackCode.STR16; +import static infra.cloud.serialize.format.MessagePackCode.STR32; +import static infra.cloud.serialize.format.MessagePackCode.STR8; +import static infra.cloud.serialize.format.MessagePackCode.TRUE; +import static infra.cloud.serialize.format.MessagePackCode.UINT16; +import static infra.cloud.serialize.format.MessagePackCode.UINT32; +import static infra.cloud.serialize.format.MessagePackCode.UINT64; +import static infra.cloud.serialize.format.MessagePackCode.UINT8; /** * A writer for serializing data into MessagePack format. @@ -84,9 +83,7 @@ public MessagePackWriter(ByteBuf buffer) { * This method is used with {@link #writeStringHeader(int)} or {@link #writeBinaryHeader(int)} methods. *

          * Unlike {@link #writeFully(byte[])} method, this method does not make a defensive copy of the given byte - * array, even if it is shorter than {@link MessagePack.PackerConfig#withBufferFlushThreshold(int)}. This is - * faster than {@link #writeFully(byte[])} method but caller must not modify the byte array after calling - * this method. + * array * * @param b the data to add * @throws SerializationException if an I/O error occurs. diff --git a/today-service-client/build.gradle b/today-service-client/build.gradle index 61da229..a59dbc6 100644 --- a/today-service-client/build.gradle +++ b/today-service-client/build.gradle @@ -7,8 +7,10 @@ dependencies { api project(":today-service-api") api project(":today-service-discovery") + optional "cn.taketoday:infra-context" optional project(":today-remoting-transport-tcp") + testImplementation "cn.taketoday:infra-app-test" testImplementation project(":today-cloud-samples:demo-tests:demo-user-api") } \ No newline at end of file diff --git a/today-service-discovery/build.gradle b/today-service-discovery/build.gradle index 0c0fd7f..a0dded1 100644 --- a/today-service-discovery/build.gradle +++ b/today-service-discovery/build.gradle @@ -6,7 +6,7 @@ dependencies { implementation 'cn.taketoday:infra-beans' implementation 'cn.taketoday:infra-context' - + testImplementation 'cn.taketoday:infra-app-test' testImplementation project(":today-cloud-samples:demo-tests:demo-user-api") } \ No newline at end of file diff --git a/today-service-provider/build.gradle b/today-service-provider/build.gradle index c84a066..956e011 100644 --- a/today-service-provider/build.gradle +++ b/today-service-provider/build.gradle @@ -7,6 +7,7 @@ dependencies { api project(":today-cloud-core") api project(":today-service-api") + optional 'cn.taketoday:infra-context' optional project(":today-remoting-transport-tcp") annotationProcessor 'cn.taketoday:infra-configuration-processor' diff --git a/today-service-provider/src/main/java/infra/cloud/provider/ServiceServerProperties.java b/today-service-provider/src/main/java/infra/cloud/provider/ServiceServerProperties.java index 025a41c..d326442 100644 --- a/today-service-provider/src/main/java/infra/cloud/provider/ServiceServerProperties.java +++ b/today-service-provider/src/main/java/infra/cloud/provider/ServiceServerProperties.java @@ -14,6 +14,12 @@ * limitations under the License. */ +package infra.cloud.provider; + +import org.jspecify.annotations.Nullable; + +import java.time.Duration; + import infra.cloud.service.config.ResumeProperties; import infra.context.properties.ConfigurationProperties; import infra.context.properties.NestedConfigurationProperty; diff --git a/today-service-registration/src/main/java/infra/cloud/registry/annotation/config/AutoServiceRegistrationConfiguration.java b/today-service-registration/src/main/java/infra/cloud/registry/annotation/config/AutoServiceRegistrationConfiguration.java index aa41517..ef27a42 100644 --- a/today-service-registration/src/main/java/infra/cloud/registry/annotation/config/AutoServiceRegistrationConfiguration.java +++ b/today-service-registration/src/main/java/infra/cloud/registry/annotation/config/AutoServiceRegistrationConfiguration.java @@ -12,7 +12,11 @@ * 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. - */Properties; + */ + +package infra.cloud.registry.annotation.config; + +import infra.cloud.registry.AutoServiceRegistrationProperties; import infra.context.annotation.Configuration; import infra.context.condition.ConditionalOnProperty; import infra.context.properties.EnableConfigurationProperties; diff --git a/today-service-serialization/build.gradle b/today-service-serialization/build.gradle index aba27f8..5ccb830 100644 --- a/today-service-serialization/build.gradle +++ b/today-service-serialization/build.gradle @@ -4,10 +4,3 @@ dependencies { api "cn.taketoday:infra-core" } - -compileJava { - options.compilerArgs += [ - "--add-exports=java.base/sun.nio.ch=ALL-UNNAMED" - ] -} - diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/ExtensionTypeHeader.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/ExtensionTypeHeader.java index a3ac1cc..41155e3 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/ExtensionTypeHeader.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/ExtensionTypeHeader.java @@ -12,10 +12,16 @@ * 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. - */es */ + +package infra.cloud.serialize.format; + +import infra.lang.Assert; + public class ExtensionTypeHeader { + private final byte type; + private final int length; /** @@ -48,7 +54,7 @@ public byte getType() { } public boolean isTimestampType() { - return type == MessagePack.Code.EXT_TIMESTAMP; + return type == MessagePackCode.EXT_TIMESTAMP; } public int getLength() { diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageBufferPacker.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageBufferPacker.java deleted file mode 100644 index dfe1ecf..0000000 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageBufferPacker.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright 2021 - 2026 the TODAY 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 - * - * https://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 infra.cloud.serialize.format; - -import java.io.IOException; -import java.util.List; - -import infra.cloud.serialize.format.buffer.ArrayBufferOutput; -import infra.cloud.serialize.format.buffer.MessageBuffer; -import infra.cloud.serialize.format.buffer.MessageBufferOutput; - -/** - * MessagePacker that is useful to produce byte array output. - *

          - * This class allocates a new buffer instead of resizing the buffer when data doesn't fit in the initial capacity. - * This is faster than ByteArrayOutputStream especially when size of written bytes is large because resizing a buffer - * usually needs to copy contents of the buffer. - */ -public class MessageBufferPacker extends MessagePacker { - - protected MessageBufferPacker(MessagePack.PackerConfig config) { - this(new ArrayBufferOutput(config.getBufferSize()), config); - } - - protected MessageBufferPacker(ArrayBufferOutput out, MessagePack.PackerConfig config) { - super(out, config); - } - - public MessageBufferOutput reset(MessageBufferOutput out) throws IOException { - if (!(out instanceof ArrayBufferOutput)) { - throw new IllegalArgumentException("MessageBufferPacker accepts only ArrayBufferOutput"); - } - return super.reset(out); - } - - private ArrayBufferOutput getArrayBufferOut() { - return (ArrayBufferOutput) out; - } - - @Override - public void clear() { - super.clear(); - getArrayBufferOut().clear(); - } - - /** - * Gets copy of the written data as a byte array. - *

          - * If your application needs better performance and smaller memory consumption, you may prefer - * {@link #toMessageBuffer()} or {@link #toBufferList()} to avoid copying. - * - * @return the byte array - */ - public byte[] toByteArray() { - try { - flush(); - } - catch (IOException ex) { - // IOException must not happen because underlying ArrayBufferOutput never throws IOException - throw new RuntimeException(ex); - } - return getArrayBufferOut().toByteArray(); - } - - /** - * Gets the written data as a MessageBuffer. - *

          - * Unlike {@link #toByteArray()}, this method omits copy of the contents if size of the written data is smaller - * than a single buffer capacity. - * - * @return the MessageBuffer instance - */ - public MessageBuffer toMessageBuffer() { - try { - flush(); - } - catch (IOException ex) { - // IOException must not happen because underlying ArrayBufferOutput never throws IOException - throw new RuntimeException(ex); - } - return getArrayBufferOut().toMessageBuffer(); - } - - /** - * Returns the written data as a list of MessageBuffer. - *

          - * Unlike {@link #toByteArray()} or {@link #toMessageBuffer()}, this is the fastest method that doesn't - * copy contents in any cases. - * - * @return the list of MessageBuffer instances - */ - public List toBufferList() { - try { - flush(); - } - catch (IOException ex) { - // IOException must not happen because underlying ArrayBufferOutput never throws IOException - throw new RuntimeException(ex); - } - return getArrayBufferOut().toBufferList(); - } - - /** - * @return the size of the buffer in use - */ - public int getBufferSize() { - return getArrayBufferOut().getSize(); - } -} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageFormat.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageFormat.java index daba74b..a1f6163 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageFormat.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageFormat.java @@ -16,8 +16,6 @@ package infra.cloud.serialize.format; -import infra.cloud.serialize.format.MessagePack.Code; -import infra.cloud.serialize.format.value.ValueType; import infra.lang.VisibleForTesting; /** @@ -111,52 +109,52 @@ public static MessageFormat valueOf(final byte b) { */ @VisibleForTesting static MessageFormat toMessageFormat(final byte b) { - if (Code.isPosFixInt(b)) { + if (MessagePackCode.isPosFixInt(b)) { return POS_FIX_INT; } - if (Code.isNegFixInt(b)) { + if (MessagePackCode.isNegFixInt(b)) { return NEG_FIX_INT; } - if (Code.isFixStr(b)) { + if (MessagePackCode.isFixStr(b)) { return FIX_STR; } - if (Code.isFixedArray(b)) { + if (MessagePackCode.isFixedArray(b)) { return FIX_ARRAY; } - if (Code.isFixedMap(b)) { + if (MessagePackCode.isFixedMap(b)) { return FIX_MAP; } return switch (b) { - case Code.NIL -> NIL; - case Code.FALSE, Code.TRUE -> BOOLEAN; - case Code.BIN8 -> BIN8; - case Code.BIN16 -> BIN16; - case Code.BIN32 -> BIN32; - case Code.EXT8 -> EXT8; - case Code.EXT16 -> EXT16; - case Code.EXT32 -> EXT32; - case Code.FLOAT32 -> FLOAT32; - case Code.FLOAT64 -> FLOAT64; - case Code.UINT8 -> UINT8; - case Code.UINT16 -> UINT16; - case Code.UINT32 -> UINT32; - case Code.UINT64 -> UINT64; - case Code.INT8 -> INT8; - case Code.INT16 -> INT16; - case Code.INT32 -> INT32; - case Code.INT64 -> INT64; - case Code.FIXEXT1 -> FIX_EXT1; - case Code.FIXEXT2 -> FIX_EXT2; - case Code.FIXEXT4 -> FIX_EXT4; - case Code.FIXEXT8 -> FIX_EXT8; - case Code.FIXEXT16 -> FIX_EXT16; - case Code.STR8 -> STR8; - case Code.STR16 -> STR16; - case Code.STR32 -> STR32; - case Code.ARRAY16 -> ARRAY16; - case Code.ARRAY32 -> ARRAY32; - case Code.MAP16 -> MAP16; - case Code.MAP32 -> MAP32; + case MessagePackCode.NIL -> NIL; + case MessagePackCode.FALSE, MessagePackCode.TRUE -> BOOLEAN; + case MessagePackCode.BIN8 -> BIN8; + case MessagePackCode.BIN16 -> BIN16; + case MessagePackCode.BIN32 -> BIN32; + case MessagePackCode.EXT8 -> EXT8; + case MessagePackCode.EXT16 -> EXT16; + case MessagePackCode.EXT32 -> EXT32; + case MessagePackCode.FLOAT32 -> FLOAT32; + case MessagePackCode.FLOAT64 -> FLOAT64; + case MessagePackCode.UINT8 -> UINT8; + case MessagePackCode.UINT16 -> UINT16; + case MessagePackCode.UINT32 -> UINT32; + case MessagePackCode.UINT64 -> UINT64; + case MessagePackCode.INT8 -> INT8; + case MessagePackCode.INT16 -> INT16; + case MessagePackCode.INT32 -> INT32; + case MessagePackCode.INT64 -> INT64; + case MessagePackCode.FIXEXT1 -> FIX_EXT1; + case MessagePackCode.FIXEXT2 -> FIX_EXT2; + case MessagePackCode.FIXEXT4 -> FIX_EXT4; + case MessagePackCode.FIXEXT8 -> FIX_EXT8; + case MessagePackCode.FIXEXT16 -> FIX_EXT16; + case MessagePackCode.STR8 -> STR8; + case MessagePackCode.STR16 -> STR16; + case MessagePackCode.STR32 -> STR32; + case MessagePackCode.ARRAY16 -> ARRAY16; + case MessagePackCode.ARRAY32 -> ARRAY32; + case MessagePackCode.MAP16 -> MAP16; + case MessagePackCode.MAP32 -> MAP32; default -> NEVER_USED; }; } diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessagePack.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessagePack.java deleted file mode 100644 index 5f7fad6..0000000 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessagePack.java +++ /dev/null @@ -1,699 +0,0 @@ -/* - * Copyright 2021 - 2026 the TODAY 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 - * - * https://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 infra.cloud.serialize.format; - -import java.io.InputStream; -import java.io.OutputStream; -import java.nio.ByteBuffer; -import java.nio.channels.ReadableByteChannel; -import java.nio.channels.WritableByteChannel; -import java.nio.charset.Charset; -import java.nio.charset.CodingErrorAction; -import java.nio.charset.StandardCharsets; - -import infra.cloud.serialize.format.buffer.ArrayBufferInput; -import infra.cloud.serialize.format.buffer.ByteBufferInput; -import infra.cloud.serialize.format.buffer.ChannelBufferInput; -import infra.cloud.serialize.format.buffer.ChannelBufferOutput; -import infra.cloud.serialize.format.buffer.InputStreamBufferInput; -import infra.cloud.serialize.format.buffer.MessageBufferInput; -import infra.cloud.serialize.format.buffer.MessageBufferOutput; -import infra.cloud.serialize.format.buffer.OutputStreamBufferOutput; - -/** - * Convenience class to build packer and unpacker classes. - *

          - * You can select an appropriate factory method as following. - * - *

          - * Deserializing objects from binary: - * - * - * - * - * - * - * - * - *
          Input typeFactory methodReturn type
          byte[]{@link #newUnpacker(byte[], int, int)}{@link MessageUnpacker}
          ByteBuffer{@link #newUnpacker(ByteBuffer)}{@link MessageUnpacker}
          InputStream{@link #newUnpacker(InputStream)}{@link MessageUnpacker}
          ReadableByteChannel{@link #newUnpacker(ReadableByteChannel)}{@link MessageUnpacker}
          {@link MessageBufferInput}{@link #newUnpacker(MessageBufferInput)}{@link MessageUnpacker}
          - * - *

          - * Serializing objects into binary: - * - * - * - * - * - * - * - *
          Output typeFactory methodReturn type
          byte[]{@link #newBufferPacker()}{@link MessageBufferPacker}
          OutputStream{@link #newPacker(OutputStream)}{@link MessagePacker}
          WritableByteChannel{@link #newPacker(WritableByteChannel)}{@link MessagePacker}
          {@link MessageBufferOutput}{@link #newPacker(MessageBufferOutput)}{@link MessagePacker}
          - */ -public class MessagePack { - - /** - * Applications should use java.nio.charset.StandardCharsets.UTF_8 instead since Java 7. - */ - public static final Charset UTF8 = StandardCharsets.UTF_8; - - /** - * Configuration of a {@link MessagePacker} used by {@link #newPacker(MessageBufferOutput)} and {@link #newBufferPacker()} methods. - */ - public static final PackerConfig DEFAULT_PACKER_CONFIG = new PackerConfig(); - - /** - * Configuration of a {@link MessageUnpacker} used by {@link #newUnpacker(MessageBufferInput)} methods. - */ - public static final UnpackerConfig DEFAULT_UNPACKER_CONFIG = new UnpackerConfig(); - - /** - * The prefix code set of MessagePack format. See also https://github.com/msgpack/msgpack/blob/master/spec.md for details. - */ - public static final class Code { - public static boolean isFixInt(byte b) { - int v = b & 0xFF; - return v <= 0x7f || v >= 0xe0; - } - - public static boolean isPosFixInt(byte b) { - return (b & POSFIXINT_MASK) == 0; - } - - public static boolean isNegFixInt(byte b) { - return (b & NEGFIXINT_PREFIX) == NEGFIXINT_PREFIX; - } - - public static boolean isFixStr(byte b) { - return (b & (byte) 0xe0) == Code.FIXSTR_PREFIX; - } - - public static boolean isFixedArray(byte b) { - return (b & (byte) 0xf0) == Code.FIXARRAY_PREFIX; - } - - public static boolean isFixedMap(byte b) { - return (b & (byte) 0xf0) == Code.FIXMAP_PREFIX; - } - - public static boolean isFixedRaw(byte b) { - return (b & (byte) 0xe0) == Code.FIXSTR_PREFIX; - } - - public static final byte POSFIXINT_MASK = (byte) 0x80; - - public static final byte FIXMAP_PREFIX = (byte) 0x80; - public static final byte FIXARRAY_PREFIX = (byte) 0x90; - public static final byte FIXSTR_PREFIX = (byte) 0xa0; - - public static final byte NIL = (byte) 0xc0; - public static final byte NEVER_USED = (byte) 0xc1; - public static final byte FALSE = (byte) 0xc2; - public static final byte TRUE = (byte) 0xc3; - public static final byte BIN8 = (byte) 0xc4; - public static final byte BIN16 = (byte) 0xc5; - public static final byte BIN32 = (byte) 0xc6; - public static final byte EXT8 = (byte) 0xc7; - public static final byte EXT16 = (byte) 0xc8; - public static final byte EXT32 = (byte) 0xc9; - public static final byte FLOAT32 = (byte) 0xca; - public static final byte FLOAT64 = (byte) 0xcb; - public static final byte UINT8 = (byte) 0xcc; - public static final byte UINT16 = (byte) 0xcd; - public static final byte UINT32 = (byte) 0xce; - public static final byte UINT64 = (byte) 0xcf; - - public static final byte INT8 = (byte) 0xd0; - public static final byte INT16 = (byte) 0xd1; - public static final byte INT32 = (byte) 0xd2; - public static final byte INT64 = (byte) 0xd3; - - public static final byte FIXEXT1 = (byte) 0xd4; - public static final byte FIXEXT2 = (byte) 0xd5; - public static final byte FIXEXT4 = (byte) 0xd6; - public static final byte FIXEXT8 = (byte) 0xd7; - public static final byte FIXEXT16 = (byte) 0xd8; - - public static final byte STR8 = (byte) 0xd9; - public static final byte STR16 = (byte) 0xda; - public static final byte STR32 = (byte) 0xdb; - - public static final byte ARRAY16 = (byte) 0xdc; - public static final byte ARRAY32 = (byte) 0xdd; - - public static final byte MAP16 = (byte) 0xde; - public static final byte MAP32 = (byte) 0xdf; - - public static final byte NEGFIXINT_PREFIX = (byte) 0xe0; - - public static final byte EXT_TIMESTAMP = (byte) -1; - } - - private MessagePack() { - // Prohibit instantiation of this class - } - - /** - * Creates a packer that serializes objects into the specified output. - *

          - * {@link MessageBufferOutput} is an interface that lets applications customize memory - * allocation of internal buffer of {@link MessagePacker}. You may prefer {@link #newBufferPacker()}, - * {@link #newPacker(OutputStream)}, or {@link #newPacker(WritableByteChannel)} methods instead. - *

          - * This method is equivalent to DEFAULT_PACKER_CONFIG.newPacker(out). - * - * @param out A MessageBufferOutput that allocates buffer chunks and receives the buffer chunks with packed data filled in them - * @return A new MessagePacker instance - */ - public static MessagePacker newPacker(MessageBufferOutput out) { - return DEFAULT_PACKER_CONFIG.newPacker(out); - } - - /** - * Creates a packer that serializes objects into the specified output stream. - *

          - * Note that you don't have to wrap OutputStream in BufferedOutputStream because MessagePacker has buffering - * internally. - *

          - * This method is equivalent to DEFAULT_PACKER_CONFIG.newPacker(out). - * - * @param out The output stream that receives sequence of bytes - * @return A new MessagePacker instance - */ - public static MessagePacker newPacker(OutputStream out) { - return DEFAULT_PACKER_CONFIG.newPacker(out); - } - - /** - * Creates a packer that serializes objects into the specified writable channel. - *

          - * This method is equivalent to DEFAULT_PACKER_CONFIG.newPacker(channel). - * - * @param channel The output channel that receives sequence of bytes - * @return A new MessagePacker instance - */ - public static MessagePacker newPacker(WritableByteChannel channel) { - return DEFAULT_PACKER_CONFIG.newPacker(channel); - } - - /** - * Creates a packer that serializes objects into byte arrays. - *

          - * This method provides an optimized implementation of newDefaultBufferPacker(new ByteArrayOutputStream()). - *

          - * This method is equivalent to DEFAULT_PACKER_CONFIG.newBufferPacker(). - * - * @return A new MessageBufferPacker instance - */ - public static MessageBufferPacker newBufferPacker() { - return DEFAULT_PACKER_CONFIG.newBufferPacker(); - } - - /** - * Creates an unpacker that deserializes objects from a specified input. - *

          - * {@link MessageBufferInput} is an interface that lets applications customize memory - * allocation of internal buffer of {@link MessageUnpacker}. You may prefer - * {@link #newUnpacker(InputStream)}, {@link #newUnpacker(ReadableByteChannel)}, - * {@link #newUnpacker(byte[], int, int)}, or {@link #newUnpacker(ByteBuffer)} methods instead. - *

          - * This method is equivalent to DEFAULT_UNPACKER_CONFIG.newDefaultUnpacker(in). - * - * @param in The input stream that provides sequence of buffer chunks and optionally reuses them when MessageUnpacker consumed one completely - * @return A new MessageUnpacker instance - */ - public static MessageUnpacker newUnpacker(MessageBufferInput in) { - return DEFAULT_UNPACKER_CONFIG.newUnpacker(in); - } - - /** - * Creates an unpacker that deserializes objects from a specified input stream. - *

          - * Note that you don't have to wrap InputStream in BufferedInputStream because MessageUnpacker has buffering - * internally. - *

          - * This method is equivalent to DEFAULT_UNPACKER_CONFIG.newDefaultUnpacker(in). - * - * @param in The input stream that provides sequence of bytes - * @return A new MessageUnpacker instance - */ - public static MessageUnpacker newUnpacker(InputStream in) { - return DEFAULT_UNPACKER_CONFIG.newUnpacker(in); - } - - /** - * Creates an unpacker that deserializes objects from a specified readable channel. - *

          - * This method is equivalent to DEFAULT_UNPACKER_CONFIG.newDefaultUnpacker(in). - * - * @param channel The input channel that provides sequence of bytes - * @return A new MessageUnpacker instance - */ - public static MessageUnpacker newUnpacker(ReadableByteChannel channel) { - return DEFAULT_UNPACKER_CONFIG.newUnpacker(channel); - } - - /** - * Creates an unpacker that deserializes objects from a specified byte array. - *

          - * This method provides an optimized implementation of newDefaultUnpacker(new ByteArrayInputStream(contents)). - *

          - * This method is equivalent to DEFAULT_UNPACKER_CONFIG.newDefaultUnpacker(contents). - * - * @param contents The byte array that contains packed objects in MessagePack format - * @return A new MessageUnpacker instance that will never throw IOException - */ - public static MessageUnpacker newUnpacker(byte[] contents) { - return DEFAULT_UNPACKER_CONFIG.newUnpacker(contents); - } - - /** - * Creates an unpacker that deserializes objects from subarray of a specified byte array. - *

          - * This method provides an optimized implementation of newDefaultUnpacker(new ByteArrayInputStream(contents, offset, length)). - *

          - * This method is equivalent to DEFAULT_UNPACKER_CONFIG.newDefaultUnpacker(contents). - * - * @param contents The byte array that contains packed objects - * @param offset The index of the first byte - * @param length The number of bytes - * @return A new MessageUnpacker instance that will never throw IOException - */ - public static MessageUnpacker newUnpacker(byte[] contents, int offset, int length) { - return DEFAULT_UNPACKER_CONFIG.newUnpacker(contents, offset, length); - } - - /** - * Creates an unpacker that deserializes objects from a specified ByteBuffer. - *

          - * Note that the returned unpacker reads data from the current position of the ByteBuffer until its limit. - * However, its position does not change when unpacker reads data. You may use - * {@link MessageUnpacker#getTotalReadBytes()} to get actual amount of bytes used in ByteBuffer. - *

          - * This method supports both non-direct buffer and direct buffer. - * - * @param contents The byte buffer that contains packed objects - * @return A new MessageUnpacker instance that will never throw IOException - */ - public static MessageUnpacker newUnpacker(ByteBuffer contents) { - return DEFAULT_UNPACKER_CONFIG.newUnpacker(contents); - } - - /** - * MessagePacker configuration. - */ - public static class PackerConfig implements Cloneable { - - private int smallStringOptimizationThreshold = 512; - - private int bufferFlushThreshold = 8192; - - private int bufferSize = 8192; - - private boolean str8FormatSupport = true; - - public PackerConfig() { - } - - private PackerConfig(PackerConfig copy) { - this.smallStringOptimizationThreshold = copy.smallStringOptimizationThreshold; - this.bufferFlushThreshold = copy.bufferFlushThreshold; - this.bufferSize = copy.bufferSize; - this.str8FormatSupport = copy.str8FormatSupport; - } - - @Override - public PackerConfig clone() { - return new PackerConfig(this); - } - - @Override - public int hashCode() { - int result = smallStringOptimizationThreshold; - result = 31 * result + bufferFlushThreshold; - result = 31 * result + bufferSize; - result = 31 * result + (str8FormatSupport ? 1 : 0); - return result; - } - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof PackerConfig o)) { - return false; - } - return this.smallStringOptimizationThreshold == o.smallStringOptimizationThreshold - && this.bufferFlushThreshold == o.bufferFlushThreshold - && this.bufferSize == o.bufferSize - && this.str8FormatSupport == o.str8FormatSupport; - } - - /** - * Creates a packer that serializes objects into the specified output. - *

          - * {@link MessageBufferOutput} is an interface that lets applications customize memory - * allocation of internal buffer of {@link MessagePacker}. - * - * @param out A MessageBufferOutput that allocates buffer chunks and receives the buffer chunks with packed data filled in them - * @return A new MessagePacker instance - */ - public MessagePacker newPacker(MessageBufferOutput out) { - return new MessagePacker(out, this); - } - - /** - * Creates a packer that serializes objects into the specified output stream. - *

          - * Note that you don't have to wrap OutputStream in BufferedOutputStream because MessagePacker has buffering - * internally. - * - * @param out The output stream that receives sequence of bytes - * @return A new MessagePacker instance - */ - public MessagePacker newPacker(OutputStream out) { - return newPacker(new OutputStreamBufferOutput(out, bufferSize)); - } - - /** - * Creates a packer that serializes objects into the specified writable channel. - * - * @param channel The output channel that receives sequence of bytes - * @return A new MessagePacker instance - */ - public MessagePacker newPacker(WritableByteChannel channel) { - return newPacker(new ChannelBufferOutput(channel, bufferSize)); - } - - /** - * Creates a packer that serializes objects into byte arrays. - *

          - * This method provides an optimized implementation of newDefaultBufferPacker(new ByteArrayOutputStream()). - * - * @return A new MessageBufferPacker instance - */ - public MessageBufferPacker newBufferPacker() { - return new MessageBufferPacker(this); - } - - /** - * Use String.getBytes() for converting Java Strings that are shorter than this threshold. - * Note that this parameter is subject to change. - */ - public PackerConfig withSmallStringOptimizationThreshold(int length) { - PackerConfig copy = clone(); - copy.smallStringOptimizationThreshold = length; - return copy; - } - - public int getSmallStringOptimizationThreshold() { - return smallStringOptimizationThreshold; - } - - /** - * When the next payload size exceeds this threshold, MessagePacker will call - * {@link MessageBufferOutput#flush()} before writing more data (default: 8192). - */ - public PackerConfig withBufferFlushThreshold(int bytes) { - PackerConfig copy = clone(); - copy.bufferFlushThreshold = bytes; - return copy; - } - - public int getBufferFlushThreshold() { - return bufferFlushThreshold; - } - - /** - * When a packer is created with {@link #newPacker(OutputStream)} or {@link #newPacker(WritableByteChannel)}, the stream will be - * buffered with this size of buffer (default: 8192). - */ - public PackerConfig withBufferSize(int bytes) { - PackerConfig copy = clone(); - copy.bufferSize = bytes; - return copy; - } - - public int getBufferSize() { - return bufferSize; - } - - /** - * Disable str8 format when needed backward compatibility between - * different msgpack serializer versions. - * default true (str8 supported enabled) - */ - public PackerConfig withStr8FormatSupport(boolean str8FormatSupport) { - PackerConfig copy = clone(); - copy.str8FormatSupport = str8FormatSupport; - return copy; - } - - public boolean isStr8FormatSupport() { - return str8FormatSupport; - } - } - - /** - * MessageUnpacker configuration. - */ - public static class UnpackerConfig implements Cloneable { - - private boolean allowReadingStringAsBinary = true; - - private boolean allowReadingBinaryAsString = true; - - private CodingErrorAction actionOnMalformedString = CodingErrorAction.REPLACE; - - private CodingErrorAction actionOnUnmappableString = CodingErrorAction.REPLACE; - - private int stringSizeLimit = Integer.MAX_VALUE; - - private int bufferSize = 8192; - - private int stringDecoderBufferSize = 8192; - - public UnpackerConfig() { - } - - private UnpackerConfig(UnpackerConfig copy) { - this.allowReadingStringAsBinary = copy.allowReadingStringAsBinary; - this.allowReadingBinaryAsString = copy.allowReadingBinaryAsString; - this.actionOnMalformedString = copy.actionOnMalformedString; - this.actionOnUnmappableString = copy.actionOnUnmappableString; - this.stringDecoderBufferSize = copy.stringDecoderBufferSize; - this.stringSizeLimit = copy.stringSizeLimit; - this.bufferSize = copy.bufferSize; - } - - @Override - public UnpackerConfig clone() { - return new UnpackerConfig(this); - } - - @Override - public int hashCode() { - int result = (allowReadingStringAsBinary ? 1 : 0); - result = 31 * result + (allowReadingBinaryAsString ? 1 : 0); - result = 31 * result + (actionOnMalformedString != null ? actionOnMalformedString.hashCode() : 0); - result = 31 * result + (actionOnUnmappableString != null ? actionOnUnmappableString.hashCode() : 0); - result = 31 * result + stringSizeLimit; - result = 31 * result + bufferSize; - result = 31 * result + stringDecoderBufferSize; - return result; - } - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof UnpackerConfig o)) { - return false; - } - return this.allowReadingStringAsBinary == o.allowReadingStringAsBinary - && this.allowReadingBinaryAsString == o.allowReadingBinaryAsString - && this.actionOnMalformedString == o.actionOnMalformedString - && this.actionOnUnmappableString == o.actionOnUnmappableString - && this.stringSizeLimit == o.stringSizeLimit - && this.stringDecoderBufferSize == o.stringDecoderBufferSize - && this.bufferSize == o.bufferSize; - } - - /** - * Creates an unpacker that deserializes objects from a specified input. - *

          - * {@link MessageBufferInput} is an interface that lets applications customize memory - * allocation of internal buffer of {@link MessageUnpacker}. - * - * @param in The input stream that provides sequence of buffer chunks and optionally reuses them when MessageUnpacker consumed one completely - * @return A new MessageUnpacker instance - */ - public MessageUnpacker newUnpacker(MessageBufferInput in) { - return new MessageUnpacker(in, this); - } - - /** - * Creates an unpacker that deserializes objects from a specified input stream. - *

          - * Note that you don't have to wrap InputStream in BufferedInputStream because MessageUnpacker has buffering - * internally. - * - * @param in The input stream that provides sequence of bytes - * @return A new MessageUnpacker instance - */ - public MessageUnpacker newUnpacker(InputStream in) { - return newUnpacker(new InputStreamBufferInput(in, bufferSize)); - } - - /** - * Creates an unpacker that deserializes objects from a specified readable channel. - * - * @param channel The input channel that provides sequence of bytes - * @return A new MessageUnpacker instance - */ - public MessageUnpacker newUnpacker(ReadableByteChannel channel) { - return newUnpacker(new ChannelBufferInput(channel, bufferSize)); - } - - /** - * Creates an unpacker that deserializes objects from a specified byte array. - *

          - * This method provides an optimized implementation of newDefaultUnpacker(new ByteArrayInputStream(contents)). - * - * @param contents The byte array that contains packed objects in MessagePack format - * @return A new MessageUnpacker instance that will never throw IOException - */ - public MessageUnpacker newUnpacker(byte[] contents) { - return newUnpacker(new ArrayBufferInput(contents)); - } - - /** - * Creates an unpacker that deserializes objects from subarray of a specified byte array. - *

          - * This method provides an optimized implementation of newDefaultUnpacker(new ByteArrayInputStream(contents, offset, length)). - * - * @param contents The byte array that contains packed objects - * @param offset The index of the first byte - * @param length The number of bytes - * @return A new MessageUnpacker instance that will never throw IOException - */ - public MessageUnpacker newUnpacker(byte[] contents, int offset, int length) { - return newUnpacker(new ArrayBufferInput(contents, offset, length)); - } - - /** - * Creates an unpacker that deserializes objects from a specified ByteBuffer. - *

          - * Note that the returned unpacker reads data from the current position of the ByteBuffer until its limit. - * However, its position does not change when unpacker reads data. You may use - * {@link MessageUnpacker#getTotalReadBytes()} to get actual amount of bytes used in ByteBuffer. - * - * @param contents The byte buffer that contains packed objects - * @return A new MessageUnpacker instance that will never throw IOException - */ - public MessageUnpacker newUnpacker(ByteBuffer contents) { - return newUnpacker(new ByteBufferInput(contents)); - } - - /** - * Allows unpackBinaryHeader to read str format family (default: true) - */ - public UnpackerConfig withAllowReadingStringAsBinary(boolean enable) { - UnpackerConfig copy = clone(); - copy.allowReadingStringAsBinary = enable; - return copy; - } - - public boolean getAllowReadingStringAsBinary() { - return allowReadingStringAsBinary; - } - - /** - * Allows unpackString and unpackRawStringHeader and unpackString to read bin format family (default: true) - */ - public UnpackerConfig withAllowReadingBinaryAsString(boolean enable) { - UnpackerConfig copy = clone(); - copy.allowReadingBinaryAsString = enable; - return copy; - } - - public boolean getAllowReadingBinaryAsString() { - return allowReadingBinaryAsString; - } - - /** - * Sets action when encountered a malformed input (default: REPLACE) - */ - public UnpackerConfig withActionOnMalformedString(CodingErrorAction action) { - UnpackerConfig copy = clone(); - copy.actionOnMalformedString = action; - return copy; - } - - public CodingErrorAction getActionOnMalformedString() { - return actionOnMalformedString; - } - - /** - * Sets action when an unmappable character is found (default: REPLACE) - */ - public UnpackerConfig withActionOnUnmappableString(CodingErrorAction action) { - UnpackerConfig copy = clone(); - copy.actionOnUnmappableString = action; - return copy; - } - - public CodingErrorAction getActionOnUnmappableString() { - return actionOnUnmappableString; - } - - /** - * unpackString size limit (default: Integer.MAX_VALUE). - */ - public UnpackerConfig withStringSizeLimit(int bytes) { - UnpackerConfig copy = clone(); - copy.stringSizeLimit = bytes; - return copy; - } - - public int getStringSizeLimit() { - return stringSizeLimit; - } - - /** - * - */ - public UnpackerConfig withStringDecoderBufferSize(int bytes) { - UnpackerConfig copy = clone(); - copy.stringDecoderBufferSize = bytes; - return copy; - } - - public int getStringDecoderBufferSize() { - return stringDecoderBufferSize; - } - - /** - * When a packer is created with newUnpacker(OutputStream) or newUnpacker(WritableByteChannel), the stream will be - * buffered with this size of buffer (default: 8192). - */ - public UnpackerConfig withBufferSize(int bytes) { - UnpackerConfig copy = clone(); - copy.bufferSize = bytes; - return copy; - } - - public int getBufferSize() { - return bufferSize; - } - } - -} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessagePackCode.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessagePackCode.java new file mode 100644 index 0000000..f21119e --- /dev/null +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessagePackCode.java @@ -0,0 +1,103 @@ +/* + * Copyright 2021 - 2026 the TODAY 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 + * + * https://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 infra.cloud.serialize.format; + +/** + * The prefix code set of MessagePack format. See also https://github.com/msgpack/msgpack/blob/master/spec.md for details. + * + * @author 海子 Yang + * @since 1.0 2026/1/30 21:08 + */ +public class MessagePackCode { + + public static boolean isFixInt(byte b) { + int v = b & 0xFF; + return v <= 0x7f || v >= 0xe0; + } + + public static boolean isPosFixInt(byte b) { + return (b & POSFIXINT_MASK) == 0; + } + + public static boolean isNegFixInt(byte b) { + return (b & NEGFIXINT_PREFIX) == NEGFIXINT_PREFIX; + } + + public static boolean isFixStr(byte b) { + return (b & (byte) 0xe0) == MessagePackCode.FIXSTR_PREFIX; + } + + public static boolean isFixedArray(byte b) { + return (b & (byte) 0xf0) == MessagePackCode.FIXARRAY_PREFIX; + } + + public static boolean isFixedMap(byte b) { + return (b & (byte) 0xf0) == MessagePackCode.FIXMAP_PREFIX; + } + + public static boolean isFixedRaw(byte b) { + return (b & (byte) 0xe0) == MessagePackCode.FIXSTR_PREFIX; + } + + public static final byte POSFIXINT_MASK = (byte) 0x80; + + public static final byte FIXMAP_PREFIX = (byte) 0x80; + public static final byte FIXARRAY_PREFIX = (byte) 0x90; + public static final byte FIXSTR_PREFIX = (byte) 0xa0; + + public static final byte NIL = (byte) 0xc0; + public static final byte NEVER_USED = (byte) 0xc1; + public static final byte FALSE = (byte) 0xc2; + public static final byte TRUE = (byte) 0xc3; + public static final byte BIN8 = (byte) 0xc4; + public static final byte BIN16 = (byte) 0xc5; + public static final byte BIN32 = (byte) 0xc6; + public static final byte EXT8 = (byte) 0xc7; + public static final byte EXT16 = (byte) 0xc8; + public static final byte EXT32 = (byte) 0xc9; + public static final byte FLOAT32 = (byte) 0xca; + public static final byte FLOAT64 = (byte) 0xcb; + public static final byte UINT8 = (byte) 0xcc; + public static final byte UINT16 = (byte) 0xcd; + public static final byte UINT32 = (byte) 0xce; + public static final byte UINT64 = (byte) 0xcf; + + public static final byte INT8 = (byte) 0xd0; + public static final byte INT16 = (byte) 0xd1; + public static final byte INT32 = (byte) 0xd2; + public static final byte INT64 = (byte) 0xd3; + + public static final byte FIXEXT1 = (byte) 0xd4; + public static final byte FIXEXT2 = (byte) 0xd5; + public static final byte FIXEXT4 = (byte) 0xd6; + public static final byte FIXEXT8 = (byte) 0xd7; + public static final byte FIXEXT16 = (byte) 0xd8; + + public static final byte STR8 = (byte) 0xd9; + public static final byte STR16 = (byte) 0xda; + public static final byte STR32 = (byte) 0xdb; + + public static final byte ARRAY16 = (byte) 0xdc; + public static final byte ARRAY32 = (byte) 0xdd; + + public static final byte MAP16 = (byte) 0xde; + public static final byte MAP32 = (byte) 0xdf; + + public static final byte NEGFIXINT_PREFIX = (byte) 0xe0; + + public static final byte EXT_TIMESTAMP = (byte) -1; +} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessagePacker.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessagePacker.java deleted file mode 100644 index 7d1d4c1..0000000 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessagePacker.java +++ /dev/null @@ -1,1093 +0,0 @@ -/* - * Copyright 2021 - 2026 the TODAY 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 - * - * https://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 infra.cloud.serialize.format; - -import org.jspecify.annotations.Nullable; - -import java.io.Closeable; -import java.io.Flushable; -import java.io.IOException; -import java.math.BigInteger; -import java.nio.ByteBuffer; -import java.nio.CharBuffer; -import java.nio.charset.CharacterCodingException; -import java.nio.charset.CharsetEncoder; -import java.nio.charset.CoderResult; -import java.nio.charset.CodingErrorAction; -import java.time.Instant; -import java.util.Objects; - -import infra.cloud.serialize.format.buffer.ChannelBufferOutput; -import infra.cloud.serialize.format.buffer.MessageBuffer; -import infra.cloud.serialize.format.buffer.MessageBufferOutput; -import infra.cloud.serialize.format.buffer.OutputStreamBufferOutput; -import infra.cloud.serialize.format.value.Value; - -import static infra.cloud.serialize.format.MessagePack.Code.ARRAY16; -import static infra.cloud.serialize.format.MessagePack.Code.ARRAY32; -import static infra.cloud.serialize.format.MessagePack.Code.BIN16; -import static infra.cloud.serialize.format.MessagePack.Code.BIN32; -import static infra.cloud.serialize.format.MessagePack.Code.BIN8; -import static infra.cloud.serialize.format.MessagePack.Code.EXT16; -import static infra.cloud.serialize.format.MessagePack.Code.EXT32; -import static infra.cloud.serialize.format.MessagePack.Code.EXT8; -import static infra.cloud.serialize.format.MessagePack.Code.EXT_TIMESTAMP; -import static infra.cloud.serialize.format.MessagePack.Code.FALSE; -import static infra.cloud.serialize.format.MessagePack.Code.FIXARRAY_PREFIX; -import static infra.cloud.serialize.format.MessagePack.Code.FIXEXT1; -import static infra.cloud.serialize.format.MessagePack.Code.FIXEXT16; -import static infra.cloud.serialize.format.MessagePack.Code.FIXEXT2; -import static infra.cloud.serialize.format.MessagePack.Code.FIXEXT4; -import static infra.cloud.serialize.format.MessagePack.Code.FIXEXT8; -import static infra.cloud.serialize.format.MessagePack.Code.FIXMAP_PREFIX; -import static infra.cloud.serialize.format.MessagePack.Code.FIXSTR_PREFIX; -import static infra.cloud.serialize.format.MessagePack.Code.FLOAT32; -import static infra.cloud.serialize.format.MessagePack.Code.FLOAT64; -import static infra.cloud.serialize.format.MessagePack.Code.INT16; -import static infra.cloud.serialize.format.MessagePack.Code.INT32; -import static infra.cloud.serialize.format.MessagePack.Code.INT64; -import static infra.cloud.serialize.format.MessagePack.Code.INT8; -import static infra.cloud.serialize.format.MessagePack.Code.MAP16; -import static infra.cloud.serialize.format.MessagePack.Code.MAP32; -import static infra.cloud.serialize.format.MessagePack.Code.NIL; -import static infra.cloud.serialize.format.MessagePack.Code.STR16; -import static infra.cloud.serialize.format.MessagePack.Code.STR32; -import static infra.cloud.serialize.format.MessagePack.Code.STR8; -import static infra.cloud.serialize.format.MessagePack.Code.TRUE; -import static infra.cloud.serialize.format.MessagePack.Code.UINT16; -import static infra.cloud.serialize.format.MessagePack.Code.UINT32; -import static infra.cloud.serialize.format.MessagePack.Code.UINT64; -import static infra.cloud.serialize.format.MessagePack.Code.UINT8; - -/** - * MessagePack serializer that converts objects into binary. - * You can use factory methods of {@link MessagePack} class or {@link MessagePack.PackerConfig} class to create - * an instance. - *

          - * This class provides following primitive methods to write MessagePack values. These primitive methods write - * short bytes (1 to 7 bytes) to the internal buffer at once. There are also some utility methods for convenience. - *

          - * Primitive methods: - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
          Java typePacker methodMessagePack type
          null{@link #packNil()}Nil
          boolean{@link #packBoolean(boolean)}Boolean
          byte{@link #packByte(byte)}Integer
          short{@link #packShort(short)}Integer
          int{@link #packInt(int)}Integer
          long{@link #packLong(long)}Integer
          BigInteger{@link #packBigInteger(BigInteger)}Integer
          float{@link #packFloat(float)}Float
          double{@link #packDouble(double)}Float
          byte[]{@link #packBinaryHeader(int)}Binary
          String{@link #packRawStringHeader(int)}String
          List{@link #packArrayHeader(int)}Array
          Map{@link #packMapHeader(int)}Map
          custom user type{@link #packExtensionTypeHeader(byte, int)}Extension
          - * - *

          - * Utility methods: - * - * - * - * - * - *
          Java typePacker methodMessagePack type
          String{@link #packString(String)}String
          {@link Value}{@link #packValue(Value)}
          - * - *

          - * To write a byte array, first you call {@link #packBinaryHeader} method with length of the byte array. Then, - * you call {@link #writePayload(byte[], int, int)} or {@link #addPayload(byte[], int, int)} method to write the - * contents. - * - *

          - * To write a List, Collection or array, first you call {@link #packArrayHeader(int)} method with the number of - * elements. Then, you call packer methods for each element. - * iteration. - * - *

          - * To write a Map, first you call {@link #packMapHeader(int)} method with size of the map. Then, for each pair, - * you call packer methods for key first, and then value. You will call packer methods twice as many time as the - * size of the map. - * - *

          - * Note that packXxxHeader methods don't validate number of elements. You must call packer methods for correct - * number of times to produce valid MessagePack data. - * - *

          - * When IOException is thrown, primitive methods guarantee that all data is written to the internal buffer or no data - * is written. This is convenient behavior when you use a non-blocking output channel that may not be writable - * immediately. - */ -public class MessagePacker implements Closeable, Flushable { - - private final int smallStringOptimizationThreshold; - - private final int bufferFlushThreshold; - - private final boolean str8FormatSupport; - - /** - * Current internal buffer. - */ - protected MessageBufferOutput out; - - @Nullable - private MessageBuffer buffer; - - private int position; - - /** - * Total written byte size - */ - private long totalFlushBytes; - - /** - * String encoder - */ - @Nullable - private CharsetEncoder encoder; - - /** - * Create an MessagePacker that outputs the packed data to the given {@link MessageBufferOutput}. - * This method is available for subclasses to override. Use MessagePack.PackerConfig.newPacker method to instantiate this implementation. - * - * @param out MessageBufferOutput. Use {@link OutputStreamBufferOutput}, {@link ChannelBufferOutput} or - * your own implementation of {@link MessageBufferOutput} interface. - */ - protected MessagePacker(MessageBufferOutput out, MessagePack.PackerConfig config) { - this.out = Objects.requireNonNull(out, "MessageBufferOutput is null"); - this.smallStringOptimizationThreshold = config.getSmallStringOptimizationThreshold(); - this.bufferFlushThreshold = config.getBufferFlushThreshold(); - this.str8FormatSupport = config.isStr8FormatSupport(); - this.position = 0; - this.totalFlushBytes = 0; - } - - /** - * Replaces underlying output. - *

          - * This method flushes current internal buffer to the output, swaps it with the new given output, then returns - * the old output. - * - *

          - * This method doesn't close the old output. - * - * @param out new output - * @return the old output - * @throws IOException when underlying output throws IOException - * @throws NullPointerException the given output is null - */ - public MessageBufferOutput reset(MessageBufferOutput out) throws IOException { - // Validate the argument - MessageBufferOutput newOut = Objects.requireNonNull(out, "MessageBufferOutput is null"); - - // Flush before reset - flush(); - MessageBufferOutput old = this.out; - this.out = newOut; - - // Reset totalFlushBytes - this.totalFlushBytes = 0; - - return old; - } - - /** - * Returns total number of written bytes. - *

          - * This method returns total of amount of data flushed to the underlying output plus size of current - * internal buffer. - * - *

          - * Calling {@link #reset(MessageBufferOutput)} resets this number to 0. - */ - public long getTotalWrittenBytes() { - return totalFlushBytes + position; - } - - /** - * Clears the written data. - */ - public void clear() { - position = 0; - } - - /** - * Flushes internal buffer to the underlying output. - *

          - * This method also calls flush method of the underlying output after writing internal buffer. - */ - @Override - public void flush() throws IOException { - if (position > 0) { - flushBuffer(); - } - out.flush(); - } - - /** - * Closes underlying output. - *

          - * This method flushes internal buffer before closing. - */ - @Override - public void close() throws IOException { - try { - flush(); - } - finally { - out.close(); - } - } - - private void flushBuffer() throws IOException { - out.writeBuffer(position); - buffer = null; - totalFlushBytes += position; - position = 0; - } - - private MessageBuffer ensureCapacity(int minimumSize) throws IOException { - if (buffer == null) { - buffer = out.next(minimumSize); - } - else if (position + minimumSize >= buffer.size()) { - flushBuffer(); - buffer = out.next(minimumSize); - } - return buffer; - } - - private void writeByte(byte b) throws IOException { - ensureCapacity(1).putByte(position++, b); - } - - private void writeByteAndByte(byte b, byte v) throws IOException { - MessageBuffer buffer = ensureCapacity(2); - buffer.putByte(position++, b); - buffer.putByte(position++, v); - } - - private void writeByteAndShort(byte b, short v) throws IOException { - MessageBuffer buffer = ensureCapacity(3); - buffer.putByte(position++, b); - buffer.putShort(position, v); - position += 2; - } - - private void writeByteAndInt(byte b, int v) throws IOException { - MessageBuffer buffer = ensureCapacity(5); - buffer.putByte(position++, b); - buffer.putInt(position, v); - position += 4; - } - - private void writeByteAndFloat(byte b, float v) throws IOException { - MessageBuffer buffer = ensureCapacity(5); - buffer.putByte(position++, b); - buffer.putFloat(position, v); - position += 4; - } - - private void writeByteAndDouble(byte b, double v) throws IOException { - MessageBuffer buffer = ensureCapacity(9); - buffer.putByte(position++, b); - buffer.putDouble(position, v); - position += 8; - } - - private void writeByteAndLong(byte b, long v) throws IOException { - MessageBuffer buffer = ensureCapacity(9); - buffer.putByte(position++, b); - buffer.putLong(position, v); - position += 8; - } - - /** - * Writes a Nil value. - *

          - * This method writes a nil byte. - * - * @return this - * @throws IOException when underlying output throws IOException - */ - public MessagePacker packNil() throws IOException { - writeByte(NIL); - return this; - } - - /** - * Writes a Boolean value. - *

          - * This method writes a true byte or a false byte. - * - * @return this - * @throws IOException when underlying output throws IOException - */ - public MessagePacker packBoolean(boolean b) throws IOException { - writeByte(b ? TRUE : FALSE); - return this; - } - - /** - * Writes an Integer value. - * - *

          - * This method writes an integer using the smallest format from the int format family. - * - * @param b the integer to be written - * @return this - * @throws IOException when underlying output throws IOException - */ - public MessagePacker packByte(byte b) throws IOException { - if (b < -(1 << 5)) { - writeByteAndByte(INT8, b); - } - else { - writeByte(b); - } - return this; - } - - /** - * Writes an Integer value. - * - *

          - * This method writes an integer using the smallest format from the int format family. - * - * @param v the integer to be written - * @return this - * @throws IOException when underlying output throws IOException - */ - public MessagePacker packShort(short v) throws IOException { - if (v < -(1 << 5)) { - if (v < -(1 << 7)) { - writeByteAndShort(INT16, v); - } - else { - writeByteAndByte(INT8, (byte) v); - } - } - else if (v < (1 << 7)) { - writeByte((byte) v); - } - else { - if (v < (1 << 8)) { - writeByteAndByte(UINT8, (byte) v); - } - else { - writeByteAndShort(UINT16, v); - } - } - return this; - } - - /** - * Writes an Integer value. - * - *

          - * This method writes an integer using the smallest format from the int format family. - * - * @param r the integer to be written - * @return this - * @throws IOException when underlying output throws IOException - */ - public MessagePacker packInt(int r) throws IOException { - if (r < -(1 << 5)) { - if (r < -(1 << 15)) { - writeByteAndInt(INT32, r); - } - else if (r < -(1 << 7)) { - writeByteAndShort(INT16, (short) r); - } - else { - writeByteAndByte(INT8, (byte) r); - } - } - else if (r < (1 << 7)) { - writeByte((byte) r); - } - else { - if (r < (1 << 8)) { - writeByteAndByte(UINT8, (byte) r); - } - else if (r < (1 << 16)) { - writeByteAndShort(UINT16, (short) r); - } - else { - // unsigned 32 - writeByteAndInt(UINT32, r); - } - } - return this; - } - - /** - * Writes an Integer value. - * - *

          - * This method writes an integer using the smallest format from the int format family. - * - * @param v the integer to be written - * @return this - * @throws IOException when underlying output throws IOException - */ - public MessagePacker packLong(long v) throws IOException { - if (v < -(1L << 5)) { - if (v < -(1L << 15)) { - if (v < -(1L << 31)) { - writeByteAndLong(INT64, v); - } - else { - writeByteAndInt(INT32, (int) v); - } - } - else { - if (v < -(1 << 7)) { - writeByteAndShort(INT16, (short) v); - } - else { - writeByteAndByte(INT8, (byte) v); - } - } - } - else if (v < (1 << 7)) { - // fixnum - writeByte((byte) v); - } - else { - if (v < (1L << 16)) { - if (v < (1 << 8)) { - writeByteAndByte(UINT8, (byte) v); - } - else { - writeByteAndShort(UINT16, (short) v); - } - } - else { - if (v < (1L << 32)) { - writeByteAndInt(UINT32, (int) v); - } - else { - writeByteAndLong(UINT64, v); - } - } - } - return this; - } - - /** - * Writes an Integer value. - * - *

          - * This method writes an integer using the smallest format from the int format family. - * - * @param bi the integer to be written - * @return this - * @throws IOException when underlying output throws IOException - */ - public MessagePacker packBigInteger(BigInteger bi) throws IOException { - if (bi.bitLength() <= 63) { - packLong(bi.longValue()); - } - else if (bi.bitLength() == 64 && bi.signum() == 1) { - writeByteAndLong(UINT64, bi.longValue()); - } - else { - throw new IllegalArgumentException("MessagePack cannot serialize BigInteger larger than 2^64-1"); - } - return this; - } - - /** - * Writes a Float value. - * - *

          - * This method writes a float value using float format family. - * - * @param v the value to be written - * @return this - * @throws IOException when underlying output throws IOException - */ - public MessagePacker packFloat(float v) throws IOException { - writeByteAndFloat(FLOAT32, v); - return this; - } - - /** - * Writes a Float value. - * - *

          - * This method writes a float value using float format family. - * - * @param v the value to be written - * @return this - * @throws IOException when underlying output throws IOException - */ - public MessagePacker packDouble(double v) throws IOException { - writeByteAndDouble(FLOAT64, v); - return this; - } - - private void packStringWithGetBytes(String s) throws IOException { - // JVM performs various optimizations (memory allocation, reusing encoder etc.) when String.getBytes is used - byte[] bytes = s.getBytes(MessagePack.UTF8); - // Write the length and payload of small string to the buffer so that it avoids an extra flush of buffer - packRawStringHeader(bytes.length); - addPayload(bytes); - } - - private void prepareEncoder() { - if (encoder == null) { - this.encoder = MessagePack.UTF8.newEncoder() - .onMalformedInput(CodingErrorAction.REPLACE) - .onUnmappableCharacter(CodingErrorAction.REPLACE); - } - encoder.reset(); - } - - private int encodeStringToBufferAt(MessageBuffer buffer, int pos, String s) { - prepareEncoder(); - ByteBuffer bb = buffer.sliceAsByteBuffer(pos, buffer.size() - pos); - int startPosition = bb.position(); - CharBuffer in = CharBuffer.wrap(s); - CoderResult cr = encoder.encode(in, bb, true); - if (cr.isError()) { - try { - cr.throwException(); - } - catch (CharacterCodingException e) { - throw new MessageStringCodingException(e); - } - } - if (!cr.isUnderflow() || cr.isOverflow()) { - // Underflow should be on to ensure all of the input string is encoded - return -1; - } - // NOTE: This flush method does nothing if we use UTF8 encoder, but other general encoders require this - cr = encoder.flush(bb); - if (!cr.isUnderflow()) { - return -1; - } - return bb.position() - startPosition; - } - - private static final int UTF_8_MAX_CHAR_SIZE = 6; - - /** - * Writes a String vlaue in UTF-8 encoding. - * - *

          - * This method writes a UTF-8 string using the smallest format from the str format family by default. If {@link MessagePack.PackerConfig#withStr8FormatSupport(boolean)} is set to false, smallest format from the str format family excepting str8 format. - * - * @param s the string to be written - * @return this - * @throws IOException when underlying output throws IOException - */ - public MessagePacker packString(String s) throws IOException { - if (s.isEmpty()) { - packRawStringHeader(0); - return this; - } - else if (s.length() < smallStringOptimizationThreshold) { - // Using String.getBytes is generally faster for small strings. - // Also, when running on a platform that has a corrupted CharsetEncoder (i.e. Android 4.x), avoid using it. - packStringWithGetBytes(s); - return this; - } - else if (s.length() < (1 << 8)) { - // ensure capacity for 2-byte raw string header + the maximum string size (+ 1 byte for falback code) - MessageBuffer buffer = ensureCapacity(2 + s.length() * UTF_8_MAX_CHAR_SIZE + 1); - // keep 2-byte header region and write raw string - int written = encodeStringToBufferAt(buffer, position + 2, s); - if (written >= 0) { - if (str8FormatSupport && written < (1 << 8)) { - buffer.putByte(position++, STR8); - buffer.putByte(position++, (byte) written); - position += written; - } - else { - if (written >= (1 << 16)) { - // this must not happen because s.length() is less than 2^8 and (2^8) * UTF_8_MAX_CHAR_SIZE is less than 2^16 - throw new IllegalArgumentException("Unexpected UTF-8 encoder state"); - } - // move 1 byte backward to expand 3-byte header region to 3 bytes - buffer.putMessageBuffer(position + 3, buffer, position + 2, written); - // write 3-byte header - buffer.putByte(position++, STR16); - buffer.putShort(position, (short) written); - position += 2; - position += written; - } - return this; - } - } - else if (s.length() < (1 << 16)) { - // ensure capacity for 3-byte raw string header + the maximum string size (+ 2 bytes for fallback code) - MessageBuffer buffer = ensureCapacity(3 + s.length() * UTF_8_MAX_CHAR_SIZE + 2); - // keep 3-byte header region and write raw string - int written = encodeStringToBufferAt(buffer, position + 3, s); - if (written >= 0) { - if (written < (1 << 16)) { - buffer.putByte(position++, STR16); - buffer.putShort(position, (short) written); - position += 2; - position += written; - } - else { - // move 2 bytes backward to expand 3-byte header region to 5 bytes - buffer.putMessageBuffer(position + 5, buffer, position + 3, written); - // write 3-byte header header - buffer.putByte(position++, STR32); - buffer.putInt(position, written); - position += 4; - position += written; - } - return this; - } - } - - // Here doesn't use above optimized code for s.length() < (1 << 32) so that - // ensureCapacity is not called with an integer larger than (3 + ((1 << 16) * UTF_8_MAX_CHAR_SIZE) + 2). - // This makes it sure that MessageBufferOutput.next won't be called a size larger than - // 384KB, which is OK size to keep in memory. - - // fallback - packStringWithGetBytes(s); - return this; - } - - /** - * Writes a Timestamp value. - * - *

          - * This method writes a timestamp value using timestamp format family. - * - * @param instant the timestamp to be written - * @return this packer - * @throws IOException when underlying output throws IOException - */ - public MessagePacker packTimestamp(Instant instant) throws IOException { - return packTimestamp(instant.getEpochSecond(), instant.getNano()); - } - - /** - * Writes a Timesamp value using a millisecond value (e.g., System.currentTimeMillis()) - * - * @param millis the millisecond value - * @return this packer - * @throws IOException when underlying output throws IOException - */ - public MessagePacker packTimestamp(long millis) throws IOException { - return packTimestamp(Instant.ofEpochMilli(millis)); - } - - private static final long NANOS_PER_SECOND = 1000000000L; - - /** - * Writes a Timestamp value. - * - *

          - * This method writes a timestamp value using timestamp format family. - * - * @param epochSecond the number of seconds from 1970-01-01T00:00:00Z - * @param nanoAdjustment the nanosecond adjustment to the number of seconds, positive or negative - * @return this - * @throws IOException when underlying output throws IOException - * @throws ArithmeticException when epochSecond plus nanoAdjustment in seconds exceeds the range of long - */ - public MessagePacker packTimestamp(long epochSecond, int nanoAdjustment) throws IOException, ArithmeticException { - long sec = Math.addExact(epochSecond, Math.floorDiv(nanoAdjustment, NANOS_PER_SECOND)); - long nsec = Math.floorMod((long) nanoAdjustment, NANOS_PER_SECOND); - - if (sec >>> 34 == 0) { - // sec can be serialized in 34 bits. - long data64 = (nsec << 34) | sec; - if ((data64 & 0xffffffff00000000L) == 0L) { - // sec can be serialized in 32 bits and nsec is 0. - // use timestamp 32 - writeTimestamp32((int) sec); - } - else { - // sec exceeded 32 bits or nsec is not 0. - // use timestamp 64 - writeTimestamp64(data64); - } - } - else { - // use timestamp 96 format - writeTimestamp96(sec, (int) nsec); - } - return this; - } - - private void writeTimestamp32(int sec) throws IOException { - // timestamp 32 in fixext 4 - MessageBuffer buffer = ensureCapacity(6); - buffer.putByte(position++, FIXEXT4); - buffer.putByte(position++, EXT_TIMESTAMP); - buffer.putInt(position, sec); - position += 4; - } - - private void writeTimestamp64(long data64) throws IOException { - // timestamp 64 in fixext 8 - MessageBuffer buffer = ensureCapacity(10); - buffer.putByte(position++, FIXEXT8); - buffer.putByte(position++, EXT_TIMESTAMP); - buffer.putLong(position, data64); - position += 8; - } - - private void writeTimestamp96(long sec, int nsec) throws IOException { - // timestamp 96 in ext 8 - MessageBuffer buffer = ensureCapacity(15); - buffer.putByte(position++, EXT8); - buffer.putByte(position++, (byte) 12); // length of nsec and sec - buffer.putByte(position++, EXT_TIMESTAMP); - buffer.putInt(position, nsec); - position += 4; - buffer.putLong(position, sec); - position += 8; - } - - /** - * Writes header of an Array value. - *

          - * You will call other packer methods for each element after this method call. - *

          - * You don't have to call anything at the end of iteration. - * - * @param arraySize number of elements to be written - * @return this - * @throws IOException when underlying output throws IOException - */ - public MessagePacker packArrayHeader(int arraySize) throws IOException { - if (arraySize < 0) { - throw new IllegalArgumentException("array size must be >= 0"); - } - - if (arraySize < (1 << 4)) { - writeByte((byte) (FIXARRAY_PREFIX | arraySize)); - } - else if (arraySize < (1 << 16)) { - writeByteAndShort(ARRAY16, (short) arraySize); - } - else { - writeByteAndInt(ARRAY32, arraySize); - } - return this; - } - - /** - * Writes header of a Map value. - *

          - * After this method call, for each key-value pair, you will call packer methods for key first, and then value. - * You will call packer methods twice as many time as the size of the map. - *

          - * You don't have to call anything at the end of iteration. - * - * @param mapSize number of pairs to be written - * @return this - * @throws IOException when underlying output throws IOException - */ - public MessagePacker packMapHeader(int mapSize) throws IOException { - if (mapSize < 0) { - throw new IllegalArgumentException("map size must be >= 0"); - } - - if (mapSize < (1 << 4)) { - writeByte((byte) (FIXMAP_PREFIX | mapSize)); - } - else if (mapSize < (1 << 16)) { - writeByteAndShort(MAP16, (short) mapSize); - } - else { - writeByteAndInt(MAP32, mapSize); - } - return this; - } - - /** - * Writes a dynamically typed value. - * - * @param v the value to be written - * @return this - * @throws IOException when underlying output throws IOException - */ - public MessagePacker packValue(Value v) throws IOException { - v.writeTo(this); - return this; - } - - /** - * Writes header of an Extension value. - *

          - * You MUST call {@link #writePayload(byte[])} or {@link #addPayload(byte[])} method to write body binary. - * - * @param extType the extension type tag to be written - * @param payloadLen number of bytes of a payload binary to be written - * @return this - * @throws IOException when underlying output throws IOException - */ - public MessagePacker packExtensionTypeHeader(byte extType, int payloadLen) throws IOException { - if (payloadLen < (1 << 8)) { - if (payloadLen > 0 && (payloadLen & (payloadLen - 1)) == 0) { // check whether dataLen == 2^x - if (payloadLen == 1) { - writeByteAndByte(FIXEXT1, extType); - } - else if (payloadLen == 2) { - writeByteAndByte(FIXEXT2, extType); - } - else if (payloadLen == 4) { - writeByteAndByte(FIXEXT4, extType); - } - else if (payloadLen == 8) { - writeByteAndByte(FIXEXT8, extType); - } - else if (payloadLen == 16) { - writeByteAndByte(FIXEXT16, extType); - } - else { - writeByteAndByte(EXT8, (byte) payloadLen); - writeByte(extType); - } - } - else { - writeByteAndByte(EXT8, (byte) payloadLen); - writeByte(extType); - } - } - else if (payloadLen < (1 << 16)) { - writeByteAndShort(EXT16, (short) payloadLen); - writeByte(extType); - } - else { - writeByteAndInt(EXT32, payloadLen); - writeByte(extType); - - // TODO support dataLen > 2^31 - 1 - } - return this; - } - - /** - * Writes header of a Binary value. - *

          - * You MUST call {@link #writePayload(byte[])} or {@link #addPayload(byte[])} method to write body binary. - * - * @param len number of bytes of a binary to be written - * @return this - * @throws IOException when underlying output throws IOException - */ - public MessagePacker packBinaryHeader(int len) throws IOException { - if (len < (1 << 8)) { - writeByteAndByte(BIN8, (byte) len); - } - else if (len < (1 << 16)) { - writeByteAndShort(BIN16, (short) len); - } - else { - writeByteAndInt(BIN32, len); - } - return this; - } - - /** - * Writes header of a String value. - *

          - * Length must be number of bytes of a string in UTF-8 encoding. - *

          - * You MUST call {@link #writePayload(byte[])} or {@link #addPayload(byte[])} method to write body of the - * UTF-8 encoded string. - * - * @param len number of bytes of a UTF-8 string to be written - * @return this - * @throws IOException when underlying output throws IOException - */ - public MessagePacker packRawStringHeader(int len) throws IOException { - if (len < (1 << 5)) { - writeByte((byte) (FIXSTR_PREFIX | len)); - } - else if (str8FormatSupport && len < (1 << 8)) { - writeByteAndByte(STR8, (byte) len); - } - else if (len < (1 << 16)) { - writeByteAndShort(STR16, (short) len); - } - else { - writeByteAndInt(STR32, len); - } - return this; - } - - /** - * Writes a byte array to the output. - *

          - * This method is used with {@link #packRawStringHeader(int)} or {@link #packBinaryHeader(int)} methods. - *

          - * Unlike {@link #writePayload(byte[])} method, this method does not make a defensive copy of the given byte - * array, even if it is shorter than {@link MessagePack.PackerConfig#withBufferFlushThreshold(int)}. This is - * faster than {@link #writePayload(byte[])} method but caller must not modify the byte array after calling - * this method. - * - * @param data the data to add - * @return this - * @throws IOException when underlying output throws IOException - * @see #writePayload(byte[]) - */ - public MessagePacker packBinary(@Nullable byte[] data) throws IOException { - if (data == null || data.length == 0) { - return packBinaryHeader(0); - } - return packBinaryHeader(data.length) - .addPayload(data); - } - - /** - * Writes a byte array to the output. - *

          - * This method is used with {@link #packRawStringHeader(int)} or {@link #packBinaryHeader(int)} methods. - * - * @param src the data to add - * @return this - * @throws IOException when underlying output throws IOException - */ - public MessagePacker writePayload(byte[] src) throws IOException { - return writePayload(src, 0, src.length); - } - - /** - * Writes a byte array to the output. - *

          - * This method is used with {@link #packRawStringHeader(int)} or {@link #packBinaryHeader(int)} methods. - * - * @param src the data to add - * @param off the start offset in the data - * @param len the number of bytes to add - * @return this - * @throws IOException when underlying output throws IOException - */ - public MessagePacker writePayload(byte[] src, int off, int len) throws IOException { - if (buffer == null || buffer.size() - position < len || len > bufferFlushThreshold) { - flush(); // call flush before write - // Directly write payload to the output without using the buffer - out.write(src, off, len); - totalFlushBytes += len; - } - else { - buffer.putBytes(position, src, off, len); - position += len; - } - return this; - } - - /** - * Writes a byte array to the output. - *

          - * This method is used with {@link #packRawStringHeader(int)} or {@link #packBinaryHeader(int)} methods. - *

          - * Unlike {@link #writePayload(byte[])} method, this method does not make a defensive copy of the given byte - * array, even if it is shorter than {@link MessagePack.PackerConfig#withBufferFlushThreshold(int)}. This is - * faster than {@link #writePayload(byte[])} method but caller must not modify the byte array after calling - * this method. - * - * @param src the data to add - * @return this - * @throws IOException when underlying output throws IOException - * @see #writePayload(byte[]) - */ - public MessagePacker addPayload(byte[] src) throws IOException { - return addPayload(src, 0, src.length); - } - - /** - * Writes a byte array to the output. - *

          - * This method is used with {@link #packRawStringHeader(int)} or {@link #packBinaryHeader(int)} methods. - *

          - * Unlike {@link #writePayload(byte[], int, int)} method, this method does not make a defensive copy of the - * given byte array, even if it is shorter than {@link MessagePack.PackerConfig#withBufferFlushThreshold(int)}. - * This is faster than {@link #writePayload(byte[])} method but caller must not modify the byte array after - * calling this method. - * - * @param src the data to add - * @param off the start offset in the data - * @param len the number of bytes to add - * @return this - * @throws IOException when underlying output throws IOException - * @see #writePayload(byte[], int, int) - */ - public MessagePacker addPayload(byte[] src, int off, int len) throws IOException { - if (buffer == null || buffer.size() - position < len || len > bufferFlushThreshold) { - flush(); // call flush before add - // Directly add the payload without using the buffer - out.add(src, off, len); - totalFlushBytes += len; - } - else { - buffer.putBytes(position, src, off, len); - position += len; - } - return this; - } - - // - - public MessagePacker write(boolean val) throws IOException { - return packBoolean(val); - } - - public MessagePacker write(byte val) throws IOException { - return packByte(val); - } - - public MessagePacker write(short val) throws IOException { - return packShort(val); - } - - public MessagePacker write(int val) throws IOException { - return packInt(val); - } - - public MessagePacker write(long val) throws IOException { - return packLong(val); - } - - public MessagePacker write(float val) throws IOException { - return packFloat(val); - } - - public MessagePacker write(double val) throws IOException { - return packDouble(val); - } - - public MessagePacker write(@Nullable byte[] bytes) throws IOException { - return packBinary(bytes); - } - - public MessagePacker write(String s) throws IOException { - return packString(s); - } - - public MessagePacker write(Instant instant) throws IOException { - return packTimestamp(instant); - } - -} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageStringCodingException.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageStringCodingException.java deleted file mode 100644 index f4a5de7..0000000 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageStringCodingException.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2021 - 2026 the TODAY 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 - * - * https://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 infra.cloud.serialize.format; - -import java.nio.charset.CharacterCodingException; - -/** - * Thrown to indicate an error when encoding/decoding a String value - */ -public class MessageStringCodingException extends MessagePackException { - - public MessageStringCodingException(CharacterCodingException cause) { - super(null, cause); - } - - @Override - public CharacterCodingException getCause() { - return (CharacterCodingException) super.getCause(); - } -} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageTypeCastException.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageTypeCastException.java deleted file mode 100644 index 4c3ba0b..0000000 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageTypeCastException.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright 2021 - 2026 the TODAY 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 - * - * https://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 infra.cloud.serialize.format; - -public class MessageTypeCastException extends MessageTypeException { - - public MessageTypeCastException() { - super(null, null); - } - -} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageUnpacker.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageUnpacker.java deleted file mode 100644 index 0fa2dbc..0000000 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/MessageUnpacker.java +++ /dev/null @@ -1,1638 +0,0 @@ -/* - * Copyright 2021 - 2026 the TODAY 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 - * - * https://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 infra.cloud.serialize.format; - -import java.io.Closeable; -import java.io.IOException; -import java.math.BigInteger; -import java.nio.ByteBuffer; -import java.nio.CharBuffer; -import java.nio.charset.CharacterCodingException; -import java.nio.charset.CharsetDecoder; -import java.nio.charset.CoderResult; -import java.nio.charset.CodingErrorAction; -import java.time.Instant; -import java.util.Objects; - -import infra.cloud.serialize.format.MessagePack.Code; -import infra.cloud.serialize.format.buffer.MessageBuffer; -import infra.cloud.serialize.format.buffer.MessageBufferInput; -import infra.cloud.serialize.format.value.ImmutableValue; -import infra.cloud.serialize.format.value.Value; -import infra.cloud.serialize.format.value.ValueFactory; -import infra.cloud.serialize.format.value.Variable; - -import static infra.cloud.serialize.format.MessagePack.Code.EXT_TIMESTAMP; - -/** - * MessagePack deserializer that converts binary into objects. - * You can use factory methods of {@link MessagePack} class or {@link MessagePack.UnpackerConfig} class to create - * an instance. - * To read values as statically-typed Java objects, there are two typical use cases. - *

          - * One use case is to read objects as {@link Value} using {@link #unpackValue} method. A {@link Value} object - * contains type of the deserialized value as well as the value itself so that you can inspect type of the - * deserialized values later. You can repeat {@link #unpackValue} until {@link #hasNext()} method returns false so - * that you can deserialize sequence of MessagePack values. - *

          - * The other use case is to use {@link #getNextFormat()} and {@link MessageFormat#getValueType()} methods followed - * by unpackXxx methods corresponding to returned type. Following code snipet is a typical application code: - *

          
          - *     MessageUnpacker unpacker = MessagePack.newDefaultUnpacker(...);
          - *     while(unpacker.hasNext()) {
          - *         MessageFormat format = unpacker.getNextFormat();
          - *         ValueType type = format.getValueType();
          - *         int length;
          - *         ExtensionTypeHeader extension;
          - *         switch(type) {
          - *             case NIL:
          - *                 unpacker.unpackNil();
          - *                 break;
          - *             case BOOLEAN:
          - *                 unpacker.unpackBoolean();
          - *                 break;
          - *             case INTEGER:
          - *                 switch (format) {
          - *                 case UINT64:
          - *                     unpacker.unpackBigInteger();
          - *                     break;
          - *                 case INT64:
          - *                 case UINT32:
          - *                     unpacker.unpackLong();
          - *                     break;
          - *                 default:
          - *                     unpacker.unpackInt();
          - *                     break;
          - *                 }
          - *                 break;
          - *             case FLOAT:
          - *                 unpacker.unpackDouble();
          - *                 break;
          - *             case STRING:
          - *                 unpacker.unpackString();
          - *                 break;
          - *             case BINARY:
          - *                 length = unpacker.unpackBinaryHeader();
          - *                 unpacker.readPayload(new byte[length]);
          - *                 break;
          - *             case ARRAY:
          - *                 length = unpacker.unpackArrayHeader();
          - *                 for (int i = 0; i < length; i++) {
          - *                     readRecursively(unpacker);
          - *                 }
          - *                 break;
          - *             case MAP:
          - *                 length = unpacker.unpackMapHeader();
          - *                 for (int i = 0; i < length; i++) {
          - *                     readRecursively(unpacker);  // key
          - *                     readRecursively(unpacker);  // value
          - *                 }
          - *                 break;
          - *             case EXTENSION:
          - *                 extension = unpacker.unpackExtensionTypeHeader();
          - *                 unpacker.readPayload(new byte[extension.getLength()]);
          - *                 break;
          - *             }
          - *         }
          - *     }
          - *
          - * 

          - * Following methods correspond to the MessagePack types: - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
          MessagePack typeUnpacker methodJava type
          Nil{@link #unpackNil()}null
          Boolean{@link #unpackBoolean()}boolean
          Integer{@link #unpackByte()}byte
          Integer{@link #unpackShort()}short
          Integer{@link #unpackInt()}int
          Integer{@link #unpackLong()}long
          Integer{@link #unpackBigInteger()}BigInteger
          Float{@link #unpackFloat()}float
          Float{@link #unpackDouble()}double
          Binary{@link #unpackBinaryHeader()}byte array
          String{@link #unpackRawStringHeader()}String
          String{@link #unpackString()}String
          Array{@link #unpackArrayHeader()}Array
          Map{@link #unpackMapHeader()}Map
          Extension{@link #unpackExtensionTypeHeader()}{@link ExtensionTypeHeader}
          - * - *

          - * To read a byte array, first call {@link #unpackBinaryHeader} method to get length of the byte array. Then, - * call {@link #readPayload(int)} or {@link #readPayloadAsReference(int)} method to read the the contents. - * - *

          - * To read an Array type, first call {@link #unpackArrayHeader()} method to get number of elements. Then, - * call unpacker methods for each element. - * - *

          - * To read a Map, first call {@link #unpackMapHeader()} method to get number of pairs of the map. Then, - * for each pair, call unpacker methods for key first, and then value. will call unpacker methods twice - * as many time as the returned count. - */ -public class MessageUnpacker implements Closeable { - - private static final MessageBuffer EMPTY_BUFFER = MessageBuffer.wrap(new byte[0]); - - private final boolean allowReadingStringAsBinary; - private final boolean allowReadingBinaryAsString; - private final CodingErrorAction actionOnMalformedString; - private final CodingErrorAction actionOnUnmappableString; - private final int stringSizeLimit; - private final int stringDecoderBufferSize; - - private MessageBufferInput in; - - /** - * Points to the current buffer to read - */ - private MessageBuffer buffer = EMPTY_BUFFER; - - /** - * Cursor position in the current buffer - */ - private int position; - - /** - * Total read byte size - */ - private int totalReadBytes; - - /** - * An extra buffer for reading a small number value across the input buffer boundary. - * At most 8-byte buffer (for readLong used by uint 64 and UTF-8 character decoding) is required. - */ - private final MessageBuffer numberBuffer = MessageBuffer.allocate(8); - - /** - * After calling prepareNumberBuffer(), the caller should use this variable to read from the returned MessageBuffer. - */ - private int nextReadPosition; - - /** - * For decoding String in unpackString. - */ - private StringBuilder decodeStringBuffer; - - /** - * For decoding String in unpackString. - */ - private CharsetDecoder decoder; - - /** - * Buffer for decoding strings - */ - private CharBuffer decodeBuffer; - - /** - * Create an MessageUnpacker that reads data from the given MessageBufferInput. - * This method is available for subclasses to override. Use MessagePack.UnpackerConfig.newUnpacker method to instantiate this implementation. - */ - protected MessageUnpacker(MessageBufferInput in, MessagePack.UnpackerConfig config) { - this.in = Objects.requireNonNull(in, "MessageBufferInput is null"); - this.allowReadingStringAsBinary = config.getAllowReadingStringAsBinary(); - this.allowReadingBinaryAsString = config.getAllowReadingBinaryAsString(); - this.actionOnMalformedString = config.getActionOnMalformedString(); - this.actionOnUnmappableString = config.getActionOnUnmappableString(); - this.stringSizeLimit = config.getStringSizeLimit(); - this.stringDecoderBufferSize = config.getStringDecoderBufferSize(); - } - - /** - * Replaces underlying input. - *

          - * This method clears internal buffer, swaps the underlying input with the new given input, then returns - * the old input. - * - *

          - * This method doesn't close the old input. - * - * @param in new input - * @return the old input - * @throws IOException never happens unless a subclass overrides this method - * @throws NullPointerException the given input is null - */ - public MessageBufferInput reset(MessageBufferInput in) throws IOException { - MessageBufferInput newIn = Objects.requireNonNull(in, "MessageBufferInput is null"); - - // Reset the internal states - MessageBufferInput old = this.in; - this.in = newIn; - this.buffer = EMPTY_BUFFER; - this.position = 0; - this.totalReadBytes = 0; - // No need to initialize the already allocated string decoder here since we can reuse it. - - return old; - } - - /** - * Returns total number of read bytes. - *

          - * This method returns total of amount of data consumed from the underlying input minus size of data - * remained still unused in the current internal buffer. - * - *

          - * Calling {@link #reset(MessageBufferInput)} resets this number to 0. - */ - public int getTotalReadBytes() { - return totalReadBytes + position; - } - - /** - * Get the next buffer without changing the position - */ - private MessageBuffer getNextBuffer() throws IOException { - MessageBuffer next = in.next(); - if (next == null) { - throw new MessageInsufficientBufferException(); - } - assert (buffer != null); - totalReadBytes += buffer.size(); - return next; - } - - private void nextBuffer() throws IOException { - buffer = getNextBuffer(); - position = 0; - } - - /** - * Returns a short size buffer (upto 8 bytes) to read a number value - * - * @throws MessageInsufficientBufferException If no more buffer can be acquired from the input source for reading the specified data length - */ - private MessageBuffer prepareNumberBuffer(int readLength) throws IOException { - int remaining = buffer.size() - position; - if (remaining >= readLength) { - // When the data is contained inside the default buffer - nextReadPosition = position; - position += readLength; // here assumes following buffer.getXxx never throws exception - return buffer; // Return the default buffer - } - else { - // When the default buffer doesn't contain the whole length, - // fill the temporary buffer from the current data fragment and - // next fragment(s). - - int off = 0; - if (remaining > 0) { - numberBuffer.putMessageBuffer(0, buffer, position, remaining); - readLength -= remaining; - off += remaining; - } - - while (true) { - nextBuffer(); - int nextSize = buffer.size(); - if (nextSize >= readLength) { - numberBuffer.putMessageBuffer(off, buffer, 0, readLength); - position = readLength; - break; - } - else { - numberBuffer.putMessageBuffer(off, buffer, 0, nextSize); - readLength -= nextSize; - off += nextSize; - } - } - - nextReadPosition = 0; - return numberBuffer; - } - } - - private static int utf8MultibyteCharacterSize(byte firstByte) { - return Integer.numberOfLeadingZeros(~(firstByte & 0xff) << 24); - } - - /** - * Returns true if this unpacker has more elements. - * When this returns true, subsequent call to {@link #getNextFormat()} returns an - * MessageFormat instance. If false, next {@link #getNextFormat()} call will throw an MessageInsufficientBufferException. - * - * @return true if this unpacker has more elements to read - */ - public boolean hasNext() throws IOException { - return ensureBuffer(); - } - - private boolean ensureBuffer() throws IOException { - while (buffer.size() <= position) { - MessageBuffer next = in.next(); - if (next == null) { - return false; - } - totalReadBytes += buffer.size(); - buffer = next; - position = 0; - } - return true; - } - - /** - * Returns format of the next value. - * - *

          - * Note that this method doesn't consume data from the internal buffer unlike the other unpack methods. - * Calling this method twice will return the same value. - * - *

          - * To not throw {@link MessageInsufficientBufferException}, this method should be called only when - * {@link #hasNext()} returns true. - * - * @return the next MessageFormat - * @throws IOException when underlying input throws IOException - * @throws MessageInsufficientBufferException when the end of file reached, i.e. {@link #hasNext()} == false. - */ - public MessageFormat getNextFormat() throws IOException { - // makes sure that buffer has at least 1 byte - if (!ensureBuffer()) { - throw new MessageInsufficientBufferException(); - } - byte b = buffer.getByte(position); - return MessageFormat.valueOf(b); - } - - /** - * Read a byte value at the cursor and proceed the cursor. - */ - private byte readInt8() throws IOException { - if (buffer.size() > position) { - byte b = buffer.getByte(position); - position++; - return b; - } - else { - nextBuffer(); - if (buffer.size() > 0) { - byte b = buffer.getByte(0); - position = 1; - return b; - } - return readInt8(); - } - } - - private short readInt16() throws IOException { - MessageBuffer numberBuffer = prepareNumberBuffer(2); - return numberBuffer.getShort(nextReadPosition); - } - - private int readInt32() throws IOException { - MessageBuffer numberBuffer = prepareNumberBuffer(4); - return numberBuffer.getInt(nextReadPosition); - } - - private long readInt64() throws IOException { - MessageBuffer numberBuffer = prepareNumberBuffer(8); - return numberBuffer.getLong(nextReadPosition); - } - - private float readFloat32() throws IOException { - MessageBuffer numberBuffer = prepareNumberBuffer(4); - return numberBuffer.getFloat(nextReadPosition); - } - - private double readFloat64() throws IOException { - MessageBuffer numberBuffer = prepareNumberBuffer(8); - return numberBuffer.getDouble(nextReadPosition); - } - - /** - * Skip the next value, then move the cursor at the end of the value - */ - public void skipValue() throws IOException { - skipValue(1); - } - - /** - * Skip next values, then move the cursor at the end of the value - * - * @param count number of values to skip - */ - public void skipValue(int count) throws IOException { - while (count > 0) { - byte b = readInt8(); - MessageFormat f = MessageFormat.valueOf(b); - switch (f) { - case POS_FIX_INT: - case NEG_FIX_INT: - case BOOLEAN: - case NIL: - break; - case FIX_MAP: { - int mapLen = b & 0x0f; - count += mapLen * 2; - break; - } - case FIX_ARRAY: { - int arrayLen = b & 0x0f; - count += arrayLen; - break; - } - case FIX_STR: { - int strLen = b & 0x1f; - skipPayload(strLen); - break; - } - case INT8: - case UINT8: - skipPayload(1); - break; - case INT16: - case UINT16: - skipPayload(2); - break; - case INT32: - case UINT32: - case FLOAT32: - skipPayload(4); - break; - case INT64: - case UINT64: - case FLOAT64: - skipPayload(8); - break; - case BIN8: - case STR8: - skipPayload(readNextLength8()); - break; - case BIN16: - case STR16: - skipPayload(readNextLength16()); - break; - case BIN32: - case STR32: - skipPayload(readNextLength32()); - break; - case FIX_EXT1: - skipPayload(2); - break; - case FIX_EXT2: - skipPayload(3); - break; - case FIX_EXT4: - skipPayload(5); - break; - case FIX_EXT8: - skipPayload(9); - break; - case FIX_EXT16: - skipPayload(17); - break; - case EXT8: - skipPayload(readNextLength8() + 1); - break; - case EXT16: - skipPayload(readNextLength16() + 1); - break; - case EXT32: - int extLen = readNextLength32(); - // Skip the first ext type header (1-byte) first in case ext length is Integer.MAX_VALUE - skipPayload(1); - skipPayload(extLen); - break; - case ARRAY16: - count += readNextLength16(); - break; - case ARRAY32: - count += readNextLength32(); - break; - case MAP16: - count += readNextLength16() * 2; - break; - case MAP32: - count += readNextLength32() * 2; // TODO check int overflow - break; - case NEVER_USED: - throw new MessageNeverUsedFormatException("Encountered 0xC1 \"NEVER_USED\" byte"); - } - - count--; - } - } - - /** - * Create an exception for the case when an unexpected byte value is read - */ - private static MessagePackException unexpected(String expected, byte b) { - MessageFormat format = MessageFormat.valueOf(b); - if (format == MessageFormat.NEVER_USED) { - return new MessageNeverUsedFormatException(String.format("Expected %s, but encountered 0xC1 \"NEVER_USED\" byte", expected)); - } - else { - String name = format.getValueType().name(); - String typeName = name.charAt(0) + name.substring(1).toLowerCase(); - return new MessageTypeException(String.format("Expected %s, but got %s (%02x)", expected, typeName, b)); - } - } - - private static MessagePackException unexpectedExtension(String expected, int expectedType, int actualType) { - return new MessageTypeException(String.format("Expected extension type %s (%d), but got extension type %d", - expected, expectedType, actualType)); - } - - public ImmutableValue unpackValue() throws IOException { - MessageFormat mf = getNextFormat(); - switch (mf.getValueType()) { - case NIL: - readInt8(); - return ValueFactory.newNil(); - case BOOLEAN: - return ValueFactory.newBoolean(unpackBoolean()); - case INTEGER: - if (mf == MessageFormat.UINT64) { - return ValueFactory.newInteger(unpackBigInteger()); - } - else { - return ValueFactory.newInteger(unpackLong()); - } - case FLOAT: - return ValueFactory.newFloat(unpackDouble()); - case STRING: { - int length = unpackRawStringHeader(); - if (length > stringSizeLimit) { - throw new MessageSizeException(String.format("cannot unpack a String of size larger than %,d: %,d", stringSizeLimit, length), length); - } - return ValueFactory.newString(readPayload(length), true); - } - case BINARY: { - int length = unpackBinaryHeader(); - return ValueFactory.newBinary(readPayload(length), true); - } - case ARRAY: { - int size = unpackArrayHeader(); - Value[] array = new Value[size]; - for (int i = 0; i < size; i++) { - array[i] = unpackValue(); - } - return ValueFactory.newArray(array, true); - } - case MAP: { - int size = unpackMapHeader(); - Value[] kvs = new Value[size * 2]; - for (int i = 0; i < size * 2; ) { - kvs[i] = unpackValue(); - i++; - kvs[i] = unpackValue(); - i++; - } - return ValueFactory.newMap(kvs, true); - } - case EXTENSION: { - ExtensionTypeHeader extHeader = unpackExtensionTypeHeader(); - if (extHeader.getType() == EXT_TIMESTAMP) { - return ValueFactory.newTimestamp(unpackTimestamp(extHeader)); - } - return ValueFactory.newExtension(extHeader.getType(), readPayload(extHeader.getLength())); - } - default: - throw new MessageNeverUsedFormatException("Unknown value type"); - } - } - - public Variable unpackValue(Variable var) throws IOException { - MessageFormat mf = getNextFormat(); - switch (mf.getValueType()) { - case NIL: - readInt8(); - var.setNilValue(); - return var; - case BOOLEAN: - var.setBooleanValue(unpackBoolean()); - return var; - case INTEGER: - if (mf == MessageFormat.UINT64) { - var.setIntegerValue(unpackBigInteger()); - return var; - } - var.setIntegerValue(unpackLong()); - return var; - case FLOAT: - var.setFloatValue(unpackDouble()); - return var; - case STRING: { - int length = unpackRawStringHeader(); - if (length > stringSizeLimit) { - throw new MessageSizeException(String.format("cannot unpack a String of size larger than %,d: %,d", stringSizeLimit, length), length); - } - var.setStringValue(readPayload(length)); - return var; - } - case BINARY: { - int length = unpackBinaryHeader(); - var.setBinaryValue(readPayload(length)); - return var; - } - case ARRAY: { - int size = unpackArrayHeader(); - Value[] kvs = new Value[size]; - for (int i = 0; i < size; i++) { - kvs[i] = unpackValue(); - } - var.setArrayValue(kvs); - return var; - } - case MAP: { - int size = unpackMapHeader(); - Value[] kvs = new Value[size * 2]; - for (int i = 0; i < size * 2; ) { - kvs[i] = unpackValue(); - i++; - kvs[i] = unpackValue(); - i++; - } - var.setMapValue(kvs); - return var; - } - case EXTENSION: { - ExtensionTypeHeader extHeader = unpackExtensionTypeHeader(); - if (extHeader.getType() == EXT_TIMESTAMP) { - var.setTimestampValue(unpackTimestamp(extHeader)); - } - else { - var.setExtensionValue(extHeader.getType(), readPayload(extHeader.getLength())); - } - return var; - } - default: - throw new MessageFormatException("Unknown value type"); - } - } - - /** - * Reads a Nil byte. - * - * @throws MessageTypeException when value is not MessagePack Nil type - * @throws IOException when underlying input throws IOException - */ - public void unpackNil() throws IOException { - byte b = readInt8(); - if (b == Code.NIL) { - return; - } - throw unexpected("Nil", b); - } - - /** - * Peeks a Nil byte and reads it if next byte is a nil value. - *

          - * The difference from {@link #unpackNil()} is that unpackNil throws an exception if the next byte is not nil value - * while this tryUnpackNil method returns false without changing position. - * - * @return true if a nil value is read - * @throws MessageInsufficientBufferException when the end of file reached - * @throws IOException when underlying input throws IOException - */ - public boolean tryUnpackNil() throws IOException { - // makes sure that buffer has at least 1 byte - if (!ensureBuffer()) { - throw new MessageInsufficientBufferException(); - } - byte b = buffer.getByte(position); - if (b == Code.NIL) { - readInt8(); - return true; - } - return false; - } - - /** - * Reads true or false. - * - * @return the read value - * @throws MessageTypeException when value is not MessagePack Boolean type - * @throws IOException when underlying input throws IOException - */ - public boolean unpackBoolean() throws IOException { - byte b = readInt8(); - if (b == Code.FALSE) { - return false; - } - else if (b == Code.TRUE) { - return true; - } - throw unexpected("boolean", b); - } - - /** - * Reads a byte. - *

          - * This method throws {@link MessageIntegerOverflowException} if the value doesn't fit in the range of byte. This may happen when {@link #getNextFormat()} returns UINT8, INT16, or larger integer formats. - * - * @return the read value - * @throws MessageIntegerOverflowException when value doesn't fit in the range of byte - * @throws MessageTypeException when value is not MessagePack Integer type - * @throws IOException when underlying input throws IOException - */ - public byte unpackByte() throws IOException { - byte b = readInt8(); - if (Code.isFixInt(b)) { - return b; - } - switch (b) { - case Code.UINT8: // unsigned int 8 - byte u8 = readInt8(); - if (u8 < (byte) 0) { - throw overflowU8(u8); - } - return u8; - case Code.UINT16: // unsigned int 16 - short u16 = readInt16(); - if (u16 < 0 || u16 > Byte.MAX_VALUE) { - throw overflowU16(u16); - } - return (byte) u16; - case Code.UINT32: // unsigned int 32 - int u32 = readInt32(); - if (u32 < 0 || u32 > Byte.MAX_VALUE) { - throw overflowU32(u32); - } - return (byte) u32; - case Code.UINT64: // unsigned int 64 - long u64 = readInt64(); - if (u64 < 0L || u64 > Byte.MAX_VALUE) { - throw overflowU64(u64); - } - return (byte) u64; - case Code.INT8: // signed int 8 - return readInt8(); - case Code.INT16: // signed int 16 - short i16 = readInt16(); - if (i16 < Byte.MIN_VALUE || i16 > Byte.MAX_VALUE) { - throw overflowI16(i16); - } - return (byte) i16; - case Code.INT32: // signed int 32 - int i32 = readInt32(); - if (i32 < Byte.MIN_VALUE || i32 > Byte.MAX_VALUE) { - throw overflowI32(i32); - } - return (byte) i32; - case Code.INT64: // signed int 64 - long i64 = readInt64(); - if (i64 < Byte.MIN_VALUE || i64 > Byte.MAX_VALUE) { - throw overflowI64(i64); - } - return (byte) i64; - } - throw unexpected("Integer", b); - } - - /** - * Reads a short. - *

          - * This method throws {@link MessageIntegerOverflowException} if the value - * doesn't fit in the range of short. This may happen when {@link #getNextFormat()} - * returns UINT16, INT32, or larger integer formats. - * - * @return the read value - * @throws MessageIntegerOverflowException when value doesn't fit in the range of short - * @throws MessageTypeException when value is not MessagePack Integer type - * @throws IOException when underlying input throws IOException - */ - public short unpackShort() throws IOException { - byte b = readInt8(); - if (Code.isFixInt(b)) { - return b; - } - switch (b) { - case Code.UINT8: // unsigned int 8 - byte u8 = readInt8(); - return (short) (u8 & 0xff); - case Code.UINT16: // unsigned int 16 - short u16 = readInt16(); - if (u16 < (short) 0) { - throw overflowU16(u16); - } - return u16; - case Code.UINT32: // unsigned int 32 - int u32 = readInt32(); - if (u32 < 0 || u32 > Short.MAX_VALUE) { - throw overflowU32(u32); - } - return (short) u32; - case Code.UINT64: // unsigned int 64 - long u64 = readInt64(); - if (u64 < 0L || u64 > Short.MAX_VALUE) { - throw overflowU64(u64); - } - return (short) u64; - case Code.INT8: // signed int 8 - return readInt8(); - case Code.INT16: // signed int 16 - return readInt16(); - case Code.INT32: // signed int 32 - int i32 = readInt32(); - if (i32 < Short.MIN_VALUE || i32 > Short.MAX_VALUE) { - throw overflowI32(i32); - } - return (short) i32; - case Code.INT64: // signed int 64 - long i64 = readInt64(); - if (i64 < Short.MIN_VALUE || i64 > Short.MAX_VALUE) { - throw overflowI64(i64); - } - return (short) i64; - } - throw unexpected("Integer", b); - } - - /** - * Reads a int. - *

          - * This method throws {@link MessageIntegerOverflowException} if the value - * doesn't fit in the range of int. This may happen when {@link #getNextFormat()} - * returns UINT32, INT64, or larger integer formats. - * - * @return the read value - * @throws MessageIntegerOverflowException when value doesn't fit in the range of int - * @throws MessageTypeException when value is not MessagePack Integer type - * @throws IOException when underlying input throws IOException - */ - public int unpackInt() throws IOException { - byte b = readInt8(); - if (Code.isFixInt(b)) { - return b; - } - switch (b) { - case Code.UINT8: // unsigned int 8 - byte u8 = readInt8(); - return u8 & 0xff; - case Code.UINT16: // unsigned int 16 - short u16 = readInt16(); - return u16 & 0xffff; - case Code.UINT32: // unsigned int 32 - int u32 = readInt32(); - if (u32 < 0) { - throw overflowU32(u32); - } - return u32; - case Code.UINT64: // unsigned int 64 - long u64 = readInt64(); - if (u64 < 0L || u64 > (long) Integer.MAX_VALUE) { - throw overflowU64(u64); - } - return (int) u64; - case Code.INT8: // signed int 8 - return readInt8(); - case Code.INT16: // signed int 16 - return readInt16(); - case Code.INT32: // signed int 32 - return readInt32(); - case Code.INT64: // signed int 64 - long i64 = readInt64(); - if (i64 < (long) Integer.MIN_VALUE || i64 > (long) Integer.MAX_VALUE) { - throw overflowI64(i64); - } - return (int) i64; - } - throw unexpected("Integer", b); - } - - /** - * Reads a long. - *

          - * This method throws {@link MessageIntegerOverflowException} if the value doesn't - * fit in the range of long. This may happen when {@link #getNextFormat()} returns UINT64. - * - * @return the read value - * @throws MessageIntegerOverflowException when value doesn't fit in the range of long - * @throws MessageTypeException when value is not MessagePack Integer type - * @throws IOException when underlying input throws IOException - */ - public long unpackLong() throws IOException { - byte b = readInt8(); - if (Code.isFixInt(b)) { - return b; - } - switch (b) { - case Code.UINT8: // unsigned int 8 - byte u8 = readInt8(); - return u8 & 0xff; - case Code.UINT16: // unsigned int 16 - short u16 = readInt16(); - return u16 & 0xffff; - case Code.UINT32: // unsigned int 32 - int u32 = readInt32(); - if (u32 < 0) { - return (long) (u32 & 0x7fffffff) + 0x80000000L; - } - else { - return u32; - } - case Code.UINT64: // unsigned int 64 - long u64 = readInt64(); - if (u64 < 0L) { - throw overflowU64(u64); - } - return u64; - case Code.INT8: // signed int 8 - return readInt8(); - case Code.INT16: // signed int 16 - return readInt16(); - case Code.INT32: // signed int 32 - return readInt32(); - case Code.INT64: // signed int 64 - return readInt64(); - } - throw unexpected("Integer", b); - } - - /** - * Reads a BigInteger. - * - * @return the read value - * @throws MessageTypeException when value is not MessagePack Integer type - * @throws IOException when underlying input throws IOException - */ - public BigInteger unpackBigInteger() throws IOException { - byte b = readInt8(); - if (Code.isFixInt(b)) { - return BigInteger.valueOf(b); - } - switch (b) { - case Code.UINT8: // unsigned int 8 - byte u8 = readInt8(); - return BigInteger.valueOf(u8 & 0xff); - case Code.UINT16: // unsigned int 16 - short u16 = readInt16(); - return BigInteger.valueOf(u16 & 0xffff); - case Code.UINT32: // unsigned int 32 - int u32 = readInt32(); - if (u32 < 0) { - return BigInteger.valueOf((long) (u32 & 0x7fffffff) + 0x80000000L); - } - else { - return BigInteger.valueOf(u32); - } - case Code.UINT64: // unsigned int 64 - long u64 = readInt64(); - if (u64 < 0L) { - return BigInteger.valueOf(u64 + Long.MAX_VALUE + 1L).setBit(63); - } - else { - return BigInteger.valueOf(u64); - } - case Code.INT8: // signed int 8 - byte i8 = readInt8(); - return BigInteger.valueOf(i8); - case Code.INT16: // signed int 16 - short i16 = readInt16(); - return BigInteger.valueOf(i16); - case Code.INT32: // signed int 32 - int i32 = readInt32(); - return BigInteger.valueOf(i32); - case Code.INT64: // signed int 64 - long i64 = readInt64(); - return BigInteger.valueOf(i64); - } - throw unexpected("Integer", b); - } - - /** - * Reads a float. - *

          - * This method rounds value to the range of float when precision of the read - * value is larger than the range of float. This may happen when {@link #getNextFormat()} returns FLOAT64. - * - * @return the read value - * @throws MessageTypeException when value is not MessagePack Float type - * @throws IOException when underlying input throws IOException - */ - public float unpackFloat() throws IOException { - byte b = readInt8(); - return switch (b) { - case Code.FLOAT32 -> readFloat32(); - case Code.FLOAT64 -> { - double dv = readFloat64(); - yield (float) dv; - } - default -> throw unexpected("Float", b); - }; - } - - /** - * Reads a double. - * - * @return the read value - * @throws MessageTypeException when value is not MessagePack Float type - * @throws IOException when underlying input throws IOException - */ - public double unpackDouble() throws IOException { - byte b = readInt8(); - return switch (b) { - case Code.FLOAT32 -> readFloat32(); - case Code.FLOAT64 -> readFloat64(); - default -> throw unexpected("Float", b); - }; - } - - private static final String EMPTY_STRING = ""; - - private void resetDecoder() { - if (decoder == null) { - decodeBuffer = CharBuffer.allocate(stringDecoderBufferSize); - decoder = MessagePack.UTF8.newDecoder() - .onMalformedInput(actionOnMalformedString) - .onUnmappableCharacter(actionOnUnmappableString); - } - else { - decoder.reset(); - } - if (decodeStringBuffer == null) { - decodeStringBuffer = new StringBuilder(); - } - else { - decodeStringBuffer.setLength(0); - } - } - - public String unpackString() throws IOException { - int len = unpackRawStringHeader(); - if (len == 0) { - return EMPTY_STRING; - } - if (len > stringSizeLimit) { - throw new MessageSizeException(String.format("cannot unpack a String of size larger than %,d: %,d", stringSizeLimit, len), len); - } - - resetDecoder(); // should be invoked only once per value - - if (buffer.size() - position >= len) { - return decodeStringFastPath(len); - } - - try { - int rawRemaining = len; - while (rawRemaining > 0) { - int bufferRemaining = buffer.size() - position; - if (bufferRemaining >= rawRemaining) { - decodeStringBuffer.append(decodeStringFastPath(rawRemaining)); - break; - } - else if (bufferRemaining == 0) { - nextBuffer(); - } - else { - ByteBuffer bb = buffer.sliceAsByteBuffer(position, bufferRemaining); - int bbStartPosition = bb.position(); - decodeBuffer.clear(); - - CoderResult cr = decoder.decode(bb, decodeBuffer, false); - int readLen = bb.position() - bbStartPosition; - position += readLen; - rawRemaining -= readLen; - decodeStringBuffer.append(decodeBuffer.flip()); - - if (cr.isError()) { - handleCoderError(cr); - } - if (cr.isUnderflow() && readLen < bufferRemaining) { - // handle incomplete multibyte character - int incompleteMultiBytes = utf8MultibyteCharacterSize(buffer.getByte(position)); - ByteBuffer multiByteBuffer = ByteBuffer.allocate(incompleteMultiBytes); - buffer.getBytes(position, buffer.size() - position, multiByteBuffer); - - // read until multiByteBuffer is filled - while (true) { - nextBuffer(); - - int more = multiByteBuffer.remaining(); - if (buffer.size() >= more) { - buffer.getBytes(0, more, multiByteBuffer); - position = more; - break; - } - else { - buffer.getBytes(0, buffer.size(), multiByteBuffer); - position = buffer.size(); - } - } - multiByteBuffer.position(0); - decodeBuffer.clear(); - cr = decoder.decode(multiByteBuffer, decodeBuffer, false); - if (cr.isError()) { - handleCoderError(cr); - } - if (cr.isOverflow() || (cr.isUnderflow() && multiByteBuffer.position() < multiByteBuffer.limit())) { - // isOverflow or isOverflow must not happen. if happened, throw exception - try { - cr.throwException(); - throw new MessageFormatException("Unexpected UTF-8 multibyte sequence"); - } - catch (Exception ex) { - throw new MessageFormatException("Unexpected UTF-8 multibyte sequence", ex); - } - } - rawRemaining -= multiByteBuffer.limit(); - decodeStringBuffer.append(decodeBuffer.flip()); - } - } - } - return decodeStringBuffer.toString(); - } - catch (CharacterCodingException e) { - throw new MessageStringCodingException(e); - } - } - - private void handleCoderError(CoderResult cr) throws CharacterCodingException { - if ((cr.isMalformed() && actionOnMalformedString == CodingErrorAction.REPORT) || - (cr.isUnmappable() && actionOnUnmappableString == CodingErrorAction.REPORT)) { - cr.throwException(); - } - } - - private String decodeStringFastPath(int length) { - if (actionOnMalformedString == CodingErrorAction.REPLACE && - actionOnUnmappableString == CodingErrorAction.REPLACE && - buffer.hasArray()) { - String s = new String(buffer.array(), buffer.arrayOffset() + position, length, MessagePack.UTF8); - position += length; - return s; - } - else { - ByteBuffer bb = buffer.sliceAsByteBuffer(position, length); - CharBuffer cb; - try { - cb = decoder.decode(bb); - } - catch (CharacterCodingException e) { - throw new MessageStringCodingException(e); - } - position += length; - return cb.toString(); - } - } - - public Instant unpackTimestamp() throws IOException { - ExtensionTypeHeader ext = unpackExtensionTypeHeader(); - return unpackTimestamp(ext); - } - - /** - * Unpack timestamp that can be used after reading the extension type header with unpackExtensionTypeHeader. - */ - public Instant unpackTimestamp(ExtensionTypeHeader ext) throws IOException { - if (ext.getType() != EXT_TIMESTAMP) { - throw unexpectedExtension("Timestamp", EXT_TIMESTAMP, ext.getType()); - } - switch (ext.getLength()) { - case 4: { - // Need to convert Java's int (int32) to uint32 - long u32 = readInt32() & 0xffffffffL; - return Instant.ofEpochSecond(u32); - } - case 8: { - long data64 = readInt64(); - int nsec = (int) (data64 >>> 34); - long sec = data64 & 0x00000003ffffffffL; - return Instant.ofEpochSecond(sec, nsec); - } - case 12: { - // Need to convert Java's int (int32) to uint32 - long nsecU32 = readInt32() & 0xffffffffL; - long sec = readInt64(); - return Instant.ofEpochSecond(sec, nsecU32); - } - default: - throw new MessageFormatException(String.format("Timestamp extension type (%d) expects 4, 8, or 12 bytes of payload but got %d bytes", - EXT_TIMESTAMP, ext.getLength())); - } - } - - /** - * Reads header of an array. - * - *

          - * This method returns number of elements to be read. After this method call, you call unpacker methods for - * each element. You don't have to call anything at the end of iteration. - * - * @return the size of the array to be read - * @throws MessageTypeException when value is not MessagePack Array type - * @throws MessageSizeException when size of the array is larger than 2^31 - 1 - * @throws IOException when underlying input throws IOException - */ - public int unpackArrayHeader() throws IOException { - byte b = readInt8(); - if (Code.isFixedArray(b)) { // fixarray - return b & 0x0f; - } - return switch (b) { - // array 16 - case Code.ARRAY16 -> readNextLength16(); - // array 32 - case Code.ARRAY32 -> readNextLength32(); - default -> throw unexpected("Array", b); - }; - } - - /** - * Reads header of a map. - * - *

          - * This method returns number of pairs to be read. After this method call, for each pair, you call unpacker - * methods for key first, and then value. You will call unpacker methods twice as many time as the returned - * count. You don't have to call anything at the end of iteration. - * - * @return the size of the map to be read - * @throws MessageTypeException when value is not MessagePack Map type - * @throws MessageSizeException when size of the map is larger than 2^31 - 1 - * @throws IOException when underlying input throws IOException - */ - public int unpackMapHeader() throws IOException { - byte b = readInt8(); - if (Code.isFixedMap(b)) { // fixmap - return b & 0x0f; - } - return switch (b) { - case Code.MAP16 -> readNextLength16();// map 16 - case Code.MAP32 -> readNextLength32();// map 32 - default -> throw unexpected("Map", b); - }; - } - - public ExtensionTypeHeader unpackExtensionTypeHeader() throws IOException { - byte b = readInt8(); - switch (b) { - case Code.FIXEXT1: { - byte type = readInt8(); - return new ExtensionTypeHeader(type, 1); - } - case Code.FIXEXT2: { - byte type = readInt8(); - return new ExtensionTypeHeader(type, 2); - } - case Code.FIXEXT4: { - byte type = readInt8(); - return new ExtensionTypeHeader(type, 4); - } - case Code.FIXEXT8: { - byte type = readInt8(); - return new ExtensionTypeHeader(type, 8); - } - case Code.FIXEXT16: { - byte type = readInt8(); - return new ExtensionTypeHeader(type, 16); - } - case Code.EXT8: { - MessageBuffer numberBuffer = prepareNumberBuffer(2); - int u8 = numberBuffer.getByte(nextReadPosition); - int length = u8 & 0xff; - byte type = numberBuffer.getByte(nextReadPosition + 1); - return new ExtensionTypeHeader(type, length); - } - case Code.EXT16: { - MessageBuffer numberBuffer = prepareNumberBuffer(3); - int u16 = numberBuffer.getShort(nextReadPosition); - int length = u16 & 0xffff; - byte type = numberBuffer.getByte(nextReadPosition + 2); - return new ExtensionTypeHeader(type, length); - } - case Code.EXT32: { - MessageBuffer numberBuffer = prepareNumberBuffer(5); - int length = numberBuffer.getInt(nextReadPosition); - if (length < 0) { - throw overflowU32Size(length); - } - byte type = numberBuffer.getByte(nextReadPosition + 4); - return new ExtensionTypeHeader(type, length); - } - } - - throw unexpected("Ext", b); - } - - private int tryReadStringHeader(byte b) throws IOException { - return switch (b) { - case Code.STR8 -> readNextLength8(); // str 8 - case Code.STR16 -> readNextLength16(); // str 16 - case Code.STR32 -> readNextLength32(); // str 32 - default -> -1; - }; - } - - private int tryReadBinaryHeader(byte b) throws IOException { - return switch (b) { - case Code.BIN8 -> readNextLength8(); // bin 8 - case Code.BIN16 -> readNextLength16(); // bin 16 - case Code.BIN32 -> readNextLength32(); // bin 32 - default -> -1; - }; - } - - public int unpackRawStringHeader() throws IOException { - byte b = readInt8(); - if (Code.isFixedRaw(b)) { // FixRaw - return b & 0x1f; - } - int len = tryReadStringHeader(b); - if (len >= 0) { - return len; - } - - if (allowReadingBinaryAsString) { - len = tryReadBinaryHeader(b); - if (len >= 0) { - return len; - } - } - throw unexpected("String", b); - } - - /** - * Reads header of a binary. - * - *

          - * This method returns number of bytes to be read. After this method call, you call a readPayload method such as - * {@link #readPayload(int)} with the returned count. - * - *

          - * You can divide readPayload method into multiple calls. In this case, you must repeat readPayload methods - * until total amount of bytes becomes equal to the returned count. - * - * @return the size of the map to be read - * @throws MessageTypeException when value is not MessagePack Map type - * @throws MessageSizeException when size of the map is larger than 2^31 - 1 - * @throws IOException when underlying input throws IOException - */ - public int unpackBinaryHeader() throws IOException { - byte b = readInt8(); - if (Code.isFixedRaw(b)) { // FixRaw - return b & 0x1f; - } - int len = tryReadBinaryHeader(b); - if (len >= 0) { - return len; - } - - if (allowReadingStringAsBinary) { - len = tryReadStringHeader(b); - if (len >= 0) { - return len; - } - } - throw unexpected("Binary", b); - } - - /** - * Reads payload bytes of binary, extension, or raw string types. - *

          - * This consumes specified amount of bytes into the specified byte array. - * - * @throws IOException when underlying input throws IOException - */ - public byte[] unpackBinary() throws IOException { - int size = unpackBinaryHeader(); - return readPayload(size); - } - - /** - * Skip reading the specified number of bytes. Use this method only if you know skipping data is safe. - * For simply skipping the next value, use {@link #skipValue()}. - */ - private void skipPayload(int numBytes) throws IOException { - if (numBytes < 0) { - throw new IllegalArgumentException("payload size must be >= 0: " + numBytes); - } - while (true) { - int bufferRemaining = buffer.size() - position; - if (bufferRemaining >= numBytes) { - position += numBytes; - return; - } - else { - position += bufferRemaining; - numBytes -= bufferRemaining; - } - nextBuffer(); - } - } - - /** - * Reads payload bytes of binary, extension, or raw string types. - * - *

          - * This consumes bytes, copies them to the specified buffer, and moves forward position of the byte buffer - * until ByteBuffer.remaining() returns 0. - * - * @param dst the byte buffer into which the data is read - * @throws IOException when underlying input throws IOException - */ - public void readPayload(ByteBuffer dst) throws IOException { - while (true) { - int dstRemaining = dst.remaining(); - int bufferRemaining = buffer.size() - position; - if (bufferRemaining >= dstRemaining) { - buffer.getBytes(position, dstRemaining, dst); - position += dstRemaining; - return; - } - buffer.getBytes(position, bufferRemaining, dst); - position += bufferRemaining; - - nextBuffer(); - } - } - - /** - * Reads payload bytes of binary, extension, or raw string types. - * - *

          - * This consumes bytes, copies them to the specified buffer - * This is usually faster than readPayload(ByteBuffer) by using unsafe.copyMemory - * - * @param dst the Message buffer into which the data is read - * @param off the offset in the Message buffer - * @param len the number of bytes to read - * @throws IOException when underlying input throws IOException - */ - public void readPayload(MessageBuffer dst, int off, int len) throws IOException { - while (true) { - int bufferRemaining = buffer.size() - position; - if (bufferRemaining >= len) { - dst.putMessageBuffer(off, buffer, position, len); - position += len; - return; - } - dst.putMessageBuffer(off, buffer, position, bufferRemaining); - off += bufferRemaining; - len -= bufferRemaining; - position += bufferRemaining; - - nextBuffer(); - } - } - - /** - * Reads payload bytes of binary, extension, or raw string types. - *

          - * This consumes specified amount of bytes into the specified byte array. - * - *

          - * This method is equivalent to readPayload(dst, 0, dst.length). - * - * @param dst the byte array into which the data is read - * @throws IOException when underlying input throws IOException - */ - public void readPayload(byte[] dst) throws IOException { - readPayload(dst, 0, dst.length); - } - - /** - * Reads payload bytes of binary, extension, or raw string types. - *

          - * This method allocates a new byte array and consumes specified amount of bytes into the byte array. - * - *

          - * This method is equivalent to readPayload(new byte[length]). - * - * @param length number of bytes to be read - * @return the new byte array - * @throws IOException when underlying input throws IOException - */ - public byte[] readPayload(int length) throws IOException { - byte[] newArray = new byte[length]; - readPayload(newArray); - return newArray; - } - - /** - * Reads payload bytes of binary, extension, or raw string types. - *

          - * This consumes specified amount of bytes into the specified byte array. - * - * @param dst the byte array into which the data is read - * @param off the offset in the dst array - * @param len the number of bytes to read - * @throws IOException when underlying input throws IOException - */ - public void readPayload(byte[] dst, int off, int len) throws IOException { - while (true) { - int bufferRemaining = buffer.size() - position; - if (bufferRemaining >= len) { - buffer.getBytes(position, dst, off, len); - position += len; - return; - } - buffer.getBytes(position, dst, off, bufferRemaining); - off += bufferRemaining; - len -= bufferRemaining; - position += bufferRemaining; - - nextBuffer(); - } - } - - /** - * Reads payload bytes of binary, extension, or raw string types as a reference to internal buffer. - *

          - * Note: This methods may return raw memory region, access to which has no strict boundary checks. - * To use this method safely, you need to understand the internal buffer handling of msgpack-java. - * - *

          - * This consumes specified amount of bytes and returns its reference or copy. This method tries to - * return reference as much as possible because it is faster. However, it may copy data to a newly - * allocated buffer if reference is not applicable. - * - * @param length number of bytes to be read - * @throws IOException when underlying input throws IOException - */ - public MessageBuffer readPayloadAsReference(int length) throws IOException { - int bufferRemaining = buffer.size() - position; - if (bufferRemaining >= length) { - MessageBuffer slice = buffer.slice(position, length); - position += length; - return slice; - } - MessageBuffer dst = MessageBuffer.allocate(length); - readPayload(dst, 0, length); - return dst; - } - - private int readNextLength8() throws IOException { - byte u8 = readInt8(); - return u8 & 0xff; - } - - private int readNextLength16() throws IOException { - short u16 = readInt16(); - return u16 & 0xffff; - } - - private int readNextLength32() throws IOException { - int u32 = readInt32(); - if (u32 < 0) { - throw overflowU32Size(u32); - } - return u32; - } - - /** - * Closes underlying input. - */ - @Override - public void close() throws IOException { - totalReadBytes += position; - buffer = EMPTY_BUFFER; - position = 0; - in.close(); - } - - private static MessageIntegerOverflowException overflowU8(byte u8) { - BigInteger bi = BigInteger.valueOf(u8 & 0xff); - return new MessageIntegerOverflowException(bi); - } - - private static MessageIntegerOverflowException overflowU16(short u16) { - BigInteger bi = BigInteger.valueOf(u16 & 0xffff); - return new MessageIntegerOverflowException(bi); - } - - private static MessageIntegerOverflowException overflowU32(int u32) { - BigInteger bi = BigInteger.valueOf((long) (u32 & 0x7fffffff) + 0x80000000L); - return new MessageIntegerOverflowException(bi); - } - - private static MessageIntegerOverflowException overflowU64(long u64) { - BigInteger bi = BigInteger.valueOf(u64 + Long.MAX_VALUE + 1L).setBit(63); - return new MessageIntegerOverflowException(bi); - } - - private static MessageIntegerOverflowException overflowI16(short i16) { - BigInteger bi = BigInteger.valueOf(i16); - return new MessageIntegerOverflowException(bi); - } - - private static MessageIntegerOverflowException overflowI32(int i32) { - BigInteger bi = BigInteger.valueOf(i32); - return new MessageIntegerOverflowException(bi); - } - - private static MessageIntegerOverflowException overflowI64(long i64) { - BigInteger bi = BigInteger.valueOf(i64); - return new MessageIntegerOverflowException(bi); - } - - private static MessageSizeException overflowU32Size(int u32) { - long lv = (long) (u32 & 0x7fffffff) + 0x80000000L; - return new MessageSizeException(lv); - } -} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ValueType.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/ValueType.java similarity index 69% rename from today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ValueType.java rename to today-service-serialization/src/main/java/infra/cloud/serialize/format/ValueType.java index 89be1a1..83b429a 100644 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ValueType.java +++ b/today-service-serialization/src/main/java/infra/cloud/serialize/format/ValueType.java @@ -14,9 +14,7 @@ * limitations under the License. */ -package infra.cloud.serialize.format.value; - -import infra.cloud.serialize.format.MessageFormat; +package infra.cloud.serialize.format; /** * Representation of MessagePack types. @@ -45,54 +43,19 @@ public enum ValueType { */ private final boolean numberType; + private final boolean rawType; - private ValueType(boolean numberType, boolean rawType) { + ValueType(boolean numberType, boolean rawType) { this.numberType = numberType; this.rawType = rawType; } - public boolean isNilType() { - return this == NIL; - } - - public boolean isBooleanType() { - return this == BOOLEAN; - } - public boolean isNumberType() { return numberType; } - public boolean isIntegerType() { - return this == INTEGER; - } - - public boolean isFloatType() { - return this == FLOAT; - } - public boolean isRawType() { return rawType; } - - public boolean isStringType() { - return this == STRING; - } - - public boolean isBinaryType() { - return this == BINARY; - } - - public boolean isArrayType() { - return this == ARRAY; - } - - public boolean isMapType() { - return this == MAP; - } - - public boolean isExtensionType() { - return this == EXTENSION; - } } diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/ArrayBufferInput.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/ArrayBufferInput.java deleted file mode 100644 index 5cc42c5..0000000 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/ArrayBufferInput.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright 2021 - 2026 the TODAY 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 - * - * https://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 infra.cloud.serialize.format.buffer; - -import java.util.Objects; - -/** - * MessageBufferInput adapter for byte arrays - */ -public class ArrayBufferInput implements MessageBufferInput { - - private MessageBuffer buffer; - - private boolean isEmpty; - - public ArrayBufferInput(MessageBuffer buf) { - this.buffer = buf; - this.isEmpty = buf == null; - } - - public ArrayBufferInput(byte[] arr) { - this(arr, 0, arr.length); - } - - public ArrayBufferInput(byte[] arr, int offset, int length) { - this(MessageBuffer.wrap(Objects.requireNonNull(arr, "input array is null"), offset, length)); - } - - /** - * Reset buffer. This method returns the old buffer. - * - * @param buf new buffer. This can be null to make this input empty. - * @return the old buffer. - */ - public MessageBuffer reset(MessageBuffer buf) { - MessageBuffer old = this.buffer; - this.buffer = buf; - this.isEmpty = buf == null; - return old; - } - - public void reset(byte[] arr) { - reset(MessageBuffer.wrap(Objects.requireNonNull(arr, "input array is null"))); - } - - public void reset(byte[] arr, int offset, int len) { - reset(MessageBuffer.wrap(Objects.requireNonNull(arr, "input array is null"), offset, len)); - } - - @Override - public MessageBuffer next() { - if (isEmpty) { - return null; - } - isEmpty = true; - return buffer; - } - - @Override - public void close() { - buffer = null; - isEmpty = true; - } -} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/ArrayBufferOutput.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/ArrayBufferOutput.java deleted file mode 100644 index c7941fe..0000000 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/ArrayBufferOutput.java +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Copyright 2021 - 2026 the TODAY 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 - * - * https://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 infra.cloud.serialize.format.buffer; - -import java.util.ArrayList; -import java.util.List; - -/** - * MessageBufferOutput adapter that writes data into a list of byte arrays. - *

          - * This class allocates a new buffer instead of resizing the buffer when data doesn't fit in the initial capacity. - * This is faster than ByteArrayOutputStream especially when size of written bytes is large because resizing a buffer - * usually needs to copy contents of the buffer. - */ -public class ArrayBufferOutput implements MessageBufferOutput { - - private final ArrayList list; - - private final int bufferSize; - - private MessageBuffer lastBuffer; - - public ArrayBufferOutput() { - this(8192); - } - - public ArrayBufferOutput(int bufferSize) { - this.bufferSize = bufferSize; - this.list = new ArrayList<>(); - } - - /** - * Gets the size of the written data. - * - * @return number of bytes - */ - public int getSize() { - int size = 0; - for (MessageBuffer buffer : list) { - size += buffer.size(); - } - return size; - } - - /** - * Gets a copy of the written data as a byte array. - *

          - * If your application needs better performance and smaller memory consumption, you may prefer - * {@link #toMessageBuffer()} or {@link #toBufferList()} to avoid copying. - * - * @return the byte array - */ - public byte[] toByteArray() { - byte[] data = new byte[getSize()]; - int off = 0; - for (MessageBuffer buffer : list) { - buffer.getBytes(0, data, off, buffer.size()); - off += buffer.size(); - } - return data; - } - - /** - * Gets the written data as a MessageBuffer. - *

          - * Unlike {@link #toByteArray()}, this method omits copy of the contents if size of the written data is smaller - * than a single buffer capacity. - * - * @return the MessageBuffer instance - */ - public MessageBuffer toMessageBuffer() { - if (list.size() == 1) { - return list.get(0); - } - else if (list.isEmpty()) { - return MessageBuffer.allocate(0); - } - else { - return MessageBuffer.wrap(toByteArray()); - } - } - - /** - * Returns the written data as a list of MessageBuffer. - *

          - * Unlike {@link #toByteArray()} or {@link #toMessageBuffer()}, this is the fastest method that doesn't - * copy contents in any cases. - * - * @return the list of MessageBuffer instances - */ - public List toBufferList() { - return new ArrayList<>(list); - } - - /** - * Clears the written data. - */ - public void clear() { - list.clear(); - } - - @Override - public MessageBuffer next(int minimumSize) { - if (lastBuffer != null && lastBuffer.size() > minimumSize) { - return lastBuffer; - } - else { - int size = Math.max(bufferSize, minimumSize); - MessageBuffer buffer = MessageBuffer.allocate(size); - lastBuffer = buffer; - return buffer; - } - } - - @Override - public void writeBuffer(int length) { - list.add(lastBuffer.slice(0, length)); - if (lastBuffer.size() - length > bufferSize / 4) { - lastBuffer = lastBuffer.slice(length, lastBuffer.size() - length); - } - else { - lastBuffer = null; - } - } - - @Override - public void write(byte[] buffer, int offset, int length) { - MessageBuffer copy = MessageBuffer.allocate(length); - copy.putBytes(0, buffer, offset, length); - list.add(copy); - } - - @Override - public void add(byte[] buffer, int offset, int length) { - MessageBuffer wrapped = MessageBuffer.wrap(buffer, offset, length); - list.add(wrapped); - } - - @Override - public void close() { - } - - @Override - public void flush() { - } -} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/ByteBufferInput.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/ByteBufferInput.java deleted file mode 100644 index 03af151..0000000 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/ByteBufferInput.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2021 - 2026 the TODAY 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 - * - * https://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 infra.cloud.serialize.format.buffer; - -import java.nio.ByteBuffer; -import java.util.Objects; - -/** - * {@link MessageBufferInput} adapter for {@link ByteBuffer} - */ -public class ByteBufferInput - implements MessageBufferInput { - private ByteBuffer input; - private boolean isRead = false; - - public ByteBufferInput(ByteBuffer input) { - this.input = Objects.requireNonNull(input, "input ByteBuffer is null").slice(); - } - - /** - * Reset buffer. - * - * @param input new buffer - * @return the old buffer - */ - public ByteBuffer reset(ByteBuffer input) { - ByteBuffer old = this.input; - this.input = Objects.requireNonNull(input, "input ByteBuffer is null").slice(); - isRead = false; - return old; - } - - @Override - public MessageBuffer next() { - if (isRead) { - return null; - } - - MessageBuffer b = MessageBuffer.wrap(input); - isRead = true; - return b; - } - - @Override - public void close() { - // Nothing to do - } -} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/ChannelBufferInput.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/ChannelBufferInput.java deleted file mode 100644 index 912cc7b..0000000 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/ChannelBufferInput.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright 2021 - 2026 the TODAY 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 - * - * https://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 infra.cloud.serialize.format.buffer; - -import java.io.IOException; -import java.nio.ByteBuffer; -import java.nio.channels.ReadableByteChannel; -import java.util.Objects; - -import infra.lang.Assert; - -/** - * {@link MessageBufferInput} adapter for {@link ReadableByteChannel} - */ -public class ChannelBufferInput implements MessageBufferInput { - - private ReadableByteChannel channel; - - private final MessageBuffer buffer; - - public ChannelBufferInput(ReadableByteChannel channel) { - this(channel, 8192); - } - - public ChannelBufferInput(ReadableByteChannel channel, int bufferSize) { - this.channel = Objects.requireNonNull(channel, "input channel is null"); - Assert.isTrue(bufferSize > 0, () -> "buffer size must be > 0: " + bufferSize); - this.buffer = MessageBuffer.allocate(bufferSize); - } - - /** - * Reset channel. This method doesn't close the old resource. - * - * @param channel new channel - * @return the old resource - */ - public ReadableByteChannel reset(ReadableByteChannel channel) throws IOException { - ReadableByteChannel old = this.channel; - this.channel = channel; - return old; - } - - @Override - public MessageBuffer next() throws IOException { - ByteBuffer b = buffer.sliceAsByteBuffer(); - int ret = channel.read(b); - if (ret == -1) { - return null; - } - b.flip(); - return buffer.slice(0, b.limit()); - } - - @Override - public void close() throws IOException { - channel.close(); - } -} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/ChannelBufferOutput.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/ChannelBufferOutput.java deleted file mode 100644 index 5844c27..0000000 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/ChannelBufferOutput.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright 2021 - 2026 the TODAY 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 - * - * https://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 infra.cloud.serialize.format.buffer; - -import java.io.IOException; -import java.nio.ByteBuffer; -import java.nio.channels.WritableByteChannel; -import java.util.Objects; - -/** - * {@link MessageBufferOutput} adapter for {@link WritableByteChannel} - */ -public class ChannelBufferOutput implements MessageBufferOutput { - - private WritableByteChannel channel; - - private MessageBuffer buffer; - - public ChannelBufferOutput(WritableByteChannel channel) { - this(channel, 8192); - } - - public ChannelBufferOutput(WritableByteChannel channel, int bufferSize) { - this.channel = Objects.requireNonNull(channel, "output channel is null"); - this.buffer = MessageBuffer.allocate(bufferSize); - } - - /** - * Reset channel. This method doesn't close the old channel. - * - * @param channel new channel - * @return the old channel - */ - public WritableByteChannel reset(WritableByteChannel channel) { - WritableByteChannel old = this.channel; - this.channel = channel; - return old; - } - - @Override - public MessageBuffer next(int minimumSize) throws IOException { - if (buffer.size() < minimumSize) { - buffer = MessageBuffer.allocate(minimumSize); - } - return buffer; - } - - @Override - public void writeBuffer(int length) throws IOException { - ByteBuffer bb = buffer.sliceAsByteBuffer(0, length); - while (bb.hasRemaining()) { - channel.write(bb); - } - } - - @Override - public void write(byte[] buffer, int offset, int length) throws IOException { - ByteBuffer bb = ByteBuffer.wrap(buffer, offset, length); - while (bb.hasRemaining()) { - channel.write(bb); - } - } - - @Override - public void add(byte[] buffer, int offset, int length) throws IOException { - write(buffer, offset, length); - } - - @Override - public void close() throws IOException { - channel.close(); - } - - @Override - public void flush() { - } - -} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/DirectBufferAccess.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/DirectBufferAccess.java deleted file mode 100644 index a13756d..0000000 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/DirectBufferAccess.java +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Copyright 2021 - 2026 the TODAY 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 - * - * https://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 infra.cloud.serialize.format.buffer; - -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.nio.Buffer; -import java.nio.ByteBuffer; - -import sun.misc.Unsafe; -import sun.nio.ch.DirectBuffer; - -/** - * Wraps the difference of access methods to DirectBuffers between Android and others. - */ -class DirectBufferAccess { - - private DirectBufferAccess() { - } - - enum DirectBufferConstructorType { - ARGS_LONG_LONG, - ARGS_LONG_INT_REF, - ARGS_LONG_INT, - ARGS_INT_INT, - ARGS_MB_INT_INT - } - - // For Java >=9, invokes a jdk.internal.ref.Cleaner - static Method mInvokeCleaner; - - // TODO We should use MethodHandle for efficiency, but it is not available in JDK6 - static Constructor byteBufferConstructor; - static Class directByteBufferClass; - static DirectBufferConstructorType directBufferConstructorType; - static Method memoryBlockWrapFromJni; - - static { - try { - final ByteBuffer direct = ByteBuffer.allocateDirect(1); - // Find the hidden constructor for DirectByteBuffer - directByteBufferClass = direct.getClass(); - Constructor directByteBufferConstructor = null; - DirectBufferConstructorType constructorType = null; - Method mbWrap = null; - try { - // JDK21 DirectByteBuffer(long, long) - directByteBufferConstructor = directByteBufferClass.getDeclaredConstructor(long.class, long.class); - constructorType = DirectBufferConstructorType.ARGS_LONG_LONG; - } - catch (NoSuchMethodException e00) { - try { - // TODO We should use MethodHandle for Java7, which can avoid the cost of boxing with JIT optimization - directByteBufferConstructor = directByteBufferClass.getDeclaredConstructor(long.class, int.class, Object.class); - constructorType = DirectBufferConstructorType.ARGS_LONG_INT_REF; - } - catch (NoSuchMethodException e0) { - try { - // https://android.googlesource.com/platform/libcore/+/master/luni/src/main/java/java/nio/DirectByteBuffer.java - // DirectByteBuffer(long address, int capacity) - directByteBufferConstructor = directByteBufferClass.getDeclaredConstructor(long.class, int.class); - constructorType = DirectBufferConstructorType.ARGS_LONG_INT; - } - catch (NoSuchMethodException e1) { - try { - directByteBufferConstructor = directByteBufferClass.getDeclaredConstructor(int.class, int.class); - constructorType = DirectBufferConstructorType.ARGS_INT_INT; - } - catch (NoSuchMethodException e2) { - Class aClass = Class.forName("java.nio.MemoryBlock"); - mbWrap = aClass.getDeclaredMethod("wrapFromJni", int.class, long.class); - mbWrap.setAccessible(true); - directByteBufferConstructor = directByteBufferClass.getDeclaredConstructor(aClass, int.class, int.class); - constructorType = DirectBufferConstructorType.ARGS_MB_INT_INT; - } - } - } - } - - byteBufferConstructor = directByteBufferConstructor; - directBufferConstructorType = constructorType; - memoryBlockWrapFromJni = mbWrap; - - if (byteBufferConstructor == null) { - throw new RuntimeException("Constructor of DirectByteBuffer is not found"); - } - - try { - byteBufferConstructor.setAccessible(true); - } - catch (RuntimeException e) { - // This is a Java9+ exception, so we need to detect it without importing it for Java8 support - if ("java.lang.reflect.InaccessibleObjectException".equals(e.getClass().getName())) { - byteBufferConstructor = null; - } - else { - throw e; - } - } - - setupCleanerJava9(direct); - } - catch (Exception e) { - throw new RuntimeException(e); - } - } - - private static void setupCleanerJava9(final ByteBuffer direct) { - Object obj = getInvokeCleanerMethod(direct); - if (obj instanceof Throwable) { - throw new RuntimeException((Throwable) obj); - } - mInvokeCleaner = (Method) obj; - } - - /** - * Checks if we have a usable {@link Unsafe#invokeCleaner}. - * - * @param direct a direct buffer - * @return the method or an error - */ - private static Object getInvokeCleanerMethod(ByteBuffer direct) { - try { - // See https://bugs.openjdk.java.net/browse/JDK-8171377 - Method m = MessageBuffer.unsafe.getClass().getDeclaredMethod( - "invokeCleaner", ByteBuffer.class); - m.invoke(MessageBuffer.unsafe, direct); - return m; - } - catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) { - return e; - } - } - - static long getAddress(Buffer buffer) { - return ((DirectBuffer) buffer).address(); - } - - static ByteBuffer newByteBuffer(long address, int index, int length, ByteBuffer reference) { - if (byteBufferConstructor == null) { - throw new IllegalStateException("Can't create a new DirectByteBuffer. In JDK17+, two JVM options needs to be set: " + - "--add-opens=java.base/java.nio=ALL-UNNAMED and --add-opens=java.base/sun.nio.ch=ALL-UNNAMED"); - } - try { - return switch (directBufferConstructorType) { - case ARGS_LONG_LONG -> (ByteBuffer) byteBufferConstructor.newInstance(address + index, (long) length); - case ARGS_LONG_INT_REF -> (ByteBuffer) byteBufferConstructor.newInstance(address + index, length, reference); - case ARGS_LONG_INT -> (ByteBuffer) byteBufferConstructor.newInstance(address + index, length); - case ARGS_INT_INT -> (ByteBuffer) byteBufferConstructor.newInstance((int) address + index, length); - case ARGS_MB_INT_INT -> (ByteBuffer) byteBufferConstructor.newInstance( - memoryBlockWrapFromJni.invoke(null, address + index, length), length, 0); - }; - } - catch (Throwable e) { - // Convert checked exception to unchecked exception - throw new RuntimeException(e); - } - } -} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/InputStreamBufferInput.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/InputStreamBufferInput.java deleted file mode 100644 index c9c0bb2..0000000 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/InputStreamBufferInput.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright 2021 - 2026 the TODAY 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 - * - * https://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 infra.cloud.serialize.format.buffer; - -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.nio.channels.FileChannel; -import java.util.Objects; - -import infra.lang.Assert; - -/** - * {@link MessageBufferInput} adapter for {@link InputStream} - */ -public class InputStreamBufferInput implements MessageBufferInput { - - private InputStream in; - - private final byte[] buffer; - - public static MessageBufferInput newBufferInput(InputStream in) { - Assert.notNull(in, "InputStream is null"); - if (in instanceof FileInputStream) { - FileChannel channel = ((FileInputStream) in).getChannel(); - if (channel != null) { - return new ChannelBufferInput(channel); - } - } - return new InputStreamBufferInput(in); - } - - public InputStreamBufferInput(InputStream in) { - this(in, 8192); - } - - public InputStreamBufferInput(InputStream in, int bufferSize) { - this.in = Objects.requireNonNull(in, "input is null"); - this.buffer = new byte[bufferSize]; - } - - /** - * Reset Stream. This method doesn't close the old resource. - * - * @param in new stream - * @return the old resource - */ - public InputStream reset(InputStream in) throws IOException { - InputStream old = this.in; - this.in = in; - return old; - } - - @Override - public MessageBuffer next() throws IOException { - int readLen = in.read(buffer); - if (readLen == -1) { - return null; - } - return MessageBuffer.wrap(buffer, 0, readLen); - } - - @Override - public void close() - throws IOException { - in.close(); - } -} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/MessageBuffer.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/MessageBuffer.java deleted file mode 100644 index 5849859..0000000 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/MessageBuffer.java +++ /dev/null @@ -1,573 +0,0 @@ -/* - * Copyright 2021 - 2026 the TODAY 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 - * - * https://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 infra.cloud.serialize.format.buffer; - -import java.lang.reflect.Constructor; -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.nio.BufferOverflowException; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.util.Objects; - -import infra.lang.Assert; -import sun.misc.Unsafe; - -/** - * MessageBuffer class is an abstraction of memory with fast methods to serialize and deserialize primitive values - * to/from the memory. All MessageBuffer implementations ensure short/int/float/long/double values are written in - * big-endian order. - *

          - * Applications can allocate a new buffer using {@link #allocate(int)} method, or wrap an byte array or ByteBuffer - * using {@link #wrap(byte[], int, int)} methods. {@link #wrap(ByteBuffer)} method supports both direct buffers and - * array-backed buffers. - *

          - * MessageBuffer class itself is optimized for little-endian CPU archtectures so that JVM (HotSpot) can take advantage - * of the fastest JIT format which skips TypeProfile checking. To ensure this performance, applications must not import - * unnecessary classes such as MessagePackBE. On big-endian CPU archtectures, it automatically uses a subclass that - * includes TypeProfile overhead but still faster than stndard ByteBuffer class. On JVMs older than Java 7 and JVMs - * without Unsafe API (such as Android), implementation falls back to an universal implementation that uses ByteBuffer - * internally. - */ -public class MessageBuffer { - - static final boolean isUniversalBuffer; - - static final Unsafe unsafe; - - static final int javaVersion = getJavaVersion(); - - /** - * Reference to MessageBuffer Constructors - */ - private static final Constructor mbArrConstructor; - private static final Constructor mbBBConstructor; - - /** - * The offset from the object memory header to its byte array data - */ - static final int ARRAY_BYTE_BASE_OFFSET; - - private static final String UNIVERSAL_MESSAGE_BUFFER = "infra.cloud.serialize.format.buffer.MessageBufferU"; - private static final String BIGENDIAN_MESSAGE_BUFFER = "infra.cloud.serialize.format.buffer.MessageBufferBE"; - private static final String DEFAULT_MESSAGE_BUFFER = "infra.cloud.serialize.format.buffer.MessageBuffer"; - - static { - boolean useUniversalBuffer = false; - Unsafe unsafeInstance = null; - int arrayByteBaseOffset = 16; - - try { - boolean hasUnsafe = false; - try { - hasUnsafe = Class.forName("sun.misc.Unsafe") != null; - } - catch (Exception ignored) { - } - - // Detect android VM - boolean isAndroid = System.getProperty("java.runtime.name", "").toLowerCase().contains("android"); - - // Is Google App Engine? - boolean isGAE = System.getProperty("com.google.appengine.runtime.version") != null; - - // For Java6, android and JVM that has no Unsafe class, use Universal MessageBuffer (based on ByteBuffer). - useUniversalBuffer = - Boolean.parseBoolean(System.getProperty("msgpack.universal-buffer", "false")) - || isAndroid - || isGAE - || javaVersion < 7 - || !hasUnsafe; - - if (!useUniversalBuffer) { - // Fetch theUnsafe object for Oracle and OpenJDK - Field field = Unsafe.class.getDeclaredField("theUnsafe"); - field.setAccessible(true); - unsafeInstance = (Unsafe) field.get(null); - if (unsafeInstance == null) { - throw new RuntimeException("Unsafe is unavailable"); - } - arrayByteBaseOffset = unsafeInstance.arrayBaseOffset(byte[].class); - int arrayByteIndexScale = unsafeInstance.arrayIndexScale(byte[].class); - - // Make sure the VM thinks bytes are only one byte wide - if (arrayByteIndexScale != 1) { - throw new IllegalStateException("Byte array index scale must be 1, but is " + arrayByteIndexScale); - } - } - } - catch (Exception e) { - e.printStackTrace(System.err); - // Use MessageBufferU - useUniversalBuffer = true; - } - finally { - // Initialize the static fields - unsafe = unsafeInstance; - ARRAY_BYTE_BASE_OFFSET = arrayByteBaseOffset; - - // Switch MessageBuffer implementation according to the environment - isUniversalBuffer = useUniversalBuffer; - String bufferClsName; - if (isUniversalBuffer) { - bufferClsName = UNIVERSAL_MESSAGE_BUFFER; - } - else { - // Check the endian of this CPU - boolean isLittleEndian = ByteOrder.nativeOrder() == ByteOrder.LITTLE_ENDIAN; - bufferClsName = isLittleEndian ? DEFAULT_MESSAGE_BUFFER : BIGENDIAN_MESSAGE_BUFFER; - } - - if (DEFAULT_MESSAGE_BUFFER.equals(bufferClsName)) { - // No need to use reflection here, we're not using a MessageBuffer subclass. - mbArrConstructor = null; - mbBBConstructor = null; - } - else { - try { - // We need to use reflection here to find MessageBuffer implementation classes because - // importing these classes creates TypeProfile and adds some overhead to method calls. - - // MessageBufferX (default, BE or U) class - Class bufferCls = Class.forName(bufferClsName); - - // MessageBufferX(byte[]) constructor - Constructor mbArrCstr = bufferCls.getDeclaredConstructor(byte[].class, int.class, int.class); - mbArrCstr.setAccessible(true); - mbArrConstructor = mbArrCstr; - - // MessageBufferX(ByteBuffer) constructor - Constructor mbBBCstr = bufferCls.getDeclaredConstructor(ByteBuffer.class); - mbBBCstr.setAccessible(true); - mbBBConstructor = mbBBCstr; - } - catch (Exception e) { - e.printStackTrace(System.err); - throw new RuntimeException(e); // No more fallback exists if MessageBuffer constructors are inaccessible - } - } - } - } - - private static int getJavaVersion() { - String javaVersion = System.getProperty("java.specification.version", ""); - int dotPos = javaVersion.indexOf('.'); - if (dotPos != -1) { - try { - int major = Integer.parseInt(javaVersion.substring(0, dotPos)); - int minor = Integer.parseInt(javaVersion.substring(dotPos + 1)); - return major > 1 ? major : minor; - } - catch (NumberFormatException e) { - e.printStackTrace(System.err); - } - } - else { - try { - return Integer.parseInt(javaVersion); - } - catch (NumberFormatException e) { - e.printStackTrace(System.err); - } - } - return 6; - } - - /** - * Base object for resolving the relative address of the raw byte array. - * If base == null, the address value is a raw memory address - */ - protected final Object base; - - /** - * Head address of the underlying memory. If base is null, the address is a direct memory address, and if not, - * it is the relative address within an array object (base) - */ - protected final long address; - - /** - * Size of the underlying memory - */ - protected final int size; - - /** - * Reference is used to hold a reference to an object that holds the underlying memory so that it cannot be - * released by the garbage collector. - */ - protected final ByteBuffer reference; - - /** - * Allocates a new MessageBuffer backed by a byte array. - * - * @throws IllegalArgumentException If the capacity is a negative integer - */ - public static MessageBuffer allocate(int size) { - if (size < 0) { - throw new IllegalArgumentException("size must not be negative"); - } - return wrap(new byte[size]); - } - - /** - * Wraps a byte array into a MessageBuffer. - *

          - * The new MessageBuffer will be backed by the given byte array. - * Modifications to the new MessageBuffer will cause the byte array to be modified and vice versa. - *

          - * The new buffer's size will be array.length. hasArray() will return true. - * - * @param array the byte array that will gack this MessageBuffer - * @return a new MessageBuffer that wraps the given byte array - */ - public static MessageBuffer wrap(byte[] array) { - return newMessageBuffer(array, 0, array.length); - } - - /** - * Wraps a byte array into a MessageBuffer. - *

          - * The new MessageBuffer will be backed by the given byte array. - * Modifications to the new MessageBuffer will cause the byte array to be modified and vice versa. - *

          - * The new buffer's size will be length. hasArray() will return true. - * - * @param array the byte array that will gack this MessageBuffer - * @param offset The offset of the subarray to be used; must be non-negative and no larger than array.length - * @param length The length of the subarray to be used; must be non-negative and no larger than array.length - offset - * @return a new MessageBuffer that wraps the given byte array - */ - public static MessageBuffer wrap(byte[] array, int offset, int length) { - return newMessageBuffer(array, offset, length); - } - - /** - * Wraps a ByteBuffer into a MessageBuffer. - *

          - * The new MessageBuffer will be backed by the given byte buffer. Modifications to the new MessageBuffer will cause the byte buffer to be modified and vice versa. However, change of position, limit, or mark of given byte buffer doesn't affect MessageBuffer. - *

          - * The new buffer's size will be bb.remaining(). hasArray() will return the same result with bb.hasArray(). - * - * @param bb the byte buffer that will gack this MessageBuffer - * @return a new MessageBuffer that wraps the given byte array - * @throws IllegalArgumentException given byte buffer returns false both from hasArray() and isDirect() - * @throws UnsupportedOperationException given byte buffer is a direct buffer and this platform doesn't support Unsafe API - */ - public static MessageBuffer wrap(ByteBuffer bb) { - return newMessageBuffer(bb); - } - - /** - * Creates a new MessageBuffer instance backed by a java heap array - */ - private static MessageBuffer newMessageBuffer(byte[] arr, int off, int len) { - Objects.requireNonNull(arr); - if (mbArrConstructor != null) { - return newInstance(mbArrConstructor, arr, off, len); - } - return new MessageBuffer(arr, off, len); - } - - /** - * Creates a new MessageBuffer instance backed by ByteBuffer - */ - private static MessageBuffer newMessageBuffer(ByteBuffer bb) { - Objects.requireNonNull(bb); - if (mbBBConstructor != null) { - return newInstance(mbBBConstructor, bb); - } - return new MessageBuffer(bb); - } - - /** - * Creates a new MessageBuffer instance - * - * @param constructor A MessageBuffer constructor - * @return new MessageBuffer instance - */ - private static MessageBuffer newInstance(Constructor constructor, Object... args) { - try { - // We need to use reflection to create MessageBuffer instances in order to prevent TypeProfile generation for getInt method. TypeProfile will be - // generated to resolve one of the method references when two or more classes overrides the method. - return (MessageBuffer) constructor.newInstance(args); - } - catch (InstantiationException e) { - // should never happen - throw new IllegalStateException(e); - } - catch (IllegalAccessException e) { - // should never happen unless security manager restricts this reflection - throw new IllegalStateException(e); - } - catch (InvocationTargetException e) { - if (e.getCause() instanceof RuntimeException) { - // underlying constructor may throw RuntimeException - throw (RuntimeException) e.getCause(); - } - else if (e.getCause() instanceof Error) { - throw (Error) e.getCause(); - } - // should never happen - throw new IllegalStateException(e.getCause()); - } - } - - /** - * Create a MessageBuffer instance from an java heap array - */ - MessageBuffer(byte[] arr, int offset, int length) { - this.base = arr; // non-null is already checked at newMessageBuffer - this.address = ARRAY_BYTE_BASE_OFFSET + offset; - this.size = length; - this.reference = null; - } - - /** - * Create a MessageBuffer instance from a given ByteBuffer instance - */ - MessageBuffer(ByteBuffer bb) { - if (bb.isDirect()) { - if (isUniversalBuffer) { - // MessageBufferU overrides almost all methods, only field 'size' is used. - this.base = null; - this.address = 0; - this.size = bb.remaining(); - this.reference = null; - return; - } - // Direct buffer or off-heap memory - this.base = null; - this.address = DirectBufferAccess.getAddress(bb) + bb.position(); - this.size = bb.remaining(); - this.reference = bb; - } - else if (bb.hasArray()) { - this.base = bb.array(); - this.address = ARRAY_BYTE_BASE_OFFSET + bb.arrayOffset() + bb.position(); - this.size = bb.remaining(); - this.reference = null; - } - else { - throw new IllegalArgumentException("Only the array-backed ByteBuffer or DirectBuffer is supported"); - } - } - - protected MessageBuffer(Object base, long address, int length) { - this.base = base; - this.address = address; - this.size = length; - this.reference = null; - } - - /** - * Gets the size of the buffer. - *

          - * MessageBuffer doesn't have limit unlike ByteBuffer. Instead, you can use {@link #slice(int, int)} to get a - * part of the buffer. - * - * @return number of bytes - */ - public int size() { - return size; - } - - public MessageBuffer slice(int offset, int length) { - // TODO ensure deleting this slice does not collapse this MessageBuffer - if (offset == 0 && length == size()) { - return this; - } - else { - Assert.isTrue(offset + length <= size(), "offset must <= size - length"); - return new MessageBuffer(base, address + offset, length); - } - } - - public byte getByte(int index) { - return unsafe.getByte(base, address + index); - } - - public boolean getBoolean(int index) { - return unsafe.getBoolean(base, address + index); - } - - public short getShort(int index) { - short v = unsafe.getShort(base, address + index); - return Short.reverseBytes(v); - } - - /** - * Read a big-endian int value at the specified index - */ - public int getInt(int index) { - // Reading little-endian value - int i = unsafe.getInt(base, address + index); - // Reversing the endian - return Integer.reverseBytes(i); - } - - public float getFloat(int index) { - return Float.intBitsToFloat(getInt(index)); - } - - public long getLong(int index) { - long l = unsafe.getLong(base, address + index); - return Long.reverseBytes(l); - } - - public double getDouble(int index) { - return Double.longBitsToDouble(getLong(index)); - } - - public void getBytes(int index, byte[] dst, int dstOffset, int length) { - unsafe.copyMemory(base, address + index, dst, ARRAY_BYTE_BASE_OFFSET + dstOffset, length); - } - - public void getBytes(int index, int len, ByteBuffer dst) { - if (dst.remaining() < len) { - throw new BufferOverflowException(); - } - ByteBuffer src = sliceAsByteBuffer(index, len); - dst.put(src); - } - - public void putByte(int index, byte v) { - unsafe.putByte(base, address + index, v); - } - - public void putBoolean(int index, boolean v) { - unsafe.putBoolean(base, address + index, v); - } - - public void putShort(int index, short v) { - v = Short.reverseBytes(v); - unsafe.putShort(base, address + index, v); - } - - /** - * Write a big-endian integer value to the memory - */ - public void putInt(int index, int v) { - // Reversing the endian - v = Integer.reverseBytes(v); - unsafe.putInt(base, address + index, v); - } - - public void putFloat(int index, float v) { - putInt(index, Float.floatToRawIntBits(v)); - } - - public void putLong(int index, long l) { - // Reversing the endian - l = Long.reverseBytes(l); - unsafe.putLong(base, address + index, l); - } - - public void putDouble(int index, double v) { - putLong(index, Double.doubleToRawLongBits(v)); - } - - public void putBytes(int index, byte[] src, int srcOffset, int length) { - unsafe.copyMemory(src, ARRAY_BYTE_BASE_OFFSET + srcOffset, base, address + index, length); - } - - public void putByteBuffer(int index, ByteBuffer src, int len) { - assert (len <= src.remaining()); - assert (!isUniversalBuffer); - - if (src.isDirect()) { - unsafe.copyMemory(null, DirectBufferAccess.getAddress(src) + src.position(), base, address + index, len); - src.position(src.position() + len); - } - else if (src.hasArray()) { - byte[] srcArray = src.array(); - unsafe.copyMemory(srcArray, ARRAY_BYTE_BASE_OFFSET + src.position(), base, address + index, len); - src.position(src.position() + len); - } - else { - if (hasArray()) { - src.get((byte[]) base, index, len); - } - else { - for (int i = 0; i < len; ++i) { - unsafe.putByte(base, address + index, src.get()); - } - } - } - } - - public void putMessageBuffer(int index, MessageBuffer src, int srcOffset, int len) { - unsafe.copyMemory(src.base, src.address + srcOffset, base, address + index, len); - } - - /** - * Create a ByteBuffer view of the range [index, index+length) of this memory - */ - public ByteBuffer sliceAsByteBuffer(int index, int length) { - if (hasArray()) { - return ByteBuffer.wrap((byte[]) base, (int) ((address - ARRAY_BYTE_BASE_OFFSET) + index), length); - } - else { - assert (!isUniversalBuffer); - return DirectBufferAccess.newByteBuffer(address, index, length, reference); - } - } - - /** - * Get a ByteBuffer view of this buffer - */ - public ByteBuffer sliceAsByteBuffer() { - return sliceAsByteBuffer(0, size()); - } - - public boolean hasArray() { - return base != null; - } - - /** - * Get a copy of this buffer - */ - public byte[] toByteArray() { - byte[] b = new byte[size()]; - unsafe.copyMemory(base, address, b, ARRAY_BYTE_BASE_OFFSET, size()); - return b; - } - - public byte[] array() { - return (byte[]) base; - } - - public int arrayOffset() { - return (int) address - ARRAY_BYTE_BASE_OFFSET; - } - - /** - * Copy this buffer contents to another MessageBuffer - */ - public void copyTo(int index, MessageBuffer dst, int offset, int length) { - unsafe.copyMemory(base, address + index, dst.base, dst.address + offset, length); - } - - public String toHexString(int offset, int length) { - StringBuilder s = new StringBuilder(); - for (int i = offset; i < length; ++i) { - if (i != offset) { - s.append(" "); - } - s.append(String.format("%02x", getByte(i))); - } - return s.toString(); - } -} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/MessageBufferBE.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/MessageBufferBE.java deleted file mode 100644 index 3c5bbd5..0000000 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/MessageBufferBE.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright 2021 - 2026 the TODAY 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 - * - * https://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 infra.cloud.serialize.format.buffer; - -import java.nio.ByteBuffer; - -import infra.lang.Assert; - -/** - * MessageBufferBE is a {@link MessageBuffer} implementation tailored to big-endian machines. - * The specification of Message Pack demands writing short/int/float/long/double values in the big-endian format. - * In the big-endian machine, we do not need to swap the byte order. - */ -public class MessageBufferBE extends MessageBuffer { - - MessageBufferBE(byte[] arr, int offset, int length) { - super(arr, offset, length); - } - - MessageBufferBE(ByteBuffer bb) { - super(bb); - } - - private MessageBufferBE(Object base, long address, int length) { - super(base, address, length); - } - - @Override - public MessageBufferBE slice(int offset, int length) { - if (offset == 0 && length == size()) { - return this; - } - else { - Assert.isTrue(offset + length <= size(), "offset must <= size - length"); - return new MessageBufferBE(base, address + offset, length); - } - } - - @Override - public short getShort(int index) { - return unsafe.getShort(base, address + index); - } - - @Override - public int getInt(int index) { - // We can simply return the integer value as big-endian value - return unsafe.getInt(base, address + index); - } - - public long getLong(int index) { - return unsafe.getLong(base, address + index); - } - - @Override - public float getFloat(int index) { - return unsafe.getFloat(base, address + index); - } - - @Override - public double getDouble(int index) { - return unsafe.getDouble(base, address + index); - } - - @Override - public void putShort(int index, short v) { - unsafe.putShort(base, address + index, v); - } - - @Override - public void putInt(int index, int v) { - unsafe.putInt(base, address + index, v); - } - - @Override - public void putLong(int index, long v) { - unsafe.putLong(base, address + index, v); - } - - @Override - public void putDouble(int index, double v) { - unsafe.putDouble(base, address + index, v); - } -} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/MessageBufferInput.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/MessageBufferInput.java deleted file mode 100644 index 23dc526..0000000 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/MessageBufferInput.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2021 - 2026 the TODAY 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 - * - * https://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 infra.cloud.serialize.format.buffer; - -import org.jspecify.annotations.Nullable; - -import java.io.Closeable; -import java.io.IOException; - -/** - * Provides a sequence of MessageBuffer instances. - *

          - * A MessageBufferInput implementation has control of lifecycle - * of the memory so that it can reuse previously allocated memory, - * use memory pools, or use memory-mapped files. - */ -public interface MessageBufferInput extends Closeable { - - /** - * Returns a next buffer to read. - *

          - * This method should return a MessageBuffer instance that has data filled in. When this method is called twice, - * the previously returned buffer is no longer used. Thus, implementation of this method can safely discard it. - * This is useful when it uses a memory pool. - * - * @return the next MessageBuffer, or return null if no more buffer is available. - * @throws IOException when IO error occurred when reading the data - */ - @Nullable - MessageBuffer next() throws IOException; - - /** - * Closes the input. - *

          - * When this method is called, the buffer previously returned from {@link #next()} method is no longer used. - * Thus, implementation of this method can safely discard it. - *

          - * If the input is already closed then invoking this method has no effect. - * - * @throws IOException when IO error occurred when closing the data source - */ - @Override - void close() throws IOException; - -} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/MessageBufferOutput.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/MessageBufferOutput.java deleted file mode 100644 index 4826849..0000000 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/MessageBufferOutput.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright 2021 - 2026 the TODAY 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 - * - * https://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 infra.cloud.serialize.format.buffer; - -import java.io.Closeable; -import java.io.Flushable; -import java.io.IOException; - -/** - * Provides a buffered output stream that writes sequence of MessageBuffer instances. - *

          - * A MessageBufferOutput implementation has total control of the buffer memory so that it can reuse buffer memory, - * use buffer pools, or use memory-mapped files. - */ -public interface MessageBufferOutput extends Closeable, Flushable { - - /** - * Allocates the next buffer to write. - *

          - * This method should return a MessageBuffer instance that has specified size of capacity at least. - *

          - * When this method is called twice, the previously returned buffer is no longer used. This method may be called - * twice without call of {@link #writeBuffer(int)} in between. In this case, the buffer should be - * discarded without flushing it to the output. - * - * @param minimumSize the mimium required buffer size to allocate - * @return the MessageBuffer instance with at least minimumSize bytes of capacity - */ - MessageBuffer next(int minimumSize) throws IOException; - - /** - * Writes the previously allocated buffer. - *

          - * This method should write the buffer previously returned from {@link #next(int)} method until specified number of - * bytes. Once the buffer is written, the buffer is no longer used. - *

          - * This method is not always called for each {@link #next(int)} call. In this case, the buffer should be discarded - * without flushing it to the output when the next {@link #next(int)} is called. - * - * @param length the number of bytes to write - */ - void writeBuffer(int length) throws IOException; - - /** - * Writes an external payload data. - * This method should follow semantics of OutputStream. - * - * @param buffer the data to write - * @param offset the start offset in the data - * @param length the number of bytes to write - */ - void write(byte[] buffer, int offset, int length) throws IOException; - - /** - * Writes an external payload data. - *

          - * Unlike {@link #write(byte[], int, int)} method, the buffer is given - this MessageBufferOutput implementation - * gets ownership of the buffer and may modify contents of the buffer. Contents of this buffer won't be modified - * by the caller. - * - * @param buffer the data to add - * @param offset the start offset in the data - * @param length the number of bytes to add - */ - void add(byte[] buffer, int offset, int length) throws IOException; - -} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/MessageBufferU.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/MessageBufferU.java deleted file mode 100644 index 6f3b143..0000000 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/MessageBufferU.java +++ /dev/null @@ -1,243 +0,0 @@ -/* - * Copyright 2021 - 2026 the TODAY 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 - * - * https://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 infra.cloud.serialize.format.buffer; - -import java.nio.ByteBuffer; - -import infra.lang.Assert; - -/** - * Universal MessageBuffer implementation supporting Java6 and Android. - * This buffer always uses ByteBuffer-based memory access - */ -public class MessageBufferU extends MessageBuffer { - - private final ByteBuffer wrap; - - MessageBufferU(byte[] arr, int offset, int length) { - super(arr, offset, length); - this.wrap = ByteBuffer.wrap(arr, offset, length).slice(); - } - - MessageBufferU(ByteBuffer bb) { - super(bb); - this.wrap = bb.slice(); - } - - private MessageBufferU(Object base, long address, int length, ByteBuffer wrap) { - super(base, address, length); - this.wrap = wrap; - } - - @Override - public MessageBufferU slice(int offset, int length) { - if (offset == 0 && length == size()) { - return this; - } - else { - Assert.isTrue(offset + length <= size(), "offset must <= size - length"); - try { - wrap.position(offset); - wrap.limit(offset + length); - return new MessageBufferU(base, address + offset, length, wrap.slice()); - } - finally { - resetBufferPosition(); - } - } - } - - private void resetBufferPosition() { - wrap.position(0); - wrap.limit(size); - } - - @Override - public byte getByte(int index) { - return wrap.get(index); - } - - @Override - public boolean getBoolean(int index) { - return wrap.get(index) != 0; - } - - @Override - public short getShort(int index) { - return wrap.getShort(index); - } - - @Override - public int getInt(int index) { - return wrap.getInt(index); - } - - @Override - public float getFloat(int index) { - return wrap.getFloat(index); - } - - @Override - public long getLong(int index) { - return wrap.getLong(index); - } - - @Override - public double getDouble(int index) { - return wrap.getDouble(index); - } - - @Override - public void getBytes(int index, int len, ByteBuffer dst) { - try { - wrap.position(index); - wrap.limit(index + len); - dst.put(wrap); - } - finally { - resetBufferPosition(); - } - } - - @Override - public void putByte(int index, byte v) { - wrap.put(index, v); - } - - @Override - public void putBoolean(int index, boolean v) { - wrap.put(index, v ? (byte) 1 : (byte) 0); - } - - @Override - public void putShort(int index, short v) { - wrap.putShort(index, v); - } - - @Override - public void putInt(int index, int v) { - wrap.putInt(index, v); - } - - @Override - public void putFloat(int index, float v) { - wrap.putFloat(index, v); - } - - @Override - public void putLong(int index, long l) { - wrap.putLong(index, l); - } - - @Override - public void putDouble(int index, double v) { - wrap.putDouble(index, v); - } - - @Override - public ByteBuffer sliceAsByteBuffer(int index, int length) { - try { - wrap.position(index); - wrap.limit(index + length); - return wrap.slice(); - } - finally { - resetBufferPosition(); - } - } - - @Override - public ByteBuffer sliceAsByteBuffer() { - return sliceAsByteBuffer(0, size); - } - - @Override - public void getBytes(int index, byte[] dst, int dstOffset, int length) { - try { - wrap.position(index); - wrap.get(dst, dstOffset, length); - } - finally { - resetBufferPosition(); - } - } - - @Override - public void putByteBuffer(int index, ByteBuffer src, int len) { - assert (len <= src.remaining()); - - if (src.hasArray()) { - putBytes(index, src.array(), src.position() + src.arrayOffset(), len); - src.position(src.position() + len); - } - else { - int prevSrcLimit = src.limit(); - try { - src.limit(src.position() + len); - wrap.position(index); - wrap.put(src); - } - finally { - src.limit(prevSrcLimit); - } - } - } - - @Override - public void putBytes(int index, byte[] src, int srcOffset, int length) { - try { - wrap.position(index); - wrap.put(src, srcOffset, length); - } - finally { - resetBufferPosition(); - } - } - - @Override - public void copyTo(int index, MessageBuffer dst, int offset, int length) { - try { - wrap.position(index); - dst.putByteBuffer(offset, wrap, length); - } - finally { - resetBufferPosition(); - } - } - - @Override - public void putMessageBuffer(int index, MessageBuffer src, int srcOffset, int len) { - putByteBuffer(index, src.sliceAsByteBuffer(srcOffset, len), len); - } - - @Override - public byte[] toByteArray() { - byte[] b = new byte[size()]; - getBytes(0, b, 0, b.length); - return b; - } - - @Override - public boolean hasArray() { - return !wrap.isDirect(); - } - - @Override - public byte[] array() { - return hasArray() ? wrap.array() : null; - } -} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/OutputStreamBufferOutput.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/OutputStreamBufferOutput.java deleted file mode 100644 index 713d387..0000000 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/buffer/OutputStreamBufferOutput.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright 2021 - 2026 the TODAY 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 - * - * https://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 infra.cloud.serialize.format.buffer; - -import java.io.IOException; -import java.io.OutputStream; -import java.util.Objects; - -/** - * MessageBufferOutput adapter for {@link OutputStream}. - */ -public class OutputStreamBufferOutput implements MessageBufferOutput { - - private OutputStream out; - - private MessageBuffer buffer; - - public OutputStreamBufferOutput(OutputStream out) { - this(out, 8192); - } - - public OutputStreamBufferOutput(OutputStream out, int bufferSize) { - this.out = Objects.requireNonNull(out, "output is null"); - this.buffer = MessageBuffer.allocate(bufferSize); - } - - /** - * Reset Stream. This method doesn't close the old stream. - * - * @param out new stream - * @return the old stream - */ - public OutputStream reset(OutputStream out) { - OutputStream old = this.out; - this.out = out; - return old; - } - - @Override - public MessageBuffer next(int minimumSize) throws IOException { - if (buffer.size() < minimumSize) { - buffer = MessageBuffer.allocate(minimumSize); - } - return buffer; - } - - @Override - public void writeBuffer(int length) throws IOException { - write(buffer.array(), buffer.arrayOffset(), length); - } - - @Override - public void write(byte[] buffer, int offset, int length) throws IOException { - out.write(buffer, offset, length); - } - - @Override - public void add(byte[] buffer, int offset, int length) throws IOException { - write(buffer, offset, length); - } - - @Override - public void close() throws IOException { - out.close(); - } - - @Override - public void flush() throws IOException { - out.flush(); - } -} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ArrayValue.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ArrayValue.java deleted file mode 100644 index d21a0d0..0000000 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ArrayValue.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2021 - 2026 the TODAY 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 - * - * https://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 infra.cloud.serialize.format.value; - -import java.util.Iterator; -import java.util.List; - -/** - * Representation of MessagePack's Array type. - *

          - * MessagePack's Array type can represent sequence of values. - */ -public interface ArrayValue extends Value, Iterable { - - /** - * Returns number of elements in this array. - */ - int size(); - - /** - * Returns the element at the specified position in this array. - * - * @throws IndexOutOfBoundsException If the index is out of range - * (index < 0 || index >= size()) - */ - Value get(int index); - - /** - * Returns the element at the specified position in this array. - * This method returns an ImmutableNilValue if the index is out of range. - */ - Value getOrNilValue(int index); - - /** - * Returns an iterator over elements. - */ - Iterator iterator(); - - /** - * Returns the value as {@code List}. - */ - List list(); -} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/BinaryValue.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/BinaryValue.java deleted file mode 100644 index b914b32..0000000 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/BinaryValue.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2021 - 2026 the TODAY 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 - * - * https://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 infra.cloud.serialize.format.value; - -/** - * Representation of MessagePack's Binary type. - * - * MessagePack's Binary type can represent a byte array at most 264-1 bytes. - * - * @see RawValue - */ -public interface BinaryValue - extends RawValue { -} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/BooleanValue.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/BooleanValue.java deleted file mode 100644 index cd61b36..0000000 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/BooleanValue.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2021 - 2026 the TODAY 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 - * - * https://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 infra.cloud.serialize.format.value; - -/** - * Representation MessagePack's Boolean type. - * - * MessagePack's Boolean type can represent {@code true} or {@code false}. - */ -public interface BooleanValue - extends Value { - /** - * Returns the value as a {@code boolean}. - */ - boolean getBoolean(); -} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ExtensionValue.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ExtensionValue.java deleted file mode 100644 index 3bed4c7..0000000 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ExtensionValue.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2021 - 2026 the TODAY 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 - * - * https://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 infra.cloud.serialize.format.value; - -/** - * Representation of MessagePack's Extension type. - * - * MessagePack's Extension type can represent represents a tuple of type information and a byte array where type information is an - * integer whose meaning is defined by applications. - * - * As the type information, applications can use 0 to 127 as the application-specific types. -1 to -128 is reserved for MessagePack's future extension. - */ -public interface ExtensionValue - extends Value { - byte getType(); - - byte[] getData(); -} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/FloatValue.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/FloatValue.java deleted file mode 100644 index c9c9039..0000000 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/FloatValue.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2021 - 2026 the TODAY 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 - * - * https://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 infra.cloud.serialize.format.value; - -/** - * Representation of MessagePack's Float type. - *

          - * MessagePack's Float type can represent IEEE 754 double precision floating point numbers including NaN and infinity. This is same with Java's {@code double} type. - * - * @see NumberValue - */ -public interface FloatValue extends NumberValue { - -} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableArrayValue.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableArrayValue.java deleted file mode 100644 index 07a0c71..0000000 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableArrayValue.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2021 - 2026 the TODAY 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 - * - * https://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 infra.cloud.serialize.format.value; - -import java.util.Iterator; -import java.util.List; - -/** - * Immutable representation of MessagePack's Array type. - * - * MessagePack's Array type can represent sequence of values. - */ -public interface ImmutableArrayValue - extends ArrayValue, ImmutableValue { - /** - * Returns an iterator over elements. - * Returned Iterator does not support {@code remove()} method since the value is immutable. - */ - Iterator iterator(); - - /** - * Returns the value as {@code List}. - * Returned List is immutable. It does not support {@code put()}, {@code clear()}, or other methods that modify the value. - */ - List list(); -} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableBinaryValue.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableBinaryValue.java deleted file mode 100644 index 76743c0..0000000 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableBinaryValue.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2021 - 2026 the TODAY 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 - * - * https://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 infra.cloud.serialize.format.value; - -/** - * Immutable representation of MessagePack's Binary type. - * - * MessagePack's Binary type can represent a byte array at most 264-1 bytes. - * - * @see ImmutableRawValue - */ -public interface ImmutableBinaryValue - extends BinaryValue, ImmutableRawValue { -} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableBooleanValue.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableBooleanValue.java deleted file mode 100644 index 47735f1..0000000 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableBooleanValue.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright 2021 - 2026 the TODAY 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 - * - * https://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 infra.cloud.serialize.format.value; - -/** - * Immutable representation of MessagePack's Boolean type. - * - * MessagePack's Boolean type can represent {@code true} or {@code false}. - */ -public interface ImmutableBooleanValue - extends BooleanValue, ImmutableValue { -} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableExtensionValue.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableExtensionValue.java deleted file mode 100644 index a094055..0000000 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableExtensionValue.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright 2021 - 2026 the TODAY 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 - * - * https://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 infra.cloud.serialize.format.value; - -/** - * Immutable representation of MessagePack's Extension type. - * - * @see ExtensionValue - */ -public interface ImmutableExtensionValue - extends ExtensionValue, ImmutableValue { -} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableFloatValue.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableFloatValue.java deleted file mode 100644 index 17850b6..0000000 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableFloatValue.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2021 - 2026 the TODAY 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 - * - * https://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 infra.cloud.serialize.format.value; - -/** - * Immutable representation of MessagePack's Float type. - * - * MessagePack's Float type can represent IEEE 754 double precision floating point numbers including NaN and infinity. This is same with Java's {@code double} type. - * - * @see ImmutableNumberValue - */ -public interface ImmutableFloatValue - extends FloatValue, ImmutableNumberValue { -} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableIntegerValue.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableIntegerValue.java deleted file mode 100644 index 3541c8e..0000000 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableIntegerValue.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright 2021 - 2026 the TODAY 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 - * - * https://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 infra.cloud.serialize.format.value; - -/** - * Immutable representation of MessagePack's Integer type. - * - * MessagePack's Integer type can represent from -263 to 264-1. - */ -public interface ImmutableIntegerValue - extends IntegerValue, ImmutableNumberValue { -} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableMapValue.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableMapValue.java deleted file mode 100644 index 949402a..0000000 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableMapValue.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright 2021 - 2026 the TODAY 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 - * - * https://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 infra.cloud.serialize.format.value; - -/** - * Immutable representation of MessagePack's Map type. - * - * MessagePack's Map type can represent sequence of key-value pairs. - */ -public interface ImmutableMapValue - extends MapValue, ImmutableValue { -} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableNilValue.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableNilValue.java deleted file mode 100644 index d488fb8..0000000 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableNilValue.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright 2021 - 2026 the TODAY 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 - * - * https://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 infra.cloud.serialize.format.value; - -/** - * Immutable representation of MessagePack's Nil type. - */ -public interface ImmutableNilValue extends NilValue, ImmutableValue { - -} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableNumberValue.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableNumberValue.java deleted file mode 100644 index a85d3dc..0000000 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableNumberValue.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2021 - 2026 the TODAY 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 - * - * https://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 infra.cloud.serialize.format.value; - -/** - * Immutable base interface of {@link ImmutableIntegerValue} and {@link ImmutableFloatValue} interfaces. To extract primitive type values, call toXXX methods, which may lose some information by rounding or truncation. - * - * @see ImmutableIntegerValue - * @see ImmutableFloatValue - */ -public interface ImmutableNumberValue - extends NumberValue, ImmutableValue { -} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableRawValue.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableRawValue.java deleted file mode 100644 index 5ff67cd..0000000 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableRawValue.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2021 - 2026 the TODAY 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 - * - * https://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 infra.cloud.serialize.format.value; - -/** - * Immutable base interface of {@link ImmutableStringValue} and {@link ImmutableBinaryValue} interfaces. - *

          - * MessagePack's Raw type can represent a byte array at most 264-1 bytes. - * - * @see ImmutableStringValue - * @see ImmutableBinaryValue - */ -public interface ImmutableRawValue - extends RawValue, ImmutableValue { -} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableStringValue.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableStringValue.java deleted file mode 100644 index 0a0e092..0000000 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableStringValue.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2021 - 2026 the TODAY 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 - * - * https://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 infra.cloud.serialize.format.value; - -/** - * Immutable representation of MessagePack's String type. - * - * @see StringValue - * @see ImmutableRawValue - */ -public interface ImmutableStringValue - extends StringValue, ImmutableRawValue { -} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableTimestampValue.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableTimestampValue.java deleted file mode 100644 index 82f1903..0000000 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableTimestampValue.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright 2021 - 2026 the TODAY 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 - * - * https://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 infra.cloud.serialize.format.value; - -/** - * Immutable representation of MessagePack's Timestamp type. - * - * @see TimestampValue - */ -public interface ImmutableTimestampValue - extends TimestampValue, ImmutableValue { -} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableValue.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableValue.java deleted file mode 100644 index 3776fca..0000000 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ImmutableValue.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2021 - 2026 the TODAY 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 - * - * https://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 infra.cloud.serialize.format.value; - -/** - * Immutable declaration of {@link Value} interface. - */ -public interface ImmutableValue extends Value { - - @Override - ImmutableNilValue asNilValue(); - - @Override - ImmutableBooleanValue asBooleanValue(); - - @Override - ImmutableIntegerValue asIntegerValue(); - - @Override - ImmutableFloatValue asFloatValue(); - - @Override - ImmutableArrayValue asArrayValue(); - - @Override - ImmutableMapValue asMapValue(); - - @Override - ImmutableRawValue asRawValue(); - - @Override - ImmutableBinaryValue asBinaryValue(); - - @Override - ImmutableStringValue asStringValue(); - - @Override - ImmutableTimestampValue asTimestampValue(); -} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/IntegerValue.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/IntegerValue.java deleted file mode 100644 index 3644159..0000000 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/IntegerValue.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright 2021 - 2026 the TODAY 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 - * - * https://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 infra.cloud.serialize.format.value; - -import java.math.BigInteger; - -import infra.cloud.serialize.format.MessageFormat; -import infra.cloud.serialize.format.MessageIntegerOverflowException; - -/** - * Representation of MessagePack's Integer type. - * - * MessagePack's Integer type can represent from -263 to 264-1. - */ -public interface IntegerValue - extends NumberValue { - /** - * Returns true if the value is in the range of [-27 to 27-1]. - */ - boolean isInByteRange(); - - /** - * Returns true if the value is in the range of [-215 to 215-1] - */ - boolean isInShortRange(); - - /** - * Returns true if the value is in the range of [-231 to 231-1] - */ - boolean isInIntRange(); - - /** - * Returns true if the value is in the range of [-263 to 263-1] - */ - boolean isInLongRange(); - - /** - * Returns the most succinct MessageFormat type to represent this integer value. - * - * @return the smallest integer type of MessageFormat that is big enough to store the value. - */ - MessageFormat mostSuccinctMessageFormat(); - - /** - * Returns the value as a {@code byte}, otherwise throws an exception. - * - * @throws MessageIntegerOverflowException If the value does not fit in the range of {@code byte} type. - */ - byte asByte(); - - /** - * Returns the value as a {@code short}, otherwise throws an exception. - * - * @throws MessageIntegerOverflowException If the value does not fit in the range of {@code short} type. - */ - short asShort(); - - /** - * Returns the value as an {@code int}, otherwise throws an exception. - * - * @throws MessageIntegerOverflowException If the value does not fit in the range of {@code int} type. - */ - int asInt(); - - /** - * Returns the value as a {@code long}, otherwise throws an exception. - * - * @throws MessageIntegerOverflowException If the value does not fit in the range of {@code long} type. - */ - long asLong(); - - /** - * Returns the value as a {@code BigInteger}. - */ - BigInteger asBigInteger(); -} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/MapValue.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/MapValue.java deleted file mode 100644 index 7082342..0000000 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/MapValue.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2021 - 2026 the TODAY 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 - * - * https://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 infra.cloud.serialize.format.value; - -import java.util.Collection; -import java.util.Map; -import java.util.Set; - -/** - * Representation of MessagePack's Map type. - *

          - * MessagePack's Map type can represent sequence of key-value pairs. - */ -public interface MapValue extends Value { - - /** - * Returns number of key-value pairs in this array. - */ - int size(); - - Set keySet(); - - Set> entrySet(); - - Collection values(); - - /** - * Returns the value as {@code Map}. - */ - Map map(); - - /** - * Returns the key-value pairs as an array of {@code Value}. - *

          - * Odd elements are keys. Next element of an odd element is a value corresponding to the key. - *

          - * For example, if this value represents {"k1": "v1", "k2": "v2"}, this method returns ["k1", "v1", "k2", "v2"]. - */ - Value[] getKeyValueArray(); - -} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/NilValue.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/NilValue.java deleted file mode 100644 index d598e20..0000000 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/NilValue.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright 2021 - 2026 the TODAY 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 - * - * https://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 infra.cloud.serialize.format.value; - -/** - * Representation of MessagePack's Nil type. - */ -public interface NilValue extends Value { - -} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/NumberValue.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/NumberValue.java deleted file mode 100644 index cf85e9c..0000000 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/NumberValue.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright 2021 - 2026 the TODAY 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 - * - * https://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 infra.cloud.serialize.format.value; - -import java.math.BigInteger; - -/** - * Base interface of {@link IntegerValue} and {@link FloatValue} interfaces. To extract primitive type values, call toXXX methods, which may lose some information by rounding or truncation. - * - * @see IntegerValue - * @see FloatValue - */ -public interface NumberValue extends Value { - - /** - * Represent this value as a byte value, which may involve rounding or truncation of the original value. - * the value. - */ - byte toByte(); - - /** - * Represent this value as a short value, which may involve rounding or truncation of the original value. - */ - short toShort(); - - /** - * Represent this value as an int value, which may involve rounding or truncation of the original value. - * value. - */ - int toInt(); - - /** - * Represent this value as a long value, which may involve rounding or truncation of the original value. - */ - long toLong(); - - /** - * Represent this value as a BigInteger, which may involve rounding or truncation of the original value. - */ - BigInteger toBigInteger(); - - /** - * Represent this value as a 32-bit float value, which may involve rounding or truncation of the original value. - */ - float toFloat(); - - /** - * Represent this value as a 64-bit double value, which may involve rounding or truncation of the original value. - */ - double toDouble(); -} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/RawValue.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/RawValue.java deleted file mode 100644 index 1a8f7a4..0000000 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/RawValue.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2021 - 2026 the TODAY 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 - * - * https://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 infra.cloud.serialize.format.value; - -import java.nio.ByteBuffer; - -import infra.cloud.serialize.format.MessageStringCodingException; - -/** - * Base interface of {@link StringValue} and {@link BinaryValue} interfaces. - *

          - * MessagePack's Raw type can represent a byte array at most 264-1 bytes. - * - * @see StringValue - * @see BinaryValue - */ -public interface RawValue - extends Value { - /** - * Returns the value as {@code byte[]}. - * - * This method copies the byte array. - */ - byte[] asByteArray(); - - /** - * Returns the value as {@code ByteBuffer}. - * - * Returned ByteBuffer is read-only. See also {@link ByteBuffer#asReadOnlyBuffer()}. - * This method doesn't copy the byte array as much as possible. - */ - ByteBuffer asByteBuffer(); - - /** - * Returns the value as {@code String}. - * - * This method throws an exception if the value includes invalid UTF-8 byte sequence. - * - * @throws MessageStringCodingException If this value includes invalid UTF-8 byte sequence. - */ - String asString(); - - /** - * Returns the value as {@code String}. - * - * This method replaces an invalid UTF-8 byte sequence with U+FFFD replacement character. - */ - String toString(); -} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/StringValue.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/StringValue.java deleted file mode 100644 index f080ea6..0000000 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/StringValue.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2021 - 2026 the TODAY 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 - * - * https://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 infra.cloud.serialize.format.value; - -/** - * Representation of MessagePack's String type. - * - * MessagePack's String type can represent a UTF-8 string at most 264-1 bytes. - * - * Note that the value could include invalid byte sequences. {@code asString()} method throws {@code MessageTypeStringCodingException} if the value includes invalid byte sequence. {@code toJson()} method replaces an invalid byte sequence with U+FFFD replacement character. - * - * @see RawValue - */ -public interface StringValue - extends RawValue { -} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/TimestampValue.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/TimestampValue.java deleted file mode 100644 index b38c4c0..0000000 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/TimestampValue.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2021 - 2026 the TODAY 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 - * - * https://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 infra.cloud.serialize.format.value; - -import java.time.Instant; - -/** - * Value representation of MessagePack's Timestamp type. - */ -public interface TimestampValue - extends ExtensionValue { - long getEpochSecond(); - - int getNano(); - - long toEpochMillis(); - - Instant toInstant(); -} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/Value.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/Value.java deleted file mode 100644 index bbb5982..0000000 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/Value.java +++ /dev/null @@ -1,331 +0,0 @@ -/* - * Copyright 2021 - 2026 the TODAY 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 - * - * https://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 infra.cloud.serialize.format.value; - -import java.io.IOException; - -import infra.cloud.serialize.format.MessagePacker; -import infra.cloud.serialize.format.MessageTypeCastException; - -/** - * Value stores a value and its type in MessagePack type system. - * - *

          Type conversion

          - *

          - * You can check type first using isXxx() methods or {@link #getValueType()} method, then convert the value to a - * subtype using asXxx() methods. You can also call asXxx() methods directly and catch - * {@link MessageTypeCastException}. - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
          MessagePack typeCheck methodConvert methodValue type
          Nil{@link #isNilValue()}{@link #asNumberValue()}{@link NilValue}
          Boolean{@link #isBooleanValue()}{@link #asBooleanValue()}{@link BooleanValue}
          Integer or Float{@link #isNumberValue()}{@link #asNumberValue()}{@link NumberValue}
          Integer{@link #isIntegerValue()}{@link #asIntegerValue()}{@link IntegerValue}
          Float{@link #isFloatValue()}{@link #asFloatValue()}{@link FloatValue}
          String or Binary{@link #isRawValue()}{@link #asRawValue()}{@link RawValue}
          String{@link #isStringValue()}{@link #asStringValue()}{@link StringValue}
          Binary{@link #isBinaryValue()}{@link #asBinaryValue()}{@link BinaryValue}
          Array{@link #isArrayValue()}{@link #asArrayValue()}{@link ArrayValue}
          Map{@link #isMapValue()}{@link #asMapValue()}{@link MapValue}
          Extension{@link #isExtensionValue()}{@link #asExtensionValue()}{@link ExtensionValue}
          - * - *

          Immutable interface

          - *

          - * Value interface is the base interface of all Value interfaces. Immutable subtypes are useful so that you can - * declare that a (final) field or elements of a container object are immutable. Method arguments should be a - * regular Value interface generally. - *

          - * You can use {@link #immutableValue()} method to get immutable subtypes. - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
          MessagePack typeSubtype methodImmutable value type
          any types{@link Value}.{@link Value#immutableValue()}{@link ImmutableValue}
          Nil{@link NilValue}.{@link NilValue#immutableValue()}{@link ImmutableNilValue}
          Boolean{@link BooleanValue}.{@link BooleanValue#immutableValue()}{@link ImmutableBooleanValue}
          Integer{@link IntegerValue}.{@link IntegerValue#immutableValue()}{@link ImmutableIntegerValue}
          Float{@link FloatValue}.{@link FloatValue#immutableValue()}{@link ImmutableFloatValue}
          Integer or Float{@link NumberValue}.{@link NumberValue#immutableValue()}{@link ImmutableNumberValue}
          String or Binary{@link RawValue}.{@link RawValue#immutableValue()}{@link ImmutableRawValue}
          String{@link StringValue}.{@link StringValue#immutableValue()}{@link ImmutableStringValue}
          Binary{@link BinaryValue}.{@link BinaryValue#immutableValue()}{@link ImmutableBinaryValue}
          Array{@link ArrayValue}.{@link ArrayValue#immutableValue()}{@link ImmutableArrayValue}
          Map{@link MapValue}.{@link MapValue#immutableValue()}{@link ImmutableMapValue}
          Extension{@link ExtensionValue}.{@link ExtensionValue#immutableValue()}{@link ImmutableExtensionValue}
          - * - *

          Converting to JSON

          - *

          - * {@link #toJson()} method returns JSON representation of a Value. See its documents for details. - *

          - * toString() also returns a string representation of a Value that is similar to JSON. However, unlike toJson() method, - * toString() may return a special format that is not be compatible with JSON when JSON doesn't support the type such - * as ExtensionValue. - */ -public interface Value { - - /** - * Returns type of this value. - *

          - * Note that you can't use instanceof to check type of a value because type of a mutable value is variable. - */ - ValueType getValueType(); - - /** - * Returns immutable copy of this value. - *

          - * This method simply returns this without copying the value if this value is already immutable. - */ - ImmutableValue immutableValue(); - - /** - * Returns true if type of this value is Nil. - *

          - * If this method returns true, {@code asNilValue} never throws exceptions. - * Note that you can't use instanceof or cast ((NilValue) thisValue) to check type of a value because type of a mutable value is variable. - */ - boolean isNilValue(); - - /** - * Returns true if type of this value is Boolean. - *

          - * If this method returns true, {@code asBooleanValue} never throws exceptions. - * Note that you can't use instanceof or cast ((BooleanValue) thisValue) to check type of a value because type of a mutable value is variable. - */ - boolean isBooleanValue(); - - /** - * Returns true if type of this value is Integer or Float. - *

          - * If this method returns true, {@code asNumberValue} never throws exceptions. - * Note that you can't use instanceof or cast ((NumberValue) thisValue) to check type of a value because type of a mutable value is variable. - */ - boolean isNumberValue(); - - /** - * Returns true if type of this value is Integer. - *

          - * If this method returns true, {@code asIntegerValue} never throws exceptions. - * Note that you can't use instanceof or cast ((IntegerValue) thisValue) to check type of a value because type of a mutable value is variable. - */ - boolean isIntegerValue(); - - /** - * Returns true if type of this value is Float. - *

          - * If this method returns true, {@code asFloatValue} never throws exceptions. - * Note that you can't use instanceof or cast ((FloatValue) thisValue) to check type of a value because type of a mutable value is variable. - */ - boolean isFloatValue(); - - /** - * Returns true if type of this value is String or Binary. - *

          - * If this method returns true, {@code asRawValue} never throws exceptions. - * Note that you can't use instanceof or cast ((RawValue) thisValue) to check type of a value because type of a mutable value is variable. - */ - boolean isRawValue(); - - /** - * Returns true if type of this value is Binary. - *

          - * If this method returns true, {@code asBinaryValue} never throws exceptions. - * Note that you can't use instanceof or cast ((BinaryValue) thisValue) to check type of a value because type of a mutable value is variable. - */ - boolean isBinaryValue(); - - /** - * Returns true if type of this value is String. - *

          - * If this method returns true, {@code asStringValue} never throws exceptions. - * Note that you can't use instanceof or cast ((StringValue) thisValue) to check type of a value because type of a mutable value is variable. - */ - boolean isStringValue(); - - /** - * Returns true if type of this value is Array. - *

          - * If this method returns true, {@code asArrayValue} never throws exceptions. - * Note that you can't use instanceof or cast ((ArrayValue) thisValue) to check type of a value because type of a mutable value is variable. - */ - boolean isArrayValue(); - - /** - * Returns true if type of this value is Map. - *

          - * If this method returns true, {@code asMapValue} never throws exceptions. - * Note that you can't use instanceof or cast ((MapValue) thisValue) to check type of a value because type of a mutable value is variable. - */ - boolean isMapValue(); - - /** - * Returns true if type of this an Extension. - *

          - * If this method returns true, {@code asExtensionValue} never throws exceptions. - * Note that you can't use instanceof or cast ((ExtensionValue) thisValue) to check type of a value because - * type of a mutable value is variable. - */ - boolean isExtensionValue(); - - /** - * Returns true if the type of this value is Timestamp. - *

          - * If this method returns true, {@code asTimestamp} never throws exceptions. - * Note that you can't use instanceof or cast ((MapValue) thisValue) to check type of a value because type of a mutable value is variable. - */ - boolean isTimestampValue(); - - /** - * Returns the value as {@code NilValue}. Otherwise throws {@code MessageTypeCastException}. - *

          - * Note that you can't use instanceof or cast ((NilValue) thisValue) to check type of a value because type of a mutable value is variable. - * - * @throws MessageTypeCastException If type of this value is not Nil. - */ - NilValue asNilValue(); - - /** - * Returns the value as {@code BooleanValue}. Otherwise throws {@code MessageTypeCastException}. - *

          - * Note that you can't use instanceof or cast ((BooleanValue) thisValue) to check type of a value because type of a mutable value is variable. - * - * @throws MessageTypeCastException If type of this value is not Boolean. - */ - BooleanValue asBooleanValue(); - - /** - * Returns the value as {@code NumberValue}. Otherwise throws {@code MessageTypeCastException}. - *

          - * Note that you can't use instanceof or cast ((NumberValue) thisValue) to check type of a value because type of a mutable value is variable. - * - * @throws MessageTypeCastException If type of this value is not Integer or Float. - */ - NumberValue asNumberValue(); - - /** - * Returns the value as {@code IntegerValue}. Otherwise throws {@code MessageTypeCastException}. - *

          - * Note that you can't use instanceof or cast ((IntegerValue) thisValue) to check type of a value because type of a mutable value is variable. - * - * @throws MessageTypeCastException If type of this value is not Integer. - */ - IntegerValue asIntegerValue(); - - /** - * Returns the value as {@code FloatValue}. Otherwise throws {@code MessageTypeCastException}. - *

          - * Note that you can't use instanceof or cast ((FloatValue) thisValue) to check type of a value because type of a mutable value is variable. - * - * @throws MessageTypeCastException If type of this value is not Float. - */ - FloatValue asFloatValue(); - - /** - * Returns the value as {@code RawValue}. Otherwise throws {@code MessageTypeCastException}. - *

          - * Note that you can't use instanceof or cast ((RawValue) thisValue) to check type of a value because type of a mutable value is variable. - * - * @throws MessageTypeCastException If type of this value is not Binary or String. - */ - RawValue asRawValue(); - - /** - * Returns the value as {@code BinaryValue}. Otherwise throws {@code MessageTypeCastException}. - *

          - * Note that you can't use instanceof or cast ((BinaryValue) thisValue) to check type of a value because type of a mutable value is variable. - * - * @throws MessageTypeCastException If type of this value is not Binary. - */ - BinaryValue asBinaryValue(); - - /** - * Returns the value as {@code StringValue}. Otherwise throws {@code MessageTypeCastException}. - *

          - * Note that you can't use instanceof or cast ((StringValue) thisValue) to check type of a value because type of a mutable value is variable. - * - * @throws MessageTypeCastException If type of this value is not String. - */ - StringValue asStringValue(); - - /** - * Returns the value as {@code ArrayValue}. Otherwise throws {@code MessageTypeCastException}. - *

          - * Note that you can't use instanceof or cast ((ArrayValue) thisValue) to check type of a value because type of a mutable value is variable. - * - * @throws MessageTypeCastException If type of this value is not Array. - */ - ArrayValue asArrayValue(); - - /** - * Returns the value as {@code MapValue}. Otherwise throws {@code MessageTypeCastException}. - *

          - * Note that you can't use instanceof or cast ((MapValue) thisValue) to check type of a value because type of a mutable value is variable. - * - * @throws MessageTypeCastException If type of this value is not Map. - */ - MapValue asMapValue(); - - /** - * Returns the value as {@code ExtensionValue}. Otherwise throws {@code MessageTypeCastException}. - *

          - * Note that you can't use instanceof or cast ((ExtensionValue) thisValue) to check type of a value - * because type of a mutable value is variable. - * - * @throws MessageTypeCastException If type of this value is not an Extension. - */ - ExtensionValue asExtensionValue(); - - /** - * Returns the value as {@code TimestampValue}. Otherwise throws {@code MessageTypeCastException}. - *

          - * Note that you can't use instanceof or cast ((TimestampValue) thisValue) to check type of a value because type of a mutable value is variable. - * - * @throws MessageTypeCastException If type of this value is not Map. - */ - TimestampValue asTimestampValue(); - - /** - * Serializes the value using the specified {@code MessagePacker} - * - * @see MessagePacker - */ - void writeTo(MessagePacker pk) throws IOException; - - /** - * Compares this value to the specified object. - *

          - * This method returns {@code true} if type and value are equivalent. - * If this value is {@code MapValue} or {@code ArrayValue}, this method check equivalence of elements recursively. - */ - boolean equals(Object obj); - - /** - * Returns json representation of this Value. - *

          - * Following behavior is not configurable at this release and they might be changed at future releases: - * - *

            - *
          • if a key of MapValue is not string, the key is converted to a string using toString method.
          • - *
          • NaN and Infinity of DoubleValue are converted to null.
          • - *
          • ExtensionValue is converted to a 2-element array where first element is a number and second element is the data encoded in hex.
          • - *
          • BinaryValue is converted to a string using UTF-8 encoding. Invalid byte sequence is replaced with U+FFFD replacement character.
          • - *
          • Invalid UTF-8 byte sequences in StringValue is replaced with U+FFFD replacement character
          • - *
              - */ - String toJson(); -} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ValueFactory.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ValueFactory.java deleted file mode 100644 index a51fa4f..0000000 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/ValueFactory.java +++ /dev/null @@ -1,274 +0,0 @@ -/* - * Copyright 2021 - 2026 the TODAY 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 - * - * https://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 infra.cloud.serialize.format.value; - -import java.math.BigInteger; -import java.time.Instant; -import java.util.AbstractMap; -import java.util.Arrays; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; - -import infra.cloud.serialize.format.value.impl.ImmutableArrayValueImpl; -import infra.cloud.serialize.format.value.impl.ImmutableBigIntegerValueImpl; -import infra.cloud.serialize.format.value.impl.ImmutableBinaryValueImpl; -import infra.cloud.serialize.format.value.impl.ImmutableBooleanValueImpl; -import infra.cloud.serialize.format.value.impl.ImmutableDoubleValueImpl; -import infra.cloud.serialize.format.value.impl.ImmutableExtensionValueImpl; -import infra.cloud.serialize.format.value.impl.ImmutableLongValueImpl; -import infra.cloud.serialize.format.value.impl.ImmutableMapValueImpl; -import infra.cloud.serialize.format.value.impl.ImmutableNilValueImpl; -import infra.cloud.serialize.format.value.impl.ImmutableStringValueImpl; -import infra.cloud.serialize.format.value.impl.ImmutableTimestampValueImpl; - -public final class ValueFactory { - private ValueFactory() { - } - - public static ImmutableNilValue newNil() { - return ImmutableNilValueImpl.get(); - } - - public static ImmutableBooleanValue newBoolean(boolean v) { - return v ? ImmutableBooleanValueImpl.TRUE : ImmutableBooleanValueImpl.FALSE; - } - - public static ImmutableIntegerValue newInteger(byte v) { - return new ImmutableLongValueImpl(v); - } - - public static ImmutableIntegerValue newInteger(short v) { - return new ImmutableLongValueImpl(v); - } - - public static ImmutableIntegerValue newInteger(int v) { - return new ImmutableLongValueImpl(v); - } - - public static ImmutableIntegerValue newInteger(long v) { - return new ImmutableLongValueImpl(v); - } - - public static ImmutableIntegerValue newInteger(BigInteger v) { - return new ImmutableBigIntegerValueImpl(v); - } - - public static ImmutableFloatValue newFloat(float v) { - return new ImmutableDoubleValueImpl(v); - } - - public static ImmutableFloatValue newFloat(double v) { - return new ImmutableDoubleValueImpl(v); - } - - public static ImmutableBinaryValue newBinary(byte[] b) { - return newBinary(b, false); - } - - public static ImmutableBinaryValue newBinary(byte[] b, boolean omitCopy) { - if (omitCopy) { - return new ImmutableBinaryValueImpl(b); - } - else { - return new ImmutableBinaryValueImpl(Arrays.copyOf(b, b.length)); - } - } - - public static ImmutableBinaryValue newBinary(byte[] b, int off, int len) { - return newBinary(b, off, len, false); - } - - public static ImmutableBinaryValue newBinary(byte[] b, int off, int len, boolean omitCopy) { - if (omitCopy && off == 0 && len == b.length) { - return new ImmutableBinaryValueImpl(b); - } - else { - return new ImmutableBinaryValueImpl(Arrays.copyOfRange(b, off, len)); - } - } - - public static ImmutableStringValue newString(String s) { - return new ImmutableStringValueImpl(s); - } - - public static ImmutableStringValue newString(byte[] b) { - return new ImmutableStringValueImpl(b); - } - - public static ImmutableStringValue newString(byte[] b, boolean omitCopy) { - if (omitCopy) { - return new ImmutableStringValueImpl(b); - } - else { - return new ImmutableStringValueImpl(Arrays.copyOf(b, b.length)); - } - } - - public static ImmutableStringValue newString(byte[] b, int off, int len) { - return newString(b, off, len, false); - } - - public static ImmutableStringValue newString(byte[] b, int off, int len, boolean omitCopy) { - if (omitCopy && off == 0 && len == b.length) { - return new ImmutableStringValueImpl(b); - } - else { - return new ImmutableStringValueImpl(Arrays.copyOfRange(b, off, len)); - } - } - - public static ImmutableArrayValue newArray(List list) { - if (list.isEmpty()) { - return ImmutableArrayValueImpl.empty(); - } - Value[] array = list.toArray(new Value[list.size()]); - return new ImmutableArrayValueImpl(array); - } - - public static ImmutableArrayValue newArray(Value... array) { - if (array.length == 0) { - return ImmutableArrayValueImpl.empty(); - } - else { - return new ImmutableArrayValueImpl(Arrays.copyOf(array, array.length)); - } - } - - public static ImmutableArrayValue newArray(Value[] array, boolean omitCopy) { - if (array.length == 0) { - return ImmutableArrayValueImpl.empty(); - } - else if (omitCopy) { - return new ImmutableArrayValueImpl(array); - } - else { - return new ImmutableArrayValueImpl(Arrays.copyOf(array, array.length)); - } - } - - public static ImmutableArrayValue emptyArray() { - return ImmutableArrayValueImpl.empty(); - } - - public static - ImmutableMapValue newMap(Map map) { - Value[] kvs = new Value[map.size() * 2]; - int index = 0; - for (Map.Entry pair : map.entrySet()) { - kvs[index] = pair.getKey(); - index++; - kvs[index] = pair.getValue(); - index++; - } - return new ImmutableMapValueImpl(kvs); - } - - public static ImmutableMapValue newMap(Value... kvs) { - if (kvs.length == 0) { - return ImmutableMapValueImpl.empty(); - } - else { - return new ImmutableMapValueImpl(Arrays.copyOf(kvs, kvs.length)); - } - } - - public static ImmutableMapValue newMap(Value[] kvs, boolean omitCopy) { - if (kvs.length == 0) { - return ImmutableMapValueImpl.empty(); - } - else if (omitCopy) { - return new ImmutableMapValueImpl(kvs); - } - else { - return new ImmutableMapValueImpl(Arrays.copyOf(kvs, kvs.length)); - } - } - - public static ImmutableMapValue emptyMap() { - return ImmutableMapValueImpl.empty(); - } - - @SafeVarargs - public static MapValue newMap(Map.Entry... pairs) { - Value[] kvs = new Value[pairs.length * 2]; - for (int i = 0; i < pairs.length; ++i) { - kvs[i * 2] = pairs[i].getKey(); - kvs[i * 2 + 1] = pairs[i].getValue(); - } - return newMap(kvs, true); - } - - public static MapBuilder newMapBuilder() { - return new MapBuilder(); - } - - public static Map.Entry newMapEntry(Value key, Value value) { - return new AbstractMap.SimpleEntry<>(key, value); - } - - public static class MapBuilder { - private final Map map = new LinkedHashMap(); - - public MapBuilder() { - } - - public MapValue build() { - return newMap(map); - } - - public MapBuilder put(Map.Entry pair) { - put(pair.getKey(), pair.getValue()); - return this; - } - - public MapBuilder put(Value key, Value value) { - map.put(key, value); - return this; - } - - public MapBuilder putAll(Iterable> entries) { - for (Map.Entry entry : entries) { - put(entry.getKey(), entry.getValue()); - } - return this; - } - - public MapBuilder putAll(Map map) { - for (Map.Entry entry : map.entrySet()) { - put(entry); - } - return this; - } - } - - public static ImmutableExtensionValue newExtension(byte type, byte[] data) { - return new ImmutableExtensionValueImpl(type, data); - } - - public static ImmutableTimestampValue newTimestamp(Instant timestamp) { - return new ImmutableTimestampValueImpl(timestamp); - } - - public static ImmutableTimestampValue newTimestamp(long millis) { - return newTimestamp(Instant.ofEpochMilli(millis)); - } - - public static ImmutableTimestampValue newTimestamp(long epochSecond, int nanoAdjustment) { - return newTimestamp(Instant.ofEpochSecond(epochSecond, nanoAdjustment)); - } -} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/Variable.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/Variable.java deleted file mode 100644 index be02bdc..0000000 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/Variable.java +++ /dev/null @@ -1,1163 +0,0 @@ -/* - * Copyright 2021 - 2026 the TODAY 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 - * - * https://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 infra.cloud.serialize.format.value; - -import java.io.IOException; -import java.math.BigDecimal; -import java.math.BigInteger; -import java.nio.ByteBuffer; -import java.nio.charset.CharacterCodingException; -import java.nio.charset.CharsetDecoder; -import java.nio.charset.CodingErrorAction; -import java.time.Instant; -import java.util.Arrays; -import java.util.Collection; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import infra.cloud.serialize.format.MessageFormat; -import infra.cloud.serialize.format.MessageIntegerOverflowException; -import infra.cloud.serialize.format.MessagePack; -import infra.cloud.serialize.format.MessagePacker; -import infra.cloud.serialize.format.MessageStringCodingException; -import infra.cloud.serialize.format.MessageTypeCastException; -import infra.cloud.serialize.format.value.impl.ImmutableBigIntegerValueImpl; - -public class Variable implements Value { - - private abstract class AbstractValueAccessor implements Value { - - @Override - public boolean isNilValue() { - return getValueType().isNilType(); - } - - @Override - public boolean isBooleanValue() { - return getValueType().isBooleanType(); - } - - @Override - public boolean isNumberValue() { - return getValueType().isNumberType(); - } - - @Override - public boolean isIntegerValue() { - return getValueType().isIntegerType(); - } - - @Override - public boolean isFloatValue() { - return getValueType().isFloatType(); - } - - @Override - public boolean isRawValue() { - return getValueType().isRawType(); - } - - @Override - public boolean isBinaryValue() { - return getValueType().isBinaryType(); - } - - @Override - public boolean isStringValue() { - return getValueType().isStringType(); - } - - @Override - public boolean isArrayValue() { - return getValueType().isArrayType(); - } - - @Override - public boolean isMapValue() { - return getValueType().isMapType(); - } - - @Override - public boolean isExtensionValue() { - return getValueType().isExtensionType(); - } - - @Override - public boolean isTimestampValue() { - return false; - } - - @Override - public NilValue asNilValue() { - throw new MessageTypeCastException(); - } - - @Override - public BooleanValue asBooleanValue() { - throw new MessageTypeCastException(); - } - - @Override - public NumberValue asNumberValue() { - throw new MessageTypeCastException(); - } - - @Override - public IntegerValue asIntegerValue() { - throw new MessageTypeCastException(); - } - - @Override - public FloatValue asFloatValue() { - throw new MessageTypeCastException(); - } - - @Override - public RawValue asRawValue() { - throw new MessageTypeCastException(); - } - - @Override - public BinaryValue asBinaryValue() { - throw new MessageTypeCastException(); - } - - @Override - public StringValue asStringValue() { - throw new MessageTypeCastException(); - } - - @Override - public ArrayValue asArrayValue() { - throw new MessageTypeCastException(); - } - - @Override - public MapValue asMapValue() { - throw new MessageTypeCastException(); - } - - @Override - public ExtensionValue asExtensionValue() { - throw new MessageTypeCastException(); - } - - @Override - public TimestampValue asTimestampValue() { - throw new MessageTypeCastException(); - } - - @Override - public boolean equals(Object obj) { - return Variable.this.equals(obj); - } - - @Override - public int hashCode() { - return Variable.this.hashCode(); - } - - @Override - public String toJson() { - return Variable.this.toJson(); - } - - @Override - public String toString() { - return Variable.this.toString(); - } - } - - public enum Type { - NULL(ValueType.NIL), - BOOLEAN(ValueType.BOOLEAN), - LONG(ValueType.INTEGER), - BIG_INTEGER(ValueType.INTEGER), - DOUBLE(ValueType.FLOAT), - BYTE_ARRAY(ValueType.BINARY), - RAW_STRING(ValueType.STRING), - LIST(ValueType.ARRAY), - MAP(ValueType.MAP), - EXTENSION(ValueType.EXTENSION), - TIMESTAMP(ValueType.EXTENSION); - - private final ValueType valueType; - - Type(ValueType valueType) { - this.valueType = valueType; - } - - public ValueType getValueType() { - return valueType; - } - } - - private final NilValueAccessor nilAccessor = new NilValueAccessor(); - private final BooleanValueAccessor booleanAccessor = new BooleanValueAccessor(); - private final IntegerValueAccessor integerAccessor = new IntegerValueAccessor(); - private final FloatValueAccessor floatAccessor = new FloatValueAccessor(); - private final BinaryValueAccessor binaryAccessor = new BinaryValueAccessor(); - private final StringValueAccessor stringAccessor = new StringValueAccessor(); - private final ArrayValueAccessor arrayAccessor = new ArrayValueAccessor(); - private final MapValueAccessor mapAccessor = new MapValueAccessor(); - private final ExtensionValueAccessor extensionAccessor = new ExtensionValueAccessor(); - private final TimestampValueAccessor timestampAccessor = new TimestampValueAccessor(); - - private Type type; - - private long longValue; - private double doubleValue; - private Object objectValue; - - private AbstractValueAccessor accessor; - - public Variable() { - setNilValue(); - } - - /// / - // NilValue - // - public Variable setNilValue() { - this.type = Type.NULL; - this.accessor = nilAccessor; - return this; - } - - private class NilValueAccessor - extends AbstractValueAccessor - implements NilValue { - @Override - public ValueType getValueType() { - return ValueType.NIL; - } - - @Override - public NilValue asNilValue() { - return this; - } - - @Override - public ImmutableNilValue immutableValue() { - return ValueFactory.newNil(); - } - - @Override - public void writeTo(MessagePacker pk) - throws IOException { - pk.packNil(); - } - } - - /// / - // BooleanValue - // - public Variable setBooleanValue(boolean v) { - this.type = Type.BOOLEAN; - this.accessor = booleanAccessor; - this.longValue = (v ? 1L : 0L); - return this; - } - - private class BooleanValueAccessor - extends AbstractValueAccessor - implements BooleanValue { - @Override - public ValueType getValueType() { - return ValueType.BOOLEAN; - } - - @Override - public BooleanValue asBooleanValue() { - return this; - } - - @Override - public ImmutableBooleanValue immutableValue() { - return ValueFactory.newBoolean(getBoolean()); - } - - @Override - public boolean getBoolean() { - return longValue == 1L; - } - - @Override - public void writeTo(MessagePacker pk) - throws IOException { - pk.packBoolean(longValue == 1L); - } - } - - /// / - // NumberValue - // IntegerValue - // FloatValue - // - - private static final BigInteger LONG_MIN = BigInteger.valueOf(Long.MIN_VALUE); - private static final BigInteger LONG_MAX = BigInteger.valueOf(Long.MAX_VALUE); - private static final long BYTE_MIN = Byte.MIN_VALUE; - private static final long BYTE_MAX = Byte.MAX_VALUE; - private static final long SHORT_MIN = Short.MIN_VALUE; - private static final long SHORT_MAX = Short.MAX_VALUE; - private static final long INT_MIN = Integer.MIN_VALUE; - private static final long INT_MAX = Integer.MAX_VALUE; - - private abstract class AbstractNumberValueAccessor - extends AbstractValueAccessor - implements NumberValue { - @Override - public NumberValue asNumberValue() { - return this; - } - - @Override - public byte toByte() { - if (type == Type.BIG_INTEGER) { - return ((BigInteger) objectValue).byteValue(); - } - return (byte) longValue; - } - - @Override - public short toShort() { - if (type == Type.BIG_INTEGER) { - return ((BigInteger) objectValue).shortValue(); - } - return (short) longValue; - } - - @Override - public int toInt() { - if (type == Type.BIG_INTEGER) { - return ((BigInteger) objectValue).intValue(); - } - return (int) longValue; - } - - @Override - public long toLong() { - if (type == Type.BIG_INTEGER) { - return ((BigInteger) objectValue).longValue(); - } - return longValue; - } - - @Override - public BigInteger toBigInteger() { - if (type == Type.BIG_INTEGER) { - return (BigInteger) objectValue; - } - else if (type == Type.DOUBLE) { - return new BigDecimal(doubleValue).toBigInteger(); - } - return BigInteger.valueOf(longValue); - } - - @Override - public float toFloat() { - if (type == Type.BIG_INTEGER) { - return ((BigInteger) objectValue).floatValue(); - } - else if (type == Type.DOUBLE) { - return (float) doubleValue; - } - return (float) longValue; - } - - @Override - public double toDouble() { - if (type == Type.BIG_INTEGER) { - return ((BigInteger) objectValue).doubleValue(); - } - else if (type == Type.DOUBLE) { - return doubleValue; - } - return (double) longValue; - } - } - - /// / - // IntegerValue - // - public Variable setIntegerValue(long v) { - this.type = Type.LONG; - this.accessor = integerAccessor; - this.longValue = v; - return this; - } - - public Variable setIntegerValue(BigInteger v) { - if (0 <= v.compareTo(LONG_MIN) && v.compareTo(LONG_MAX) <= 0) { - this.type = Type.LONG; - this.accessor = integerAccessor; - this.longValue = v.longValue(); - } - else { - this.type = Type.BIG_INTEGER; - this.accessor = integerAccessor; - this.objectValue = v; - } - return this; - } - - private class IntegerValueAccessor - extends AbstractNumberValueAccessor - implements IntegerValue { - @Override - public ValueType getValueType() { - return ValueType.INTEGER; - } - - @Override - public IntegerValue asIntegerValue() { - return this; - } - - @Override - public ImmutableIntegerValue immutableValue() { - if (type == Type.BIG_INTEGER) { - return ValueFactory.newInteger((BigInteger) objectValue); - } - return ValueFactory.newInteger(longValue); - } - - @Override - public boolean isInByteRange() { - if (type == Type.BIG_INTEGER) { - return false; - } - return BYTE_MIN <= longValue && longValue <= BYTE_MAX; - } - - @Override - public boolean isInShortRange() { - if (type == Type.BIG_INTEGER) { - return false; - } - return SHORT_MIN <= longValue && longValue <= SHORT_MAX; - } - - @Override - public boolean isInIntRange() { - if (type == Type.BIG_INTEGER) { - return false; - } - return INT_MIN <= longValue && longValue <= INT_MAX; - } - - @Override - public boolean isInLongRange() { - return type != Type.BIG_INTEGER; - } - - @Override - public MessageFormat mostSuccinctMessageFormat() { - return ImmutableBigIntegerValueImpl.mostSuccinctMessageFormat(this); - } - - @Override - public byte asByte() { - if (!isInByteRange()) { - throw new MessageIntegerOverflowException(longValue); - } - return (byte) longValue; - } - - @Override - public short asShort() { - if (!isInByteRange()) { - throw new MessageIntegerOverflowException(longValue); - } - return (short) longValue; - } - - @Override - public int asInt() { - if (!isInIntRange()) { - throw new MessageIntegerOverflowException(longValue); - } - return (int) longValue; - } - - @Override - public long asLong() { - if (!isInLongRange()) { - throw new MessageIntegerOverflowException(longValue); - } - return longValue; - } - - @Override - public BigInteger asBigInteger() { - if (type == Type.BIG_INTEGER) { - return (BigInteger) objectValue; - } - else { - return BigInteger.valueOf(longValue); - } - } - - @Override - public void writeTo(MessagePacker pk) - throws IOException { - if (type == Type.BIG_INTEGER) { - pk.packBigInteger((BigInteger) objectValue); - } - else { - pk.packLong(longValue); - } - } - } - - /// / - // FloatValue - // - public Variable setFloatValue(double v) { - this.type = Type.DOUBLE; - this.accessor = floatAccessor; - this.doubleValue = v; - this.longValue = (long) v; // AbstractNumberValueAccessor uses toLong - return this; - } - - public Variable setFloatValue(float v) { - this.type = Type.DOUBLE; - this.accessor = floatAccessor; - this.longValue = (long) v; // AbstractNumberValueAccessor uses toLong - return this; - } - - private class FloatValueAccessor extends AbstractNumberValueAccessor implements FloatValue { - - @Override - public FloatValue asFloatValue() { - return this; - } - - @Override - public ImmutableFloatValue immutableValue() { - return ValueFactory.newFloat(doubleValue); - } - - @Override - public ValueType getValueType() { - return ValueType.FLOAT; - } - - @Override - public void writeTo(MessagePacker pk) throws IOException { - pk.packDouble(doubleValue); - } - } - - /// / - // RawValue - // BinaryValue - // StringValue - // - - private abstract class AbstractRawValueAccessor - extends AbstractValueAccessor - implements RawValue { - @Override - public RawValue asRawValue() { - return this; - } - - @Override - public byte[] asByteArray() { - return (byte[]) objectValue; - } - - @Override - public ByteBuffer asByteBuffer() { - return ByteBuffer.wrap(asByteArray()); - } - - @Override - public String asString() { - byte[] raw = (byte[]) objectValue; - try { - CharsetDecoder reportDecoder = MessagePack.UTF8.newDecoder() - .onMalformedInput(CodingErrorAction.REPORT) - .onUnmappableCharacter(CodingErrorAction.REPORT); - return reportDecoder.decode(ByteBuffer.wrap(raw)).toString(); - } - catch (CharacterCodingException ex) { - throw new MessageStringCodingException(ex); - } - } - - // override for performance optimization - @Override - public String toString() { - byte[] raw = (byte[]) objectValue; - try { - CharsetDecoder reportDecoder = MessagePack.UTF8.newDecoder() - .onMalformedInput(CodingErrorAction.REPLACE) - .onUnmappableCharacter(CodingErrorAction.REPLACE); - return reportDecoder.decode(ByteBuffer.wrap(raw)).toString(); - } - catch (CharacterCodingException ex) { - throw new MessageStringCodingException(ex); - } - } - } - - /// / - // BinaryValue - // - public Variable setBinaryValue(byte[] v) { - this.type = Type.BYTE_ARRAY; - this.accessor = binaryAccessor; - this.objectValue = v; - return this; - } - - private class BinaryValueAccessor - extends AbstractRawValueAccessor - implements BinaryValue { - @Override - public ValueType getValueType() { - return ValueType.BINARY; - } - - @Override - public BinaryValue asBinaryValue() { - return this; - } - - @Override - public ImmutableBinaryValue immutableValue() { - return ValueFactory.newBinary(asByteArray()); - } - - @Override - public void writeTo(MessagePacker pk) - throws IOException { - byte[] data = (byte[]) objectValue; - pk.packBinaryHeader(data.length); - pk.writePayload(data); - } - } - - // StringValue - // - - public Variable setStringValue(String v) { - return setStringValue(v.getBytes(MessagePack.UTF8)); - } - - public Variable setStringValue(byte[] v) { - this.type = Type.RAW_STRING; - this.accessor = stringAccessor; - this.objectValue = v; - return this; - } - - private class StringValueAccessor extends AbstractRawValueAccessor implements StringValue { - - @Override - public ValueType getValueType() { - return ValueType.STRING; - } - - @Override - public StringValue asStringValue() { - return this; - } - - @Override - public ImmutableStringValue immutableValue() { - return ValueFactory.newString((byte[]) objectValue); - } - - @Override - public void writeTo(MessagePacker pk) - throws IOException { - byte[] data = (byte[]) objectValue; - pk.packRawStringHeader(data.length); - pk.writePayload(data); - } - } - - /// / - // ArrayValue - // - public Variable setArrayValue(List v) { - this.type = Type.LIST; - this.accessor = arrayAccessor; - this.objectValue = v.toArray(new Value[v.size()]); - return this; - } - - public Variable setArrayValue(Value[] v) { - this.type = Type.LIST; - this.accessor = arrayAccessor; - this.objectValue = v; - return this; - } - - private class ArrayValueAccessor - extends AbstractValueAccessor - implements ArrayValue { - @Override - public ValueType getValueType() { - return ValueType.ARRAY; - } - - @Override - public ArrayValue asArrayValue() { - return this; - } - - @Override - public ImmutableArrayValue immutableValue() { - return ValueFactory.newArray(array()); - } - - @Override - public int size() { - return array().length; - } - - @Override - public Value get(int index) { - return array()[index]; - } - - @Override - public Value getOrNilValue(int index) { - Value[] a = array(); - if (a.length < index && index >= 0) { - return ValueFactory.newNil(); - } - return a[index]; - } - - @Override - public Iterator iterator() { - return list().iterator(); - } - - @Override - public List list() { - return Arrays.asList(array()); - } - - public Value[] array() { - return (Value[]) objectValue; - } - - @Override - public void writeTo(MessagePacker pk) - throws IOException { - immutableValue().writeTo(pk); - } - } - - /// / - // MapValue - // - public Variable setMapValue(Map v) { - this.type = Type.MAP; - this.accessor = mapAccessor; - Value[] kvs = new Value[v.size() * 2]; - Iterator> ite = v.entrySet().iterator(); - int i = 0; - while (ite.hasNext()) { - Map.Entry pair = ite.next(); - kvs[i] = pair.getKey(); - i++; - kvs[i] = pair.getValue(); - i++; - } - this.objectValue = kvs; - return this; - } - - public Variable setMapValue(Value[] kvs) { - this.type = Type.MAP; - this.accessor = mapAccessor; - this.objectValue = kvs; - return this; - } - - private class MapValueAccessor extends AbstractValueAccessor implements MapValue { - - @Override - public ValueType getValueType() { - return ValueType.MAP; - } - - @Override - public MapValue asMapValue() { - return this; - } - - @Override - public ImmutableMapValue immutableValue() { - return ValueFactory.newMap(getKeyValueArray()); - } - - @Override - public int size() { - return getKeyValueArray().length / 2; - } - - @Override - public Set keySet() { - return immutableValue().keySet(); - } - - @Override - public Set> entrySet() { - return immutableValue().entrySet(); - } - - @Override - public Collection values() { - return immutableValue().values(); - } - - @Override - public Value[] getKeyValueArray() { - return (Value[]) objectValue; - } - - public Map map() { - return immutableValue().map(); - } - - @Override - public void writeTo(MessagePacker pk) - throws IOException { - immutableValue().writeTo(pk); - } - } - - /// / - // ExtensionValue - // - public Variable setExtensionValue(byte type, byte[] data) { - this.type = Type.EXTENSION; - this.accessor = extensionAccessor; - this.objectValue = ValueFactory.newExtension(type, data); - return this; - } - - private class ExtensionValueAccessor - extends AbstractValueAccessor - implements ExtensionValue { - @Override - public ValueType getValueType() { - return ValueType.EXTENSION; - } - - @Override - public ExtensionValue asExtensionValue() { - return this; - } - - @Override - public ImmutableExtensionValue immutableValue() { - return (ImmutableExtensionValue) objectValue; - } - - @Override - public byte getType() { - return ((ImmutableExtensionValue) objectValue).getType(); - } - - @Override - public byte[] getData() { - return ((ImmutableExtensionValue) objectValue).getData(); - } - - @Override - public void writeTo(MessagePacker pk) - throws IOException { - ((ImmutableExtensionValue) objectValue).writeTo(pk); - } - } - - public Variable setTimestampValue(Instant timestamp) { - this.type = Type.TIMESTAMP; - this.accessor = timestampAccessor; - this.objectValue = ValueFactory.newTimestamp(timestamp); - return this; - } - - private class TimestampValueAccessor - extends AbstractValueAccessor - implements TimestampValue { - @Override - public boolean isTimestampValue() { - return true; - } - - @Override - public ValueType getValueType() { - return ValueType.EXTENSION; - } - - @Override - public TimestampValue asTimestampValue() { - return this; - } - - @Override - public ImmutableTimestampValue immutableValue() { - return (ImmutableTimestampValue) objectValue; - } - - @Override - public byte getType() { - return ((ImmutableTimestampValue) objectValue).getType(); - } - - @Override - public byte[] getData() { - return ((ImmutableTimestampValue) objectValue).getData(); - } - - @Override - public void writeTo(MessagePacker pk) - throws IOException { - ((ImmutableTimestampValue) objectValue).writeTo(pk); - } - - @Override - public long getEpochSecond() { - return ((ImmutableTimestampValue) objectValue).getEpochSecond(); - } - - @Override - public int getNano() { - return ((ImmutableTimestampValue) objectValue).getNano(); - } - - @Override - public long toEpochMillis() { - return ((ImmutableTimestampValue) objectValue).toEpochMillis(); - } - - @Override - public Instant toInstant() { - return ((ImmutableTimestampValue) objectValue).toInstant(); - } - } - - /// / - // Value - // - @Override - public ImmutableValue immutableValue() { - return accessor.immutableValue(); - } - - @Override - public void writeTo(MessagePacker pk) - throws IOException { - accessor.writeTo(pk); - } - - @Override - public int hashCode() { - return immutableValue().hashCode(); // TODO optimize - } - - @Override - public boolean equals(Object o) { - return immutableValue().equals(o); // TODO optimize - } - - @Override - public String toJson() { - return immutableValue().toJson(); // TODO optimize - } - - @Override - public String toString() { - return immutableValue().toString(); // TODO optimize - } - - @Override - public ValueType getValueType() { - return type.getValueType(); - } - - @Override - public boolean isNilValue() { - return getValueType().isNilType(); - } - - @Override - public boolean isBooleanValue() { - return getValueType().isBooleanType(); - } - - @Override - public boolean isNumberValue() { - return getValueType().isNumberType(); - } - - @Override - public boolean isIntegerValue() { - return getValueType().isIntegerType(); - } - - @Override - public boolean isFloatValue() { - return getValueType().isFloatType(); - } - - @Override - public boolean isRawValue() { - return getValueType().isRawType(); - } - - @Override - public boolean isBinaryValue() { - return getValueType().isBinaryType(); - } - - @Override - public boolean isStringValue() { - return getValueType().isStringType(); - } - - @Override - public boolean isArrayValue() { - return getValueType().isArrayType(); - } - - @Override - public boolean isMapValue() { - return getValueType().isMapType(); - } - - @Override - public boolean isExtensionValue() { - return getValueType().isExtensionType(); - } - - @Override - public boolean isTimestampValue() { - return this.type == Type.TIMESTAMP; - } - - @Override - public NilValue asNilValue() { - if (!isNilValue()) { - throw new MessageTypeCastException(); - } - return (NilValue) accessor; - } - - @Override - public BooleanValue asBooleanValue() { - if (!isBooleanValue()) { - throw new MessageTypeCastException(); - } - return (BooleanValue) accessor; - } - - @Override - public NumberValue asNumberValue() { - if (!isNumberValue()) { - throw new MessageTypeCastException(); - } - return (NumberValue) accessor; - } - - @Override - public IntegerValue asIntegerValue() { - if (!isIntegerValue()) { - throw new MessageTypeCastException(); - } - return (IntegerValue) accessor; - } - - @Override - public FloatValue asFloatValue() { - if (!isFloatValue()) { - throw new MessageTypeCastException(); - } - return (FloatValue) accessor; - } - - @Override - public RawValue asRawValue() { - if (!isRawValue()) { - throw new MessageTypeCastException(); - } - return (RawValue) accessor; - } - - @Override - public BinaryValue asBinaryValue() { - if (!isBinaryValue()) { - throw new MessageTypeCastException(); - } - return (BinaryValue) accessor; - } - - @Override - public StringValue asStringValue() { - if (!isStringValue()) { - throw new MessageTypeCastException(); - } - return (StringValue) accessor; - } - - @Override - public ArrayValue asArrayValue() { - if (!isArrayValue()) { - throw new MessageTypeCastException(); - } - return (ArrayValue) accessor; - } - - @Override - public MapValue asMapValue() { - if (!isMapValue()) { - throw new MessageTypeCastException(); - } - return (MapValue) accessor; - } - - @Override - public ExtensionValue asExtensionValue() { - if (!isExtensionValue()) { - throw new MessageTypeCastException(); - } - return (ExtensionValue) accessor; - } - - @Override - public TimestampValue asTimestampValue() { - if (!isTimestampValue()) { - throw new MessageTypeCastException(); - } - return (TimestampValue) accessor; - } -} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/AbstractImmutableRawValue.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/AbstractImmutableRawValue.java deleted file mode 100644 index 941341d..0000000 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/AbstractImmutableRawValue.java +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Copyright 2021 - 2026 the TODAY 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 - * - * https://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 infra.cloud.serialize.format.value.impl; - -import java.nio.ByteBuffer; -import java.nio.charset.CharacterCodingException; -import java.nio.charset.CharsetDecoder; -import java.nio.charset.CodingErrorAction; -import java.util.Arrays; - -import infra.cloud.serialize.format.MessagePack; -import infra.cloud.serialize.format.MessageStringCodingException; -import infra.cloud.serialize.format.value.ImmutableRawValue; - -public abstract class AbstractImmutableRawValue - extends AbstractImmutableValue - implements ImmutableRawValue { - protected final byte[] data; - private volatile String decodedStringCache; - private volatile CharacterCodingException codingException; - - public AbstractImmutableRawValue(byte[] data) { - this.data = data; - } - - public AbstractImmutableRawValue(String string) { - this.decodedStringCache = string; - this.data = string.getBytes(MessagePack.UTF8); // TODO - } - - @Override - public ImmutableRawValue asRawValue() { - return this; - } - - @Override - public byte[] asByteArray() { - return Arrays.copyOf(data, data.length); - } - - @Override - public ByteBuffer asByteBuffer() { - return ByteBuffer.wrap(data).asReadOnlyBuffer(); - } - - @Override - public String asString() { - if (decodedStringCache == null) { - decodeString(); - } - if (codingException != null) { - throw new MessageStringCodingException(codingException); - } - else { - return decodedStringCache; - } - } - - @Override - public String toJson() { - StringBuilder sb = new StringBuilder(); - appendJsonString(sb, toString()); - return sb.toString(); - } - - private void decodeString() { - synchronized(data) { - if (decodedStringCache != null) { - return; - } - try { - CharsetDecoder reportDecoder = MessagePack.UTF8.newDecoder() - .onMalformedInput(CodingErrorAction.REPORT) - .onUnmappableCharacter(CodingErrorAction.REPORT); - this.decodedStringCache = reportDecoder.decode(asByteBuffer()).toString(); - } - catch (CharacterCodingException ex) { - try { - CharsetDecoder replaceDecoder = MessagePack.UTF8.newDecoder() - .onMalformedInput(CodingErrorAction.REPLACE) - .onUnmappableCharacter(CodingErrorAction.REPLACE); - this.decodedStringCache = replaceDecoder.decode(asByteBuffer()).toString(); - } - catch (CharacterCodingException neverThrown) { - throw new MessageStringCodingException(neverThrown); - } - this.codingException = ex; - } - } - } - - @Override - public String toString() { - if (decodedStringCache == null) { - decodeString(); - } - return decodedStringCache; - } - - static void appendJsonString(StringBuilder sb, String string) { - sb.append("\""); - for (int i = 0; i < string.length(); i++) { - char ch = string.charAt(i); - if (ch < 0x20) { - switch (ch) { - case '\n': - sb.append("\\n"); - break; - case '\r': - sb.append("\\r"); - break; - case '\t': - sb.append("\\t"); - break; - case '\f': - sb.append("\\f"); - break; - case '\b': - sb.append("\\b"); - break; - default: - // control chars - escapeChar(sb, ch); - break; - } - } - else if (ch <= 0x7f) { - switch (ch) { - case '\\': - sb.append("\\\\"); - break; - case '"': - sb.append("\\\""); - break; - default: - sb.append(ch); - break; - } - } - else if (ch >= 0xd800 && ch <= 0xdfff) { - // surrogates - escapeChar(sb, ch); - } - else { - sb.append(ch); - } - } - sb.append("\""); - } - - private static final char[] HEX_TABLE = "0123456789ABCDEF".toCharArray(); - - private static void escapeChar(StringBuilder sb, int ch) { - sb.append("\\u"); - sb.append(HEX_TABLE[(ch >> 12) & 0x0f]); - sb.append(HEX_TABLE[(ch >> 8) & 0x0f]); - sb.append(HEX_TABLE[(ch >> 4) & 0x0f]); - sb.append(HEX_TABLE[ch & 0x0f]); - } -} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/AbstractImmutableValue.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/AbstractImmutableValue.java deleted file mode 100644 index 50c1643..0000000 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/AbstractImmutableValue.java +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Copyright 2021 - 2026 the TODAY 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 - * - * https://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 infra.cloud.serialize.format.value.impl; - -import infra.cloud.serialize.format.MessageTypeCastException; -import infra.cloud.serialize.format.value.ImmutableArrayValue; -import infra.cloud.serialize.format.value.ImmutableBinaryValue; -import infra.cloud.serialize.format.value.ImmutableBooleanValue; -import infra.cloud.serialize.format.value.ImmutableExtensionValue; -import infra.cloud.serialize.format.value.ImmutableFloatValue; -import infra.cloud.serialize.format.value.ImmutableIntegerValue; -import infra.cloud.serialize.format.value.ImmutableMapValue; -import infra.cloud.serialize.format.value.ImmutableNilValue; -import infra.cloud.serialize.format.value.ImmutableNumberValue; -import infra.cloud.serialize.format.value.ImmutableRawValue; -import infra.cloud.serialize.format.value.ImmutableStringValue; -import infra.cloud.serialize.format.value.ImmutableTimestampValue; -import infra.cloud.serialize.format.value.ImmutableValue; - -abstract class AbstractImmutableValue implements ImmutableValue { - - @Override - public boolean isNilValue() { - return getValueType().isNilType(); - } - - @Override - public boolean isBooleanValue() { - return getValueType().isBooleanType(); - } - - @Override - public boolean isNumberValue() { - return getValueType().isNumberType(); - } - - @Override - public boolean isIntegerValue() { - return getValueType().isIntegerType(); - } - - @Override - public boolean isFloatValue() { - return getValueType().isFloatType(); - } - - @Override - public boolean isRawValue() { - return getValueType().isRawType(); - } - - @Override - public boolean isBinaryValue() { - return getValueType().isBinaryType(); - } - - @Override - public boolean isStringValue() { - return getValueType().isStringType(); - } - - @Override - public boolean isArrayValue() { - return getValueType().isArrayType(); - } - - @Override - public boolean isMapValue() { - return getValueType().isMapType(); - } - - @Override - public boolean isExtensionValue() { - return getValueType().isExtensionType(); - } - - @Override - public boolean isTimestampValue() { - return false; - } - - @Override - public ImmutableNilValue asNilValue() { - throw new MessageTypeCastException(); - } - - @Override - public ImmutableBooleanValue asBooleanValue() { - throw new MessageTypeCastException(); - } - - @Override - public ImmutableNumberValue asNumberValue() { - throw new MessageTypeCastException(); - } - - @Override - public ImmutableIntegerValue asIntegerValue() { - throw new MessageTypeCastException(); - } - - @Override - public ImmutableFloatValue asFloatValue() { - throw new MessageTypeCastException(); - } - - @Override - public ImmutableRawValue asRawValue() { - throw new MessageTypeCastException(); - } - - @Override - public ImmutableBinaryValue asBinaryValue() { - throw new MessageTypeCastException(); - } - - @Override - public ImmutableStringValue asStringValue() { - throw new MessageTypeCastException(); - } - - @Override - public ImmutableArrayValue asArrayValue() { - throw new MessageTypeCastException(); - } - - @Override - public ImmutableMapValue asMapValue() { - throw new MessageTypeCastException(); - } - - @Override - public ImmutableExtensionValue asExtensionValue() { - throw new MessageTypeCastException(); - } - - @Override - public ImmutableTimestampValue asTimestampValue() { - throw new MessageTypeCastException(); - } -} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableArrayValueImpl.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableArrayValueImpl.java deleted file mode 100644 index 93cc5e2..0000000 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableArrayValueImpl.java +++ /dev/null @@ -1,239 +0,0 @@ -/* - * Copyright 2021 - 2026 the TODAY 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 - * - * https://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 infra.cloud.serialize.format.value.impl; - -import java.io.IOException; -import java.util.AbstractList; -import java.util.Arrays; -import java.util.Iterator; -import java.util.List; -import java.util.NoSuchElementException; - -import infra.cloud.serialize.format.MessagePacker; -import infra.cloud.serialize.format.value.ArrayValue; -import infra.cloud.serialize.format.value.ImmutableArrayValue; -import infra.cloud.serialize.format.value.IntegerValue; -import infra.cloud.serialize.format.value.Value; -import infra.cloud.serialize.format.value.ValueType; - -/** - * {@code ImmutableArrayValueImpl} Implements {@code ImmutableArrayValue} using a {@code Value[]} field. - * - * @see IntegerValue - */ -public class ImmutableArrayValueImpl - extends AbstractImmutableValue - implements ImmutableArrayValue { - private static final ImmutableArrayValueImpl EMPTY = new ImmutableArrayValueImpl(new Value[0]); - - public static ImmutableArrayValue empty() { - return EMPTY; - } - - private final Value[] array; - - public ImmutableArrayValueImpl(Value[] array) { - this.array = array; - } - - @Override - public ValueType getValueType() { - return ValueType.ARRAY; - } - - @Override - public ImmutableArrayValue immutableValue() { - return this; - } - - @Override - public ImmutableArrayValue asArrayValue() { - return this; - } - - @Override - public int size() { - return array.length; - } - - @Override - public Value get(int index) { - return array[index]; - } - - @Override - public Value getOrNilValue(int index) { - if (index < array.length && index >= 0) { - return array[index]; - } - return ImmutableNilValueImpl.get(); - } - - @Override - public Iterator iterator() { - return new Ite(array); - } - - @Override - public List list() { - return new ImmutableArrayValueList(array); - } - - @Override - public void writeTo(MessagePacker pk) - throws IOException { - pk.packArrayHeader(array.length); - for (int i = 0; i < array.length; i++) { - array[i].writeTo(pk); - } - } - - @Override - public boolean equals(Object o) { - if (o == this) { - return true; - } - if (!(o instanceof Value)) { - return false; - } - Value v = (Value) o; - - if (v instanceof ImmutableArrayValueImpl) { - ImmutableArrayValueImpl oa = (ImmutableArrayValueImpl) v; - return Arrays.equals(array, oa.array); - } - else { - if (!v.isArrayValue()) { - return false; - } - ArrayValue av = v.asArrayValue(); - if (size() != av.size()) { - return false; - } - Iterator oi = av.iterator(); - int i = 0; - while (i < array.length) { - if (!oi.hasNext() || !array[i].equals(oi.next())) { - return false; - } - i++; - } - return true; - } - } - - @Override - public int hashCode() { - int h = 1; - for (int i = 0; i < array.length; i++) { - Value obj = array[i]; - h = 31 * h + obj.hashCode(); - } - return h; - } - - @Override - public String toJson() { - if (array.length == 0) { - return "[]"; - } - StringBuilder sb = new StringBuilder(); - sb.append("["); - sb.append(array[0].toJson()); - for (int i = 1; i < array.length; i++) { - sb.append(","); - sb.append(array[i].toJson()); - } - sb.append("]"); - return sb.toString(); - } - - @Override - public String toString() { - if (array.length == 0) { - return "[]"; - } - StringBuilder sb = new StringBuilder(); - sb.append("["); - appendString(sb, array[0]); - for (int i = 1; i < array.length; i++) { - sb.append(","); - appendString(sb, array[i]); - } - sb.append("]"); - return sb.toString(); - } - - private static void appendString(StringBuilder sb, Value value) { - if (value.isRawValue()) { - sb.append(value.toJson()); - } - else { - sb.append(value.toString()); - } - } - - private static class ImmutableArrayValueList - extends AbstractList { - private final Value[] array; - - public ImmutableArrayValueList(Value[] array) { - this.array = array; - } - - @Override - public Value get(int index) { - return array[index]; - } - - @Override - public int size() { - return array.length; - } - } - - private static class Ite - implements Iterator { - private final Value[] array; - private int index; - - public Ite(Value[] array) { - this.array = array; - this.index = 0; - } - - @Override - public boolean hasNext() { - return index != array.length; - } - - @Override - public Value next() { - int i = index; - if (i >= array.length) { - throw new NoSuchElementException(); - } - index = i + 1; - return array[i]; - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - } -} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableBigIntegerValueImpl.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableBigIntegerValueImpl.java deleted file mode 100644 index aef31f8..0000000 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableBigIntegerValueImpl.java +++ /dev/null @@ -1,232 +0,0 @@ -/* - * Copyright 2021 - 2026 the TODAY 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 - * - * https://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 infra.cloud.serialize.format.value.impl; - -import java.io.IOException; -import java.math.BigInteger; - -import infra.cloud.serialize.format.MessageFormat; -import infra.cloud.serialize.format.MessageIntegerOverflowException; -import infra.cloud.serialize.format.MessagePacker; -import infra.cloud.serialize.format.value.ImmutableIntegerValue; -import infra.cloud.serialize.format.value.ImmutableNumberValue; -import infra.cloud.serialize.format.value.IntegerValue; -import infra.cloud.serialize.format.value.Value; -import infra.cloud.serialize.format.value.ValueType; - -/** - * {@code ImmutableBigIntegerValueImpl} Implements {@code ImmutableBigIntegerValue} using a {@code BigInteger} field. - * - * @see IntegerValue - */ -public class ImmutableBigIntegerValueImpl extends AbstractImmutableValue implements ImmutableIntegerValue { - - public static MessageFormat mostSuccinctMessageFormat(IntegerValue v) { - if (v.isInByteRange()) { - return MessageFormat.INT8; - } - else if (v.isInShortRange()) { - return MessageFormat.INT16; - } - else if (v.isInIntRange()) { - return MessageFormat.INT32; - } - else if (v.isInLongRange()) { - return MessageFormat.INT64; - } - else { - return MessageFormat.UINT64; - } - } - - private final BigInteger value; - - public ImmutableBigIntegerValueImpl(BigInteger value) { - this.value = value; - } - - private static final BigInteger BYTE_MIN = BigInteger.valueOf(Byte.MIN_VALUE); - private static final BigInteger BYTE_MAX = BigInteger.valueOf(Byte.MAX_VALUE); - private static final BigInteger SHORT_MIN = BigInteger.valueOf(Short.MIN_VALUE); - private static final BigInteger SHORT_MAX = BigInteger.valueOf(Short.MAX_VALUE); - private static final BigInteger INT_MIN = BigInteger.valueOf(Integer.MIN_VALUE); - private static final BigInteger INT_MAX = BigInteger.valueOf(Integer.MAX_VALUE); - private static final BigInteger LONG_MIN = BigInteger.valueOf(Long.MIN_VALUE); - private static final BigInteger LONG_MAX = BigInteger.valueOf(Long.MAX_VALUE); - - @Override - public ValueType getValueType() { - return ValueType.INTEGER; - } - - @Override - public ImmutableIntegerValue immutableValue() { - return this; - } - - @Override - public ImmutableNumberValue asNumberValue() { - return this; - } - - @Override - public ImmutableIntegerValue asIntegerValue() { - return this; - } - - @Override - public byte toByte() { - return value.byteValue(); - } - - @Override - public short toShort() { - return value.shortValue(); - } - - @Override - public int toInt() { - return value.intValue(); - } - - @Override - public long toLong() { - return value.longValue(); - } - - @Override - public BigInteger toBigInteger() { - return value; - } - - @Override - public float toFloat() { - return value.floatValue(); - } - - @Override - public double toDouble() { - return value.doubleValue(); - } - - @Override - public boolean isInByteRange() { - return 0 <= value.compareTo(BYTE_MIN) && value.compareTo(BYTE_MAX) <= 0; - } - - @Override - public boolean isInShortRange() { - return 0 <= value.compareTo(SHORT_MIN) && value.compareTo(SHORT_MAX) <= 0; - } - - @Override - public boolean isInIntRange() { - return 0 <= value.compareTo(INT_MIN) && value.compareTo(INT_MAX) <= 0; - } - - @Override - public boolean isInLongRange() { - return 0 <= value.compareTo(LONG_MIN) && value.compareTo(LONG_MAX) <= 0; - } - - @Override - public MessageFormat mostSuccinctMessageFormat() { - return mostSuccinctMessageFormat(this); - } - - @Override - public byte asByte() { - if (!isInByteRange()) { - throw new MessageIntegerOverflowException(value); - } - return value.byteValue(); - } - - @Override - public short asShort() { - if (!isInShortRange()) { - throw new MessageIntegerOverflowException(value); - } - return value.shortValue(); - } - - @Override - public int asInt() { - if (!isInIntRange()) { - throw new MessageIntegerOverflowException(value); - } - return value.intValue(); - } - - @Override - public long asLong() { - if (!isInLongRange()) { - throw new MessageIntegerOverflowException(value); - } - return value.longValue(); - } - - @Override - public BigInteger asBigInteger() { - return value; - } - - @Override - public void writeTo(MessagePacker pk) - throws IOException { - pk.packBigInteger(value); - } - - @Override - public boolean equals(Object o) { - if (o == this) { - return true; - } - if (!(o instanceof Value v)) { - return false; - } - - if (!v.isIntegerValue()) { - return false; - } - IntegerValue iv = v.asIntegerValue(); - return value.equals(iv.toBigInteger()); - } - - @Override - public int hashCode() { - if (INT_MIN.compareTo(value) <= 0 && value.compareTo(INT_MAX) <= 0) { - return (int) value.longValue(); - } - else if (LONG_MIN.compareTo(value) <= 0 - && value.compareTo(LONG_MAX) <= 0) { - long v = value.longValue(); - return (int) (v ^ (v >>> 32)); - } - return value.hashCode(); - } - - @Override - public String toJson() { - return value.toString(); - } - - @Override - public String toString() { - return toJson(); - } -} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableBinaryValueImpl.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableBinaryValueImpl.java deleted file mode 100644 index a085523..0000000 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableBinaryValueImpl.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright 2021 - 2026 the TODAY 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 - * - * https://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 infra.cloud.serialize.format.value.impl; - -import java.io.IOException; -import java.util.Arrays; - -import infra.cloud.serialize.format.MessagePacker; -import infra.cloud.serialize.format.value.ImmutableBinaryValue; -import infra.cloud.serialize.format.value.StringValue; -import infra.cloud.serialize.format.value.Value; -import infra.cloud.serialize.format.value.ValueType; - -/** - * {@code ImmutableBinaryValueImpl} Implements {@code ImmutableBinaryValue} using a {@code byte[]} field. - * This implementation caches result of {@code toString()} and {@code asString()} using a private {@code String} field. - * - * @see StringValue - */ -public class ImmutableBinaryValueImpl - extends AbstractImmutableRawValue - implements ImmutableBinaryValue { - public ImmutableBinaryValueImpl(byte[] data) { - super(data); - } - - @Override - public ValueType getValueType() { - return ValueType.BINARY; - } - - @Override - public ImmutableBinaryValue immutableValue() { - return this; - } - - @Override - public ImmutableBinaryValue asBinaryValue() { - return this; - } - - @Override - public void writeTo(MessagePacker pk) - throws IOException { - pk.packBinaryHeader(data.length); - pk.writePayload(data); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (!(o instanceof Value)) { - return false; - } - Value v = (Value) o; - if (!v.isBinaryValue()) { - return false; - } - - if (v instanceof ImmutableBinaryValueImpl) { - ImmutableBinaryValueImpl bv = (ImmutableBinaryValueImpl) v; - return Arrays.equals(data, bv.data); - } - else { - return Arrays.equals(data, v.asBinaryValue().asByteArray()); - } - } - - @Override - public int hashCode() { - return Arrays.hashCode(data); - } -} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableBooleanValueImpl.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableBooleanValueImpl.java deleted file mode 100644 index 5f2c257..0000000 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableBooleanValueImpl.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright 2021 - 2026 the TODAY 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 - * - * https://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 infra.cloud.serialize.format.value.impl; - -import java.io.IOException; - -import infra.cloud.serialize.format.MessagePacker; -import infra.cloud.serialize.format.value.BooleanValue; -import infra.cloud.serialize.format.value.ImmutableBooleanValue; -import infra.cloud.serialize.format.value.Value; -import infra.cloud.serialize.format.value.ValueType; - -/** - * {@code ImmutableBooleanValueImpl} Implements {@code ImmutableBooleanValue} using a {@code boolean} field. - * - * This class is a singleton. {@code ImmutableBooleanValueImpl.trueInstance()} and {@code ImmutableBooleanValueImpl.falseInstance()} are the only instances of this class. - * - * @see BooleanValue - */ -public class ImmutableBooleanValueImpl - extends AbstractImmutableValue - implements ImmutableBooleanValue { - public static final ImmutableBooleanValue TRUE = new ImmutableBooleanValueImpl(true); - public static final ImmutableBooleanValue FALSE = new ImmutableBooleanValueImpl(false); - - private final boolean value; - - private ImmutableBooleanValueImpl(boolean value) { - this.value = value; - } - - @Override - public ValueType getValueType() { - return ValueType.BOOLEAN; - } - - @Override - public ImmutableBooleanValue asBooleanValue() { - return this; - } - - @Override - public ImmutableBooleanValue immutableValue() { - return this; - } - - @Override - public boolean getBoolean() { - return value; - } - - @Override - public void writeTo(MessagePacker packer) - throws IOException { - packer.packBoolean(value); - } - - @Override - public boolean equals(Object o) { - if (o == this) { - return true; - } - if (!(o instanceof Value)) { - return false; - } - Value v = (Value) o; - - if (!v.isBooleanValue()) { - return false; - } - return value == v.asBooleanValue().getBoolean(); - } - - @Override - public int hashCode() { - if (value) { - return 1231; - } - else { - return 1237; - } - } - - @Override - public String toJson() { - return Boolean.toString(value); - } - - @Override - public String toString() { - return toJson(); - } -} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableDoubleValueImpl.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableDoubleValueImpl.java deleted file mode 100644 index 97fdc5e..0000000 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableDoubleValueImpl.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright 2021 - 2026 the TODAY 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 - * - * https://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 infra.cloud.serialize.format.value.impl; - -import java.io.IOException; -import java.math.BigDecimal; -import java.math.BigInteger; - -import infra.cloud.serialize.format.MessagePacker; -import infra.cloud.serialize.format.value.FloatValue; -import infra.cloud.serialize.format.value.ImmutableFloatValue; -import infra.cloud.serialize.format.value.ImmutableNumberValue; -import infra.cloud.serialize.format.value.Value; -import infra.cloud.serialize.format.value.ValueType; - -/** - * {@code ImmutableDoubleValueImpl} Implements {@code ImmutableFloatValue} using a {@code double} field. - * - * @see FloatValue - */ -public class ImmutableDoubleValueImpl extends AbstractImmutableValue implements ImmutableFloatValue { - - private final double value; - - public ImmutableDoubleValueImpl(double value) { - this.value = value; - } - - @Override - public ValueType getValueType() { - return ValueType.FLOAT; - } - - @Override - public ImmutableDoubleValueImpl immutableValue() { - return this; - } - - @Override - public ImmutableNumberValue asNumberValue() { - return this; - } - - @Override - public ImmutableFloatValue asFloatValue() { - return this; - } - - @Override - public byte toByte() { - return (byte) value; - } - - @Override - public short toShort() { - return (short) value; - } - - @Override - public int toInt() { - return (int) value; - } - - @Override - public long toLong() { - return (long) value; - } - - @Override - public BigInteger toBigInteger() { - return new BigDecimal(value).toBigInteger(); - } - - @Override - public float toFloat() { - return (float) value; - } - - @Override - public double toDouble() { - return value; - } - - @Override - public void writeTo(MessagePacker pk) - throws IOException { - pk.packDouble(value); - } - - @Override - public boolean equals(Object o) { - if (o == this) { - return true; - } - if (!(o instanceof Value)) { - return false; - } - Value v = (Value) o; - - if (!v.isFloatValue()) { - return false; - } - return value == v.asFloatValue().toDouble(); - } - - @Override - public int hashCode() { - long v = Double.doubleToLongBits(value); - return (int) (v ^ (v >>> 32)); - } - - @Override - public String toJson() { - if (Double.isNaN(value) || Double.isInfinite(value)) { - return "null"; - } - else { - return Double.toString(value); - } - } - - @Override - public String toString() { - return Double.toString(value); - } -} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableExtensionValueImpl.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableExtensionValueImpl.java deleted file mode 100644 index 3a5aac5..0000000 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableExtensionValueImpl.java +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright 2021 - 2026 the TODAY 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 - * - * https://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 infra.cloud.serialize.format.value.impl; - -import java.io.IOException; -import java.util.Arrays; - -import infra.cloud.serialize.format.MessagePacker; -import infra.cloud.serialize.format.value.ExtensionValue; -import infra.cloud.serialize.format.value.ImmutableExtensionValue; -import infra.cloud.serialize.format.value.Value; -import infra.cloud.serialize.format.value.ValueType; - -/** - * {@code ImmutableExtensionValueImpl} Implements {@code ImmutableExtensionValue} using a {@code byte} and a {@code byte[]} fields. - * - * @see ExtensionValue - */ -public class ImmutableExtensionValueImpl - extends AbstractImmutableValue - implements ImmutableExtensionValue { - private final byte type; - private final byte[] data; - - public ImmutableExtensionValueImpl(byte type, byte[] data) { - this.type = type; - this.data = data; - } - - @Override - public ValueType getValueType() { - return ValueType.EXTENSION; - } - - @Override - public ImmutableExtensionValue immutableValue() { - return this; - } - - @Override - public ImmutableExtensionValue asExtensionValue() { - return this; - } - - @Override - public byte getType() { - return type; - } - - @Override - public byte[] getData() { - return data; - } - - @Override - public void writeTo(MessagePacker packer) - throws IOException { - packer.packExtensionTypeHeader(type, data.length); - packer.writePayload(data); - } - - @Override - public boolean equals(Object o) { - if (o == this) { - return true; - } - if (!(o instanceof Value)) { - return false; - } - Value v = (Value) o; - - if (!v.isExtensionValue()) { - return false; - } - ExtensionValue ev = v.asExtensionValue(); - return type == ev.getType() && Arrays.equals(data, ev.getData()); - } - - @Override - public int hashCode() { - int hash = 31 + type; - for (byte e : data) { - hash = 31 * hash + e; - } - return hash; - } - - @Override - public String toJson() { - StringBuilder sb = new StringBuilder(); - sb.append('['); - sb.append(Byte.toString(type)); - sb.append(",\""); - for (byte e : data) { - sb.append(Integer.toString((int) e, 16)); - } - sb.append("\"]"); - return sb.toString(); - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append('('); - sb.append(Byte.toString(type)); - sb.append(",0x"); - for (byte e : data) { - sb.append(Integer.toString((int) e, 16)); - } - sb.append(")"); - return sb.toString(); - } -} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableLongValueImpl.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableLongValueImpl.java deleted file mode 100644 index aa50f4a..0000000 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableLongValueImpl.java +++ /dev/null @@ -1,211 +0,0 @@ -/* - * Copyright 2021 - 2026 the TODAY 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 - * - * https://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 infra.cloud.serialize.format.value.impl; - -import java.io.IOException; -import java.math.BigInteger; - -import infra.cloud.serialize.format.MessageFormat; -import infra.cloud.serialize.format.MessageIntegerOverflowException; -import infra.cloud.serialize.format.MessagePacker; -import infra.cloud.serialize.format.value.ImmutableIntegerValue; -import infra.cloud.serialize.format.value.ImmutableNumberValue; -import infra.cloud.serialize.format.value.IntegerValue; -import infra.cloud.serialize.format.value.Value; -import infra.cloud.serialize.format.value.ValueType; - -/** - * {@code ImmutableLongValueImpl} Implements {@code ImmutableIntegerValue} using a {@code long} field. - * - * @see IntegerValue - */ -public class ImmutableLongValueImpl - extends AbstractImmutableValue - implements ImmutableIntegerValue { - private final long value; - - public ImmutableLongValueImpl(long value) { - this.value = value; - } - - private static final long BYTE_MIN = (long) Byte.MIN_VALUE; - private static final long BYTE_MAX = (long) Byte.MAX_VALUE; - private static final long SHORT_MIN = (long) Short.MIN_VALUE; - private static final long SHORT_MAX = (long) Short.MAX_VALUE; - private static final long INT_MIN = (long) Integer.MIN_VALUE; - private static final long INT_MAX = (long) Integer.MAX_VALUE; - - @Override - public ValueType getValueType() { - return ValueType.INTEGER; - } - - @Override - public ImmutableIntegerValue immutableValue() { - return this; - } - - @Override - public ImmutableNumberValue asNumberValue() { - return this; - } - - @Override - public ImmutableIntegerValue asIntegerValue() { - return this; - } - - @Override - public byte toByte() { - return (byte) value; - } - - @Override - public short toShort() { - return (short) value; - } - - @Override - public int toInt() { - return (int) value; - } - - @Override - public long toLong() { - return value; - } - - @Override - public BigInteger toBigInteger() { - return BigInteger.valueOf(value); - } - - @Override - public float toFloat() { - return (float) value; - } - - @Override - public double toDouble() { - return (double) value; - } - - @Override - public boolean isInByteRange() { - return BYTE_MIN <= value && value <= BYTE_MAX; - } - - @Override - public boolean isInShortRange() { - return SHORT_MIN <= value && value <= SHORT_MAX; - } - - @Override - public boolean isInIntRange() { - return INT_MIN <= value && value <= INT_MAX; - } - - @Override - public boolean isInLongRange() { - return true; - } - - @Override - public MessageFormat mostSuccinctMessageFormat() { - return ImmutableBigIntegerValueImpl.mostSuccinctMessageFormat(this); - } - - @Override - public byte asByte() { - if (!isInByteRange()) { - throw new MessageIntegerOverflowException(value); - } - return (byte) value; - } - - @Override - public short asShort() { - if (!isInShortRange()) { - throw new MessageIntegerOverflowException(value); - } - return (short) value; - } - - @Override - public int asInt() { - if (!isInIntRange()) { - throw new MessageIntegerOverflowException(value); - } - return (int) value; - } - - @Override - public long asLong() { - return value; - } - - @Override - public BigInteger asBigInteger() { - return BigInteger.valueOf(value); - } - - @Override - public void writeTo(MessagePacker pk) - throws IOException { - pk.packLong(value); - } - - @Override - public boolean equals(Object o) { - if (o == this) { - return true; - } - if (!(o instanceof Value)) { - return false; - } - Value v = (Value) o; - if (!v.isIntegerValue()) { - return false; - } - - IntegerValue iv = v.asIntegerValue(); - if (!iv.isInLongRange()) { - return false; - } - return value == iv.toLong(); - } - - @Override - public int hashCode() { - if (INT_MIN <= value && value <= INT_MAX) { - return (int) value; - } - else { - return (int) (value ^ (value >>> 32)); - } - } - - @Override - public String toJson() { - return Long.toString(value); - } - - @Override - public String toString() { - return toJson(); - } -} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableMapValueImpl.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableMapValueImpl.java deleted file mode 100644 index 1e65f9b..0000000 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableMapValueImpl.java +++ /dev/null @@ -1,330 +0,0 @@ -/* - * Copyright 2021 - 2026 the TODAY 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 - * - * https://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 infra.cloud.serialize.format.value.impl; - -import java.io.IOException; -import java.util.AbstractCollection; -import java.util.AbstractMap; -import java.util.AbstractSet; -import java.util.Arrays; -import java.util.Collection; -import java.util.Iterator; -import java.util.Map; -import java.util.NoSuchElementException; -import java.util.Set; - -import infra.cloud.serialize.format.MessagePacker; -import infra.cloud.serialize.format.value.ImmutableMapValue; -import infra.cloud.serialize.format.value.MapValue; -import infra.cloud.serialize.format.value.Value; -import infra.cloud.serialize.format.value.ValueType; - -/** - * {@code ImmutableMapValueImpl} Implements {@code ImmutableMapValue} using a {@code Value[]} field. - * - * @see MapValue - */ -public class ImmutableMapValueImpl - extends AbstractImmutableValue - implements ImmutableMapValue { - private static final ImmutableMapValueImpl EMPTY = new ImmutableMapValueImpl(new Value[0]); - - public static ImmutableMapValue empty() { - return EMPTY; - } - - private final Value[] kvs; - - public ImmutableMapValueImpl(Value[] kvs) { - this.kvs = kvs; - } - - @Override - public ValueType getValueType() { - return ValueType.MAP; - } - - @Override - public ImmutableMapValue immutableValue() { - return this; - } - - @Override - public ImmutableMapValue asMapValue() { - return this; - } - - @Override - public Value[] getKeyValueArray() { - return Arrays.copyOf(kvs, kvs.length); - } - - @Override - public int size() { - return kvs.length / 2; - } - - @Override - public Set keySet() { - return new KeySet(kvs); - } - - @Override - public Set> entrySet() { - return new EntrySet(kvs); - } - - @Override - public Collection values() { - return new ValueCollection(kvs); - } - - @Override - public Map map() { - return new ImmutableMapValueMap(kvs); - } - - @Override - public void writeTo(MessagePacker pk) - throws IOException { - pk.packMapHeader(kvs.length / 2); - for (int i = 0; i < kvs.length; i++) { - kvs[i].writeTo(pk); - } - } - - @Override - public boolean equals(Object o) { - if (o == this) { - return true; - } - if (!(o instanceof Value)) { - return false; - } - Value v = (Value) o; - - if (!v.isMapValue()) { - return false; - } - MapValue mv = v.asMapValue(); - return map().equals(mv.map()); - } - - @Override - public int hashCode() { - int h = 0; - for (int i = 0; i < kvs.length; i += 2) { - h += kvs[i].hashCode() ^ kvs[i + 1].hashCode(); - } - return h; - } - - @Override - public String toJson() { - if (kvs.length == 0) { - return "{}"; - } - StringBuilder sb = new StringBuilder(); - sb.append("{"); - appendJsonKey(sb, kvs[0]); - sb.append(":"); - sb.append(kvs[1].toJson()); - for (int i = 2; i < kvs.length; i += 2) { - sb.append(","); - appendJsonKey(sb, kvs[i]); - sb.append(":"); - sb.append(kvs[i + 1].toJson()); - } - sb.append("}"); - return sb.toString(); - } - - private static void appendJsonKey(StringBuilder sb, Value key) { - if (key.isRawValue()) { - sb.append(key.toJson()); - } - else { - ImmutableStringValueImpl.appendJsonString(sb, key.toString()); - } - } - - @Override - public String toString() { - if (kvs.length == 0) { - return "{}"; - } - StringBuilder sb = new StringBuilder(); - sb.append("{"); - appendString(sb, kvs[0]); - sb.append(":"); - appendString(sb, kvs[1]); - for (int i = 2; i < kvs.length; i += 2) { - sb.append(","); - appendString(sb, kvs[i]); - sb.append(":"); - appendString(sb, kvs[i + 1]); - } - sb.append("}"); - return sb.toString(); - } - - private static void appendString(StringBuilder sb, Value value) { - if (value.isRawValue()) { - sb.append(value.toJson()); - } - else { - sb.append(value.toString()); - } - } - - private static class ImmutableMapValueMap - extends AbstractMap { - private final Value[] kvs; - - public ImmutableMapValueMap(Value[] kvs) { - this.kvs = kvs; - } - - @Override - public Set> entrySet() { - return new EntrySet(kvs); - } - } - - private static class EntrySet - extends AbstractSet> { - private final Value[] kvs; - - EntrySet(Value[] kvs) { - this.kvs = kvs; - } - - @Override - public int size() { - return kvs.length / 2; - } - - @Override - public Iterator> iterator() { - return new EntrySetIterator(kvs); - } - } - - private static class EntrySetIterator - implements Iterator> { - private final Value[] kvs; - private int index; - - EntrySetIterator(Value[] kvs) { - this.kvs = kvs; - this.index = 0; - } - - @Override - public boolean hasNext() { - return index < kvs.length; - } - - @Override - public Map.Entry next() { - if (index >= kvs.length) { - throw new NoSuchElementException(); // TODO message - } - - Value key = kvs[index]; - Value value = kvs[index + 1]; - Map.Entry pair = new AbstractMap.SimpleImmutableEntry(key, value); - - index += 2; - return pair; - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); // TODO message - } - } - - private static class KeySet - extends AbstractSet { - private Value[] kvs; - - KeySet(Value[] kvs) { - this.kvs = kvs; - } - - @Override - public int size() { - return kvs.length / 2; - } - - @Override - public Iterator iterator() { - return new EntryIterator(kvs, 0); - } - } - - private static class ValueCollection - extends AbstractCollection { - private Value[] kvs; - - ValueCollection(Value[] kvs) { - this.kvs = kvs; - } - - @Override - public int size() { - return kvs.length / 2; - } - - @Override - public Iterator iterator() { - return new EntryIterator(kvs, 1); - } - } - - private static class EntryIterator - implements Iterator { - private Value[] kvs; - private int index; - - public EntryIterator(Value[] kvs, int offset) { - this.kvs = kvs; - this.index = offset; - } - - @Override - public boolean hasNext() { - return index < kvs.length; - } - - @Override - public Value next() { - int i = index; - if (i >= kvs.length) { - throw new NoSuchElementException(); - } - index = i + 2; - return kvs[i]; - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - } -} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableNilValueImpl.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableNilValueImpl.java deleted file mode 100644 index 3714d29..0000000 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableNilValueImpl.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright 2021 - 2026 the TODAY 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 - * - * https://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 infra.cloud.serialize.format.value.impl; - -import java.io.IOException; - -import infra.cloud.serialize.format.MessagePacker; -import infra.cloud.serialize.format.value.ImmutableNilValue; -import infra.cloud.serialize.format.value.NilValue; -import infra.cloud.serialize.format.value.Value; -import infra.cloud.serialize.format.value.ValueType; - -/** - * {@code ImmutableNilValueImpl} Implements {@code ImmutableNilValue}. - *

              - * This class is a singleton. {@code ImmutableNilValueImpl.get()} is the only instances of this class. - * - * @see NilValue - */ -public class ImmutableNilValueImpl extends AbstractImmutableValue implements ImmutableNilValue { - - private static ImmutableNilValue instance = new ImmutableNilValueImpl(); - - public static ImmutableNilValue get() { - return instance; - } - - private ImmutableNilValueImpl() { - } - - @Override - public ValueType getValueType() { - return ValueType.NIL; - } - - @Override - public ImmutableNilValue immutableValue() { - return this; - } - - @Override - public ImmutableNilValue asNilValue() { - return this; - } - - @Override - public void writeTo(MessagePacker pk) - throws IOException { - pk.packNil(); - } - - @Override - public boolean equals(Object o) { - if (o == this) { - return true; - } - if (!(o instanceof Value)) { - return false; - } - return ((Value) o).isNilValue(); - } - - @Override - public int hashCode() { - return 0; - } - - @Override - public String toString() { - return toJson(); - } - - @Override - public String toJson() { - return "null"; - } -} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableStringValueImpl.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableStringValueImpl.java deleted file mode 100644 index 8acd0df..0000000 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableStringValueImpl.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright 2021 - 2026 the TODAY 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 - * - * https://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 infra.cloud.serialize.format.value.impl; - -import java.io.IOException; -import java.util.Arrays; - -import infra.cloud.serialize.format.MessagePacker; -import infra.cloud.serialize.format.value.ImmutableStringValue; -import infra.cloud.serialize.format.value.StringValue; -import infra.cloud.serialize.format.value.Value; -import infra.cloud.serialize.format.value.ValueType; - -/** - * {@code ImmutableStringValueImpl} Implements {@code ImmutableStringValue} using a {@code byte[]} field. - * This implementation caches result of {@code toString()} and {@code asString()} using a private {@code String} field. - * - * @see StringValue - */ -public class ImmutableStringValueImpl - extends AbstractImmutableRawValue - implements ImmutableStringValue { - public ImmutableStringValueImpl(byte[] data) { - super(data); - } - - public ImmutableStringValueImpl(String string) { - super(string); - } - - @Override - public ValueType getValueType() { - return ValueType.STRING; - } - - @Override - public ImmutableStringValue immutableValue() { - return this; - } - - @Override - public ImmutableStringValue asStringValue() { - return this; - } - - @Override - public void writeTo(MessagePacker pk) - throws IOException { - pk.packRawStringHeader(data.length); - pk.writePayload(data); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (!(o instanceof Value)) { - return false; - } - Value v = (Value) o; - if (!v.isStringValue()) { - return false; - } - - if (v instanceof ImmutableStringValueImpl) { - ImmutableStringValueImpl bv = (ImmutableStringValueImpl) v; - return Arrays.equals(data, bv.data); - } - else { - return Arrays.equals(data, v.asStringValue().asByteArray()); - } - } - - @Override - public int hashCode() { - return Arrays.hashCode(data); - } -} diff --git a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableTimestampValueImpl.java b/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableTimestampValueImpl.java deleted file mode 100644 index eb2838c..0000000 --- a/today-service-serialization/src/main/java/infra/cloud/serialize/format/value/impl/ImmutableTimestampValueImpl.java +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Copyright 2021 - 2026 the TODAY 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 - * - * https://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 infra.cloud.serialize.format.value.impl; - -import java.io.IOException; -import java.time.Instant; -import java.util.Arrays; - -import infra.cloud.serialize.format.MessagePacker; -import infra.cloud.serialize.format.buffer.MessageBuffer; -import infra.cloud.serialize.format.value.ExtensionValue; -import infra.cloud.serialize.format.value.ImmutableExtensionValue; -import infra.cloud.serialize.format.value.ImmutableTimestampValue; -import infra.cloud.serialize.format.value.TimestampValue; -import infra.cloud.serialize.format.value.Value; -import infra.cloud.serialize.format.value.ValueType; - -import static infra.cloud.serialize.format.MessagePack.Code.EXT_TIMESTAMP; - -/** - * {@code ImmutableTimestampValueImpl} Implements {@code ImmutableTimestampValue} using a {@code byte} and a {@code byte[]} fields. - * - * @see TimestampValue - */ -public class ImmutableTimestampValueImpl - extends AbstractImmutableValue - implements ImmutableExtensionValue, ImmutableTimestampValue { - private final Instant instant; - private byte[] data; - - public ImmutableTimestampValueImpl(Instant timestamp) { - this.instant = timestamp; - } - - @Override - public boolean isTimestampValue() { - return true; - } - - @Override - public byte getType() { - return EXT_TIMESTAMP; - } - - @Override - public ValueType getValueType() { - // Note: Future version should return ValueType.TIMESTAMP instead. - return ValueType.EXTENSION; - } - - @Override - public ImmutableTimestampValue immutableValue() { - return this; - } - - @Override - public ImmutableExtensionValue asExtensionValue() { - return this; - } - - @Override - public ImmutableTimestampValue asTimestampValue() { - return this; - } - - @Override - public byte[] getData() { - if (data == null) { - // See MessagePacker.packTimestampImpl - byte[] bytes; - long sec = getEpochSecond(); - int nsec = getNano(); - if (sec >>> 34 == 0) { - long data64 = ((long) nsec << 34) | sec; - if ((data64 & 0xffffffff00000000L) == 0L) { - bytes = new byte[4]; - MessageBuffer.wrap(bytes).putInt(0, (int) sec); - } - else { - bytes = new byte[8]; - MessageBuffer.wrap(bytes).putLong(0, data64); - } - } - else { - bytes = new byte[12]; - MessageBuffer buffer = MessageBuffer.wrap(bytes); - buffer.putInt(0, nsec); - buffer.putLong(4, sec); - } - data = bytes; - } - return data; - } - - @Override - public long getEpochSecond() { - return instant.getEpochSecond(); - } - - @Override - public int getNano() { - return instant.getNano(); - } - - @Override - public long toEpochMillis() { - return instant.toEpochMilli(); - } - - @Override - public Instant toInstant() { - return instant; - } - - @Override - public void writeTo(MessagePacker packer) - throws IOException { - packer.packTimestamp(instant); - } - - @Override - public boolean equals(Object o) { - // Implements same behavior with ImmutableExtensionValueImpl. - if (o == this) { - return true; - } - if (!(o instanceof Value)) { - return false; - } - Value v = (Value) o; - - if (!v.isExtensionValue()) { - return false; - } - ExtensionValue ev = v.asExtensionValue(); - - // Here should use isTimestampValue and asTimestampValue instead. However, because - // adding these methods to Value interface can't keep backward compatibility without - // using "default" keyword since Java 7, here uses instanceof of and cast instead. - if (ev instanceof TimestampValue) { - TimestampValue tv = (TimestampValue) ev; - return instant.equals(tv.toInstant()); - } - else { - return EXT_TIMESTAMP == ev.getType() && Arrays.equals(getData(), ev.getData()); - } - } - - @Override - public int hashCode() { - // Implements same behavior with ImmutableExtensionValueImpl. - int hash = EXT_TIMESTAMP; - hash *= 31; - hash = instant.hashCode(); - return hash; - } - - @Override - public String toJson() { - return "\"" + toInstant().toString() + "\""; - } - - @Override - public String toString() { - return toInstant().toString(); - } -} From 8731f0ddb655d4093468a3ec52ffd6e5c20e7778 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Mon, 9 Mar 2026 21:28:33 +0800 Subject: [PATCH 071/104] :arrow_up: ./gradlew wrapper --gradle-version=9.4.0 --- gradle/wrapper/gradle-wrapper.jar | Bin 46175 -> 48966 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 61285a659d17295f1de7c53e24fdf13ad755c379..d997cfc60f4cff0e7451d19d49a82fa986695d07 100644 GIT binary patch delta 39855 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

              SdO`o?U^bCPz6Ehh!k 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


              Xdyd*p!l1Y@nCA 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 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 19a6bde..dbc3ce4 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-9.3.0-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.4.0-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew index adff685..0262dcb 100755 --- a/gradlew +++ b/gradlew @@ -57,7 +57,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/b631911858264c0b6e4d6603d677ff5218766cee/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. From 25b1e3a3ee50febdbd195f944861c5854857caf0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Mon, 9 Mar 2026 21:58:40 +0800 Subject: [PATCH 072/104] :art: --- .../cloud/client/DefaultServiceInstance.java | 71 +++++-------------- .../infra/cloud/client/ServiceInstance.java | 6 -- .../cloud/provider/LocalServiceHolder.java | 4 +- .../cloud/provider/ServicesProvider.java | 13 +++- .../AbstractAutoServiceRegistration.java | 22 ++++-- .../registry/AutoServiceRegistration.java | 6 ++ .../cloud/registry/RegistrationFactory.java | 13 ++++ 7 files changed, 67 insertions(+), 68 deletions(-) diff --git a/today-cloud-core/src/main/java/infra/cloud/client/DefaultServiceInstance.java b/today-cloud-core/src/main/java/infra/cloud/client/DefaultServiceInstance.java index a32ca57..2b36c56 100644 --- a/today-cloud-core/src/main/java/infra/cloud/client/DefaultServiceInstance.java +++ b/today-cloud-core/src/main/java/infra/cloud/client/DefaultServiceInstance.java @@ -16,9 +16,6 @@ package infra.cloud.client; -import org.jspecify.annotations.Nullable; - -import java.net.URI; import java.util.LinkedHashMap; import java.util.Map; import java.util.Objects; @@ -27,6 +24,12 @@ /** * Default implementation of {@link ServiceInstance}. + *

              + * This class represents a service instance with properties such as instance ID, + * service ID, host, port, security status, and metadata. It provides constructors + * for creating instances with varying levels of detail and includes standard + * object methods like {@code toString()}, {@code equals()}, and {@code hashCode()}. + *

              * * @author Harry Yang * @since 1.0 2023/11/19 20:52 @@ -45,9 +48,6 @@ public class DefaultServiceInstance implements ServiceInstance { private Map metadata = new LinkedHashMap<>(); - @Nullable - private URI uri; - public DefaultServiceInstance() { } @@ -56,7 +56,18 @@ public DefaultServiceInstance() { * @param serviceId the id of the service. * @param host the host where the service instance can be found. * @param port the port on which the service is running. - * @param secure indicates whether or not the connection needs to be secure. + * @param secure indicates whether the connection needs to be secure. + */ + public DefaultServiceInstance(String instanceId, String serviceId, String host, int port, boolean secure) { + this(instanceId, serviceId, host, port, secure, new LinkedHashMap<>()); + } + + /** + * @param instanceId the id of the instance. + * @param serviceId the id of the service. + * @param host the host where the service instance can be found. + * @param port the port on which the service is running. + * @param secure indicates whether the connection needs to be secure. * @param metadata a map containing metadata. */ public DefaultServiceInstance(String instanceId, String serviceId, String host, @@ -69,42 +80,6 @@ public DefaultServiceInstance(String instanceId, String serviceId, String host, this.metadata = metadata; } - /** - * @param instanceId the id of the instance. - * @param serviceId the id of the service. - * @param host the host where the service instance can be found. - * @param port the port on which the service is running. - * @param secure indicates whether or not the connection needs to be secure. - */ - public DefaultServiceInstance(String instanceId, String serviceId, String host, int port, boolean secure) { - this(instanceId, serviceId, host, port, secure, new LinkedHashMap<>()); - } - - /** - * Creates a URI from the given ServiceInstance's host:port. - * - * @param instance the ServiceInstance. - * @return URI of the form (secure)?https:http + "host:port". Scheme port default used - * if port not set. - */ - public static URI getUri(ServiceInstance instance) { - String scheme = (instance.isSecure()) ? "https" : "http"; - int port = instance.getPort(); - if (port <= 0) { - port = (instance.isSecure()) ? 443 : 80; - } - String uri = String.format("%s://%s:%s", scheme, instance.getHost(), port); - return URI.create(uri); - } - - @Override - public URI getHttpURI() { - if (uri == null) { - uri = getUri(this); - } - return uri; - } - @Override public Map getMetadata() { return metadata; @@ -159,16 +134,6 @@ public void setSecure(boolean secure) { this.secure = secure; } - public void setUri(URI uri) { - this.uri = uri; - this.host = this.uri.getHost(); - this.port = this.uri.getPort(); - String scheme = this.uri.getScheme(); - if ("https".equals(scheme)) { - this.secure = true; - } - } - @Override public String toString() { return ToStringBuilder.forInstance(this) diff --git a/today-cloud-core/src/main/java/infra/cloud/client/ServiceInstance.java b/today-cloud-core/src/main/java/infra/cloud/client/ServiceInstance.java index b87e6f3..fa1ed36 100644 --- a/today-cloud-core/src/main/java/infra/cloud/client/ServiceInstance.java +++ b/today-cloud-core/src/main/java/infra/cloud/client/ServiceInstance.java @@ -16,7 +16,6 @@ package infra.cloud.client; -import java.net.URI; import java.util.Map; /** @@ -56,11 +55,6 @@ default String getInstanceId() { */ boolean isSecure(); - /** - * @return The service URI address. - */ - URI getHttpURI(); - /** * @return The key / value pair metadata associated with the service instance. */ diff --git a/today-service-provider/src/main/java/infra/cloud/provider/LocalServiceHolder.java b/today-service-provider/src/main/java/infra/cloud/provider/LocalServiceHolder.java index 64140c9..07e3b8e 100644 --- a/today-service-provider/src/main/java/infra/cloud/provider/LocalServiceHolder.java +++ b/today-service-provider/src/main/java/infra/cloud/provider/LocalServiceHolder.java @@ -26,7 +26,6 @@ import infra.beans.factory.SmartInitializingSingleton; import infra.cloud.service.ServiceMetadata; import infra.cloud.service.ServiceMetadataProvider; -import infra.context.ApplicationContext; import infra.context.support.ApplicationObjectSupport; import infra.lang.Assert; import infra.stereotype.Service; @@ -70,8 +69,7 @@ public List getServices() { @Override public void afterSingletonsInstantiated() { - ApplicationContext context = obtainApplicationContext(); - List services = context.getAnnotatedBeans(Service.class); + List services = applicationContext().getAnnotatedBeans(Service.class); for (Object service : services) { Class serviceImpl = ClassUtils.getUserClass(service); diff --git a/today-service-provider/src/main/java/infra/cloud/provider/ServicesProvider.java b/today-service-provider/src/main/java/infra/cloud/provider/ServicesProvider.java index 45bc361..327b3d7 100644 --- a/today-service-provider/src/main/java/infra/cloud/provider/ServicesProvider.java +++ b/today-service-provider/src/main/java/infra/cloud/provider/ServicesProvider.java @@ -21,11 +21,22 @@ import infra.cloud.service.ServiceMetadata; /** - * @author 海子 Yang + * Provider interface for discovering and retrieving available service metadata. + *

              + * Implementations of this interface are responsible for providing a list of + * {@link ServiceMetadata} representing the services currently available in the cloud environment. + *

              + * + * @author Hai Zi Yang * @since 1.0 2025/8/24 22:08 */ public interface ServicesProvider { + /** + * Retrieves a list of metadata for all available services. + * + * @return a list of {@link ServiceMetadata} objects + */ List getServices(); } diff --git a/today-service-registration/src/main/java/infra/cloud/registry/AbstractAutoServiceRegistration.java b/today-service-registration/src/main/java/infra/cloud/registry/AbstractAutoServiceRegistration.java index 4109447..441fe6a 100644 --- a/today-service-registration/src/main/java/infra/cloud/registry/AbstractAutoServiceRegistration.java +++ b/today-service-registration/src/main/java/infra/cloud/registry/AbstractAutoServiceRegistration.java @@ -25,14 +25,20 @@ import infra.cloud.registry.event.InstancePreRegisteredEvent; import infra.cloud.registry.event.InstanceRegisteredEvent; import infra.cloud.service.ServiceMetadata; +import infra.context.ApplicationContext; import infra.context.SmartLifecycle; import infra.context.support.ApplicationObjectSupport; /** - * Lifecycle methods that may be useful and common to {@link ServiceRegistry} - * implementations. + * Provides common lifecycle management methods for {@link ServiceRegistry} implementations. + *

              + * This abstract class handles the registration and un-registration processes of service + * instances, including event publishing and lifecycle callbacks via {@link RegistrationLifecycle}. + * It implements {@link SmartLifecycle} to integrate with the application context's lifecycle. + *

              * - * @param Registration type passed to the {@link ServiceRegistry}. + * @param The type of {@link Registration} used by the {@link ServiceRegistry}. + * @param The type of configuration or source object associated with the registry. * @author Spencer Gibb * @author Zen Huifer * @author 海子 Yang @@ -73,10 +79,11 @@ public void start() { logger.info("Registering services to registry: [{}]", serviceRegistry); if (!running.get()) { + ApplicationContext context = applicationContext(); RegistrationFactory registrationFactory = getRegistrationFactory(); for (ServiceMetadata serviceMetadata : servicesProvider.getServices()) { R registration = registrationFactory.createRegistration(serviceMetadata); - obtainApplicationContext().publishEvent(new InstancePreRegisteredEvent(this, registration)); + context.publishEvent(new InstancePreRegisteredEvent(this, registration)); for (RegistrationLifecycle lifecycle : registrationLifecycles) { lifecycle.postProcessBeforeStartRegister(registration); @@ -86,7 +93,7 @@ public void start() { lifecycle.postProcessAfterStartRegister(registration); } - obtainApplicationContext().publishEvent(new InstanceRegisteredEvent<>(this, registration, getConfiguration())); + context.publishEvent(new InstanceRegisteredEvent<>(this, registration, getConfiguration())); registrations.add(registration); } running.compareAndSet(false, true); @@ -152,6 +159,11 @@ public void stop() { */ protected abstract boolean isEnabled(); + /** + * Returns the factory used to create {@link Registration} instances for the services. + * + * @return the registration factory + */ protected abstract RegistrationFactory getRegistrationFactory(); } diff --git a/today-service-registration/src/main/java/infra/cloud/registry/AutoServiceRegistration.java b/today-service-registration/src/main/java/infra/cloud/registry/AutoServiceRegistration.java index 07d40d2..a71d591 100644 --- a/today-service-registration/src/main/java/infra/cloud/registry/AutoServiceRegistration.java +++ b/today-service-registration/src/main/java/infra/cloud/registry/AutoServiceRegistration.java @@ -17,6 +17,12 @@ package infra.cloud.registry; /** + * Interface for auto service registration. + *

              + * Implementations of this interface are responsible for automatically registering + * services with a service discovery system during application startup. + *

              + * * @author Spencer Gibb * @author 海子 Yang */ diff --git a/today-service-registration/src/main/java/infra/cloud/registry/RegistrationFactory.java b/today-service-registration/src/main/java/infra/cloud/registry/RegistrationFactory.java index 743f03d..eb40b52 100644 --- a/today-service-registration/src/main/java/infra/cloud/registry/RegistrationFactory.java +++ b/today-service-registration/src/main/java/infra/cloud/registry/RegistrationFactory.java @@ -20,11 +20,24 @@ import infra.cloud.service.ServiceMetadata; /** + * A factory interface responsible for creating {@link Registration} instances. + *

              + * Implementations of this interface should generate a specific registration object + * based on the provided {@link ServiceMetadata}. This is typically used during the + * service discovery process to register a service instance with a registry center. + * + * @param the type of registration, which must extend {@link Registration} * @author 海子 Yang * @since 1.0 2025/8/24 22:12 */ public interface RegistrationFactory { + /** + * Creates a new registration instance using the given service metadata. + * + * @param serviceMetadata the metadata containing information about the service to be registered + * @return a new instance of {@code R} representing the service registration + */ R createRegistration(ServiceMetadata serviceMetadata); } From 0b58d21cd103a3a5fc8daf57acd380f7abe22e26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Mon, 9 Mar 2026 22:42:53 +0800 Subject: [PATCH 073/104] :art: --- ...tractServiceInterfaceMetadataProvider.java | 30 +++++++++++++++++++ .../service/ServiceInterfaceMetadata.java | 26 ++++++++++++++++ .../ServiceInterfaceMetadataProvider.java | 14 +++++++++ .../infra/cloud/service/ServiceMetadata.java | 2 ++ .../service/ServiceMetadataProvider.java | 13 ++++++++ .../infra/cloud/service/ServiceMethod.java | 4 +++ .../ServiceClientAutoConfiguration.java | 2 +- .../DefaultRemotingOperationsProvider.java | 30 ++++++++++--------- .../service/RemotingOperationsProvider.java | 13 ++++++++ .../cloud/service/ServiceInterfaceMethod.java | 8 +++++ .../cloud/provider/LocalServiceHolder.java | 10 +++++-- 11 files changed, 135 insertions(+), 17 deletions(-) diff --git a/today-service-api/src/main/java/infra/cloud/service/AbstractServiceInterfaceMetadataProvider.java b/today-service-api/src/main/java/infra/cloud/service/AbstractServiceInterfaceMetadataProvider.java index 9aa86d5..79bd263 100644 --- a/today-service-api/src/main/java/infra/cloud/service/AbstractServiceInterfaceMetadataProvider.java +++ b/today-service-api/src/main/java/infra/cloud/service/AbstractServiceInterfaceMetadataProvider.java @@ -24,6 +24,13 @@ import infra.util.ReflectionUtils; /** + * Abstract base class for providing metadata about service interfaces. + *

              This class implements the {@link ServiceInterfaceMetadataProvider} interface and provides + * a common implementation for extracting service method metadata from a given service interface. + * It relies on a {@link ServiceMetadataProvider} to obtain general service metadata and uses + * reflection to identify and process service methods. + * + * @param the type of the service method, which must extend {@link ServiceMethod} * @author 海子 Yang * @since 1.0 2025/8/10 16:53 */ @@ -31,6 +38,13 @@ public abstract class AbstractServiceInterfaceMetadataProvider getMetadata(Class serviceInterface) { return new ServiceInterfaceMetadata<>(serviceInterface, serviceMetadata, serviceMethods); } + /** + * Creates a specific service method instance based on the provided service metadata, + * service interface, and reflected method. + * + * @param serviceMetadata the general metadata of the service + * @param serviceInterface the service interface class + * @param method the reflected method to be wrapped + * @return a new instance of {@code M} representing the service method + */ protected abstract M createServiceMethod(ServiceMetadata serviceMetadata, Class serviceInterface, Method method); + /** + * Determines whether the given method should be considered a service method. + *

              By default, this implementation excludes standard {@link Object} methods. + * + * @param method the method to check + * @return {@code true} if the method is a service method, {@code false} otherwise + */ protected boolean isServiceMethod(Method method) { return !ReflectionUtils.isObjectMethod(method); } diff --git a/today-service-api/src/main/java/infra/cloud/service/ServiceInterfaceMetadata.java b/today-service-api/src/main/java/infra/cloud/service/ServiceInterfaceMetadata.java index 4763628..76d9733 100644 --- a/today-service-api/src/main/java/infra/cloud/service/ServiceInterfaceMetadata.java +++ b/today-service-api/src/main/java/infra/cloud/service/ServiceInterfaceMetadata.java @@ -20,6 +20,10 @@ import java.util.List; /** + * Metadata container for a service interface, holding the associated service metadata, + * the service interface class, and an immutable list of its service methods. + * + * @param the type of service method, which must extend {@link ServiceMethod} * @author 海子 Yang * @since 1.0 2025/8/9 21:59 */ @@ -31,20 +35,42 @@ public class ServiceInterfaceMetadata { private final List serviceMethods; + /** + * Constructs a new {@code ServiceInterfaceMetadata} instance. + * + * @param serviceInterface the class representing the service interface + * @param serviceMetadata the metadata associated with the service + * @param serviceMethods the list of service methods belonging to this interface + */ public ServiceInterfaceMetadata(Class serviceInterface, ServiceMetadata serviceMetadata, List serviceMethods) { this.serviceInterface = serviceInterface; this.serviceMetadata = serviceMetadata; this.serviceMethods = serviceMethods; } + /** + * Returns the class representing the service interface. + * + * @return the service interface class + */ public Class getServiceInterface() { return serviceInterface; } + /** + * Returns the metadata associated with the service. + * + * @return the service metadata + */ public ServiceMetadata getServiceMetadata() { return serviceMetadata; } + /** + * Returns an unmodifiable list of service methods belonging to this interface. + * + * @return an immutable list of service methods + */ public List getServiceMethods() { return Collections.unmodifiableList(serviceMethods); } diff --git a/today-service-api/src/main/java/infra/cloud/service/ServiceInterfaceMetadataProvider.java b/today-service-api/src/main/java/infra/cloud/service/ServiceInterfaceMetadataProvider.java index d96330a..a409d1b 100644 --- a/today-service-api/src/main/java/infra/cloud/service/ServiceInterfaceMetadataProvider.java +++ b/today-service-api/src/main/java/infra/cloud/service/ServiceInterfaceMetadataProvider.java @@ -17,11 +17,25 @@ package infra.cloud.service; /** + * Provider interface for retrieving metadata associated with a service interface. + *

              + * This interface is responsible for extracting and providing structural or descriptive + * information about a given service interface, typically used in RPC or cloud service + * discovery scenarios. The metadata is generic over {@link ServiceMethod} to allow + * flexible method-level descriptions. + * + * @param the type of service method metadata, which must extend {@link ServiceMethod} * @author 海子 Yang * @since 1.0 2025/8/10 08:22 */ public interface ServiceInterfaceMetadataProvider { + /** + * Retrieves the metadata for the specified service interface. + * + * @param serviceInterface the class object of the service interface to inspect + * @return the metadata associated with the given service interface + */ ServiceInterfaceMetadata getMetadata(Class serviceInterface); } diff --git a/today-service-api/src/main/java/infra/cloud/service/ServiceMetadata.java b/today-service-api/src/main/java/infra/cloud/service/ServiceMetadata.java index ba9e7cb..30c5f0d 100644 --- a/today-service-api/src/main/java/infra/cloud/service/ServiceMetadata.java +++ b/today-service-api/src/main/java/infra/cloud/service/ServiceMetadata.java @@ -21,6 +21,8 @@ import infra.core.style.ToStringBuilder; /** + * Metadata representing a service, including its unique identifier and version. + * * @author 海子 Yang * @since 1.0 2025/8/9 21:51 */ diff --git a/today-service-api/src/main/java/infra/cloud/service/ServiceMetadataProvider.java b/today-service-api/src/main/java/infra/cloud/service/ServiceMetadataProvider.java index e974c71..db4b834 100644 --- a/today-service-api/src/main/java/infra/cloud/service/ServiceMetadataProvider.java +++ b/today-service-api/src/main/java/infra/cloud/service/ServiceMetadataProvider.java @@ -17,11 +17,24 @@ package infra.cloud.service; /** + * Provider interface for retrieving metadata associated with service interfaces. + *

              + * Implementations of this interface are responsible for supplying {@link ServiceMetadata} + * for a given service interface class. This metadata typically includes configuration, + * routing information, or other descriptive attributes required by the service infrastructure. + *

              + * * @author 海子 Yang * @since 1.0 2025/8/9 21:50 */ public interface ServiceMetadataProvider { + /** + * Retrieves the metadata for the specified service interface. + * + * @param serviceInterface the class object representing the service interface + * @return the {@link ServiceMetadata} associated with the given interface + */ ServiceMetadata getMetadata(Class serviceInterface); } diff --git a/today-service-api/src/main/java/infra/cloud/service/ServiceMethod.java b/today-service-api/src/main/java/infra/cloud/service/ServiceMethod.java index 6ba4227..6b10fb0 100644 --- a/today-service-api/src/main/java/infra/cloud/service/ServiceMethod.java +++ b/today-service-api/src/main/java/infra/cloud/service/ServiceMethod.java @@ -23,6 +23,10 @@ import infra.core.MethodParameter; /** + * Represents a method within a service, encapsulating metadata such as the service interface, + * the underlying {@link Method}, and its parameters. This class provides access to service + * identification, metadata, and reflection-based method details. + * * @author 海子 Yang * @since 1.0 2025/8/10 08:20 */ diff --git a/today-service-client/src/main/java/infra/cloud/client/annotation/config/ServiceClientAutoConfiguration.java b/today-service-client/src/main/java/infra/cloud/client/annotation/config/ServiceClientAutoConfiguration.java index 10ccb64..2c57716 100644 --- a/today-service-client/src/main/java/infra/cloud/client/annotation/config/ServiceClientAutoConfiguration.java +++ b/today-service-client/src/main/java/infra/cloud/client/annotation/config/ServiceClientAutoConfiguration.java @@ -44,7 +44,7 @@ @DisableDIAutoConfiguration @ConditionalOnDiscoveryEnabled @EnableConfigurationProperties(SimpleDiscoveryProperties.class) -public class ServiceClientAutoConfiguration { +public final class ServiceClientAutoConfiguration { @Component public static DefaultServiceProxyFactory serviceProxyFactory( diff --git a/today-service-client/src/main/java/infra/cloud/service/DefaultRemotingOperationsProvider.java b/today-service-client/src/main/java/infra/cloud/service/DefaultRemotingOperationsProvider.java index 0d025c5..16278a3 100644 --- a/today-service-client/src/main/java/infra/cloud/service/DefaultRemotingOperationsProvider.java +++ b/today-service-client/src/main/java/infra/cloud/service/DefaultRemotingOperationsProvider.java @@ -18,9 +18,7 @@ import java.time.Duration; import java.util.ArrayList; -import java.util.List; import java.util.concurrent.ConcurrentHashMap; -import java.util.function.Function; import infra.cloud.client.DiscoveryClient; import infra.cloud.client.ServiceInstance; @@ -31,10 +29,17 @@ import reactor.core.publisher.Flux; /** + * Default implementation of {@link RemotingOperationsProvider} that provides remoting operations + * based on service discovery. It maintains a cache of {@link RemotingClient} instances keyed by + * service ID and periodically refreshes the list of available service instances for load balancing. + *

              + * This class also acts as a function to convert {@link ServiceInstance} lists into + * {@link LoadBalanceTarget} lists for the load balancer. + * * @author 海子 Yang * @since 1.0 2025/8/10 22:08 */ -public class DefaultRemotingOperationsProvider implements RemotingOperationsProvider, Function, List> { +public class DefaultRemotingOperationsProvider implements RemotingOperationsProvider { private final DiscoveryClient discoveryClient; @@ -61,19 +66,16 @@ public RemotingOperations getRemotingOperations(ServiceMethod serviceMethod) { public RemotingOperations getRemotingOperations(String serviceId) { return remotingClientMap.computeIfAbsent(serviceId, name -> RemotingClient.forLoadBalance(Flux.interval(discoveryPeriod) .map(i -> discoveryClient.getInstances(name)) - .map(this)) + .map(instances -> { + var targets = new ArrayList(instances.size()); + for (ServiceInstance instance : instances) { + targets.add(LoadBalanceTarget.of(instance.getInstanceId(), + TcpClientTransport.create(instance.getHost(), instance.getPort()))); + } + return targets; + })) .weightedLoadBalanceStrategy() .build()); } - @Override - public List apply(List instances) { - var targets = new ArrayList(instances.size()); - for (ServiceInstance instance : instances) { - targets.add(LoadBalanceTarget.of(instance.getInstanceId(), - TcpClientTransport.create(instance.getHost(), instance.getPort()))); - } - return targets; - } - } diff --git a/today-service-client/src/main/java/infra/cloud/service/RemotingOperationsProvider.java b/today-service-client/src/main/java/infra/cloud/service/RemotingOperationsProvider.java index f159278..90f5d9c 100644 --- a/today-service-client/src/main/java/infra/cloud/service/RemotingOperationsProvider.java +++ b/today-service-client/src/main/java/infra/cloud/service/RemotingOperationsProvider.java @@ -19,11 +19,24 @@ import infra.remoting.RemotingOperations; /** + * Provider for obtaining {@link RemotingOperations} instances based on a given service method. + *

              + * This interface defines a contract for retrieving remote operation handlers dynamically + * according to the specified {@link ServiceMethod}. Implementations are responsible for + * returning the appropriate remoting operations capable of handling the requested service. + *

              + * * @author 海子 Yang * @since 1.0 2025/8/10 22:10 */ public interface RemotingOperationsProvider { + /** + * Retrieves the {@link RemotingOperations} instance associated with the given service method. + * + * @param serviceMethod the specific service method to obtain remoting operations for + * @return the corresponding {@link RemotingOperations} instance; must not be null + */ RemotingOperations getRemotingOperations(ServiceMethod serviceMethod); } diff --git a/today-service-client/src/main/java/infra/cloud/service/ServiceInterfaceMethod.java b/today-service-client/src/main/java/infra/cloud/service/ServiceInterfaceMethod.java index 03012d2..c1c21a9 100644 --- a/today-service-client/src/main/java/infra/cloud/service/ServiceInterfaceMethod.java +++ b/today-service-client/src/main/java/infra/cloud/service/ServiceInterfaceMethod.java @@ -22,6 +22,14 @@ import java.util.ArrayList; /** + * Represents a method defined in a service interface, extending {@link ServiceMethod} + * with specific invocation logic and return value resolution strategies. + *

              + * This class determines the invocation type (e.g., blocking or non-blocking) based on + * the method's return type and configures the appropriate {@link ReturnValueResolver} + * to handle the result of the method invocation. + *

              + * * @author Harry Yang * @since 1.0 2024/1/7 21:03 */ diff --git a/today-service-provider/src/main/java/infra/cloud/provider/LocalServiceHolder.java b/today-service-provider/src/main/java/infra/cloud/provider/LocalServiceHolder.java index 07e3b8e..9668874 100644 --- a/today-service-provider/src/main/java/infra/cloud/provider/LocalServiceHolder.java +++ b/today-service-provider/src/main/java/infra/cloud/provider/LocalServiceHolder.java @@ -33,6 +33,13 @@ import infra.util.MultiValueMap; /** + * Holder for local service instances, managing the mapping between service interfaces + * and their corresponding implementations. It collects beans annotated with {@link Service} + * during the application context initialization and registers them for retrieval. + * + *

              This class implements {@link SmartInitializingSingleton} to ensure all services are + * registered after all singleton beans have been instantiated. + * * @author Harry Yang * @since 1.0 2022/10/19 21:40 */ @@ -51,9 +58,8 @@ public LocalServiceHolder(ServiceMetadataProvider serviceMetadataProvider) { this.serviceMetadataProvider = serviceMetadataProvider; } - @Nullable @SuppressWarnings("unchecked") - public T getService(Class serviceInterface) { + public @Nullable T getService(Class serviceInterface) { return (T) localServices.get(serviceInterface); } From 9e46880fde58cf578b45ce22fa5bb7b7e3148a08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Mon, 9 Mar 2026 23:04:00 +0800 Subject: [PATCH 074/104] :art: --- .../demo-registry/src/main/resources/application.yaml | 2 +- .../demo-user-rest/src/main/resources/application.yaml | 2 +- .../demo-user-service/src/main/resources/application.yaml | 6 +++--- .../src/main/java/infra/remoting/RemotingOperations.java | 3 +++ today-service-registry-simple-api/build.gradle | 2 +- today-service-registry-simple-discovery/build.gradle | 2 +- today-service-registry-simple-registration/build.gradle | 2 +- today-service-registry-simple-server/build.gradle | 2 +- 8 files changed, 12 insertions(+), 9 deletions(-) diff --git a/today-cloud-samples/demo-tests/demo-registry/src/main/resources/application.yaml b/today-cloud-samples/demo-tests/demo-registry/src/main/resources/application.yaml index 3d8f09d..a4bd446 100644 --- a/today-cloud-samples/demo-tests/demo-registry/src/main/resources/application.yaml +++ b/today-cloud-samples/demo-tests/demo-registry/src/main/resources/application.yaml @@ -1,5 +1,5 @@ server: - port: 5000 + port: 9000 web: resources: diff --git a/today-cloud-samples/demo-tests/demo-user-rest/src/main/resources/application.yaml b/today-cloud-samples/demo-tests/demo-user-rest/src/main/resources/application.yaml index 0fd8750..a4f20a0 100644 --- a/today-cloud-samples/demo-tests/demo-user-rest/src/main/resources/application.yaml +++ b/today-cloud-samples/demo-tests/demo-user-rest/src/main/resources/application.yaml @@ -5,7 +5,7 @@ infra: cloud: service-registry: - uri: http://localhost:5000 + uri: http://localhost:9000 logging: level: diff --git a/today-cloud-samples/demo-tests/demo-user-service/src/main/resources/application.yaml b/today-cloud-samples/demo-tests/demo-user-service/src/main/resources/application.yaml index 2db6060..aff40d8 100644 --- a/today-cloud-samples/demo-tests/demo-user-service/src/main/resources/application.yaml +++ b/today-cloud-samples/demo-tests/demo-user-service/src/main/resources/application.yaml @@ -8,12 +8,12 @@ infra: fail-fast: true simple: - instance-port: 9000 - uri: http://localhost:5000 + instance-port: 8080 + uri: http://localhost:9000 service: server: - port: 9000 + port: 8080 logging: level: diff --git a/today-remoting/src/main/java/infra/remoting/RemotingOperations.java b/today-remoting/src/main/java/infra/remoting/RemotingOperations.java index 863549a..69b913e 100644 --- a/today-remoting/src/main/java/infra/remoting/RemotingOperations.java +++ b/today-remoting/src/main/java/infra/remoting/RemotingOperations.java @@ -22,6 +22,9 @@ import reactor.core.publisher.Mono; /** + * Operations for performing remoting interactions including Fire-and-Forget, + * Request-Response, Request-Stream, Request-Channel, and Metadata Push. + * * @author 海子 Yang * @since 1.0 2025/8/2 23:10 */ diff --git a/today-service-registry-simple-api/build.gradle b/today-service-registry-simple-api/build.gradle index 53ed243..5f0555b 100644 --- a/today-service-registry-simple-api/build.gradle +++ b/today-service-registry-simple-api/build.gradle @@ -3,7 +3,7 @@ description = "TODAY Service Simple Registry API" dependencies { implementation project(":today-cloud-core") - implementation 'cn.taketoday:infra-starter-web' + implementation 'cn.taketoday:infra-starter-webmvc' implementation 'cn.taketoday:infra-starter-http-service' implementation 'cn.taketoday:infra-starter-restclient' diff --git a/today-service-registry-simple-discovery/build.gradle b/today-service-registry-simple-discovery/build.gradle index e8c396f..3e7dcb1 100644 --- a/today-service-registry-simple-discovery/build.gradle +++ b/today-service-registry-simple-discovery/build.gradle @@ -5,7 +5,7 @@ dependencies { api project(":today-service-discovery") api project(":today-service-registry-simple-api") - implementation 'cn.taketoday:infra-starter-web' + implementation 'cn.taketoday:infra-starter-webmvc' annotationProcessor 'cn.taketoday:infra-configuration-processor' } \ No newline at end of file diff --git a/today-service-registry-simple-registration/build.gradle b/today-service-registry-simple-registration/build.gradle index c708e43..a4a6aac 100644 --- a/today-service-registry-simple-registration/build.gradle +++ b/today-service-registry-simple-registration/build.gradle @@ -5,7 +5,7 @@ dependencies { api project(":today-service-registration") api project(":today-service-registry-simple-api") - implementation 'cn.taketoday:infra-starter-web' + implementation 'cn.taketoday:infra-starter-webmvc' annotationProcessor 'cn.taketoday:infra-configuration-processor' } \ No newline at end of file diff --git a/today-service-registry-simple-server/build.gradle b/today-service-registry-simple-server/build.gradle index e58c017..5d36598 100644 --- a/today-service-registry-simple-server/build.gradle +++ b/today-service-registry-simple-server/build.gradle @@ -5,7 +5,7 @@ dependencies { api project(":today-cloud-core") api project(":today-service-registry-simple-api") - implementation 'cn.taketoday:infra-starter-web' + implementation 'cn.taketoday:infra-starter-webmvc' annotationProcessor 'cn.taketoday:infra-configuration-processor' } \ No newline at end of file From ab0c69e103c39a353f662b264ca7b49b04a848ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Tue, 10 Mar 2026 14:16:14 +0800 Subject: [PATCH 075/104] =?UTF-8?q?:art:=20=E9=85=8D=E7=BD=AE=20demo-regis?= =?UTF-8?q?try?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../demo-registry/src/main/resources/application.yaml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/today-cloud-samples/demo-tests/demo-registry/src/main/resources/application.yaml b/today-cloud-samples/demo-tests/demo-registry/src/main/resources/application.yaml index a4bd446..7ec9d3d 100644 --- a/today-cloud-samples/demo-tests/demo-registry/src/main/resources/application.yaml +++ b/today-cloud-samples/demo-tests/demo-registry/src/main/resources/application.yaml @@ -4,6 +4,8 @@ server: web: resources: add-default-mappings: false + error: + include-message: always infra: profiles: @@ -23,3 +25,8 @@ config: app: name: demo + +logging: + level: + root: info + web: trace \ No newline at end of file From 3d0cef61f514767bbc5a724df826d177266aec51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Tue, 10 Mar 2026 14:17:15 +0800 Subject: [PATCH 076/104] =?UTF-8?q?:art:=20=E6=B3=A8=E5=86=8C=E6=A3=80?= =?UTF-8?q?=E6=9F=A5=20Service=20ID?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../simple/server/SimpleHttpServiceRegistryEndpoint.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/today-service-registry-simple-server/src/main/java/infra/cloud/registry/simple/server/SimpleHttpServiceRegistryEndpoint.java b/today-service-registry-simple-server/src/main/java/infra/cloud/registry/simple/server/SimpleHttpServiceRegistryEndpoint.java index 8929bdf..71f7948 100644 --- a/today-service-registry-simple-server/src/main/java/infra/cloud/registry/simple/server/SimpleHttpServiceRegistryEndpoint.java +++ b/today-service-registry-simple-server/src/main/java/infra/cloud/registry/simple/server/SimpleHttpServiceRegistryEndpoint.java @@ -24,6 +24,7 @@ import infra.cloud.registry.simple.api.SimpleHttpServiceRegistryAPI; import infra.http.HttpStatus; import infra.http.MediaType; +import infra.lang.Assert; import infra.logging.Logger; import infra.logging.LoggerFactory; import infra.util.CollectionUtils; @@ -69,6 +70,7 @@ public List lookup(@PathVariable String serviceId) { @POST @Override public void register(@RequestBody HttpRegistration registration) { + Assert.notNull(registration.getServiceId(), "Service ID is required"); log.info("Registering service: [{}] ", registration); serviceMapping.add(registration.getServiceId(), registration); } From c9f820c9ed9e85417b8c7b58eff274594dedf58d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Tue, 10 Mar 2026 21:16:28 +0800 Subject: [PATCH 077/104] =?UTF-8?q?:sparkles:=20=E6=89=A9=E5=B1=95?= =?UTF-8?q?=E6=9C=8D=E5=8A=A1=E5=85=83=E6=95=B0=E6=8D=AE=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E5=B1=9E=E6=80=A7=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 添加 properties 字段用于存储服务级别属性 - 新增 withProperties 方法支持不可变属性更新 - 添加 getProperty 和 hasProperty 便捷方法 - 实现带属性参数的构造函数并进行空值验证 - 更新 equals、hashCode 和 toString 方法包含属性字段 - 添加完整的 JavaDoc 注释说明类功能和用法 - 创建 ServiceMetadataTests 测试类验证功能正确性 --- .../infra/cloud/service/ServiceMetadata.java | 103 +++++++++++++++++- .../cloud/service/ServiceMetadataTests.java | 44 ++++++++ 2 files changed, 141 insertions(+), 6 deletions(-) create mode 100644 today-service-api/src/test/java/infra/cloud/service/ServiceMetadataTests.java diff --git a/today-service-api/src/main/java/infra/cloud/service/ServiceMetadata.java b/today-service-api/src/main/java/infra/cloud/service/ServiceMetadata.java index 30c5f0d..a4cf70c 100644 --- a/today-service-api/src/main/java/infra/cloud/service/ServiceMetadata.java +++ b/today-service-api/src/main/java/infra/cloud/service/ServiceMetadata.java @@ -16,12 +16,21 @@ package infra.cloud.service; +import org.jspecify.annotations.Nullable; + +import java.util.Map; import java.util.Objects; import infra.core.style.ToStringBuilder; +import infra.lang.Assert; /** - * Metadata representing a service, including its unique identifier and version. + * Represents metadata for a service artifact (e.g., a JAR file) that may contain + * one or more service interfaces. + *

              + * This class encapsulates the service's identity information including its unique identifier, + * version, and service-level properties. + *

              * * @author 海子 Yang * @since 1.0 2025/8/9 21:51 @@ -30,32 +39,113 @@ public class ServiceMetadata { private final String id; - private final String version; + private final @Nullable String version; + + private final Map properties; + + /** + * Constructs a new {@code ServiceMetadata} with the specified id and version. + * + * @param id the unique identifier of the service + * @param version the version of the service, may be {@code null} + */ + public ServiceMetadata(String id, @Nullable String version) { + this(id, version, null); + } - public ServiceMetadata(String id, String version) { + /** + * Constructs a new {@code ServiceMetadata} with the specified id, version, and properties. + * + * @param id the unique identifier of the service + * @param version the version of the service, may be {@code null} + * @param properties the properties + */ + public ServiceMetadata(String id, @Nullable String version, @Nullable Map properties) { + Assert.notNull(id, "service id is required"); this.id = id; this.version = version; + this.properties = properties == null ? Map.of() : Map.copyOf(properties); } + /** + * Returns the unique identifier of the service. + * + * @return the service ID + */ public String getId() { return id; } - public String getVersion() { + /** + * Returns the version of the service, which may be {@code null} if not specified. + * + * @return the service version, or {@code null} + */ + public @Nullable String getVersion() { return version; } + /** + * Returns the properties associated with this service artifact. + *

              + * The returned map is unmodifiable and represents a snapshot of the properties + * at construction time. This ensures thread-safety and prevents accidental modification. + *

              + * + * @return the properties map (never null) + */ + public Map getProperties() { + return properties; + } + + /** + * Creates a new {@code ServiceMetadata} instance with the specified properties, + * while retaining the current {@code id} and {@code version}. + *

              + * This method follows an immutable pattern, returning a new instance rather than + * modifying the existing one. If the provided properties map is {@code null}, + * the resulting instance will have an empty properties map. + *

              + * + * @param properties the new properties to associate with the service, may be {@code null} + * @return a new {@code ServiceMetadata} instance with the updated properties + */ + public ServiceMetadata withProperties(@Nullable Map properties) { + return new ServiceMetadata(id, version, properties); + } + + /** + * Convenience method to retrieve a specific property value. + * + * @param key the property key + * @return the property value, or {@code null} if not present + */ + public @Nullable String getProperty(String key) { + return this.properties.get(key); + } + + /** + * Checks if a property exists for the given key. + * + * @param key the property key + * @return {@code true} if the property exists, {@code false} otherwise + */ + public boolean hasProperty(String key) { + return this.properties.containsKey(key); + } + @Override public boolean equals(Object o) { if (!(o instanceof ServiceMetadata that)) return false; return Objects.equals(id, that.id) - && Objects.equals(version, that.version); + && Objects.equals(version, that.version) + && Objects.equals(properties, that.properties); } @Override public int hashCode() { - return Objects.hash(id, version); + return Objects.hash(id, version, properties); } @Override @@ -63,6 +153,7 @@ public String toString() { return ToStringBuilder.forInstance(this) .append("id", id) .append("version", version) + .append("properties", properties) .toString(); } diff --git a/today-service-api/src/test/java/infra/cloud/service/ServiceMetadataTests.java b/today-service-api/src/test/java/infra/cloud/service/ServiceMetadataTests.java new file mode 100644 index 0000000..f8e68b8 --- /dev/null +++ b/today-service-api/src/test/java/infra/cloud/service/ServiceMetadataTests.java @@ -0,0 +1,44 @@ +/* + * Copyright 2021 - 2026 the TODAY 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 + * + * https://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 infra.cloud.service; + +import org.junit.jupiter.api.Test; + +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author 海子 Yang + * @since 1.0 2026/3/10 16:17 + */ +class ServiceMetadataTests { + + @Test + void testService() { + ServiceMetadata metadata = new ServiceMetadata("test-service", "1.0"); + + ServiceMetadata withProps = metadata.withProperties(Map.of( + "env", "test" + )); + + assertThat(metadata.getProperties()).isEmpty(); + assertThat(withProps.getProperties()).hasSize(1); + + } + +} \ No newline at end of file From 626c0a70874fd1aa6c198fcd16e5ca6695fe5f79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Tue, 10 Mar 2026 21:17:13 +0800 Subject: [PATCH 078/104] =?UTF-8?q?:recycle:=20=E9=87=8D=E6=9E=84=E6=9C=8D?= =?UTF-8?q?=E5=8A=A1=E9=85=8D=E7=BD=AE=E5=B1=9E=E6=80=A7=E5=89=8D=E7=BC=80?= =?UTF-8?q?=E5=B9=B6=E4=BC=98=E5=8C=96=E4=BB=A3=E7=A0=81=E7=BB=93=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将服务提供商配置属性前缀从 service.server 修改为 today.service.server - 将服务注册配置属性前缀从 infra.cloud.service-registry 修改为 today.service-registry.simple - 重命名包路径 infra.cloud.provider.annotation.config 为 infra.cloud.provider.config - 为 ServiceProviderAutoConfiguration 类添加详细文档注释 - 为 DefaultServiceInterfaceMetadataProvider 类添加完整 JavaDoc 注释 - 为 ServerTransportFactory 接口添加详细的泛型参数和方法说明 - 为 ServiceProviderServer 类添加完整的类级别文档注释 - 移除 AutoServiceRegistration 中重复的作者标记 - 优化代码结构,提高可读性和维护性 --- ...faultServiceInterfaceMetadataProvider.java | 21 +++++++++++++++++++ .../provider/ServerTransportFactory.java | 13 ++++++++++-- .../cloud/provider/ServiceProviderServer.java | 8 +++++++ .../provider/ServiceServerProperties.java | 2 +- .../ServiceProviderAutoConfiguration.java | 8 ++++--- .../registry/AutoServiceRegistration.java | 1 - .../AutoServiceRegistrationProperties.java | 2 +- ...oServiceRegistrationAutoConfiguration.java | 2 +- .../AutoServiceRegistrationConfiguration.java | 2 +- .../registry/simple/HttpRegistration.java | 6 ++++++ .../simple/config/SimpleHttpProperties.java | 2 +- .../simple/SimpleAutoServiceRegistration.java | 8 +++++++ .../simple/SimpleRegistryProperties.java | 2 +- 13 files changed, 65 insertions(+), 12 deletions(-) rename today-service-provider/src/main/java/infra/cloud/provider/{annotation => }/config/ServiceProviderAutoConfiguration.java (95%) diff --git a/today-service-provider/src/main/java/infra/cloud/provider/DefaultServiceInterfaceMetadataProvider.java b/today-service-provider/src/main/java/infra/cloud/provider/DefaultServiceInterfaceMetadataProvider.java index 3eb5c1e..2660cb3 100644 --- a/today-service-provider/src/main/java/infra/cloud/provider/DefaultServiceInterfaceMetadataProvider.java +++ b/today-service-provider/src/main/java/infra/cloud/provider/DefaultServiceInterfaceMetadataProvider.java @@ -24,15 +24,36 @@ import infra.cloud.service.ServiceMethod; /** + * Default implementation of {@link AbstractServiceInterfaceMetadataProvider} that creates + * {@link ServiceMethod} instances for service interface methods. + * + *

              This provider is responsible for generating metadata representations of methods + * defined in service interfaces, using the underlying {@link ServiceMetadataProvider} + * to retrieve base service metadata. + * * @author 海子 Yang * @since 1.0 2025/8/20 22:12 */ public class DefaultServiceInterfaceMetadataProvider extends AbstractServiceInterfaceMetadataProvider { + /** + * Constructs a new {@code DefaultServiceInterfaceMetadataProvider} with the specified + * service metadata provider. + * + * @param serviceMetadataProvider the provider used to retrieve base service metadata + */ public DefaultServiceInterfaceMetadataProvider(ServiceMetadataProvider serviceMetadataProvider) { super(serviceMetadataProvider); } + /** + * Creates a new {@link ServiceMethod} instance for the given method of a service interface. + * + * @param serviceMetadata the base metadata of the service + * @param serviceInterface the service interface class + * @param method the method for which to create metadata + * @return a new {@code ServiceMethod} instance + */ @Override protected ServiceMethod createServiceMethod(ServiceMetadata serviceMetadata, Class serviceInterface, Method method) { return new ServiceMethod(serviceMetadata, serviceInterface, method); diff --git a/today-service-provider/src/main/java/infra/cloud/provider/ServerTransportFactory.java b/today-service-provider/src/main/java/infra/cloud/provider/ServerTransportFactory.java index 44117e0..b813450 100644 --- a/today-service-provider/src/main/java/infra/cloud/provider/ServerTransportFactory.java +++ b/today-service-provider/src/main/java/infra/cloud/provider/ServerTransportFactory.java @@ -20,8 +20,12 @@ import infra.remoting.transport.ServerTransport; /** - * ServerTransport factory + * Factory interface for creating {@link ServerTransport} instances. + *

              + * Implementations of this interface are responsible for instantiating and configuring + * server transport objects that handle incoming network connections and communication. * + * @param the type of closeable resource associated with the transport * @author 海子 Yang * @see ServerTransport * @since 1.0 2025/8/22 22:18 @@ -29,7 +33,12 @@ public interface ServerTransportFactory { /** - * Creates {@link ServerTransport} + * Creates a new {@link ServerTransport} instance. + *

              + * The returned transport is ready to accept connections and handle communication + * according to its specific implementation details. + * + * @return a new {@code ServerTransport} instance */ ServerTransport createTransport(); diff --git a/today-service-provider/src/main/java/infra/cloud/provider/ServiceProviderServer.java b/today-service-provider/src/main/java/infra/cloud/provider/ServiceProviderServer.java index 0ef539c..6f44263 100644 --- a/today-service-provider/src/main/java/infra/cloud/provider/ServiceProviderServer.java +++ b/today-service-provider/src/main/java/infra/cloud/provider/ServiceProviderServer.java @@ -31,6 +31,14 @@ import reactor.core.publisher.Mono; /** + * The {@code ServiceProviderServer} is responsible for starting and managing the lifecycle of a service provider. + * It implements {@link SmartLifecycle} to handle startup and shutdown processes, and {@link ChannelAcceptor} + * to accept incoming connections and configure the communication channel with the appropriate handler. + *

              + * This server utilizes a {@link ServiceChannelHandler} to process channels and relies on a + * {@link ServerTransportFactory} to create the underlying transport mechanism. It also supports optional + * session resumption via the {@link Resume} component. + * * @author 海子 Yang * @since 1.0 2025/8/21 22:25 */ diff --git a/today-service-provider/src/main/java/infra/cloud/provider/ServiceServerProperties.java b/today-service-provider/src/main/java/infra/cloud/provider/ServiceServerProperties.java index d326442..2f5dcc8 100644 --- a/today-service-provider/src/main/java/infra/cloud/provider/ServiceServerProperties.java +++ b/today-service-provider/src/main/java/infra/cloud/provider/ServiceServerProperties.java @@ -32,7 +32,7 @@ * @author Harry Yang * @since 1.0 2023/9/4 16:56 */ -@ConfigurationProperties("service.server") +@ConfigurationProperties("today.service.server") public class ServiceServerProperties { /** diff --git a/today-service-provider/src/main/java/infra/cloud/provider/annotation/config/ServiceProviderAutoConfiguration.java b/today-service-provider/src/main/java/infra/cloud/provider/config/ServiceProviderAutoConfiguration.java similarity index 95% rename from today-service-provider/src/main/java/infra/cloud/provider/annotation/config/ServiceProviderAutoConfiguration.java rename to today-service-provider/src/main/java/infra/cloud/provider/config/ServiceProviderAutoConfiguration.java index dec990d..104d6b8 100644 --- a/today-service-provider/src/main/java/infra/cloud/provider/annotation/config/ServiceProviderAutoConfiguration.java +++ b/today-service-provider/src/main/java/infra/cloud/provider/config/ServiceProviderAutoConfiguration.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package infra.cloud.provider.annotation.config; +package infra.cloud.provider.config; import org.jspecify.annotations.Nullable; @@ -46,13 +46,15 @@ import infra.stereotype.Component; /** + * Auto-configuration for the Service Provider. + * * @author 海子 Yang * @since 1.0 2025/8/10 22:31 */ @DisableDIAutoConfiguration @ConditionalOnDiscoveryEnabled @EnableConfigurationProperties({ InetProperties.class, ServiceServerProperties.class }) -public class ServiceProviderAutoConfiguration { +public final class ServiceProviderAutoConfiguration { @Component public static LocalServiceHolder localServiceHolder(ServiceMetadataProvider metadataProvider) { @@ -89,7 +91,7 @@ public static ResumeTokenGenerator resumeTokenGenerator() { @Component @ConditionalOnMissingBean - @ConditionalOnBooleanProperty(name = "service.server.resume.enabled", matchIfMissing = true) + @ConditionalOnBooleanProperty(name = "today.service.server.resume.enabled", matchIfMissing = true) public static Resume remotingResume(@Nullable ResumableFramesStoreFactory storeFactory, ResumeTokenGenerator resumeTokenGenerator, ServiceServerProperties properties) { ResumeProperties resume = properties.resume; diff --git a/today-service-registration/src/main/java/infra/cloud/registry/AutoServiceRegistration.java b/today-service-registration/src/main/java/infra/cloud/registry/AutoServiceRegistration.java index a71d591..5d047cc 100644 --- a/today-service-registration/src/main/java/infra/cloud/registry/AutoServiceRegistration.java +++ b/today-service-registration/src/main/java/infra/cloud/registry/AutoServiceRegistration.java @@ -23,7 +23,6 @@ * services with a service discovery system during application startup. *

              * - * @author Spencer Gibb * @author 海子 Yang */ public interface AutoServiceRegistration { diff --git a/today-service-registration/src/main/java/infra/cloud/registry/AutoServiceRegistrationProperties.java b/today-service-registration/src/main/java/infra/cloud/registry/AutoServiceRegistrationProperties.java index 801d7b0..1d58ac4 100644 --- a/today-service-registration/src/main/java/infra/cloud/registry/AutoServiceRegistrationProperties.java +++ b/today-service-registration/src/main/java/infra/cloud/registry/AutoServiceRegistrationProperties.java @@ -22,7 +22,7 @@ * @author Spencer Gibb * @author 海子 Yang */ -@ConfigurationProperties("infra.cloud.service-registry.auto-registration") +@ConfigurationProperties("today.service.auto-registration") public class AutoServiceRegistrationProperties { /** diff --git a/today-service-registration/src/main/java/infra/cloud/registry/annotation/config/AutoServiceRegistrationAutoConfiguration.java b/today-service-registration/src/main/java/infra/cloud/registry/annotation/config/AutoServiceRegistrationAutoConfiguration.java index 798182b..ce87aef 100644 --- a/today-service-registration/src/main/java/infra/cloud/registry/annotation/config/AutoServiceRegistrationAutoConfiguration.java +++ b/today-service-registration/src/main/java/infra/cloud/registry/annotation/config/AutoServiceRegistrationAutoConfiguration.java @@ -32,7 +32,7 @@ @DisableDependencyInjection @Configuration(proxyBeanMethods = false) @Import(AutoServiceRegistrationConfiguration.class) -@ConditionalOnProperty(value = "infra.cloud.service-registry.auto-registration.enabled", matchIfMissing = true) +@ConditionalOnProperty(value = "today.service.auto-registration.enabled", matchIfMissing = true) public class AutoServiceRegistrationAutoConfiguration { public AutoServiceRegistrationAutoConfiguration(@Nullable AutoServiceRegistration autoRegistration, AutoServiceRegistrationProperties properties) { diff --git a/today-service-registration/src/main/java/infra/cloud/registry/annotation/config/AutoServiceRegistrationConfiguration.java b/today-service-registration/src/main/java/infra/cloud/registry/annotation/config/AutoServiceRegistrationConfiguration.java index ef27a42..cca037c 100644 --- a/today-service-registration/src/main/java/infra/cloud/registry/annotation/config/AutoServiceRegistrationConfiguration.java +++ b/today-service-registration/src/main/java/infra/cloud/registry/annotation/config/AutoServiceRegistrationConfiguration.java @@ -27,7 +27,7 @@ */ @Configuration(proxyBeanMethods = false) @EnableConfigurationProperties(AutoServiceRegistrationProperties.class) -@ConditionalOnProperty(value = "infra.cloud.service-registry.auto-registration.enabled", matchIfMissing = true) +@ConditionalOnProperty(value = "today.service.auto-registration.enabled", matchIfMissing = true) public class AutoServiceRegistrationConfiguration { } diff --git a/today-service-registry-simple-api/src/main/java/infra/cloud/registry/simple/HttpRegistration.java b/today-service-registry-simple-api/src/main/java/infra/cloud/registry/simple/HttpRegistration.java index ac79349..41e3c53 100644 --- a/today-service-registry-simple-api/src/main/java/infra/cloud/registry/simple/HttpRegistration.java +++ b/today-service-registry-simple-api/src/main/java/infra/cloud/registry/simple/HttpRegistration.java @@ -20,6 +20,12 @@ import infra.cloud.client.Registration; /** + * HTTP based service registration implementation. + *

              + * This class extends {@link DefaultServiceInstance} and implements {@link Registration} + * to provide service registration capabilities over HTTP, including status management. + *

              + * * @author Harry Yang * @since 1.0 2023/11/20 21:59 */ diff --git a/today-service-registry-simple-api/src/main/java/infra/cloud/registry/simple/config/SimpleHttpProperties.java b/today-service-registry-simple-api/src/main/java/infra/cloud/registry/simple/config/SimpleHttpProperties.java index b88eb61..7f8d72b 100644 --- a/today-service-registry-simple-api/src/main/java/infra/cloud/registry/simple/config/SimpleHttpProperties.java +++ b/today-service-registry-simple-api/src/main/java/infra/cloud/registry/simple/config/SimpleHttpProperties.java @@ -24,7 +24,7 @@ * @author 海子 Yang * @since 1.0 2025/8/24 17:54 */ -@ConfigurationProperties(prefix = "infra.cloud.service-registry") +@ConfigurationProperties(prefix = "today.service-registry.simple") public class SimpleHttpProperties { private URI uri; diff --git a/today-service-registry-simple-registration/src/main/java/infra/cloud/registry/simple/SimpleAutoServiceRegistration.java b/today-service-registry-simple-registration/src/main/java/infra/cloud/registry/simple/SimpleAutoServiceRegistration.java index 012dff2..ca9a501 100644 --- a/today-service-registry-simple-registration/src/main/java/infra/cloud/registry/simple/SimpleAutoServiceRegistration.java +++ b/today-service-registry-simple-registration/src/main/java/infra/cloud/registry/simple/SimpleAutoServiceRegistration.java @@ -25,6 +25,14 @@ import infra.cloud.registry.ServiceRegistry; /** + * Auto-service registration implementation for the simple registry. + *

              + * This class extends {@link AbstractAutoServiceRegistration} to provide + * automatic service registration capabilities using {@link HttpRegistration} + * and {@link Status}. It utilizes {@link HttpRegistrationFactory} for creating + * registration instances and {@link SimpleRegistryProperties} for configuration. + *

              + * * @author 海子 Yang * @since 1.0 2025/8/23 21:50 */ diff --git a/today-service-registry-simple-registration/src/main/java/infra/cloud/registry/simple/SimpleRegistryProperties.java b/today-service-registry-simple-registration/src/main/java/infra/cloud/registry/simple/SimpleRegistryProperties.java index 1a5bb54..a571b51 100644 --- a/today-service-registry-simple-registration/src/main/java/infra/cloud/registry/simple/SimpleRegistryProperties.java +++ b/today-service-registry-simple-registration/src/main/java/infra/cloud/registry/simple/SimpleRegistryProperties.java @@ -24,7 +24,7 @@ * @author 海子 Yang * @since 1.0 2025/8/23 21:52 */ -@ConfigurationProperties(prefix = "infra.cloud.service-registry.simple") +@ConfigurationProperties(prefix = "today.service-registry.simple") public class SimpleRegistryProperties { private boolean enabled = true; From 50bf2f566b1d62585460d42595c2ff0c63a8b105 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Tue, 10 Mar 2026 21:17:40 +0800 Subject: [PATCH 079/104] =?UTF-8?q?:sparkles:=20=E6=9B=B4=E6=96=B0?= =?UTF-8?q?=E6=9C=8D=E5=8A=A1=E5=85=83=E6=95=B0=E6=8D=AE=E9=85=8D=E7=BD=AE?= =?UTF-8?q?=E5=92=8C=E5=8A=A0=E8=BD=BD=E6=9C=BA=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../demo-tests/demo-user-api/build.gradle | 24 ++- .../demo/service/UserServiceApplication.java | 5 +- .../src/main/resources/application.yaml | 21 +- .../PackageInfoServiceMetadataProvider.java | 179 +++++++++++++++++- 4 files changed, 213 insertions(+), 16 deletions(-) diff --git a/today-cloud-samples/demo-tests/demo-user-api/build.gradle b/today-cloud-samples/demo-tests/demo-user-api/build.gradle index d5e8a67..d04308e 100644 --- a/today-cloud-samples/demo-tests/demo-user-api/build.gradle +++ b/today-cloud-samples/demo-tests/demo-user-api/build.gradle @@ -13,4 +13,26 @@ jar { manifest.attributes["Specification-Version"] = project.version manifest.attributes["Specification-Vendor"] = 'TODAY Tech' manifest.attributes["Specification-Vendor-Id"] = 'cn.taketoday' -} \ No newline at end of file +} + +apply plugin: 'java' + +tasks.register('generateServiceMetadata') { + doLast { + def outputDir = file("$buildDir/resources/main/META-INF") + outputDir.mkdirs() + + def propsFile = new File(outputDir, 'service-metadata.properties') + def props = new Properties() + + props.setProperty('service.id', project.name) + props.setProperty('service.version', project.version.toString()) + + propsFile.withOutputStream { out -> + props.store(out, "Generated service metadata - DO NOT EDIT") + } + println "Generated service metadata: ${propsFile.absolutePath}" + } +} + +processResources.dependsOn('generateServiceMetadata') diff --git a/today-cloud-samples/demo-tests/demo-user-service/src/main/java/cn/taketoday/demo/service/UserServiceApplication.java b/today-cloud-samples/demo-tests/demo-user-service/src/main/java/cn/taketoday/demo/service/UserServiceApplication.java index 61ddc51..da99b59 100644 --- a/today-cloud-samples/demo-tests/demo-user-service/src/main/java/cn/taketoday/demo/service/UserServiceApplication.java +++ b/today-cloud-samples/demo-tests/demo-user-service/src/main/java/cn/taketoday/demo/service/UserServiceApplication.java @@ -16,9 +16,10 @@ package cn.taketoday.demo.service; -import infra.app.Application; import infra.app.InfraApplication; +import static infra.app.Application.forNormalApplication; + /** * @author Harry Yang * @since 1.0 2022/10/18 00:04 @@ -27,7 +28,7 @@ public class UserServiceApplication { public static void main(String[] args) { - Application.forNormalApplication(UserServiceApplication.class) + forNormalApplication(UserServiceApplication.class) .keepAlive() .run(args); } diff --git a/today-cloud-samples/demo-tests/demo-user-service/src/main/resources/application.yaml b/today-cloud-samples/demo-tests/demo-user-service/src/main/resources/application.yaml index aff40d8..511396b 100644 --- a/today-cloud-samples/demo-tests/demo-user-service/src/main/resources/application.yaml +++ b/today-cloud-samples/demo-tests/demo-user-service/src/main/resources/application.yaml @@ -1,19 +1,18 @@ - infra: profiles: active: dev - cloud: - service-registry: - auto-registration: - fail-fast: true - simple: - instance-port: 8080 - uri: http://localhost:9000 -service: - server: - port: 8080 +today: + service: + auto-registration: + fail-fast: true + server: + port: 8080 + + service-registry: + simple: + uri: http://localhost:9000 logging: level: diff --git a/today-service-api/src/main/java/infra/cloud/service/PackageInfoServiceMetadataProvider.java b/today-service-api/src/main/java/infra/cloud/service/PackageInfoServiceMetadataProvider.java index 78642b2..e0d74cf 100644 --- a/today-service-api/src/main/java/infra/cloud/service/PackageInfoServiceMetadataProvider.java +++ b/today-service-api/src/main/java/infra/cloud/service/PackageInfoServiceMetadataProvider.java @@ -16,20 +16,195 @@ package infra.cloud.service; +import org.jspecify.annotations.Nullable; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.util.Enumeration; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Properties; +import java.util.concurrent.ConcurrentHashMap; + +import infra.util.StringUtils; + /** - * Read ServiceMetadata from {@link Package} MANIFEST.MF file + * Reads {@link ServiceMetadata} from configuration files located in + * {@code META-INF/service-metadata.properties} on the classpath. + *

              + * This implementation supports multiple loading strategies: + *

              + *
                + *
              1. Load from {@code META-INF/service-metadata.properties} (development and production)
              2. + *
              3. Fallback to {@link Package} MANIFEST.MF if properties file is not found
              4. + *
              5. Ultimate fallback to package name if neither metadata source is available
              6. + *
              + *

              + * Metadata instances are cached per package to ensure memory efficiency and safe sharing. + *

              * * @author 海子 Yang * @since 1.0 2025/8/9 21:55 */ public class PackageInfoServiceMetadataProvider implements ServiceMetadataProvider { + public static final String DEFAULT_METADATA_LOCATION = "META-INF/service-metadata.properties"; + + public static final String KEY_SERVICE_ID = "service.id"; + public static final String KEY_SERVICE_VERSION = "service.version"; + public static final String KEY_SERVICE_GROUP = "service.group"; + public static final String KEY_SERVICE_DESCRIPTION = "service.description"; + + /** + * Cache to store ServiceMetadata instances per package. + */ + private final Map metadataCache = new ConcurrentHashMap<>(); + + private final String metadataLocation; + + /** + * Constructs a provider with the default metadata location. + */ + public PackageInfoServiceMetadataProvider() { + this(DEFAULT_METADATA_LOCATION); + } + + /** + * Constructs a provider with a custom metadata location. + * + * @param metadataLocation the classpath location of the metadata file + */ + public PackageInfoServiceMetadataProvider(String metadataLocation) { + this.metadataLocation = metadataLocation; + } + @Override public ServiceMetadata getMetadata(Class serviceInterface) { + return metadataCache.computeIfAbsent(getCacheKey(serviceInterface), key -> loadMetadata(serviceInterface)); + } + + /** + * Loads metadata for the given service interface. + *

              + * Loading strategy: + * 1. Try to load from properties file + * 2. Fallback to Package MANIFEST.MF + * 3. Ultimate fallback to package name + *

              + * + * @param serviceInterface the service interface class + * @return a ServiceMetadata instance (never null) + */ + protected ServiceMetadata loadMetadata(Class serviceInterface) { + Properties props = loadProperties(serviceInterface); + if (props != null) { + return createMetadataFromProperties(props); + } + Package servicePackage = serviceInterface.getPackage(); String specificationTitle = servicePackage.getSpecificationTitle(); String specificationVersion = servicePackage.getSpecificationVersion(); - return new ServiceMetadata(specificationTitle, specificationVersion); + + if (specificationTitle != null && !specificationTitle.isBlank()) { + return new ServiceMetadata(specificationTitle, specificationVersion); + } + + String packageName = serviceInterface.getPackageName(); + return new ServiceMetadata(packageName, null); + } + + /** + * Loads properties from the metadata file. + * + * @param serviceInterface the service interface class + * @return loaded properties, or empty map if not found + */ + protected @Nullable Properties loadProperties(Class serviceInterface) { + try { + ClassLoader classLoader = serviceInterface.getClassLoader(); + if (classLoader == null) { + classLoader = ClassLoader.getSystemClassLoader(); + } + + Enumeration urls = classLoader.getResources(metadataLocation); + while (urls.hasMoreElements()) { + URL url = urls.nextElement(); + try (InputStream input = url.openStream()) { + Properties props = new Properties(); + props.load(input); + + // 验证是否包含必需的 service.id + String serviceId = props.getProperty(KEY_SERVICE_ID); + if (StringUtils.hasText(serviceId)) { + return props; + } + } + } + } + catch (IOException ex) { + // 静默失败,降级到其他策略 + } + + return null; + } + + /** + * Creates ServiceMetadata from loaded properties. + * + * @param props the loaded properties + * @return a new ServiceMetadata instance + */ + protected ServiceMetadata createMetadataFromProperties(Properties props) { + String serviceId = props.getProperty(KEY_SERVICE_ID); + String version = props.getProperty(KEY_SERVICE_VERSION); + + Map metadata = new LinkedHashMap<>(); + + addPropertyIfPresent(metadata, props, KEY_SERVICE_DESCRIPTION); + addPropertyIfPresent(metadata, props, KEY_SERVICE_GROUP); + + return new ServiceMetadata(serviceId, version, metadata); + } + + /** + * Helper method to add a property if it's present. + */ + private void addPropertyIfPresent(Map metadata, Properties props, String key) { + String value = props.getProperty(key); + if (value != null && !value.isBlank()) { + metadata.put(key.substring(key.indexOf('.') + 1), value); + } + } + + /** + * Generates a cache key for the given service interface. + *

              + * Using the package name as the key ensures that all service interfaces + * within the same package share the same ServiceMetadata. + *

              + * + * @param serviceInterface the service interface class + * @return the cache key (package name) + */ + protected String getCacheKey(Class serviceInterface) { + return serviceInterface.getPackageName(); + } + + /** + * Clears the internal cache. + */ + public void clearCache() { + metadataCache.clear(); + } + + /** + * Returns the number of cached metadata entries. + * + * @return the number of cached service metadata instances + */ + public int getCacheSize() { + return metadataCache.size(); } } From 9d7f01a1f56a1dd04da8ed80d4da4d405975225a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Wed, 11 Mar 2026 23:32:45 +0800 Subject: [PATCH 080/104] =?UTF-8?q?:sparkles:=20=E6=B7=BB=E5=8A=A0Gradle?= =?UTF-8?q?=E6=8F=92=E4=BB=B6=E5=92=8C=E6=9C=8D=E5=8A=A1=E5=85=83=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E7=94=9F=E6=88=90=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在cloud-module.gradle中添加LICENSE和NOTICE文件到JAR包 - 集成signing.gradle用于发布时的签名功能 - 简化publications.gradle中的发布配置 - 在build.gradle中添加版本判断和项目过滤逻辑 - 新增today-cloud-gradle-plugin模块及其相关类 - 添加CloudApplicationExtension和ServiceMetadataExtension扩展 - 实现GenerateServiceMetadata任务生成服务元数据 - 在demo-user-api中应用新的云应用插件 - 移除旧的服务注册配置并使用新配置方式 --- build.gradle | 18 +++- gradle/cloud-module.gradle | 9 ++ gradle/publications.gradle | 96 ++++++++----------- gradle/signing.gradle | 13 +++ settings.gradle | 9 +- .../today-cloud-gradle-plugin/build.gradle | 30 ++++++ .../plugin/CloudApplicationExtension.java | 35 +++++++ .../cloud/plugin/GenerateServiceMetadata.java | 94 ++++++++++++++++++ .../infra/cloud/plugin/InfraCloudPlugin.java | 56 +++++++++++ .../java/infra/cloud/plugin/ModuleType.java | 27 ++++++ .../plugin/ServiceMetadataExtension.java | 88 +++++++++++++++++ .../java/infra/cloud/plugin/package-info.java | 23 +++++ .../demo-tests/demo-registry/build.gradle | 16 ---- .../demo-tests/demo-user-api/build.gradle | 24 +---- .../src/main/resources/application.yaml | 9 +- today-cloud-samples/settings.gradle | 40 ++++++++ today-service-api/build.gradle | 2 +- today-service-client/build.gradle | 2 +- today-service-discovery/build.gradle | 2 +- 19 files changed, 480 insertions(+), 113 deletions(-) create mode 100644 gradle/signing.gradle create mode 100644 today-cloud-build/today-cloud-gradle-plugin/build.gradle create mode 100644 today-cloud-build/today-cloud-gradle-plugin/src/main/java/infra/cloud/plugin/CloudApplicationExtension.java create mode 100644 today-cloud-build/today-cloud-gradle-plugin/src/main/java/infra/cloud/plugin/GenerateServiceMetadata.java create mode 100644 today-cloud-build/today-cloud-gradle-plugin/src/main/java/infra/cloud/plugin/InfraCloudPlugin.java create mode 100644 today-cloud-build/today-cloud-gradle-plugin/src/main/java/infra/cloud/plugin/ModuleType.java create mode 100644 today-cloud-build/today-cloud-gradle-plugin/src/main/java/infra/cloud/plugin/ServiceMetadataExtension.java create mode 100644 today-cloud-build/today-cloud-gradle-plugin/src/main/java/infra/cloud/plugin/package-info.java create mode 100644 today-cloud-samples/settings.gradle diff --git a/build.gradle b/build.gradle index cf70453..c9ce304 100644 --- a/build.gradle +++ b/build.gradle @@ -4,19 +4,33 @@ plugins { } ext { + isSnapshot = version.endsWith('SNAPSHOT') + isReleaseVersion = !isSnapshot + configProjects = [project(":today-cloud-bom"), project(":today-cloud-dependencies")] javaProjects = subprojects - configProjects samplesProjects = subprojects.findAll { it.path.startsWith(":today-cloud-samples") } - moduleProjects = javaProjects - samplesProjects + moduleProjects = javaProjects - samplesProjects - [ + project(":today-cloud-build"), + ] } configure(allprojects) { group = "cn.taketoday.cloud" + if (it.hasProperty("skipDocs")) { + it.afterEvaluate { + it.getTasks().matching(task -> { + return JavaBasePlugin.DOCUMENTATION_GROUP == task.getGroup() + || "distribution" == task.getGroup() + }).forEach(task -> task.setEnabled(false)) + } + } + repositories { mavenLocal() mavenCentral() - if (version.endsWith('-SNAPSHOT')) { + if (isSnapshot) { maven { url = "https://central.sonatype.com/repository/maven-snapshots/" } maven { url "https://repo.spring.io/milestone" } maven { url "https://repo.spring.io/snapshot" } diff --git a/gradle/cloud-module.gradle b/gradle/cloud-module.gradle index b6baa89..0ca5712 100644 --- a/gradle/cloud-module.gradle +++ b/gradle/cloud-module.gradle @@ -19,6 +19,13 @@ jar { manifest.attributes["Automatic-Module-Name"] = project.name.replace('-', '.') // for Jigsaw manifest.attributes["Created-By"] = "${System.getProperty("java.version")} (${System.getProperty("java.specification.vendor")})" + + from("${rootDir}") { + include "LICENSE" + include "NOTICE" + into "META-INF" + expand(copyright: new Date().format("yyyy"), version: project.version) + } } normalization { @@ -70,6 +77,8 @@ publishing { } } +apply from: "$rootDir/gradle/signing.gradle" + // Disable publication of test fixture artifacts. if (configurations.findByName("testFixturesApiElements") != null) { components.java.withVariantsFromConfiguration(configurations.testFixturesApiElements) { skip() } diff --git a/gradle/publications.gradle b/gradle/publications.gradle index ed7fd9a..b7f8cb1 100644 --- a/gradle/publications.gradle +++ b/gradle/publications.gradle @@ -1,67 +1,47 @@ apply plugin: "signing" apply plugin: "maven-publish" -String repoUsername = System.getProperty("repoUsername") -String repoPassword = System.getProperty("repoPassword") - -publishing { - publications { - mavenJava(MavenPublication) { - pom { - afterEvaluate { - name = project.name - description = project.description - } - url = "https://github.com/today-tech/today-cloud" - organization { - name = "TODAY Tech" - url = "https://taketoday.cn" - } - licenses { - license { - name = 'The Apache License, Version 2.0' - url = 'https://www.apache.org/licenses/LICENSE-2.0.txt' - distribution = "repo" - } - } - scm { - url = "https://github.com/today-tech/today-cloud.git" - connection = "scm:git:git://github.com/today-tech/today-cloud" - developerConnection = "scm:git:git://github.com/today-tech/today-cloud" - } - developers { - developer { - id = "taketoday" - name = "Harry Yang" - email = "taketoday@foxmail.com" - } - } - issueManagement { - system = "GitHub" - url = "https://github.com/today-tech/today-cloud/issues" - } +publishing.publications.withType(MavenPublication.class) { + pom { + afterEvaluate { + name = project.name + description = project.description + } + url = "https://github.com/today-tech/today-cloud" + organization { + name = "TODAY Tech" + url = "https://taketoday.cn" + } + licenses { + license { + name = 'The Apache License, Version 2.0' + url = 'https://www.apache.org/licenses/LICENSE-2.0.txt' + distribution = "repo" } - versionMapping { - usage('java-api') { - fromResolutionResult() - } - usage('java-runtime') { - fromResolutionResult() - } + } + scm { + url = "https://github.com/today-tech/today-cloud.git" + connection = "scm:git:git://github.com/today-tech/today-cloud" + developerConnection = "scm:git:git://github.com/today-tech/today-cloud" + } + developers { + developer { + id = "taketoday" + name = "Harry Yang" + email = "taketoday@foxmail.com" } } + issueManagement { + system = "GitHub" + url = "https://github.com/today-tech/today-cloud/issues" + } } - - repositories { - maven { - url = version.endsWith('SNAPSHOT') - ? 'https://oss.sonatype.org/content/repositories/snapshots/' - : 'https://oss.sonatype.org/service/local/staging/deploy/maven2/' - - credentials { - username = repoUsername - password = repoPassword - } + versionMapping { + usage('java-api') { + fromResolutionResult() + } + usage('java-runtime') { + fromResolutionResult() } } -} +} \ No newline at end of file diff --git a/gradle/signing.gradle b/gradle/signing.gradle new file mode 100644 index 0000000..ce4517e --- /dev/null +++ b/gradle/signing.gradle @@ -0,0 +1,13 @@ + +if (isReleaseVersion) { + apply plugin: "signing" + + signing { + def signingKey = findProperty("signing.key") + def signingKeyId = findProperty("signing.keyId") + def signingPassword = findProperty("signing.password") + useInMemoryPgpKeys(signingKeyId, signingKey, signingPassword) + + sign(publishing.publications) + } +} diff --git a/settings.gradle b/settings.gradle index ec54479..21ef18a 100644 --- a/settings.gradle +++ b/settings.gradle @@ -48,11 +48,4 @@ include 'today-remoting-transport-tcp' include 'today-remoting-transport-local' include 'today-remoting-transport-websocket' -// Samples - -include 'today-cloud-samples:demo-tests:demo-registry' -include 'today-cloud-samples:demo-tests:demo-user-api' -include 'today-cloud-samples:demo-tests:demo-user-rest' -include 'today-cloud-samples:demo-tests:demo-user-service' -include 'today-cloud-samples:today-petclinic' - +include 'today-cloud-build:today-cloud-gradle-plugin' diff --git a/today-cloud-build/today-cloud-gradle-plugin/build.gradle b/today-cloud-build/today-cloud-gradle-plugin/build.gradle new file mode 100644 index 0000000..4343fbb --- /dev/null +++ b/today-cloud-build/today-cloud-gradle-plugin/build.gradle @@ -0,0 +1,30 @@ +plugins { + id "java-gradle-plugin" +// id "com.gradle.plugin-publish" version "1.3.1" +} + +description = "TODAY Cloud Applications Gradle Plugins" + +dependencies { + api 'cn.taketoday:infra-core' + + optional "org.graalvm.buildtools:native-gradle-plugin" + implementation 'org.apache.commons:commons-compress' + implementation 'io.spring.gradle:dependency-management-plugin' +} + +gradlePlugin { + automatedPublishing = true + website = "https://github.com/today-tech/today-cloud" + vcsUrl = "https://github.com/today-tech/today-cloud" + plugins { + todayCloudPlugin { + id = "today.cloud-application" + tags.set(['cloud', 'application']) + displayName = "TODAY Cloud Applications Gradle Plugin" + description = "TODAY Cloud Applications Gradle Plugin" + implementationClass = "infra.cloud.plugin.InfraCloudPlugin" + } + } +} + diff --git a/today-cloud-build/today-cloud-gradle-plugin/src/main/java/infra/cloud/plugin/CloudApplicationExtension.java b/today-cloud-build/today-cloud-gradle-plugin/src/main/java/infra/cloud/plugin/CloudApplicationExtension.java new file mode 100644 index 0000000..410d3c7 --- /dev/null +++ b/today-cloud-build/today-cloud-gradle-plugin/src/main/java/infra/cloud/plugin/CloudApplicationExtension.java @@ -0,0 +1,35 @@ +/* + * Copyright 2021 - 2026 the TODAY 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 + * + * https://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 infra.cloud.plugin; + +import org.gradle.api.Project; +import org.gradle.api.provider.Property; +import org.gradle.api.tasks.Input; + +/** + * @author 海子 Yang + * @since 1.0 2026/3/10 22:50 + */ +public abstract class CloudApplicationExtension { + + public CloudApplicationExtension(Project project) { + } + + @Input + public abstract Property getServiceModuleType(); + +} diff --git a/today-cloud-build/today-cloud-gradle-plugin/src/main/java/infra/cloud/plugin/GenerateServiceMetadata.java b/today-cloud-build/today-cloud-gradle-plugin/src/main/java/infra/cloud/plugin/GenerateServiceMetadata.java new file mode 100644 index 0000000..7dc8d7a --- /dev/null +++ b/today-cloud-build/today-cloud-gradle-plugin/src/main/java/infra/cloud/plugin/GenerateServiceMetadata.java @@ -0,0 +1,94 @@ +/* + * Copyright 2021 - 2026 the TODAY 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 + * + * https://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 infra.cloud.plugin; + +import org.gradle.api.DefaultTask; +import org.gradle.api.Project; +import org.gradle.api.provider.Provider; +import org.gradle.api.tasks.TaskAction; +import org.gradle.work.DisableCachingByDefault; +import org.jspecify.annotations.Nullable; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Properties; + +import infra.util.CollectionUtils; + +/** + * @author 海子 Yang + * @since 1.0 2026/3/10 21:59 + */ +@DisableCachingByDefault(because = "Not worth caching") +public abstract class GenerateServiceMetadata extends DefaultTask { + + @TaskAction + public void generate() throws IOException { + Project project = getProject(); + ServiceMetadataExtension serviceMetadata = project.getExtensions().getByType(ServiceMetadataExtension.class); + + var outputDir = project.getLayout().getBuildDirectory().dir("resources/main/META-INF").get().getAsFile(); + File propertiesFile = new File(outputDir, "service-metadata.properties"); + createFileIfNecessary(propertiesFile); + + Properties properties = CollectionUtils.createSortedProperties(true); + + properties.setProperty("service.id", serviceMetadata.getServiceId().get()); + properties.setProperty("service.version", serviceMetadata.getServiceVersion().get()); + + convertToStringValues(serviceMetadata.getAdditional().get()) + .forEach((name, value) -> { + if (value != null) { + properties.put("service." + name, value); + } + }); + + try (FileOutputStream outputStream = new FileOutputStream(propertiesFile)) { + properties.store(outputStream, "Generated service metadata - DO NOT EDIT"); + } + + } + + private void createFileIfNecessary(File file) throws IOException { + if (file.exists()) { + return; + } + File parent = file.getParentFile(); + if (!parent.isDirectory() && !parent.mkdirs()) { + throw new IllegalStateException( + "Cannot create parent directory for '" + file.getAbsolutePath() + "'"); + } + if (!file.createNewFile()) { + throw new IllegalStateException("Cannot create target file '" + file.getAbsolutePath() + "'"); + } + } + + private Map convertToStringValues(Map input) { + Map output = new LinkedHashMap<>(); + input.forEach((key, value) -> { + if (value instanceof Provider provider) { + value = provider.getOrNull(); + } + output.put(key, value != null ? value.toString() : null); + }); + return output; + } + +} diff --git a/today-cloud-build/today-cloud-gradle-plugin/src/main/java/infra/cloud/plugin/InfraCloudPlugin.java b/today-cloud-build/today-cloud-gradle-plugin/src/main/java/infra/cloud/plugin/InfraCloudPlugin.java new file mode 100644 index 0000000..ed62f10 --- /dev/null +++ b/today-cloud-build/today-cloud-gradle-plugin/src/main/java/infra/cloud/plugin/InfraCloudPlugin.java @@ -0,0 +1,56 @@ +/* + * Copyright 2021 - 2026 the TODAY 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 + * + * https://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 infra.cloud.plugin; + +import org.gradle.api.Plugin; +import org.gradle.api.Project; +import org.gradle.api.plugins.BasePlugin; +import org.gradle.api.plugins.JavaLibraryPlugin; +import org.gradle.api.plugins.JavaPlugin; +import org.gradle.api.tasks.TaskContainer; + +/** + * @author 海子 Yang + * @since 1.0 2026/3/10 21:31 + */ +public class InfraCloudPlugin implements Plugin { + + public static final String GENERATE_SERVICE_METADATA_TASK_NAME = "generateServiceMetadata"; + + @Override + public void apply(Project project) { + project.getPlugins().apply(JavaPlugin.class); + project.getPlugins().apply(JavaLibraryPlugin.class); + + TaskContainer tasks = project.getTasks(); + createExtensions(project); + + tasks.register(GENERATE_SERVICE_METADATA_TASK_NAME, GenerateServiceMetadata.class, task -> { + task.setGroup(BasePlugin.BUILD_GROUP); + task.setDescription("Generates a service-metadata.properties file."); + }); + + tasks.getByName(JavaPlugin.PROCESS_RESOURCES_TASK_NAME) + .dependsOn(GENERATE_SERVICE_METADATA_TASK_NAME); + } + + private void createExtensions(Project project) { + project.getExtensions().create("serviceMetadata", ServiceMetadataExtension.class, project); + project.getExtensions().create("cloudApplication", CloudApplicationExtension.class, project); + } + +} diff --git a/today-cloud-build/today-cloud-gradle-plugin/src/main/java/infra/cloud/plugin/ModuleType.java b/today-cloud-build/today-cloud-gradle-plugin/src/main/java/infra/cloud/plugin/ModuleType.java new file mode 100644 index 0000000..c9456a7 --- /dev/null +++ b/today-cloud-build/today-cloud-gradle-plugin/src/main/java/infra/cloud/plugin/ModuleType.java @@ -0,0 +1,27 @@ +/* + * Copyright 2021 - 2026 the TODAY 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 + * + * https://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 infra.cloud.plugin; + +/** + * @author 海子 Yang + * @since 1.0 2026/3/10 22:51 + */ +public enum ModuleType { + SERVICE_API, + + SERVICE_IMPLEMENTATION, +} diff --git a/today-cloud-build/today-cloud-gradle-plugin/src/main/java/infra/cloud/plugin/ServiceMetadataExtension.java b/today-cloud-build/today-cloud-gradle-plugin/src/main/java/infra/cloud/plugin/ServiceMetadataExtension.java new file mode 100644 index 0000000..09509cc --- /dev/null +++ b/today-cloud-build/today-cloud-gradle-plugin/src/main/java/infra/cloud/plugin/ServiceMetadataExtension.java @@ -0,0 +1,88 @@ +/* + * Copyright 2021 - 2026 the TODAY 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 + * + * https://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 infra.cloud.plugin; + +import org.gradle.api.Project; +import org.gradle.api.provider.MapProperty; +import org.gradle.api.provider.Property; +import org.gradle.api.tasks.Input; +import org.gradle.api.tasks.Optional; + +import java.io.Serializable; + +/** + * Extension for configuring service metadata in a Gradle project. + *

              + * This class holds metadata such as the service ID, version, and additional custom properties. + * It is designed to be used within a Gradle plugin to manage service-related configuration. + * + * @author 海子 Yang + * @since 1.0 2026/3/10 21:41 + */ +public abstract class ServiceMetadataExtension implements Serializable { + + /** + * Creates a new {@code ServiceMetadataExtension} associated with the given {@code project}. + *

              + * The service ID is defaulted to the project name, and the service version is defaulted + * to the project's version string. + * + * @param project the Gradle project to associate with this extension + */ + public ServiceMetadataExtension(Project project) { + getServiceId().convention(project.provider(project::getName)); + getDescription().convention(project.provider(project::getDescription)); + getServiceVersion().convention(project.provider(() -> project.getVersion().toString())); + } + + /** + * Gets the property representing the unique identifier of the service. + *

              + * This property is marked as an input for Gradle's up-to-date checks. + * + * @return the service ID property + */ + @Input + @Optional + public abstract Property getServiceId(); + + /** + * Gets the property representing the version of the service. + *

              + * This property is optional and marked as an input for Gradle's up-to-date checks. + * + * @return the service version property, or null if not set + */ + @Input + @Optional + public abstract Property getServiceVersion(); + + @Input + @Optional + public abstract Property getDescription(); + + /** + * Gets the map property for storing additional custom metadata. + *

              + * This property is internal and not considered for Gradle's up-to-date checks. + * + * @return the map of additional metadata + */ + @Optional + public abstract MapProperty getAdditional(); + +} diff --git a/today-cloud-build/today-cloud-gradle-plugin/src/main/java/infra/cloud/plugin/package-info.java b/today-cloud-build/today-cloud-gradle-plugin/src/main/java/infra/cloud/plugin/package-info.java new file mode 100644 index 0000000..cda2a6a --- /dev/null +++ b/today-cloud-build/today-cloud-gradle-plugin/src/main/java/infra/cloud/plugin/package-info.java @@ -0,0 +1,23 @@ +/* + * Copyright 2021 - 2026 the TODAY 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 + * + * https://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. + */ + +/** + * Central classes for the Infra Cloud Gradle plugin. + */ +@NullMarked +package infra.cloud.plugin; + +import org.jspecify.annotations.NullMarked; \ No newline at end of file diff --git a/today-cloud-samples/demo-tests/demo-registry/build.gradle b/today-cloud-samples/demo-tests/demo-registry/build.gradle index 56b821b..ed48132 100644 --- a/today-cloud-samples/demo-tests/demo-registry/build.gradle +++ b/today-cloud-samples/demo-tests/demo-registry/build.gradle @@ -1,19 +1,3 @@ -/* - * Copyright 2021 - 2026 the TODAY 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 - * - * https://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. - */ - description = "Demo Service Registry" apply plugin: "infra.application" diff --git a/today-cloud-samples/demo-tests/demo-user-api/build.gradle b/today-cloud-samples/demo-tests/demo-user-api/build.gradle index d04308e..5939e37 100644 --- a/today-cloud-samples/demo-tests/demo-user-api/build.gradle +++ b/today-cloud-samples/demo-tests/demo-user-api/build.gradle @@ -1,5 +1,7 @@ description = "Demo User API" +apply plugin: "today.cloud-application" + dependencies { implementation 'cn.taketoday:infra-context' @@ -14,25 +16,3 @@ jar { manifest.attributes["Specification-Vendor"] = 'TODAY Tech' manifest.attributes["Specification-Vendor-Id"] = 'cn.taketoday' } - -apply plugin: 'java' - -tasks.register('generateServiceMetadata') { - doLast { - def outputDir = file("$buildDir/resources/main/META-INF") - outputDir.mkdirs() - - def propsFile = new File(outputDir, 'service-metadata.properties') - def props = new Properties() - - props.setProperty('service.id', project.name) - props.setProperty('service.version', project.version.toString()) - - propsFile.withOutputStream { out -> - props.store(out, "Generated service metadata - DO NOT EDIT") - } - println "Generated service metadata: ${propsFile.absolutePath}" - } -} - -processResources.dependsOn('generateServiceMetadata') diff --git a/today-cloud-samples/demo-tests/demo-user-rest/src/main/resources/application.yaml b/today-cloud-samples/demo-tests/demo-user-rest/src/main/resources/application.yaml index a4f20a0..bc47f05 100644 --- a/today-cloud-samples/demo-tests/demo-user-rest/src/main/resources/application.yaml +++ b/today-cloud-samples/demo-tests/demo-user-rest/src/main/resources/application.yaml @@ -3,10 +3,6 @@ infra: profiles: active: dev - cloud: - service-registry: - uri: http://localhost:9000 - logging: level: root: info @@ -21,3 +17,8 @@ server: quiet-period: 0 unit: seconds timeout: 2 + +today: + service-registry: + simple: + uri: http://localhost:9000 diff --git a/today-cloud-samples/settings.gradle b/today-cloud-samples/settings.gradle new file mode 100644 index 0000000..3d9de28 --- /dev/null +++ b/today-cloud-samples/settings.gradle @@ -0,0 +1,40 @@ +pluginManagement { + repositories { + mavenLocal() + mavenCentral() + gradlePluginPortal() + } +} + +rootProject.name = 'today-cloud-samples' + +include 'demo-tests:demo-registry' +include 'demo-tests:demo-user-api' +include 'demo-tests:demo-user-rest' +include 'demo-tests:demo-user-service' +include 'today-petclinic' + +// 引用主项目以访问其模块 +includeBuild('../') { + dependencySubstitution { + substitute module('cn.taketoday.cloud:today-cloud-bom') using project(':today-cloud-bom') + substitute module('cn.taketoday.cloud:today-cloud-dependencies') using project(':today-cloud-dependencies') + substitute module('cn.taketoday.cloud:today-cloud-core') using project(':today-cloud-core') + substitute module('cn.taketoday.cloud:today-service-api') using project(':today-service-api') + substitute module('cn.taketoday.cloud:today-service-client') using project(':today-service-client') + substitute module('cn.taketoday.cloud:today-service-provider') using project(':today-service-provider') + substitute module('cn.taketoday.cloud:today-service-discovery') using project(':today-service-discovery') + substitute module('cn.taketoday.cloud:today-service-registration') using project(':today-service-registration') + substitute module('cn.taketoday.cloud:today-service-serialization') using project(':today-service-serialization') + substitute module('cn.taketoday.cloud:today-service-registry-simple-api') using project(':today-service-registry-simple-api') + substitute module('cn.taketoday.cloud:today-service-registry-simple-server') using project(':today-service-registry-simple-server') + substitute module('cn.taketoday.cloud:today-service-registry-simple-discovery') using project(':today-service-registry-simple-discovery') + substitute module('cn.taketoday.cloud:today-service-registry-simple-registration') using project(':today-service-registry-simple-registration') + substitute module('cn.taketoday.cloud:today-remoting') using project(':today-remoting') + substitute module('cn.taketoday.cloud:today-remoting-micrometer') using project(':today-remoting-micrometer') + substitute module('cn.taketoday.cloud:today-remoting-transport-tcp') using project(':today-remoting-transport-tcp') + substitute module('cn.taketoday.cloud:today-remoting-transport-local') using project(':today-remoting-transport-local') + substitute module('cn.taketoday.cloud:today-remoting-transport-websocket') using project(':today-remoting-transport-websocket') + substitute module('cn.taketoday.cloud:today-cloud-build:today-cloud-gradle-plugin') using project(':today-cloud-build:today-cloud-gradle-plugin') + } +} diff --git a/today-service-api/build.gradle b/today-service-api/build.gradle index 62d881a..9fbc979 100644 --- a/today-service-api/build.gradle +++ b/today-service-api/build.gradle @@ -11,5 +11,5 @@ dependencies { optional "com.google.protobuf:protobuf-java" - testImplementation project(":today-cloud-samples:demo-tests:demo-user-api") +// testImplementation project(":today-cloud-samples:demo-tests:demo-user-api") } \ No newline at end of file diff --git a/today-service-client/build.gradle b/today-service-client/build.gradle index a59dbc6..36e049c 100644 --- a/today-service-client/build.gradle +++ b/today-service-client/build.gradle @@ -11,6 +11,6 @@ dependencies { optional project(":today-remoting-transport-tcp") testImplementation "cn.taketoday:infra-app-test" - testImplementation project(":today-cloud-samples:demo-tests:demo-user-api") +// testImplementation project(":today-cloud-samples:demo-tests:demo-user-api") } \ No newline at end of file diff --git a/today-service-discovery/build.gradle b/today-service-discovery/build.gradle index a0dded1..4074e82 100644 --- a/today-service-discovery/build.gradle +++ b/today-service-discovery/build.gradle @@ -7,6 +7,6 @@ dependencies { implementation 'cn.taketoday:infra-context' testImplementation 'cn.taketoday:infra-app-test' - testImplementation project(":today-cloud-samples:demo-tests:demo-user-api") +// testImplementation project(":today-cloud-samples:demo-tests:demo-user-api") } \ No newline at end of file From 6d76fecd9621781a012b6cf07e8ee15f72b2412c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Sun, 15 Mar 2026 18:48:57 +0800 Subject: [PATCH 081/104] =?UTF-8?q?:recycle:=20=E9=87=8D=E6=9E=84=E9=A1=B9?= =?UTF-8?q?=E7=9B=AE=E7=BB=93=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .run/ClientApplication.run.xml | 2 +- .run/RegistryApplication.run.xml | 2 +- .run/UserServiceApplication.run.xml | 2 +- build.gradle | 2 +- gradle/cloud-module.gradle | 4 +- settings.gradle | 4 - today-cloud-bom/build.gradle | 5 +- .../today-cloud-gradle-plugin/build.gradle | 1 + .../infra/cloud/plugin/InfraCloudPlugin.java | 16 ++ today-cloud-dependencies/build.gradle | 18 +- today-cloud-samples/.gitignore | 24 ++ today-cloud-samples/build.gradle | 36 +-- today-cloud-samples/buildSrc/build.gradle | 26 ++ .../buildSrc/gradle.properties | 1 + .../buildSrc/settings.gradle | 0 today-cloud-samples/demo-tests/build.gradle | 5 + .../demo-tests/demo-registry/build.gradle | 10 +- .../demo-tests/demo-user-api/build.gradle | 4 + .../demo-tests/demo-user-rest/build.gradle | 4 +- .../demo-tests/demo-user-service/build.gradle | 8 +- today-cloud-samples/gradle.properties | 6 + .../gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 48966 bytes .../gradle/wrapper/gradle-wrapper.properties | 7 + today-cloud-samples/gradlew | 248 ++++++++++++++++++ today-cloud-samples/gradlew.bat | 93 +++++++ today-cloud-samples/settings.gradle | 36 +-- .../build.gradle | 2 +- .../registry/simple/HttpRegistration.java | 0 .../infra/cloud/registry/simple/Status.java | 0 .../api/SimpleHttpServiceRegistryAPI.java | 0 .../simple/config/SimpleHttpProperties.java | 0 ...tpServiceRegistryAPIAutoConfiguration.java | 0 ...nnotation.config.AutoConfiguration.imports | 0 .../main/resources/META-INF/today.strategies | 0 .../build.gradle | 2 +- .../discovery/SimpleHttpDiscoveryClient.java | 0 ...eHttpDiscoveryClientAutoConfiguration.java | 0 ...nnotation.config.AutoConfiguration.imports | 0 .../build.gradle | 2 +- .../simple/HttpRegistrationFactory.java | 0 .../simple/SimpleAutoServiceRegistration.java | 0 .../simple/SimpleHttpServiceRegistry.java | 0 .../simple/SimpleRegistryProperties.java | 0 ...eHttpServiceRegistryAutoConfiguration.java | 0 ...nnotation.config.AutoConfiguration.imports | 0 .../main/resources/META-INF/today.strategies | 0 .../build.gradle | 2 +- .../server/ServiceNotFoundException.java | 0 .../SimpleHttpServiceRegistryEndpoint.java | 0 ...erviceRegistryServerAutoConfiguration.java | 0 ...ditional-infra-configuration-metadata.json | 0 ...nnotation.config.AutoConfiguration.imports | 0 .../main/resources/META-INF/today.strategies | 0 ...nnotation.config.AutoConfiguration.imports | 2 +- 54 files changed, 499 insertions(+), 75 deletions(-) create mode 100644 today-cloud-samples/.gitignore create mode 100644 today-cloud-samples/buildSrc/build.gradle create mode 100644 today-cloud-samples/buildSrc/gradle.properties rename today-service-registry-simple-api/src/main/resources/META-INF/today.strategies => today-cloud-samples/buildSrc/settings.gradle (100%) create mode 100644 today-cloud-samples/gradle.properties create mode 100644 today-cloud-samples/gradle/wrapper/gradle-wrapper.jar create mode 100644 today-cloud-samples/gradle/wrapper/gradle-wrapper.properties create mode 100755 today-cloud-samples/gradlew create mode 100644 today-cloud-samples/gradlew.bat rename {today-service-registry-simple-api => today-cloud-samples/today-service-registry-simple-api}/build.gradle (86%) rename {today-service-registry-simple-api => today-cloud-samples/today-service-registry-simple-api}/src/main/java/infra/cloud/registry/simple/HttpRegistration.java (100%) rename {today-service-registry-simple-api => today-cloud-samples/today-service-registry-simple-api}/src/main/java/infra/cloud/registry/simple/Status.java (100%) rename {today-service-registry-simple-api => today-cloud-samples/today-service-registry-simple-api}/src/main/java/infra/cloud/registry/simple/api/SimpleHttpServiceRegistryAPI.java (100%) rename {today-service-registry-simple-api => today-cloud-samples/today-service-registry-simple-api}/src/main/java/infra/cloud/registry/simple/config/SimpleHttpProperties.java (100%) rename {today-service-registry-simple-api => today-cloud-samples/today-service-registry-simple-api}/src/main/java/infra/cloud/registry/simple/config/SimpleHttpServiceRegistryAPIAutoConfiguration.java (100%) rename {today-service-registry-simple-api => today-cloud-samples/today-service-registry-simple-api}/src/main/resources/META-INF/config/infra.context.annotation.config.AutoConfiguration.imports (100%) rename {today-service-registry-simple-registration => today-cloud-samples/today-service-registry-simple-api}/src/main/resources/META-INF/today.strategies (100%) rename {today-service-registry-simple-discovery => today-cloud-samples/today-service-registry-simple-discovery}/build.gradle (84%) rename {today-service-registry-simple-discovery => today-cloud-samples/today-service-registry-simple-discovery}/src/main/java/infra/cloud/registry/simple/discovery/SimpleHttpDiscoveryClient.java (100%) rename {today-service-registry-simple-discovery => today-cloud-samples/today-service-registry-simple-discovery}/src/main/java/infra/cloud/registry/simple/discovery/SimpleHttpDiscoveryClientAutoConfiguration.java (100%) rename {today-service-registry-simple-discovery => today-cloud-samples/today-service-registry-simple-discovery}/src/main/resources/META-INF/config/infra.context.annotation.config.AutoConfiguration.imports (100%) rename {today-service-registry-simple-registration => today-cloud-samples/today-service-registry-simple-registration}/build.gradle (83%) rename {today-service-registry-simple-registration => today-cloud-samples/today-service-registry-simple-registration}/src/main/java/infra/cloud/registry/simple/HttpRegistrationFactory.java (100%) rename {today-service-registry-simple-registration => today-cloud-samples/today-service-registry-simple-registration}/src/main/java/infra/cloud/registry/simple/SimpleAutoServiceRegistration.java (100%) rename {today-service-registry-simple-registration => today-cloud-samples/today-service-registry-simple-registration}/src/main/java/infra/cloud/registry/simple/SimpleHttpServiceRegistry.java (100%) rename {today-service-registry-simple-registration => today-cloud-samples/today-service-registry-simple-registration}/src/main/java/infra/cloud/registry/simple/SimpleRegistryProperties.java (100%) rename {today-service-registry-simple-registration => today-cloud-samples/today-service-registry-simple-registration}/src/main/java/infra/cloud/registry/simple/annotation/config/SimpleHttpServiceRegistryAutoConfiguration.java (100%) rename {today-service-registry-simple-registration => today-cloud-samples/today-service-registry-simple-registration}/src/main/resources/META-INF/config/infra.context.annotation.config.AutoConfiguration.imports (100%) rename {today-service-registry-simple-server => today-cloud-samples/today-service-registry-simple-registration}/src/main/resources/META-INF/today.strategies (100%) rename {today-service-registry-simple-server => today-cloud-samples/today-service-registry-simple-server}/build.gradle (86%) rename {today-service-registry-simple-server => today-cloud-samples/today-service-registry-simple-server}/src/main/java/infra/cloud/registry/simple/server/ServiceNotFoundException.java (100%) rename {today-service-registry-simple-server => today-cloud-samples/today-service-registry-simple-server}/src/main/java/infra/cloud/registry/simple/server/SimpleHttpServiceRegistryEndpoint.java (100%) rename {today-service-registry-simple-server => today-cloud-samples/today-service-registry-simple-server}/src/main/java/infra/cloud/registry/simple/server/SimpleHttpServiceRegistryServerAutoConfiguration.java (100%) rename {today-service-registry-simple-server => today-cloud-samples/today-service-registry-simple-server}/src/main/resources/META-INF/additional-infra-configuration-metadata.json (100%) rename {today-service-registry-simple-server => today-cloud-samples/today-service-registry-simple-server}/src/main/resources/META-INF/config/infra.context.annotation.config.AutoConfiguration.imports (100%) create mode 100644 today-cloud-samples/today-service-registry-simple-server/src/main/resources/META-INF/today.strategies diff --git a/.run/ClientApplication.run.xml b/.run/ClientApplication.run.xml index 1e4c0aa..f075b08 100644 --- a/.run/ClientApplication.run.xml +++ b/.run/ClientApplication.run.xml @@ -2,7 +2,7 @@

              `Lem|V$A>eR0uN8Y&sdjtu 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

              1bvi{DS7E@q1{$_8->K{_OWv2 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 literal 0 HcmV?d00001 diff --git a/today-cloud-samples/gradle/wrapper/gradle-wrapper.properties b/today-cloud-samples/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..dbc3ce4 --- /dev/null +++ b/today-cloud-samples/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,7 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-9.4.0-bin.zip +networkTimeout=10000 +validateDistributionUrl=true +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/today-cloud-samples/gradlew b/today-cloud-samples/gradlew new file mode 100755 index 0000000..0262dcb --- /dev/null +++ b/today-cloud-samples/gradlew @@ -0,0 +1,248 @@ +#!/bin/sh + +# +# Copyright © 2015 the original 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 +# +# https://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. +# +# SPDX-License-Identifier: Apache-2.0 +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/b631911858264c0b6e4d6603d677ff5218766cee/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/today-cloud-samples/gradlew.bat b/today-cloud-samples/gradlew.bat new file mode 100644 index 0000000..e509b2d --- /dev/null +++ b/today-cloud-samples/gradlew.bat @@ -0,0 +1,93 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:execute +@rem Setup the command line + + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/today-cloud-samples/settings.gradle b/today-cloud-samples/settings.gradle index 3d9de28..fa79919 100644 --- a/today-cloud-samples/settings.gradle +++ b/today-cloud-samples/settings.gradle @@ -1,11 +1,3 @@ -pluginManagement { - repositories { - mavenLocal() - mavenCentral() - gradlePluginPortal() - } -} - rootProject.name = 'today-cloud-samples' include 'demo-tests:demo-registry' @@ -14,27 +6,7 @@ include 'demo-tests:demo-user-rest' include 'demo-tests:demo-user-service' include 'today-petclinic' -// 引用主项目以访问其模块 -includeBuild('../') { - dependencySubstitution { - substitute module('cn.taketoday.cloud:today-cloud-bom') using project(':today-cloud-bom') - substitute module('cn.taketoday.cloud:today-cloud-dependencies') using project(':today-cloud-dependencies') - substitute module('cn.taketoday.cloud:today-cloud-core') using project(':today-cloud-core') - substitute module('cn.taketoday.cloud:today-service-api') using project(':today-service-api') - substitute module('cn.taketoday.cloud:today-service-client') using project(':today-service-client') - substitute module('cn.taketoday.cloud:today-service-provider') using project(':today-service-provider') - substitute module('cn.taketoday.cloud:today-service-discovery') using project(':today-service-discovery') - substitute module('cn.taketoday.cloud:today-service-registration') using project(':today-service-registration') - substitute module('cn.taketoday.cloud:today-service-serialization') using project(':today-service-serialization') - substitute module('cn.taketoday.cloud:today-service-registry-simple-api') using project(':today-service-registry-simple-api') - substitute module('cn.taketoday.cloud:today-service-registry-simple-server') using project(':today-service-registry-simple-server') - substitute module('cn.taketoday.cloud:today-service-registry-simple-discovery') using project(':today-service-registry-simple-discovery') - substitute module('cn.taketoday.cloud:today-service-registry-simple-registration') using project(':today-service-registry-simple-registration') - substitute module('cn.taketoday.cloud:today-remoting') using project(':today-remoting') - substitute module('cn.taketoday.cloud:today-remoting-micrometer') using project(':today-remoting-micrometer') - substitute module('cn.taketoday.cloud:today-remoting-transport-tcp') using project(':today-remoting-transport-tcp') - substitute module('cn.taketoday.cloud:today-remoting-transport-local') using project(':today-remoting-transport-local') - substitute module('cn.taketoday.cloud:today-remoting-transport-websocket') using project(':today-remoting-transport-websocket') - substitute module('cn.taketoday.cloud:today-cloud-build:today-cloud-gradle-plugin') using project(':today-cloud-build:today-cloud-gradle-plugin') - } -} +include 'today-service-registry-simple-api' +include 'today-service-registry-simple-server' +include 'today-service-registry-simple-discovery' +include 'today-service-registry-simple-registration' diff --git a/today-service-registry-simple-api/build.gradle b/today-cloud-samples/today-service-registry-simple-api/build.gradle similarity index 86% rename from today-service-registry-simple-api/build.gradle rename to today-cloud-samples/today-service-registry-simple-api/build.gradle index 5f0555b..6012ff2 100644 --- a/today-service-registry-simple-api/build.gradle +++ b/today-cloud-samples/today-service-registry-simple-api/build.gradle @@ -2,7 +2,7 @@ description = "TODAY Service Simple Registry API" dependencies { - implementation project(":today-cloud-core") + implementation "cn.taketoday:today-cloud-core" implementation 'cn.taketoday:infra-starter-webmvc' implementation 'cn.taketoday:infra-starter-http-service' implementation 'cn.taketoday:infra-starter-restclient' diff --git a/today-service-registry-simple-api/src/main/java/infra/cloud/registry/simple/HttpRegistration.java b/today-cloud-samples/today-service-registry-simple-api/src/main/java/infra/cloud/registry/simple/HttpRegistration.java similarity index 100% rename from today-service-registry-simple-api/src/main/java/infra/cloud/registry/simple/HttpRegistration.java rename to today-cloud-samples/today-service-registry-simple-api/src/main/java/infra/cloud/registry/simple/HttpRegistration.java diff --git a/today-service-registry-simple-api/src/main/java/infra/cloud/registry/simple/Status.java b/today-cloud-samples/today-service-registry-simple-api/src/main/java/infra/cloud/registry/simple/Status.java similarity index 100% rename from today-service-registry-simple-api/src/main/java/infra/cloud/registry/simple/Status.java rename to today-cloud-samples/today-service-registry-simple-api/src/main/java/infra/cloud/registry/simple/Status.java diff --git a/today-service-registry-simple-api/src/main/java/infra/cloud/registry/simple/api/SimpleHttpServiceRegistryAPI.java b/today-cloud-samples/today-service-registry-simple-api/src/main/java/infra/cloud/registry/simple/api/SimpleHttpServiceRegistryAPI.java similarity index 100% rename from today-service-registry-simple-api/src/main/java/infra/cloud/registry/simple/api/SimpleHttpServiceRegistryAPI.java rename to today-cloud-samples/today-service-registry-simple-api/src/main/java/infra/cloud/registry/simple/api/SimpleHttpServiceRegistryAPI.java diff --git a/today-service-registry-simple-api/src/main/java/infra/cloud/registry/simple/config/SimpleHttpProperties.java b/today-cloud-samples/today-service-registry-simple-api/src/main/java/infra/cloud/registry/simple/config/SimpleHttpProperties.java similarity index 100% rename from today-service-registry-simple-api/src/main/java/infra/cloud/registry/simple/config/SimpleHttpProperties.java rename to today-cloud-samples/today-service-registry-simple-api/src/main/java/infra/cloud/registry/simple/config/SimpleHttpProperties.java diff --git a/today-service-registry-simple-api/src/main/java/infra/cloud/registry/simple/config/SimpleHttpServiceRegistryAPIAutoConfiguration.java b/today-cloud-samples/today-service-registry-simple-api/src/main/java/infra/cloud/registry/simple/config/SimpleHttpServiceRegistryAPIAutoConfiguration.java similarity index 100% rename from today-service-registry-simple-api/src/main/java/infra/cloud/registry/simple/config/SimpleHttpServiceRegistryAPIAutoConfiguration.java rename to today-cloud-samples/today-service-registry-simple-api/src/main/java/infra/cloud/registry/simple/config/SimpleHttpServiceRegistryAPIAutoConfiguration.java diff --git a/today-service-registry-simple-api/src/main/resources/META-INF/config/infra.context.annotation.config.AutoConfiguration.imports b/today-cloud-samples/today-service-registry-simple-api/src/main/resources/META-INF/config/infra.context.annotation.config.AutoConfiguration.imports similarity index 100% rename from today-service-registry-simple-api/src/main/resources/META-INF/config/infra.context.annotation.config.AutoConfiguration.imports rename to today-cloud-samples/today-service-registry-simple-api/src/main/resources/META-INF/config/infra.context.annotation.config.AutoConfiguration.imports diff --git a/today-service-registry-simple-registration/src/main/resources/META-INF/today.strategies b/today-cloud-samples/today-service-registry-simple-api/src/main/resources/META-INF/today.strategies similarity index 100% rename from today-service-registry-simple-registration/src/main/resources/META-INF/today.strategies rename to today-cloud-samples/today-service-registry-simple-api/src/main/resources/META-INF/today.strategies diff --git a/today-service-registry-simple-discovery/build.gradle b/today-cloud-samples/today-service-registry-simple-discovery/build.gradle similarity index 84% rename from today-service-registry-simple-discovery/build.gradle rename to today-cloud-samples/today-service-registry-simple-discovery/build.gradle index 3e7dcb1..d1060b5 100644 --- a/today-service-registry-simple-discovery/build.gradle +++ b/today-cloud-samples/today-service-registry-simple-discovery/build.gradle @@ -2,7 +2,7 @@ description = "TODAY Service Simple Registry discovery" dependencies { - api project(":today-service-discovery") + api "cn.taketoday:today-service-discovery" api project(":today-service-registry-simple-api") implementation 'cn.taketoday:infra-starter-webmvc' diff --git a/today-service-registry-simple-discovery/src/main/java/infra/cloud/registry/simple/discovery/SimpleHttpDiscoveryClient.java b/today-cloud-samples/today-service-registry-simple-discovery/src/main/java/infra/cloud/registry/simple/discovery/SimpleHttpDiscoveryClient.java similarity index 100% rename from today-service-registry-simple-discovery/src/main/java/infra/cloud/registry/simple/discovery/SimpleHttpDiscoveryClient.java rename to today-cloud-samples/today-service-registry-simple-discovery/src/main/java/infra/cloud/registry/simple/discovery/SimpleHttpDiscoveryClient.java diff --git a/today-service-registry-simple-discovery/src/main/java/infra/cloud/registry/simple/discovery/SimpleHttpDiscoveryClientAutoConfiguration.java b/today-cloud-samples/today-service-registry-simple-discovery/src/main/java/infra/cloud/registry/simple/discovery/SimpleHttpDiscoveryClientAutoConfiguration.java similarity index 100% rename from today-service-registry-simple-discovery/src/main/java/infra/cloud/registry/simple/discovery/SimpleHttpDiscoveryClientAutoConfiguration.java rename to today-cloud-samples/today-service-registry-simple-discovery/src/main/java/infra/cloud/registry/simple/discovery/SimpleHttpDiscoveryClientAutoConfiguration.java diff --git a/today-service-registry-simple-discovery/src/main/resources/META-INF/config/infra.context.annotation.config.AutoConfiguration.imports b/today-cloud-samples/today-service-registry-simple-discovery/src/main/resources/META-INF/config/infra.context.annotation.config.AutoConfiguration.imports similarity index 100% rename from today-service-registry-simple-discovery/src/main/resources/META-INF/config/infra.context.annotation.config.AutoConfiguration.imports rename to today-cloud-samples/today-service-registry-simple-discovery/src/main/resources/META-INF/config/infra.context.annotation.config.AutoConfiguration.imports diff --git a/today-service-registry-simple-registration/build.gradle b/today-cloud-samples/today-service-registry-simple-registration/build.gradle similarity index 83% rename from today-service-registry-simple-registration/build.gradle rename to today-cloud-samples/today-service-registry-simple-registration/build.gradle index a4a6aac..f1c4797 100644 --- a/today-service-registry-simple-registration/build.gradle +++ b/today-cloud-samples/today-service-registry-simple-registration/build.gradle @@ -2,7 +2,7 @@ description = "TODAY Service Simple Registry" dependencies { - api project(":today-service-registration") + api "cn.taketoday:today-service-registration" api project(":today-service-registry-simple-api") implementation 'cn.taketoday:infra-starter-webmvc' diff --git a/today-service-registry-simple-registration/src/main/java/infra/cloud/registry/simple/HttpRegistrationFactory.java b/today-cloud-samples/today-service-registry-simple-registration/src/main/java/infra/cloud/registry/simple/HttpRegistrationFactory.java similarity index 100% rename from today-service-registry-simple-registration/src/main/java/infra/cloud/registry/simple/HttpRegistrationFactory.java rename to today-cloud-samples/today-service-registry-simple-registration/src/main/java/infra/cloud/registry/simple/HttpRegistrationFactory.java diff --git a/today-service-registry-simple-registration/src/main/java/infra/cloud/registry/simple/SimpleAutoServiceRegistration.java b/today-cloud-samples/today-service-registry-simple-registration/src/main/java/infra/cloud/registry/simple/SimpleAutoServiceRegistration.java similarity index 100% rename from today-service-registry-simple-registration/src/main/java/infra/cloud/registry/simple/SimpleAutoServiceRegistration.java rename to today-cloud-samples/today-service-registry-simple-registration/src/main/java/infra/cloud/registry/simple/SimpleAutoServiceRegistration.java diff --git a/today-service-registry-simple-registration/src/main/java/infra/cloud/registry/simple/SimpleHttpServiceRegistry.java b/today-cloud-samples/today-service-registry-simple-registration/src/main/java/infra/cloud/registry/simple/SimpleHttpServiceRegistry.java similarity index 100% rename from today-service-registry-simple-registration/src/main/java/infra/cloud/registry/simple/SimpleHttpServiceRegistry.java rename to today-cloud-samples/today-service-registry-simple-registration/src/main/java/infra/cloud/registry/simple/SimpleHttpServiceRegistry.java diff --git a/today-service-registry-simple-registration/src/main/java/infra/cloud/registry/simple/SimpleRegistryProperties.java b/today-cloud-samples/today-service-registry-simple-registration/src/main/java/infra/cloud/registry/simple/SimpleRegistryProperties.java similarity index 100% rename from today-service-registry-simple-registration/src/main/java/infra/cloud/registry/simple/SimpleRegistryProperties.java rename to today-cloud-samples/today-service-registry-simple-registration/src/main/java/infra/cloud/registry/simple/SimpleRegistryProperties.java diff --git a/today-service-registry-simple-registration/src/main/java/infra/cloud/registry/simple/annotation/config/SimpleHttpServiceRegistryAutoConfiguration.java b/today-cloud-samples/today-service-registry-simple-registration/src/main/java/infra/cloud/registry/simple/annotation/config/SimpleHttpServiceRegistryAutoConfiguration.java similarity index 100% rename from today-service-registry-simple-registration/src/main/java/infra/cloud/registry/simple/annotation/config/SimpleHttpServiceRegistryAutoConfiguration.java rename to today-cloud-samples/today-service-registry-simple-registration/src/main/java/infra/cloud/registry/simple/annotation/config/SimpleHttpServiceRegistryAutoConfiguration.java diff --git a/today-service-registry-simple-registration/src/main/resources/META-INF/config/infra.context.annotation.config.AutoConfiguration.imports b/today-cloud-samples/today-service-registry-simple-registration/src/main/resources/META-INF/config/infra.context.annotation.config.AutoConfiguration.imports similarity index 100% rename from today-service-registry-simple-registration/src/main/resources/META-INF/config/infra.context.annotation.config.AutoConfiguration.imports rename to today-cloud-samples/today-service-registry-simple-registration/src/main/resources/META-INF/config/infra.context.annotation.config.AutoConfiguration.imports diff --git a/today-service-registry-simple-server/src/main/resources/META-INF/today.strategies b/today-cloud-samples/today-service-registry-simple-registration/src/main/resources/META-INF/today.strategies similarity index 100% rename from today-service-registry-simple-server/src/main/resources/META-INF/today.strategies rename to today-cloud-samples/today-service-registry-simple-registration/src/main/resources/META-INF/today.strategies diff --git a/today-service-registry-simple-server/build.gradle b/today-cloud-samples/today-service-registry-simple-server/build.gradle similarity index 86% rename from today-service-registry-simple-server/build.gradle rename to today-cloud-samples/today-service-registry-simple-server/build.gradle index 5d36598..f113c6e 100644 --- a/today-service-registry-simple-server/build.gradle +++ b/today-cloud-samples/today-service-registry-simple-server/build.gradle @@ -2,7 +2,7 @@ description = "TODAY Service Simple Registry Server" dependencies { - api project(":today-cloud-core") + api "cn.taketoday:today-cloud-core" api project(":today-service-registry-simple-api") implementation 'cn.taketoday:infra-starter-webmvc' diff --git a/today-service-registry-simple-server/src/main/java/infra/cloud/registry/simple/server/ServiceNotFoundException.java b/today-cloud-samples/today-service-registry-simple-server/src/main/java/infra/cloud/registry/simple/server/ServiceNotFoundException.java similarity index 100% rename from today-service-registry-simple-server/src/main/java/infra/cloud/registry/simple/server/ServiceNotFoundException.java rename to today-cloud-samples/today-service-registry-simple-server/src/main/java/infra/cloud/registry/simple/server/ServiceNotFoundException.java diff --git a/today-service-registry-simple-server/src/main/java/infra/cloud/registry/simple/server/SimpleHttpServiceRegistryEndpoint.java b/today-cloud-samples/today-service-registry-simple-server/src/main/java/infra/cloud/registry/simple/server/SimpleHttpServiceRegistryEndpoint.java similarity index 100% rename from today-service-registry-simple-server/src/main/java/infra/cloud/registry/simple/server/SimpleHttpServiceRegistryEndpoint.java rename to today-cloud-samples/today-service-registry-simple-server/src/main/java/infra/cloud/registry/simple/server/SimpleHttpServiceRegistryEndpoint.java diff --git a/today-service-registry-simple-server/src/main/java/infra/cloud/registry/simple/server/SimpleHttpServiceRegistryServerAutoConfiguration.java b/today-cloud-samples/today-service-registry-simple-server/src/main/java/infra/cloud/registry/simple/server/SimpleHttpServiceRegistryServerAutoConfiguration.java similarity index 100% rename from today-service-registry-simple-server/src/main/java/infra/cloud/registry/simple/server/SimpleHttpServiceRegistryServerAutoConfiguration.java rename to today-cloud-samples/today-service-registry-simple-server/src/main/java/infra/cloud/registry/simple/server/SimpleHttpServiceRegistryServerAutoConfiguration.java diff --git a/today-service-registry-simple-server/src/main/resources/META-INF/additional-infra-configuration-metadata.json b/today-cloud-samples/today-service-registry-simple-server/src/main/resources/META-INF/additional-infra-configuration-metadata.json similarity index 100% rename from today-service-registry-simple-server/src/main/resources/META-INF/additional-infra-configuration-metadata.json rename to today-cloud-samples/today-service-registry-simple-server/src/main/resources/META-INF/additional-infra-configuration-metadata.json diff --git a/today-service-registry-simple-server/src/main/resources/META-INF/config/infra.context.annotation.config.AutoConfiguration.imports b/today-cloud-samples/today-service-registry-simple-server/src/main/resources/META-INF/config/infra.context.annotation.config.AutoConfiguration.imports similarity index 100% rename from today-service-registry-simple-server/src/main/resources/META-INF/config/infra.context.annotation.config.AutoConfiguration.imports rename to today-cloud-samples/today-service-registry-simple-server/src/main/resources/META-INF/config/infra.context.annotation.config.AutoConfiguration.imports diff --git a/today-cloud-samples/today-service-registry-simple-server/src/main/resources/META-INF/today.strategies b/today-cloud-samples/today-service-registry-simple-server/src/main/resources/META-INF/today.strategies new file mode 100644 index 0000000..e69de29 diff --git a/today-service-provider/src/main/resources/META-INF/config/infra.context.annotation.config.AutoConfiguration.imports b/today-service-provider/src/main/resources/META-INF/config/infra.context.annotation.config.AutoConfiguration.imports index b51f47b..d55bd92 100644 --- a/today-service-provider/src/main/resources/META-INF/config/infra.context.annotation.config.AutoConfiguration.imports +++ b/today-service-provider/src/main/resources/META-INF/config/infra.context.annotation.config.AutoConfiguration.imports @@ -1 +1 @@ -infra.cloud.provider.annotation.config.ServiceProviderAutoConfiguration \ No newline at end of file +infra.cloud.provider.config.ServiceProviderAutoConfiguration \ No newline at end of file From a7e738e166021571e904dcbf3e40ea854d166e06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Sun, 15 Mar 2026 19:00:11 +0800 Subject: [PATCH 082/104] =?UTF-8?q?:sparkles:=20=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E6=9C=8D=E5=8A=A1=E5=88=86=E7=BB=84=E5=92=8C=E6=9C=8D=E5=8A=A1?= =?UTF-8?q?=E6=8F=8F=E8=BF=B0=E5=85=83=E6=95=B0=E6=8D=AE=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在 GenerateServiceMetadata 中添加 service.group 和 service.description 属性写入 - 将 ServiceMetadataExtension 中的 description 重命名为 serviceDescription - 添加 serviceGroup 属性并设置默认值为 "default" - 配置 serviceDescription 使用项目描述作为默认值 - 配置 serviceGroup 使用 "default" 作为默认值 --- .../java/infra/cloud/plugin/GenerateServiceMetadata.java | 2 ++ .../infra/cloud/plugin/ServiceMetadataExtension.java | 9 +++++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/today-cloud-build/today-cloud-gradle-plugin/src/main/java/infra/cloud/plugin/GenerateServiceMetadata.java b/today-cloud-build/today-cloud-gradle-plugin/src/main/java/infra/cloud/plugin/GenerateServiceMetadata.java index 7dc8d7a..771a2c7 100644 --- a/today-cloud-build/today-cloud-gradle-plugin/src/main/java/infra/cloud/plugin/GenerateServiceMetadata.java +++ b/today-cloud-build/today-cloud-gradle-plugin/src/main/java/infra/cloud/plugin/GenerateServiceMetadata.java @@ -52,6 +52,8 @@ public void generate() throws IOException { properties.setProperty("service.id", serviceMetadata.getServiceId().get()); properties.setProperty("service.version", serviceMetadata.getServiceVersion().get()); + properties.setProperty("service.group", serviceMetadata.getServiceGroup().get()); + properties.setProperty("service.description", serviceMetadata.getServiceDescription().get()); convertToStringValues(serviceMetadata.getAdditional().get()) .forEach((name, value) -> { diff --git a/today-cloud-build/today-cloud-gradle-plugin/src/main/java/infra/cloud/plugin/ServiceMetadataExtension.java b/today-cloud-build/today-cloud-gradle-plugin/src/main/java/infra/cloud/plugin/ServiceMetadataExtension.java index 09509cc..d160999 100644 --- a/today-cloud-build/today-cloud-gradle-plugin/src/main/java/infra/cloud/plugin/ServiceMetadataExtension.java +++ b/today-cloud-build/today-cloud-gradle-plugin/src/main/java/infra/cloud/plugin/ServiceMetadataExtension.java @@ -45,8 +45,9 @@ public abstract class ServiceMetadataExtension implements Serializable { */ public ServiceMetadataExtension(Project project) { getServiceId().convention(project.provider(project::getName)); - getDescription().convention(project.provider(project::getDescription)); + getServiceDescription().convention(project.provider(project::getDescription)); getServiceVersion().convention(project.provider(() -> project.getVersion().toString())); + getServiceGroup().convention("default"); } /** @@ -73,7 +74,11 @@ public ServiceMetadataExtension(Project project) { @Input @Optional - public abstract Property getDescription(); + public abstract Property getServiceDescription(); + + @Input + @Optional + public abstract Property getServiceGroup(); /** * Gets the map property for storing additional custom metadata. From 7ec134cbfdd9a3c2f6a80ad7e82b5a37c8be6b55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Sun, 15 Mar 2026 21:46:58 +0800 Subject: [PATCH 083/104] =?UTF-8?q?fix(plugin):=20=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E6=9C=8D=E5=8A=A1=E5=85=83=E6=95=B0=E6=8D=AE=E7=94=9F=E6=88=90?= =?UTF-8?q?=E5=92=8C=E5=8A=A0=E8=BD=BD=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 修改 GenerateServiceMetadata 中 CollectionUtils.createSortedProperties 参数为 false - 添加 infra.cloud.client 包的 package-info.java 文件并配置 NullMarked 注解 - 调整 PackageInfoServiceMetadataProvider 中常量定义顺序 - 移除 service.id 验证注释以保持原有验证逻辑 - 将异常捕获改为 ignored 模式以减少日志输出 --- .../cloud/plugin/GenerateServiceMetadata.java | 2 +- .../java/infra/cloud/client/package-info.java | 20 +++++++++++++++++++ .../PackageInfoServiceMetadataProvider.java | 6 ++---- 3 files changed, 23 insertions(+), 5 deletions(-) create mode 100644 today-cloud-core/src/main/java/infra/cloud/client/package-info.java diff --git a/today-cloud-build/today-cloud-gradle-plugin/src/main/java/infra/cloud/plugin/GenerateServiceMetadata.java b/today-cloud-build/today-cloud-gradle-plugin/src/main/java/infra/cloud/plugin/GenerateServiceMetadata.java index 771a2c7..8972d88 100644 --- a/today-cloud-build/today-cloud-gradle-plugin/src/main/java/infra/cloud/plugin/GenerateServiceMetadata.java +++ b/today-cloud-build/today-cloud-gradle-plugin/src/main/java/infra/cloud/plugin/GenerateServiceMetadata.java @@ -48,7 +48,7 @@ public void generate() throws IOException { File propertiesFile = new File(outputDir, "service-metadata.properties"); createFileIfNecessary(propertiesFile); - Properties properties = CollectionUtils.createSortedProperties(true); + Properties properties = CollectionUtils.createSortedProperties(false); properties.setProperty("service.id", serviceMetadata.getServiceId().get()); properties.setProperty("service.version", serviceMetadata.getServiceVersion().get()); diff --git a/today-cloud-core/src/main/java/infra/cloud/client/package-info.java b/today-cloud-core/src/main/java/infra/cloud/client/package-info.java new file mode 100644 index 0000000..45dfba1 --- /dev/null +++ b/today-cloud-core/src/main/java/infra/cloud/client/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright 2021 - 2026 the TODAY 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 + * + * https://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. + */ + +@NullMarked +package infra.cloud.client; + +import org.jspecify.annotations.NullMarked; \ No newline at end of file diff --git a/today-service-api/src/main/java/infra/cloud/service/PackageInfoServiceMetadataProvider.java b/today-service-api/src/main/java/infra/cloud/service/PackageInfoServiceMetadataProvider.java index e0d74cf..37b8e9c 100644 --- a/today-service-api/src/main/java/infra/cloud/service/PackageInfoServiceMetadataProvider.java +++ b/today-service-api/src/main/java/infra/cloud/service/PackageInfoServiceMetadataProvider.java @@ -52,8 +52,8 @@ public class PackageInfoServiceMetadataProvider implements ServiceMetadataProvid public static final String DEFAULT_METADATA_LOCATION = "META-INF/service-metadata.properties"; public static final String KEY_SERVICE_ID = "service.id"; - public static final String KEY_SERVICE_VERSION = "service.version"; public static final String KEY_SERVICE_GROUP = "service.group"; + public static final String KEY_SERVICE_VERSION = "service.version"; public static final String KEY_SERVICE_DESCRIPTION = "service.description"; /** @@ -134,7 +134,6 @@ protected ServiceMetadata loadMetadata(Class serviceInterface) { Properties props = new Properties(); props.load(input); - // 验证是否包含必需的 service.id String serviceId = props.getProperty(KEY_SERVICE_ID); if (StringUtils.hasText(serviceId)) { return props; @@ -142,8 +141,7 @@ protected ServiceMetadata loadMetadata(Class serviceInterface) { } } } - catch (IOException ex) { - // 静默失败,降级到其他策略 + catch (IOException ignored) { } return null; From 8682a0b6d46c70f2b5b19d0386dc9c604db8347f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Sun, 15 Mar 2026 21:47:11 +0800 Subject: [PATCH 084/104] :art: --- .run/publishToMavenLocal.run.xml | 2 +- today-cloud-samples/demo-tests/demo-user-api/build.gradle | 6 ++++-- .../cloud/registry/simple/HttpRegistrationFactory.java | 3 +++ 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/.run/publishToMavenLocal.run.xml b/.run/publishToMavenLocal.run.xml index cf8c4aa..248f0ff 100644 --- a/.run/publishToMavenLocal.run.xml +++ b/.run/publishToMavenLocal.run.xml @@ -4,7 +4,7 @@ diff --git a/today-cloud-samples/demo-tests/demo-user-api/build.gradle b/today-cloud-samples/demo-tests/demo-user-api/build.gradle index 1a8b675..079526b 100644 --- a/today-cloud-samples/demo-tests/demo-user-api/build.gradle +++ b/today-cloud-samples/demo-tests/demo-user-api/build.gradle @@ -1,7 +1,5 @@ description = "Demo User API" -apply plugin: "today.cloud-application" - dependencies { implementation 'cn.taketoday:infra-context' @@ -19,4 +17,8 @@ jar { serviceMetadata { + additional = [ + "demo": "demo" + ] + } \ No newline at end of file diff --git a/today-cloud-samples/today-service-registry-simple-registration/src/main/java/infra/cloud/registry/simple/HttpRegistrationFactory.java b/today-cloud-samples/today-service-registry-simple-registration/src/main/java/infra/cloud/registry/simple/HttpRegistrationFactory.java index 13cac02..511ffa3 100644 --- a/today-cloud-samples/today-service-registry-simple-registration/src/main/java/infra/cloud/registry/simple/HttpRegistrationFactory.java +++ b/today-cloud-samples/today-service-registry-simple-registration/src/main/java/infra/cloud/registry/simple/HttpRegistrationFactory.java @@ -53,6 +53,9 @@ public HttpRegistration createRegistration(ServiceMetadata serviceMetadata) { if (registration.getServiceId() == null) { registration.setDefaultInstanceId(); } + + registration.setDefaultInstanceId(); + registration.getMetadata().putAll(serviceMetadata.getProperties()); return registration; } From 47b5a78a9f6d4116355403c2be1beb71ef2b0d75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Sun, 15 Mar 2026 21:51:34 +0800 Subject: [PATCH 085/104] :art: --- .../infra/cloud/plugin/GenerateServiceMetadata.java | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/today-cloud-build/today-cloud-gradle-plugin/src/main/java/infra/cloud/plugin/GenerateServiceMetadata.java b/today-cloud-build/today-cloud-gradle-plugin/src/main/java/infra/cloud/plugin/GenerateServiceMetadata.java index 8972d88..04e7b95 100644 --- a/today-cloud-build/today-cloud-gradle-plugin/src/main/java/infra/cloud/plugin/GenerateServiceMetadata.java +++ b/today-cloud-build/today-cloud-gradle-plugin/src/main/java/infra/cloud/plugin/GenerateServiceMetadata.java @@ -33,6 +33,14 @@ import infra.util.CollectionUtils; /** + * A Gradle task that generates service metadata properties file. + *

              + * This task reads configuration from {@link ServiceMetadataExtension} and writes + * a {@code service-metadata.properties} file to the build resources directory. + * The generated file contains service identification, versioning, grouping, + * description, and any additional custom properties. + *

              + * * @author 海子 Yang * @since 1.0 2026/3/10 21:59 */ @@ -58,7 +66,10 @@ public void generate() throws IOException { convertToStringValues(serviceMetadata.getAdditional().get()) .forEach((name, value) -> { if (value != null) { - properties.put("service." + name, value); + if (!name.startsWith("service.")) { + name = "service." + name; + } + properties.put(name, value); } }); From 5c6277a9a4bb0f664fa2d78153872f436d4bc936 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Sun, 15 Mar 2026 23:19:12 +0800 Subject: [PATCH 086/104] =?UTF-8?q?:sparkles:=20=E5=85=83=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E6=8F=90=E4=BE=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cloud/plugin/GenerateServiceMetadata.java | 5 + .../cloud/plugin/ServiceClassFinder.java | 321 ++++++++++++++++++ .../DefaultServiceMetadataProvider.java | 150 ++++++++ .../PackageInfoServiceMetadataProvider.java | 208 ------------ .../infra/cloud/service/ServiceMetadata.java | 27 +- .../cloud/service/MethodIdGeneratorTests.java | 2 - .../cloud/service/ServiceMetadataTests.java | 259 +++++++++++++- .../java/infra/cloud/service/UserService.java | 26 ++ .../ServiceClientAutoConfiguration.java | 4 +- .../ServiceProviderAutoConfiguration.java | 4 +- 10 files changed, 787 insertions(+), 219 deletions(-) create mode 100644 today-cloud-build/today-cloud-gradle-plugin/src/main/java/infra/cloud/plugin/ServiceClassFinder.java create mode 100644 today-service-api/src/main/java/infra/cloud/service/DefaultServiceMetadataProvider.java delete mode 100644 today-service-api/src/main/java/infra/cloud/service/PackageInfoServiceMetadataProvider.java create mode 100644 today-service-api/src/test/java/infra/cloud/service/UserService.java diff --git a/today-cloud-build/today-cloud-gradle-plugin/src/main/java/infra/cloud/plugin/GenerateServiceMetadata.java b/today-cloud-build/today-cloud-gradle-plugin/src/main/java/infra/cloud/plugin/GenerateServiceMetadata.java index 04e7b95..ee5f8ca 100644 --- a/today-cloud-build/today-cloud-gradle-plugin/src/main/java/infra/cloud/plugin/GenerateServiceMetadata.java +++ b/today-cloud-build/today-cloud-gradle-plugin/src/main/java/infra/cloud/plugin/GenerateServiceMetadata.java @@ -27,10 +27,12 @@ import java.io.FileOutputStream; import java.io.IOException; import java.util.LinkedHashMap; +import java.util.List; import java.util.Map; import java.util.Properties; import infra.util.CollectionUtils; +import infra.util.StringUtils; /** * A Gradle task that generates service metadata properties file. @@ -63,6 +65,9 @@ public void generate() throws IOException { properties.setProperty("service.group", serviceMetadata.getServiceGroup().get()); properties.setProperty("service.description", serviceMetadata.getServiceDescription().get()); + List interfaces = ServiceClassFinder.findInterfaces(project.getRootDir()); + properties.setProperty("service.interfaces", StringUtils.collectionToCommaDelimitedString(interfaces)); + convertToStringValues(serviceMetadata.getAdditional().get()) .forEach((name, value) -> { if (value != null) { diff --git a/today-cloud-build/today-cloud-gradle-plugin/src/main/java/infra/cloud/plugin/ServiceClassFinder.java b/today-cloud-build/today-cloud-gradle-plugin/src/main/java/infra/cloud/plugin/ServiceClassFinder.java new file mode 100644 index 0000000..90fb6f4 --- /dev/null +++ b/today-cloud-build/today-cloud-gradle-plugin/src/main/java/infra/cloud/plugin/ServiceClassFinder.java @@ -0,0 +1,321 @@ +/* + * Copyright 2021 - 2026 the TODAY 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 + * + * https://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 infra.cloud.plugin; + +import org.jspecify.annotations.Nullable; + +import java.io.File; +import java.io.FileFilter; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.Modifier; +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; +import java.util.Deque; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Set; + +import infra.bytecode.AnnotationVisitor; +import infra.bytecode.ClassReader; +import infra.bytecode.ClassVisitor; +import infra.bytecode.Type; + +/** + * Utility class for finding service interfaces within a given directory structure by scanning + * compiled {@code .class} files. This class traverses the directory tree, reads class bytecode + * to identify public interfaces, and optionally filters them based on specific annotations. + *

              + * The traversal order is deterministic: directories and files are processed in alphabetical order + * to ensure consistent results across runs. + * + * @author Harry Yang + * @since 4.0 + */ +public abstract class ServiceClassFinder { + + private static final String DOT_CLASS = ".class"; + + private static final String SERVICE = "infra.stereotype.Service"; + + /** + * File filter that accepts only files ending with {@code .class}. + */ + private static final FileFilter CLASS_FILE_FILTER = ServiceClassFinder::isClassFile; + + /** + * File filter that accepts only directories that do not start with a dot (hidden directories). + */ + private static final FileFilter PACKAGE_DIRECTORY_FILTER = ServiceClassFinder::isPackageDirectory; + + /** + * Checks if the given file is a valid Java class file. + * + * @param file the file to check + * @return {@code true} if the file is a regular file ending with {@code .class}, {@code false} otherwise + */ + private static boolean isClassFile(File file) { + return file.isFile() && file.getName().endsWith(DOT_CLASS); + } + + /** + * Checks if the given file is a valid package directory. + *

              + * A valid package directory is a directory that does not start with a dot (i.e., not hidden). + * + * @param file the file to check + * @return {@code true} if the file is a directory and not hidden, {@code false} otherwise + */ + private static boolean isPackageDirectory(File file) { + return file.isDirectory() && !file.getName().startsWith("."); + } + + /** + * Finds all public interface names within the specified root directory that are annotated + * with the given annotation name. + * + * @param rootDirectory the root directory to start scanning from + * @param annotationName the fully qualified name of the annotation to filter by, or {@code null} to ignore annotation filtering + * @return a list of fully qualified interface names matching the criteria + * @throws IOException if an I/O error occurs while reading class files + */ + public static List findInterfaces(File rootDirectory, @Nullable String annotationName) throws IOException { + InterfacesCallback callback = new InterfacesCallback(annotationName); + ServiceClassFinder.doWithInterface(rootDirectory, callback); + return callback.getInterfaces(); + } + + /** + * Finds all public interface names within the specified root directory that are annotated + * with the given annotation name. + * + * @param rootDirectory the root directory to start scanning from + * @throws IOException if an I/O error occurs while reading class files + */ + public static List findInterfaces(File rootDirectory) throws IOException { + return findInterfaces(rootDirectory, SERVICE); + } + + /** + * Traverses the directory structure starting from {@code rootDirectory}, reads each {@code .class} file, + * and invokes the provided {@code callback} for every valid public interface found. + *

              + * If the callback returns a non-null result, the traversal stops immediately and the result is returned. + * + * @param rootDirectory the root directory to start scanning from + * @param callback the callback to invoke for each discovered interface + * @param the return type of the callback + * @return the first non-null result returned by the callback, or {@code null} if no such result is produced + * @throws IOException if an I/O error occurs or if {@code rootDirectory} is not a valid directory + */ + static @Nullable T doWithInterface(File rootDirectory, InterfaceCallback callback) throws IOException { + if (!rootDirectory.exists()) { + return null; // nothing to do + } + if (!rootDirectory.isDirectory()) { + throw new IllegalArgumentException("Invalid root directory '" + rootDirectory + "'"); + } + Deque stack = new ArrayDeque<>(); + stack.push(rootDirectory); + while (!stack.isEmpty()) { + File file = stack.pop(); + if (file.isFile()) { + try (InputStream inputStream = new FileInputStream(file)) { + ClassDescriptor classDescriptor = createClassDescriptor(inputStream); + if (classDescriptor != null && classDescriptor.name != null) { + T result = callback.doWith(new InterfaceClass(classDescriptor.name, classDescriptor.annotationNames)); + if (result != null) { + return result; + } + } + } + } + if (file.isDirectory()) { + pushAllSorted(stack, file.listFiles(PACKAGE_DIRECTORY_FILTER)); + pushAllSorted(stack, file.listFiles(CLASS_FILE_FILTER)); + } + } + return null; + } + + /** + * Pushes all files from the given array onto the stack in sorted order (by name). + *

              + * Sorting ensures a deterministic traversal order. + * + * @param stack the stack to push files onto + * @param files the array of files to sort and push; may be {@code null} + */ + private static void pushAllSorted(Deque stack, File @Nullable [] files) { + if (files != null) { + Arrays.sort(files, Comparator.comparing(File::getName)); + for (File file : files) { + stack.push(file); + } + } + } + + /** + * Reads the input stream containing bytecode and extracts class metadata including the class name + * and associated annotation names. + * + * @param inputStream the input stream containing the class file data + * @return a {@link ClassDescriptor} containing the extracted metadata, or {@code null} if parsing fails + */ + private static @Nullable ClassDescriptor createClassDescriptor(InputStream inputStream) { + try { + ClassReader classReader = new ClassReader(inputStream); + ClassDescriptor classDescriptor = new ClassDescriptor(); + classReader.accept(classDescriptor, ClassReader.SKIP_CODE); + return classDescriptor; + } + catch (IOException ex) { + return null; + } + } + + /** + * A {@link ClassVisitor} implementation that captures the name of a public interface + * and collects the names of all annotations present on the class. + */ + private static final class ClassDescriptor extends ClassVisitor { + + /** + * The set of fully qualified annotation names found on the class. + */ + public final Set annotationNames = new LinkedHashSet<>(); + + /** + * The internal name of the class if it is a public interface; otherwise {@code null}. + */ + public @Nullable String name; + + @Override + public @Nullable AnnotationVisitor visitAnnotation(String desc, boolean visible) { + this.annotationNames.add(Type.forDescriptor(desc).getClassName()); + return null; + } + + @Override + public void visit(int version, int access, String name, @Nullable String signature, @Nullable String superName, String @Nullable [] interfaces) { + if (Modifier.isPublic(access) && Modifier.isInterface(access)) { + this.name = name; + } + } + + } + + /** + * A callback interface used during the traversal of class files. + * + * @param the return type of the {@link #doWith(InterfaceClass)} method + */ + interface InterfaceCallback { + + /** + * Invoked for each discovered public interface. + * + * @param interfaceClass the descriptor of the discovered interface + * @return a result value, or {@code null} to continue traversal + */ + @Nullable + T doWith(InterfaceClass interfaceClass); + + } + + /** + * Represents a discovered public interface along with its associated annotations. + */ + static final class InterfaceClass { + + private final String name; + + private final Set annotationNames; + + InterfaceClass(String name, Set annotationNames) { + this.name = name; + this.annotationNames = Set.copyOf(annotationNames); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + InterfaceClass other = (InterfaceClass) obj; + return this.name.equals(other.name); + } + + @Override + public int hashCode() { + return this.name.hashCode(); + } + + @Override + public String toString() { + return this.name; + } + + } + + /** + * A callback implementation that collects interface names matching a specific annotation. + */ + private static final class InterfacesCallback implements InterfaceCallback { + + private final Set interfaces = new LinkedHashSet<>(); + + private final @Nullable String annotationName; + + /** + * Constructs a new callback with the optional annotation filter. + * + * @param annotationName the annotation name to filter by, or {@code null} to accept all interfaces + */ + private InterfacesCallback(@Nullable String annotationName) { + this.annotationName = annotationName; + } + + @Override + public @Nullable Object doWith(InterfaceClass interfaceClass) { + if (interfaceClass.annotationNames.contains(annotationName)) { + interfaces.add(interfaceClass.name); + } + return null; + } + + /** + * Returns the collected list of interface names. + * + * @return a list of interface names that matched the annotation filter + */ + public List getInterfaces() { + return new ArrayList<>(interfaces); + } + + } + +} diff --git a/today-service-api/src/main/java/infra/cloud/service/DefaultServiceMetadataProvider.java b/today-service-api/src/main/java/infra/cloud/service/DefaultServiceMetadataProvider.java new file mode 100644 index 0000000..f1af7f3 --- /dev/null +++ b/today-service-api/src/main/java/infra/cloud/service/DefaultServiceMetadataProvider.java @@ -0,0 +1,150 @@ +/* + * Copyright 2021 - 2026 the TODAY 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 + * + * https://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 infra.cloud.service; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.Set; + +import infra.lang.Assert; +import infra.logging.Logger; +import infra.logging.LoggerFactory; +import infra.util.ClassUtils; +import infra.util.CollectionUtils; +import infra.util.MultiValueMap; +import infra.util.StringUtils; + +import static infra.lang.TodayStrategies.readStrategies; + +/** + * Default implementation of {@link ServiceMetadataProvider} that loads service metadata + * from properties files located on the classpath. + *

              + * By default, this provider searches for configuration files at + * {@code META-INF/service-metadata.properties}. It supports loading multiple + * resources with the same name from different locations in the classpath and + * aggregates the metadata into an internal cache keyed by interface name. + * + * @author 海子 Yang + * @since 1.0 2025/8/9 21:55 + */ +public class DefaultServiceMetadataProvider implements ServiceMetadataProvider { + + private static final Logger log = LoggerFactory.getLogger(DefaultServiceMetadataProvider.class); + + public static final String DEFAULT_METADATA_LOCATION = "META-INF/service-metadata.properties"; + + public static final String KEY_PREFIX = "service."; + + public static final String KEY_SERVICE_ID = "service.id"; + public static final String KEY_SERVICE_VERSION = "service.version"; + public static final String KEY_SERVICE_INTERFACES = "service.interfaces"; + + private final Map metadataCache; + + /** + * Constructs a provider with the default metadata location. + */ + public DefaultServiceMetadataProvider() { + this(DEFAULT_METADATA_LOCATION); + } + + /** + * Constructs a provider with a custom metadata location. + * + * @param metadataLocation the classpath location of the metadata file + */ + public DefaultServiceMetadataProvider(String metadataLocation) { + Assert.notNull(metadataLocation, "metadata-location is required"); + this.metadataCache = loadMetadata(metadataLocation); + } + + @Override + public ServiceMetadata getMetadata(Class serviceInterface) { + ServiceMetadata metadata = metadataCache.get(serviceInterface.getName()); + Assert.state(metadata != null, "metadata not found"); + return metadata; + } + + private Map loadMetadata(String metadataLocation) { + Map metadataCache = new HashMap<>(); + List serviceMetadata = loadResources(ClassUtils.getDefaultClassLoader(), metadataLocation); + for (ServiceMetadata metadata : serviceMetadata) { + for (String ifc : metadata.getInterfaces()) { + metadataCache.put(ifc, metadata); + } + } + return metadataCache; + } + + /** + * Creates ServiceMetadata from loaded properties. + * + * @param props the loaded properties + * @return a new ServiceMetadata instance + */ + protected ServiceMetadata createMetadata(MultiValueMap props) { + String serviceId = CollectionUtils.firstElement(props.remove(KEY_SERVICE_ID)); + String version = CollectionUtils.firstElement(props.remove(KEY_SERVICE_VERSION)); + List interfaces = props.remove(KEY_SERVICE_INTERFACES); + + Set keys = props.keySet(); + var metadata = CollectionUtils.newLinkedHashMap(keys.size()); + for (String key : keys) { + String value = props.getFirst(key); + if (StringUtils.hasText(value)) { + metadata.put(StringUtils.delete(key, KEY_PREFIX), value); + } + } + + return new ServiceMetadata(serviceId, version, interfaces, metadata); + } + + protected List loadResources(ClassLoader classLoader, String metadataLocation) { + List serviceMetadata = new ArrayList<>(); + try { + log.debug("Detecting service-metadata location '{}'", metadataLocation); + Enumeration urls = classLoader.getResources(metadataLocation); + while (urls.hasMoreElements()) { + URL url = urls.nextElement(); + Properties properties = new Properties(); + + log.debug("Reading service-metadata file '{}'", url); + try (InputStream inputStream = url.openStream()) { + properties.load(inputStream); + } + + MultiValueMap metadata = MultiValueMap.forLinkedHashMap(); + readStrategies(metadata, properties); + serviceMetadata.add(createMetadata(metadata)); + } + } + catch (IOException ex) { + throw new IllegalArgumentException( + "Unable to load service-metadata from location [%s]".formatted(metadataLocation), ex); + } + return serviceMetadata; + } + +} diff --git a/today-service-api/src/main/java/infra/cloud/service/PackageInfoServiceMetadataProvider.java b/today-service-api/src/main/java/infra/cloud/service/PackageInfoServiceMetadataProvider.java deleted file mode 100644 index 37b8e9c..0000000 --- a/today-service-api/src/main/java/infra/cloud/service/PackageInfoServiceMetadataProvider.java +++ /dev/null @@ -1,208 +0,0 @@ -/* - * Copyright 2021 - 2026 the TODAY 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 - * - * https://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 infra.cloud.service; - -import org.jspecify.annotations.Nullable; - -import java.io.IOException; -import java.io.InputStream; -import java.net.URL; -import java.util.Enumeration; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.Properties; -import java.util.concurrent.ConcurrentHashMap; - -import infra.util.StringUtils; - -/** - * Reads {@link ServiceMetadata} from configuration files located in - * {@code META-INF/service-metadata.properties} on the classpath. - *

              - * This implementation supports multiple loading strategies: - *

              - *
                - *
              1. Load from {@code META-INF/service-metadata.properties} (development and production)
              2. - *
              3. Fallback to {@link Package} MANIFEST.MF if properties file is not found
              4. - *
              5. Ultimate fallback to package name if neither metadata source is available
              6. - *
              - *

              - * Metadata instances are cached per package to ensure memory efficiency and safe sharing. - *

              - * - * @author 海子 Yang - * @since 1.0 2025/8/9 21:55 - */ -public class PackageInfoServiceMetadataProvider implements ServiceMetadataProvider { - - public static final String DEFAULT_METADATA_LOCATION = "META-INF/service-metadata.properties"; - - public static final String KEY_SERVICE_ID = "service.id"; - public static final String KEY_SERVICE_GROUP = "service.group"; - public static final String KEY_SERVICE_VERSION = "service.version"; - public static final String KEY_SERVICE_DESCRIPTION = "service.description"; - - /** - * Cache to store ServiceMetadata instances per package. - */ - private final Map metadataCache = new ConcurrentHashMap<>(); - - private final String metadataLocation; - - /** - * Constructs a provider with the default metadata location. - */ - public PackageInfoServiceMetadataProvider() { - this(DEFAULT_METADATA_LOCATION); - } - - /** - * Constructs a provider with a custom metadata location. - * - * @param metadataLocation the classpath location of the metadata file - */ - public PackageInfoServiceMetadataProvider(String metadataLocation) { - this.metadataLocation = metadataLocation; - } - - @Override - public ServiceMetadata getMetadata(Class serviceInterface) { - return metadataCache.computeIfAbsent(getCacheKey(serviceInterface), key -> loadMetadata(serviceInterface)); - } - - /** - * Loads metadata for the given service interface. - *

              - * Loading strategy: - * 1. Try to load from properties file - * 2. Fallback to Package MANIFEST.MF - * 3. Ultimate fallback to package name - *

              - * - * @param serviceInterface the service interface class - * @return a ServiceMetadata instance (never null) - */ - protected ServiceMetadata loadMetadata(Class serviceInterface) { - Properties props = loadProperties(serviceInterface); - if (props != null) { - return createMetadataFromProperties(props); - } - - Package servicePackage = serviceInterface.getPackage(); - String specificationTitle = servicePackage.getSpecificationTitle(); - String specificationVersion = servicePackage.getSpecificationVersion(); - - if (specificationTitle != null && !specificationTitle.isBlank()) { - return new ServiceMetadata(specificationTitle, specificationVersion); - } - - String packageName = serviceInterface.getPackageName(); - return new ServiceMetadata(packageName, null); - } - - /** - * Loads properties from the metadata file. - * - * @param serviceInterface the service interface class - * @return loaded properties, or empty map if not found - */ - protected @Nullable Properties loadProperties(Class serviceInterface) { - try { - ClassLoader classLoader = serviceInterface.getClassLoader(); - if (classLoader == null) { - classLoader = ClassLoader.getSystemClassLoader(); - } - - Enumeration urls = classLoader.getResources(metadataLocation); - while (urls.hasMoreElements()) { - URL url = urls.nextElement(); - try (InputStream input = url.openStream()) { - Properties props = new Properties(); - props.load(input); - - String serviceId = props.getProperty(KEY_SERVICE_ID); - if (StringUtils.hasText(serviceId)) { - return props; - } - } - } - } - catch (IOException ignored) { - } - - return null; - } - - /** - * Creates ServiceMetadata from loaded properties. - * - * @param props the loaded properties - * @return a new ServiceMetadata instance - */ - protected ServiceMetadata createMetadataFromProperties(Properties props) { - String serviceId = props.getProperty(KEY_SERVICE_ID); - String version = props.getProperty(KEY_SERVICE_VERSION); - - Map metadata = new LinkedHashMap<>(); - - addPropertyIfPresent(metadata, props, KEY_SERVICE_DESCRIPTION); - addPropertyIfPresent(metadata, props, KEY_SERVICE_GROUP); - - return new ServiceMetadata(serviceId, version, metadata); - } - - /** - * Helper method to add a property if it's present. - */ - private void addPropertyIfPresent(Map metadata, Properties props, String key) { - String value = props.getProperty(key); - if (value != null && !value.isBlank()) { - metadata.put(key.substring(key.indexOf('.') + 1), value); - } - } - - /** - * Generates a cache key for the given service interface. - *

              - * Using the package name as the key ensures that all service interfaces - * within the same package share the same ServiceMetadata. - *

              - * - * @param serviceInterface the service interface class - * @return the cache key (package name) - */ - protected String getCacheKey(Class serviceInterface) { - return serviceInterface.getPackageName(); - } - - /** - * Clears the internal cache. - */ - public void clearCache() { - metadataCache.clear(); - } - - /** - * Returns the number of cached metadata entries. - * - * @return the number of cached service metadata instances - */ - public int getCacheSize() { - return metadataCache.size(); - } - -} diff --git a/today-service-api/src/main/java/infra/cloud/service/ServiceMetadata.java b/today-service-api/src/main/java/infra/cloud/service/ServiceMetadata.java index a4cf70c..69e2f41 100644 --- a/today-service-api/src/main/java/infra/cloud/service/ServiceMetadata.java +++ b/today-service-api/src/main/java/infra/cloud/service/ServiceMetadata.java @@ -18,6 +18,7 @@ import org.jspecify.annotations.Nullable; +import java.util.List; import java.util.Map; import java.util.Objects; @@ -41,6 +42,8 @@ public class ServiceMetadata { private final @Nullable String version; + private final List interfaces; + private final Map properties; /** @@ -49,8 +52,8 @@ public class ServiceMetadata { * @param id the unique identifier of the service * @param version the version of the service, may be {@code null} */ - public ServiceMetadata(String id, @Nullable String version) { - this(id, version, null); + public ServiceMetadata(String id, @Nullable String version, List interfaces) { + this(id, version, interfaces, null); } /** @@ -59,11 +62,14 @@ public ServiceMetadata(String id, @Nullable String version) { * @param id the unique identifier of the service * @param version the version of the service, may be {@code null} * @param properties the properties + * @param interfaces interfaces class names */ - public ServiceMetadata(String id, @Nullable String version, @Nullable Map properties) { + public ServiceMetadata(String id, @Nullable String version, List interfaces, @Nullable Map properties) { Assert.notNull(id, "service id is required"); + Assert.notNull(interfaces, "interfaces is required"); this.id = id; this.version = version; + this.interfaces = interfaces; this.properties = properties == null ? Map.of() : Map.copyOf(properties); } @@ -85,6 +91,19 @@ public String getId() { return version; } + /** + * Returns the list of service interface class names contained in this artifact. + *

              + * The returned list is unmodifiable and represents a snapshot of the interfaces + * at construction time. This ensures thread-safety and prevents accidental modification. + *

              + * + * @return the list of interface class names (never null) + */ + public List getInterfaces() { + return interfaces; + } + /** * Returns the properties associated with this service artifact. *

              @@ -111,7 +130,7 @@ public Map getProperties() { * @return a new {@code ServiceMetadata} instance with the updated properties */ public ServiceMetadata withProperties(@Nullable Map properties) { - return new ServiceMetadata(id, version, properties); + return new ServiceMetadata(id, version, interfaces, properties); } /** diff --git a/today-service-api/src/test/java/infra/cloud/service/MethodIdGeneratorTests.java b/today-service-api/src/test/java/infra/cloud/service/MethodIdGeneratorTests.java index cffb62f..bd464ba 100644 --- a/today-service-api/src/test/java/infra/cloud/service/MethodIdGeneratorTests.java +++ b/today-service-api/src/test/java/infra/cloud/service/MethodIdGeneratorTests.java @@ -22,8 +22,6 @@ import java.util.Map; import java.util.Set; -import cn.taketoday.demo.service.UserService; - /** * @author 海子 Yang * @since 1.0 2025/8/11 15:20 diff --git a/today-service-api/src/test/java/infra/cloud/service/ServiceMetadataTests.java b/today-service-api/src/test/java/infra/cloud/service/ServiceMetadataTests.java index f8e68b8..8b59b7d 100644 --- a/today-service-api/src/test/java/infra/cloud/service/ServiceMetadataTests.java +++ b/today-service-api/src/test/java/infra/cloud/service/ServiceMetadataTests.java @@ -18,6 +18,9 @@ import org.junit.jupiter.api.Test; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; import java.util.Map; import static org.assertj.core.api.Assertions.assertThat; @@ -30,7 +33,7 @@ class ServiceMetadataTests { @Test void testService() { - ServiceMetadata metadata = new ServiceMetadata("test-service", "1.0"); + ServiceMetadata metadata = new ServiceMetadata("test-service", "1.0", List.of()); ServiceMetadata withProps = metadata.withProperties(Map.of( "env", "test" @@ -41,4 +44,258 @@ void testService() { } + @Test + void createWithRequiredFields() { + ServiceMetadata metadata = new ServiceMetadata("user-service", "1.0.0", List.of("com.example.UserService")); + + assertThat(metadata.getId()).isEqualTo("user-service"); + assertThat(metadata.getVersion()).isEqualTo("1.0.0"); + assertThat(metadata.getInterfaces()).containsExactly("com.example.UserService"); + assertThat(metadata.getProperties()).isEmpty(); + } + + @Test + void createWithNullVersion() { + ServiceMetadata metadata = new ServiceMetadata("user-service", null, List.of("com.example.UserService")); + + assertThat(metadata.getId()).isEqualTo("user-service"); + assertThat(metadata.getVersion()).isNull(); + assertThat(metadata.getInterfaces()).containsExactly("com.example.UserService"); + } + + @Test + void createWithEmptyInterfaces() { + ServiceMetadata metadata = new ServiceMetadata("user-service", "1.0.0", List.of()); + + assertThat(metadata.getId()).isEqualTo("user-service"); + assertThat(metadata.getVersion()).isEqualTo("1.0.0"); + assertThat(metadata.getInterfaces()).isEmpty(); + } + + @Test + void createWithProperties() { + Map props = Map.of("env", "test", "region", "us-west-2"); + ServiceMetadata metadata = new ServiceMetadata("user-service", "1.0.0", List.of(), props); + + assertThat(metadata.getProperties()).hasSize(2) + .containsEntry("env", "test") + .containsEntry("region", "us-west-2"); + } + + @Test + void createWithNullProperties() { + ServiceMetadata metadata = new ServiceMetadata("user-service", "1.0.0", List.of(), null); + + assertThat(metadata.getProperties()).isEmpty(); + } + + @Test + void createWithMultipleInterfaces() { + List interfaces = List.of("com.example.UserService", "com.example.UserAdminService"); + ServiceMetadata metadata = new ServiceMetadata("user-service", "1.0.0", interfaces); + + assertThat(metadata.getInterfaces()).hasSize(2) + .containsExactly("com.example.UserService", "com.example.UserAdminService"); + } + + @Test + void withPropertiesReturnsNewInstance() { + ServiceMetadata original = new ServiceMetadata("user-service", "1.0.0", List.of()); + Map newProps = Map.of("env", "prod"); + + ServiceMetadata modified = original.withProperties(newProps); + + assertThat(modified).isNotSameAs(original); + assertThat(original.getProperties()).isEmpty(); + assertThat(modified.getProperties()).containsEntry("env", "prod"); + } + + @Test + void withPropertiesWithNullMap() { + ServiceMetadata original = new ServiceMetadata("user-service", "1.0.0", List.of(), Map.of("env", "test")); + ServiceMetadata modified = original.withProperties(null); + + assertThat(modified.getProperties()).isEmpty(); + } + + @Test + void withPropertiesPreservesOtherFields() { + ServiceMetadata original = new ServiceMetadata("user-service", "2.0.0", List.of("com.example.UserService")); + ServiceMetadata modified = original.withProperties(Map.of("new-key", "new-value")); + + assertThat(modified.getId()).isEqualTo("user-service"); + assertThat(modified.getVersion()).isEqualTo("2.0.0"); + assertThat(modified.getInterfaces()).containsExactly("com.example.UserService"); + assertThat(modified.getProperties()).containsEntry("new-key", "new-value"); + } + + @Test + void getPropertyReturnsValue() { + Map props = Map.of("env", "production", "timeout", "30s"); + ServiceMetadata metadata = new ServiceMetadata("user-service", "1.0.0", List.of(), props); + + assertThat(metadata.getProperty("env")).isEqualTo("production"); + assertThat(metadata.getProperty("timeout")).isEqualTo("30s"); + } + + @Test + void getPropertyReturnsNullForMissingKey() { + ServiceMetadata metadata = new ServiceMetadata("user-service", "1.0.0", List.of()); + + assertThat(metadata.getProperty("nonexistent")).isNull(); + } + + @Test + void hasPropertyReturnsTrueWhenExists() { + Map props = Map.of("env", "test"); + ServiceMetadata metadata = new ServiceMetadata("user-service", "1.0.0", List.of(), props); + + assertThat(metadata.hasProperty("env")).isTrue(); + } + + @Test + void hasPropertyReturnsFalseWhenNotExists() { + ServiceMetadata metadata = new ServiceMetadata("user-service", "1.0.0", List.of()); + + assertThat(metadata.hasProperty("env")).isFalse(); + } + + @Test + void hasPropertyReturnsFalseForEmptyMetadata() { + ServiceMetadata metadata = new ServiceMetadata("user-service", "1.0.0", List.of()); + + assertThat(metadata.hasProperty("any-key")).isFalse(); + } + + @Test + void equalsReturnsTrueForSameObject() { + ServiceMetadata metadata = new ServiceMetadata("user-service", "1.0.0", List.of()); + + assertThat(metadata).isEqualTo(metadata); + } + + @Test + void equalsReturnsFalseForNull() { + ServiceMetadata metadata = new ServiceMetadata("user-service", "1.0.0", List.of()); + + assertThat(metadata).isNotEqualTo(null); + } + + @Test + void equalsReturnsFalseForDifferentType() { + ServiceMetadata metadata = new ServiceMetadata("user-service", "1.0.0", List.of()); + + assertThat(metadata).isNotEqualTo("not a ServiceMetadata"); + } + + @Test + void equalsReturnsTrueForSameValues() { + ServiceMetadata metadata1 = new ServiceMetadata("user-service", "1.0.0", List.of("com.example.UserService")); + ServiceMetadata metadata2 = new ServiceMetadata("user-service", "1.0.0", List.of("com.example.UserService")); + + assertThat(metadata1).isEqualTo(metadata2); + } + + @Test + void equalsReturnsFalseForDifferentId() { + ServiceMetadata metadata1 = new ServiceMetadata("user-service", "1.0.0", List.of()); + ServiceMetadata metadata2 = new ServiceMetadata("order-service", "1.0.0", List.of()); + + assertThat(metadata1).isNotEqualTo(metadata2); + } + + @Test + void equalsReturnsFalseForDifferentVersion() { + ServiceMetadata metadata1 = new ServiceMetadata("user-service", "1.0.0", List.of()); + ServiceMetadata metadata2 = new ServiceMetadata("user-service", "2.0.0", List.of()); + + assertThat(metadata1).isNotEqualTo(metadata2); + } + + @Test + void equalsReturnsFalseForDifferentProperties() { + ServiceMetadata metadata1 = new ServiceMetadata("user-service", "1.0.0", List.of(), Map.of("env", "test")); + ServiceMetadata metadata2 = new ServiceMetadata("user-service", "1.0.0", List.of(), Map.of("env", "prod")); + + assertThat(metadata1).isNotEqualTo(metadata2); + } + + @Test + void equalsReturnsTrueForNullVersionBoth() { + ServiceMetadata metadata1 = new ServiceMetadata("user-service", null, List.of()); + ServiceMetadata metadata2 = new ServiceMetadata("user-service", null, List.of()); + + assertThat(metadata1).isEqualTo(metadata2); + } + + @Test + void equalsReturnsTrueForEmptyPropertiesBoth() { + ServiceMetadata metadata1 = new ServiceMetadata("user-service", "1.0.0", List.of()); + ServiceMetadata metadata2 = new ServiceMetadata("user-service", "1.0.0", List.of()); + + assertThat(metadata1).isEqualTo(metadata2); + } + + @Test + void hashCodeIsConsistent() { + ServiceMetadata metadata1 = new ServiceMetadata("user-service", "1.0.0", List.of()); + ServiceMetadata metadata2 = new ServiceMetadata("user-service", "1.0.0", List.of()); + + assertThat(metadata1.hashCode()).isEqualTo(metadata2.hashCode()); + } + + @Test + void hashCodeDiffersForDifferentId() { + ServiceMetadata metadata1 = new ServiceMetadata("user-service", "1.0.0", List.of()); + ServiceMetadata metadata2 = new ServiceMetadata("order-service", "1.0.0", List.of()); + + assertThat(metadata1.hashCode()).isNotEqualTo(metadata2.hashCode()); + } + + @Test + void hashCodeDiffersForDifferentProperties() { + ServiceMetadata metadata1 = new ServiceMetadata("user-service", "1.0.0", List.of(), Map.of("env", "test")); + ServiceMetadata metadata2 = new ServiceMetadata("user-service", "1.0.0", List.of(), Map.of("env", "prod")); + + assertThat(metadata1.hashCode()).isNotEqualTo(metadata2.hashCode()); + } + + @Test + void toStringContainsId() { + ServiceMetadata metadata = new ServiceMetadata("user-service", "1.0.0", List.of()); + + assertThat(metadata.toString()).contains("user-service"); + } + + @Test + void toStringContainsVersion() { + ServiceMetadata metadata = new ServiceMetadata("user-service", "1.0.0", List.of()); + + assertThat(metadata.toString()).contains("1.0.0"); + } + + @Test + void unmodifiableInterfaces() { + List interfaces = new ArrayList<>(List.of("com.example.UserService")); + ServiceMetadata metadata = new ServiceMetadata("user-service", "1.0.0", interfaces); + + interfaces.add("com.example.AnotherService"); + + assertThat(metadata.getInterfaces()).hasSize(1) + .containsExactly("com.example.UserService"); + } + + @Test + void propertiesAreDefensivelyCopied() { + Map mutableProps = new HashMap<>(); + mutableProps.put("env", "test"); + ServiceMetadata metadata = new ServiceMetadata("user-service", "1.0.0", List.of(), mutableProps); + + mutableProps.put("new-key", "new-value"); + mutableProps.remove("env"); + + assertThat(metadata.getProperties()).hasSize(1) + .containsEntry("env", "test"); + } + } \ No newline at end of file diff --git a/today-service-api/src/test/java/infra/cloud/service/UserService.java b/today-service-api/src/test/java/infra/cloud/service/UserService.java new file mode 100644 index 0000000..1b40c48 --- /dev/null +++ b/today-service-api/src/test/java/infra/cloud/service/UserService.java @@ -0,0 +1,26 @@ +/* + * Copyright 2021 - 2026 the TODAY 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 + * + * https://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 infra.cloud.service; + +/** + * @author 海子 Yang + * @since 1.0 2026/3/15 22:36 + */ +public interface UserService { + + Object getById(long id); +} diff --git a/today-service-client/src/main/java/infra/cloud/client/annotation/config/ServiceClientAutoConfiguration.java b/today-service-client/src/main/java/infra/cloud/client/annotation/config/ServiceClientAutoConfiguration.java index 2c57716..d672c89 100644 --- a/today-service-client/src/main/java/infra/cloud/client/annotation/config/ServiceClientAutoConfiguration.java +++ b/today-service-client/src/main/java/infra/cloud/client/annotation/config/ServiceClientAutoConfiguration.java @@ -24,7 +24,7 @@ import infra.cloud.service.DefaultRemotingOperationsProvider; import infra.cloud.service.DefaultServiceInterfaceMetadataProvider; import infra.cloud.service.DefaultServiceProxyFactory; -import infra.cloud.service.PackageInfoServiceMetadataProvider; +import infra.cloud.service.DefaultServiceMetadataProvider; import infra.cloud.service.RemotingOperationsProvider; import infra.cloud.service.ReturnValueResolver; import infra.cloud.service.ServiceInterfaceMetadataProvider; @@ -62,7 +62,7 @@ public static RemotingOperationsProvider remotingOperationsProvider(DiscoveryCli @Component @ConditionalOnMissingBean public static ServiceMetadataProvider serviceMetadataProvider() { - return new PackageInfoServiceMetadataProvider(); + return new DefaultServiceMetadataProvider(); } @Component diff --git a/today-service-provider/src/main/java/infra/cloud/provider/config/ServiceProviderAutoConfiguration.java b/today-service-provider/src/main/java/infra/cloud/provider/config/ServiceProviderAutoConfiguration.java index 104d6b8..5c63f91 100644 --- a/today-service-provider/src/main/java/infra/cloud/provider/config/ServiceProviderAutoConfiguration.java +++ b/today-service-provider/src/main/java/infra/cloud/provider/config/ServiceProviderAutoConfiguration.java @@ -28,7 +28,7 @@ import infra.cloud.provider.ServiceProviderServer; import infra.cloud.provider.ServiceServerProperties; import infra.cloud.provider.TcpServerTransportFactory; -import infra.cloud.service.PackageInfoServiceMetadataProvider; +import infra.cloud.service.DefaultServiceMetadataProvider; import infra.cloud.service.ServiceInterfaceMetadataProvider; import infra.cloud.service.ServiceMetadataProvider; import infra.cloud.service.ServiceMethod; @@ -64,7 +64,7 @@ public static LocalServiceHolder localServiceHolder(ServiceMetadataProvider meta @Component @ConditionalOnMissingBean public static ServiceMetadataProvider serviceMetadataProvider() { - return new PackageInfoServiceMetadataProvider(); + return new DefaultServiceMetadataProvider(); } @Component From 0640786fcdf7c01cb5fa8cbff0ab13a2433f3fc7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Sun, 15 Mar 2026 23:21:43 +0800 Subject: [PATCH 087/104] =?UTF-8?q?:sparkles:=20=E5=85=83=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E6=8F=90=E4=BE=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/infra/cloud/plugin/ServiceClassFinder.java | 3 ++- .../src/main/java/infra/cloud/service/ServiceMetadata.java | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/today-cloud-build/today-cloud-gradle-plugin/src/main/java/infra/cloud/plugin/ServiceClassFinder.java b/today-cloud-build/today-cloud-gradle-plugin/src/main/java/infra/cloud/plugin/ServiceClassFinder.java index 90fb6f4..4612fd9 100644 --- a/today-cloud-build/today-cloud-gradle-plugin/src/main/java/infra/cloud/plugin/ServiceClassFinder.java +++ b/today-cloud-build/today-cloud-gradle-plugin/src/main/java/infra/cloud/plugin/ServiceClassFinder.java @@ -37,6 +37,7 @@ import infra.bytecode.ClassReader; import infra.bytecode.ClassVisitor; import infra.bytecode.Type; +import infra.lang.Constant; /** * Utility class for finding service interfaces within a given directory structure by scanning @@ -216,7 +217,7 @@ private static final class ClassDescriptor extends ClassVisitor { @Override public void visit(int version, int access, String name, @Nullable String signature, @Nullable String superName, String @Nullable [] interfaces) { if (Modifier.isPublic(access) && Modifier.isInterface(access)) { - this.name = name; + this.name = name.replace(Constant.PATH_SEPARATOR, Constant.PACKAGE_SEPARATOR); } } diff --git a/today-service-api/src/main/java/infra/cloud/service/ServiceMetadata.java b/today-service-api/src/main/java/infra/cloud/service/ServiceMetadata.java index 69e2f41..a0d9da3 100644 --- a/today-service-api/src/main/java/infra/cloud/service/ServiceMetadata.java +++ b/today-service-api/src/main/java/infra/cloud/service/ServiceMetadata.java @@ -172,6 +172,7 @@ public String toString() { return ToStringBuilder.forInstance(this) .append("id", id) .append("version", version) + .append("interfaces", interfaces) .append("properties", properties) .toString(); } From 5f3306bd44e4f568fe95f03af26c7fba9fbe0cf6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Sun, 15 Mar 2026 23:24:12 +0800 Subject: [PATCH 088/104] =?UTF-8?q?:sparkles:=20=E5=85=83=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E6=8F=90=E4=BE=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/infra/cloud/service/ServiceMetadata.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/today-service-api/src/main/java/infra/cloud/service/ServiceMetadata.java b/today-service-api/src/main/java/infra/cloud/service/ServiceMetadata.java index a0d9da3..f9786c6 100644 --- a/today-service-api/src/main/java/infra/cloud/service/ServiceMetadata.java +++ b/today-service-api/src/main/java/infra/cloud/service/ServiceMetadata.java @@ -159,12 +159,13 @@ public boolean equals(Object o) { return false; return Objects.equals(id, that.id) && Objects.equals(version, that.version) + && Objects.equals(interfaces, that.interfaces) && Objects.equals(properties, that.properties); } @Override public int hashCode() { - return Objects.hash(id, version, properties); + return Objects.hash(id, version, interfaces, properties); } @Override From c10db3604efc9c168d979bacecab5afde5395732 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Sun, 15 Mar 2026 23:29:12 +0800 Subject: [PATCH 089/104] =?UTF-8?q?:bug:=20=E4=BF=AE=E5=A4=8D=E6=9C=8D?= =?UTF-8?q?=E5=8A=A1=E5=85=83=E6=95=B0=E6=8D=AE=E7=94=9F=E6=88=90=E4=B8=AD?= =?UTF-8?q?=E7=9A=84=E9=A1=B9=E7=9B=AE=E7=9B=AE=E5=BD=95=E8=B7=AF=E5=BE=84?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 修复了 GenerateServiceMetadata 中使用错误的项目根目录路径 - 在 DefaultServiceMetadataProvider 中添加了 Nullable 注解支持 - 修改 createMetadata 方法参数类型从 MultiValueMap 到 Properties - 添加了接口列表为空时的空值检查和返回逻辑 - 重命名 serviceMetadata 变量为 serviceMetadataList 以提高可读性 - 优化了元数据加载过程中的空值处理机制 --- .../cloud/plugin/GenerateServiceMetadata.java | 4 +-- .../DefaultServiceMetadataProvider.java | 27 +++++++++++++------ 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/today-cloud-build/today-cloud-gradle-plugin/src/main/java/infra/cloud/plugin/GenerateServiceMetadata.java b/today-cloud-build/today-cloud-gradle-plugin/src/main/java/infra/cloud/plugin/GenerateServiceMetadata.java index ee5f8ca..2d44516 100644 --- a/today-cloud-build/today-cloud-gradle-plugin/src/main/java/infra/cloud/plugin/GenerateServiceMetadata.java +++ b/today-cloud-build/today-cloud-gradle-plugin/src/main/java/infra/cloud/plugin/GenerateServiceMetadata.java @@ -65,9 +65,9 @@ public void generate() throws IOException { properties.setProperty("service.group", serviceMetadata.getServiceGroup().get()); properties.setProperty("service.description", serviceMetadata.getServiceDescription().get()); - List interfaces = ServiceClassFinder.findInterfaces(project.getRootDir()); + List interfaces = ServiceClassFinder.findInterfaces(project.getProjectDir()); properties.setProperty("service.interfaces", StringUtils.collectionToCommaDelimitedString(interfaces)); - + convertToStringValues(serviceMetadata.getAdditional().get()) .forEach((name, value) -> { if (value != null) { diff --git a/today-service-api/src/main/java/infra/cloud/service/DefaultServiceMetadataProvider.java b/today-service-api/src/main/java/infra/cloud/service/DefaultServiceMetadataProvider.java index f1af7f3..3a61e42 100644 --- a/today-service-api/src/main/java/infra/cloud/service/DefaultServiceMetadataProvider.java +++ b/today-service-api/src/main/java/infra/cloud/service/DefaultServiceMetadataProvider.java @@ -16,6 +16,8 @@ package infra.cloud.service; +import org.jspecify.annotations.Nullable; + import java.io.IOException; import java.io.InputStream; import java.net.URL; @@ -101,13 +103,21 @@ private Map loadMetadata(String metadataLocation) { /** * Creates ServiceMetadata from loaded properties. * - * @param props the loaded properties + * @param properties the loaded properties * @return a new ServiceMetadata instance */ - protected ServiceMetadata createMetadata(MultiValueMap props) { + protected @Nullable ServiceMetadata createMetadata(Properties properties) { + MultiValueMap props = MultiValueMap.forLinkedHashMap(); + readStrategies(props, properties); + + List interfaces = props.remove(KEY_SERVICE_INTERFACES); + + if (interfaces == null) { + return null; + } + String serviceId = CollectionUtils.firstElement(props.remove(KEY_SERVICE_ID)); String version = CollectionUtils.firstElement(props.remove(KEY_SERVICE_VERSION)); - List interfaces = props.remove(KEY_SERVICE_INTERFACES); Set keys = props.keySet(); var metadata = CollectionUtils.newLinkedHashMap(keys.size()); @@ -122,7 +132,7 @@ protected ServiceMetadata createMetadata(MultiValueMap props) { } protected List loadResources(ClassLoader classLoader, String metadataLocation) { - List serviceMetadata = new ArrayList<>(); + List serviceMetadataList = new ArrayList<>(); try { log.debug("Detecting service-metadata location '{}'", metadataLocation); Enumeration urls = classLoader.getResources(metadataLocation); @@ -135,16 +145,17 @@ protected List loadResources(ClassLoader classLoader, String me properties.load(inputStream); } - MultiValueMap metadata = MultiValueMap.forLinkedHashMap(); - readStrategies(metadata, properties); - serviceMetadata.add(createMetadata(metadata)); + ServiceMetadata metadata = createMetadata(properties); + if (metadata != null) { + serviceMetadataList.add(metadata); + } } } catch (IOException ex) { throw new IllegalArgumentException( "Unable to load service-metadata from location [%s]".formatted(metadataLocation), ex); } - return serviceMetadata; + return serviceMetadataList; } } From 6bac5e1a384b78d67483a5b03b27a58b7b783a54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Mon, 16 Mar 2026 20:28:50 +0800 Subject: [PATCH 090/104] =?UTF-8?q?:art:=20=E6=8E=A5=E5=8F=A3=E5=85=83?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=20ServiceMetadata=20=E7=94=9F=E6=88=90?= =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/infra/cloud/plugin/GenerateServiceMetadata.java | 7 +++++-- ...rviceClassFinder.java => ServiceInterfacesFinder.java} | 8 ++++---- 2 files changed, 9 insertions(+), 6 deletions(-) rename today-cloud-build/today-cloud-gradle-plugin/src/main/java/infra/cloud/plugin/{ServiceClassFinder.java => ServiceInterfacesFinder.java} (97%) diff --git a/today-cloud-build/today-cloud-gradle-plugin/src/main/java/infra/cloud/plugin/GenerateServiceMetadata.java b/today-cloud-build/today-cloud-gradle-plugin/src/main/java/infra/cloud/plugin/GenerateServiceMetadata.java index 2d44516..dc4b8d9 100644 --- a/today-cloud-build/today-cloud-gradle-plugin/src/main/java/infra/cloud/plugin/GenerateServiceMetadata.java +++ b/today-cloud-build/today-cloud-gradle-plugin/src/main/java/infra/cloud/plugin/GenerateServiceMetadata.java @@ -52,6 +52,11 @@ public abstract class GenerateServiceMetadata extends DefaultTask { @TaskAction public void generate() throws IOException { Project project = getProject(); + List interfaces = ServiceInterfacesFinder.findInterfaces(project.getProjectDir()); + if (interfaces.isEmpty()) { + return; + } + ServiceMetadataExtension serviceMetadata = project.getExtensions().getByType(ServiceMetadataExtension.class); var outputDir = project.getLayout().getBuildDirectory().dir("resources/main/META-INF").get().getAsFile(); @@ -64,8 +69,6 @@ public void generate() throws IOException { properties.setProperty("service.version", serviceMetadata.getServiceVersion().get()); properties.setProperty("service.group", serviceMetadata.getServiceGroup().get()); properties.setProperty("service.description", serviceMetadata.getServiceDescription().get()); - - List interfaces = ServiceClassFinder.findInterfaces(project.getProjectDir()); properties.setProperty("service.interfaces", StringUtils.collectionToCommaDelimitedString(interfaces)); convertToStringValues(serviceMetadata.getAdditional().get()) diff --git a/today-cloud-build/today-cloud-gradle-plugin/src/main/java/infra/cloud/plugin/ServiceClassFinder.java b/today-cloud-build/today-cloud-gradle-plugin/src/main/java/infra/cloud/plugin/ServiceInterfacesFinder.java similarity index 97% rename from today-cloud-build/today-cloud-gradle-plugin/src/main/java/infra/cloud/plugin/ServiceClassFinder.java rename to today-cloud-build/today-cloud-gradle-plugin/src/main/java/infra/cloud/plugin/ServiceInterfacesFinder.java index 4612fd9..4ec61fc 100644 --- a/today-cloud-build/today-cloud-gradle-plugin/src/main/java/infra/cloud/plugin/ServiceClassFinder.java +++ b/today-cloud-build/today-cloud-gradle-plugin/src/main/java/infra/cloud/plugin/ServiceInterfacesFinder.java @@ -50,7 +50,7 @@ * @author Harry Yang * @since 4.0 */ -public abstract class ServiceClassFinder { +public abstract class ServiceInterfacesFinder { private static final String DOT_CLASS = ".class"; @@ -59,12 +59,12 @@ public abstract class ServiceClassFinder { /** * File filter that accepts only files ending with {@code .class}. */ - private static final FileFilter CLASS_FILE_FILTER = ServiceClassFinder::isClassFile; + private static final FileFilter CLASS_FILE_FILTER = ServiceInterfacesFinder::isClassFile; /** * File filter that accepts only directories that do not start with a dot (hidden directories). */ - private static final FileFilter PACKAGE_DIRECTORY_FILTER = ServiceClassFinder::isPackageDirectory; + private static final FileFilter PACKAGE_DIRECTORY_FILTER = ServiceInterfacesFinder::isPackageDirectory; /** * Checks if the given file is a valid Java class file. @@ -99,7 +99,7 @@ private static boolean isPackageDirectory(File file) { */ public static List findInterfaces(File rootDirectory, @Nullable String annotationName) throws IOException { InterfacesCallback callback = new InterfacesCallback(annotationName); - ServiceClassFinder.doWithInterface(rootDirectory, callback); + ServiceInterfacesFinder.doWithInterface(rootDirectory, callback); return callback.getInterfaces(); } From 3008ec4bc95b4d6aba6ee0a5301aa0f80e73d6d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Mon, 16 Mar 2026 21:44:52 +0800 Subject: [PATCH 091/104] =?UTF-8?q?:art:=20ServiceMetadata=20interfaces=20?= =?UTF-8?q?=E8=AE=BE=E8=AE=A1=E6=88=90=E4=B8=8D=E5=8F=AF=E5=8F=98=E7=9A=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/infra/cloud/service/ServiceMetadata.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/today-service-api/src/main/java/infra/cloud/service/ServiceMetadata.java b/today-service-api/src/main/java/infra/cloud/service/ServiceMetadata.java index f9786c6..5b99f41 100644 --- a/today-service-api/src/main/java/infra/cloud/service/ServiceMetadata.java +++ b/today-service-api/src/main/java/infra/cloud/service/ServiceMetadata.java @@ -69,7 +69,7 @@ public ServiceMetadata(String id, @Nullable String version, List interfa Assert.notNull(interfaces, "interfaces is required"); this.id = id; this.version = version; - this.interfaces = interfaces; + this.interfaces = List.copyOf(interfaces); this.properties = properties == null ? Map.of() : Map.copyOf(properties); } From 78937c0e3334ef7dea448904a27c3f49b7c40d6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Mon, 16 Mar 2026 23:06:29 +0800 Subject: [PATCH 092/104] =?UTF-8?q?:recycle:=20=E9=87=8D=E6=9E=84=E5=BA=8F?= =?UTF-8?q?=E5=88=97=E5=8C=96=E6=8E=A5=E5=8F=A3=E5=92=8C=E5=AE=9E=E7=8E=B0?= =?UTF-8?q?=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将 RpcArgumentSerialization 重命名为 ArgumentSerialization - 更新 ValueSerialization 接口的参数命名从 payload 到 writable - 添加详细的 Javadoc 注释到序列化相关接口和方法 - 修改 SimpleValueArgumentSerialization 的类型匹配逻辑 - 更新客户端和服务端的序列化器配置和调用方式 - 调整 ServiceMethodInvoker 的构造函数参数 - 优化 RequestSerializer 的请求序列化流程 - 修改 RpcRequestDeserializer 的反序列化实现 - 添加 MessagePackReader 在服务端处理器中的使用 --- .../serialize/ArgumentSerialization.java | 70 +++++++++++++++++++ .../ProtobufArgumentSerialization.java | 2 +- .../serialize/RpcArgumentSerialization.java | 43 ------------ .../SimpleValueArgumentSerialization.java | 17 +++-- .../value/FuncValueSerialization.java | 4 +- .../serialize/value/ValueSerialization.java | 39 ++++++++++- .../infra/cloud/service/ServiceMethod.java | 3 +- .../ServiceClientAutoConfiguration.java | 47 +++++++++++-- .../service/DefaultServiceProxyFactory.java | 24 +++---- .../cloud/service/ServiceMethodInvoker.java | 37 +++++----- .../service/serialize/RequestSerializer.java | 27 ++++--- .../main/resources/META-INF/today.strategies | 2 +- .../provider/RpcRequestDeserializer.java | 25 +++---- .../cloud/provider/ServiceChannelHandler.java | 3 +- 14 files changed, 217 insertions(+), 126 deletions(-) create mode 100644 today-service-api/src/main/java/infra/cloud/serialize/ArgumentSerialization.java delete mode 100644 today-service-api/src/main/java/infra/cloud/serialize/RpcArgumentSerialization.java diff --git a/today-service-api/src/main/java/infra/cloud/serialize/ArgumentSerialization.java b/today-service-api/src/main/java/infra/cloud/serialize/ArgumentSerialization.java new file mode 100644 index 0000000..1220314 --- /dev/null +++ b/today-service-api/src/main/java/infra/cloud/serialize/ArgumentSerialization.java @@ -0,0 +1,70 @@ +/* + * Copyright 2021 - 2026 the TODAY 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 + * + * https://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 infra.cloud.serialize; + +import org.jspecify.annotations.Nullable; + +import infra.core.MethodParameter; + +/** + * A strategy interface for serializing and deserializing method arguments. + *

              + * Implementations of this interface define how specific argument types are converted + * to a wire format (serialization) and reconstructed from it (deserialization). + *

              + * + * @param the type of the argument being serialized or deserialized + * @author 海子 Yang + * @since 1.0 2024/12/20 16:29 + */ +public interface ArgumentSerialization { + + /** + * Checks whether this serializer supports the given method parameter. + *

              This method is typically used to determine if the current implementation + * can handle the serialization/deserialization logic for the specified parameter. + * + * @param parameter the method parameter to check + * @return {@code true} if this serializer supports the parameter; {@code false} otherwise + */ + boolean supportsArgument(MethodParameter parameter); + + /** + * Serializes the given value based on the provided method parameter. + *

              The serialized data is written to the provided {@link Writable} instance. + * + * @param parameter the method parameter associated with the value + * @param value the value to serialize, may be {@code null} + * @param writable the destination to write the serialized data to + * @throws SerializationException if an error occurs during serialization + */ + void serialize(MethodParameter parameter, @Nullable T value, Writable writable) + throws SerializationException; + + /** + * Deserializes a value from the provided readable source based on the method parameter. + *

              Reads data from the {@link Readable} instance and reconstructs the original object. + * + * @param parameter the method parameter describing the expected type + * @param readable the source to read the serialized data from + * @return the deserialized value, or {@code null} if applicable + * @throws SerializationException if an error occurs during deserialization + */ + @Nullable + T deserialize(MethodParameter parameter, Readable readable) throws SerializationException; + +} diff --git a/today-service-api/src/main/java/infra/cloud/serialize/ProtobufArgumentSerialization.java b/today-service-api/src/main/java/infra/cloud/serialize/ProtobufArgumentSerialization.java index daad002..8cbada5 100644 --- a/today-service-api/src/main/java/infra/cloud/serialize/ProtobufArgumentSerialization.java +++ b/today-service-api/src/main/java/infra/cloud/serialize/ProtobufArgumentSerialization.java @@ -33,7 +33,7 @@ * @author 海子 Yang * @since 1.0 2024/12/20 17:46 */ -public class ProtobufArgumentSerialization implements RpcArgumentSerialization, ReturnValueSerializer { +public class ProtobufArgumentSerialization implements ArgumentSerialization, ReturnValueSerializer { private static final ConcurrentReferenceHashMap, Method> methodCache = new ConcurrentReferenceHashMap<>(); diff --git a/today-service-api/src/main/java/infra/cloud/serialize/RpcArgumentSerialization.java b/today-service-api/src/main/java/infra/cloud/serialize/RpcArgumentSerialization.java deleted file mode 100644 index 8b5cd77..0000000 --- a/today-service-api/src/main/java/infra/cloud/serialize/RpcArgumentSerialization.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2021 - 2026 the TODAY 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 - * - * https://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 infra.cloud.serialize; - -import org.jspecify.annotations.Nullable; - -import infra.core.MethodParameter; - -/** - * @author 海子 Yang - * @since 1.0 2024/12/20 16:29 - */ -public interface RpcArgumentSerialization { - - /** - * Whether the given parameter is supported by this resolver. - *

              - * static match - *

              - */ - boolean supportsArgument(MethodParameter parameter); - - void serialize(MethodParameter parameter, @Nullable T value, Writable writable) - throws SerializationException; - - @Nullable - T deserialize(MethodParameter parameter, Readable readable) throws SerializationException; - -} diff --git a/today-service-api/src/main/java/infra/cloud/serialize/SimpleValueArgumentSerialization.java b/today-service-api/src/main/java/infra/cloud/serialize/SimpleValueArgumentSerialization.java index 2b3df42..714d6a0 100644 --- a/today-service-api/src/main/java/infra/cloud/serialize/SimpleValueArgumentSerialization.java +++ b/today-service-api/src/main/java/infra/cloud/serialize/SimpleValueArgumentSerialization.java @@ -21,17 +21,23 @@ import java.util.HashMap; import java.util.Map; -import infra.beans.BeanUtils; import infra.cloud.serialize.value.ValueSerialization; import infra.core.MethodParameter; import static infra.cloud.serialize.value.ValueSerialization.map; /** + * A simple implementation of {@link ArgumentSerialization} that handles basic value types. + *

              + * This class provides serialization and deserialization support for primitive types + * and their corresponding wrapper classes, including {@code int}, {@code long}, and {@code short}. + * It maintains an internal map to associate each supported type with its specific + * {@link ValueSerialization} logic. + * * @author 海子 Yang * @since 1.0 2025/3/8 21:15 */ -public class SimpleValueArgumentSerialization implements RpcArgumentSerialization { +public class SimpleValueArgumentSerialization implements ArgumentSerialization { private final Map, ValueSerialization> serializationMap = new HashMap<>(); @@ -48,7 +54,7 @@ public SimpleValueArgumentSerialization() { @Override public boolean supportsArgument(MethodParameter parameter) { - return BeanUtils.isSimpleProperty(parameter.getParameterType()); + return serializationMap.containsKey(parameter.getParameterType()); } @Override @@ -58,9 +64,8 @@ public void serialize(MethodParameter parameter, @Nullable Object value, Writabl serialization.serialize(parameter, value, writable); } - @Nullable @Override - public Object deserialize(MethodParameter parameter, Readable readable) { + public @Nullable Object deserialize(MethodParameter parameter, Readable readable) { var serialization = findSerialization(parameter.getParameterType()); return serialization.deserialize(parameter, readable); } @@ -71,7 +76,7 @@ private ValueSerialization findSerialization(Class type) { if (serialization == null) { Class superclass = type.getSuperclass(); if (superclass == null || superclass == Object.class) { - throw new IllegalStateException("ValueSerialization for type %s not found".formatted(type)); // todo type + throw new IllegalStateException("ValueSerialization for type %s not found".formatted(type)); } return findSerialization(superclass); } diff --git a/today-service-api/src/main/java/infra/cloud/serialize/value/FuncValueSerialization.java b/today-service-api/src/main/java/infra/cloud/serialize/value/FuncValueSerialization.java index ab2c1f2..41133ac 100644 --- a/today-service-api/src/main/java/infra/cloud/serialize/value/FuncValueSerialization.java +++ b/today-service-api/src/main/java/infra/cloud/serialize/value/FuncValueSerialization.java @@ -40,8 +40,8 @@ final class FuncValueSerialization implements ValueSerialization { } @Override - public void serialize(MethodParameter parameter, T value, Writable payload) { - writer.accept(payload, value); + public void serialize(MethodParameter parameter, T value, Writable writable) { + writer.accept(writable, value); } @Override diff --git a/today-service-api/src/main/java/infra/cloud/serialize/value/ValueSerialization.java b/today-service-api/src/main/java/infra/cloud/serialize/value/ValueSerialization.java index 1bc3f3f..a459d38 100644 --- a/today-service-api/src/main/java/infra/cloud/serialize/value/ValueSerialization.java +++ b/today-service-api/src/main/java/infra/cloud/serialize/value/ValueSerialization.java @@ -20,23 +20,56 @@ import java.util.function.Function; import infra.cloud.serialize.Readable; -import infra.cloud.serialize.Writable; import infra.cloud.serialize.SerializationException; +import infra.cloud.serialize.Writable; import infra.core.MethodParameter; import infra.lang.Assert; /** + * Defines a strategy for serializing and deserializing values of type {@code T}. + *

              + * This interface provides methods to convert a Java object into a writable format + * and to reconstruct an object from a readable format, typically used in RPC or + * data persistence scenarios. It also offers a static factory method to create + * instances based on functional definitions. + * + * @param the type of value to be serialized and deserialized * @author 海子 Yang * @since 1.0 2025/3/8 21:31 */ public interface ValueSerialization { - void serialize(MethodParameter parameter, T value, Writable payload) + /** + * Serializes the given value into the provided writable output. + * + * @param parameter the method parameter context associated with this serialization + * @param value the value to serialize + * @param writable the target output to write the serialized data + * @throws SerializationException if an error occurs during serialization + */ + void serialize(MethodParameter parameter, T value, Writable writable) throws SerializationException; - T deserialize(MethodParameter parameter, Readable payload) + /** + * Deserializes a value from the provided readable input. + * + * @param parameter the method parameter context associated with this deserialization + * @param readable the source input to read the serialized data + * @return the deserialized value of type {@code T} + * @throws SerializationException if an error occurs during deserialization + */ + T deserialize(MethodParameter parameter, Readable readable) throws SerializationException; + /** + * Creates a {@code ValueSerialization} instance using the provided reader and writer functions. + * + * @param the type of value to handle + * @param reader a function to read and construct an object from {@link Readable} + * @param writer a consumer to write an object to {@link Writable} + * @return a new {@code ValueSerialization} instance + * @throws IllegalArgumentException if either reader or writer is null + */ static ValueSerialization map(Function reader, BiConsumer writer) { Assert.notNull(reader, "reader Function is required"); Assert.notNull(writer, "writer BiConsumer is required"); diff --git a/today-service-api/src/main/java/infra/cloud/service/ServiceMethod.java b/today-service-api/src/main/java/infra/cloud/service/ServiceMethod.java index 6b10fb0..b45a775 100644 --- a/today-service-api/src/main/java/infra/cloud/service/ServiceMethod.java +++ b/today-service-api/src/main/java/infra/cloud/service/ServiceMethod.java @@ -40,8 +40,7 @@ public class ServiceMethod { protected final Method method; - @Nullable - private MethodParameter returnTypeParameter; + private @Nullable MethodParameter returnTypeParameter; public ServiceMethod(ServiceMetadata serviceMetadata, Class serviceInterface, Method method) { this.parameters = initMethodParameters(method); diff --git a/today-service-client/src/main/java/infra/cloud/client/annotation/config/ServiceClientAutoConfiguration.java b/today-service-client/src/main/java/infra/cloud/client/annotation/config/ServiceClientAutoConfiguration.java index d672c89..5b52831 100644 --- a/today-service-client/src/main/java/infra/cloud/client/annotation/config/ServiceClientAutoConfiguration.java +++ b/today-service-client/src/main/java/infra/cloud/client/annotation/config/ServiceClientAutoConfiguration.java @@ -16,24 +16,36 @@ package infra.cloud.client.annotation.config; +import java.util.List; + import infra.beans.factory.ObjectProvider; import infra.cloud.client.DiscoveryClient; import infra.cloud.client.annotation.ConditionalOnDiscoveryEnabled; import infra.cloud.client.simple.SimpleDiscoveryProperties; +import infra.cloud.serialize.ArgumentSerialization; +import infra.cloud.serialize.ReturnValueDeserializer; +import infra.cloud.serialize.ThrowableSerialization; import infra.cloud.service.ClientInterceptor; import infra.cloud.service.DefaultRemotingOperationsProvider; import infra.cloud.service.DefaultServiceInterfaceMetadataProvider; -import infra.cloud.service.DefaultServiceProxyFactory; import infra.cloud.service.DefaultServiceMetadataProvider; +import infra.cloud.service.DefaultServiceProxyFactory; import infra.cloud.service.RemotingOperationsProvider; import infra.cloud.service.ReturnValueResolver; import infra.cloud.service.ServiceInterfaceMetadataProvider; import infra.cloud.service.ServiceInterfaceMethod; +import infra.cloud.service.ServiceInvoker; import infra.cloud.service.ServiceMetadataProvider; +import infra.cloud.service.ServiceMethodInvoker; +import infra.cloud.service.serialize.RequestSerializer; +import infra.cloud.service.serialize.ResponseDeserializer; import infra.context.annotation.config.DisableDIAutoConfiguration; import infra.context.condition.ConditionalOnMissingBean; import infra.context.properties.EnableConfigurationProperties; +import infra.core.io.ResourceLoader; +import infra.lang.TodayStrategies; import infra.stereotype.Component; +import io.netty.buffer.ByteBufAllocator; /** * Auto-configuration for remote service client. @@ -41,6 +53,7 @@ * @author 海子 Yang * @since 1.0 2025/8/9 22:14 */ +@SuppressWarnings("rawtypes") @DisableDIAutoConfiguration @ConditionalOnDiscoveryEnabled @EnableConfigurationProperties(SimpleDiscoveryProperties.class) @@ -48,9 +61,35 @@ public final class ServiceClientAutoConfiguration { @Component public static DefaultServiceProxyFactory serviceProxyFactory( - ServiceInterfaceMetadataProvider metadataProvider, - RemotingOperationsProvider remotingOperationsProvider, ObjectProvider clientInterceptors) { - return new DefaultServiceProxyFactory(remotingOperationsProvider, metadataProvider, clientInterceptors.orderedList()); + ServiceInterfaceMetadataProvider metadataProvider, ServiceInvoker serviceInvoker) { + return new DefaultServiceProxyFactory(metadataProvider, serviceInvoker); + } + + @Component + public static ServiceInvoker serviceInvoker(List interceptors, RemotingOperationsProvider remotingOperationsProvider, + RequestSerializer requestSerializer, ResponseDeserializer responseDeserializer) { + return new ServiceMethodInvoker(interceptors, remotingOperationsProvider, ByteBufAllocator.DEFAULT, + requestSerializer, responseDeserializer); + } + + @Component + public static ThrowableSerialization throwableSerialization() { + return new ThrowableSerialization(); + } + + @Component + public static ResponseDeserializer responseDeserializer(List serializations, + ThrowableSerialization throwableSerialization, ResourceLoader resourceLoader) { + // order after ReturnValueDeserializer beans + serializations.addAll(TodayStrategies.find(ReturnValueDeserializer.class, resourceLoader.getClassLoader())); + return new ResponseDeserializer(serializations, throwableSerialization); + } + + @Component + public static RequestSerializer requestSerializer(List argumentSerializations, ResourceLoader resourceLoader) { + List serializations = TodayStrategies.find(ArgumentSerialization.class, resourceLoader.getClassLoader()); + argumentSerializations.addAll(serializations); // order after RpcArgumentSerialization beans + return new RequestSerializer(argumentSerializations); } @Component diff --git a/today-service-client/src/main/java/infra/cloud/service/DefaultServiceProxyFactory.java b/today-service-client/src/main/java/infra/cloud/service/DefaultServiceProxyFactory.java index aba24b0..d3fa67d 100644 --- a/today-service-client/src/main/java/infra/cloud/service/DefaultServiceProxyFactory.java +++ b/today-service-client/src/main/java/infra/cloud/service/DefaultServiceProxyFactory.java @@ -28,27 +28,27 @@ import infra.lang.Assert; import infra.util.ReflectionUtils; -import io.netty.buffer.ByteBufAllocator; /** + * Default implementation of {@link ServiceProxyFactory} that creates service proxies + * using dynamic proxy mechanisms. This factory configures proxies with the necessary + * interceptors, remoting operations provider, and service interface metadata to handle + * remote method invocations. + * * @author 海子 Yang * @since 2021/7/4 22:58 */ public class DefaultServiceProxyFactory implements ServiceProxyFactory { - private final ClientInterceptor[] interceptors; - - private final RemotingOperationsProvider remotingOperationsProvider; - private final ServiceInterfaceMetadataProvider metadataProvider; - private final ByteBufAllocator allocator = ByteBufAllocator.DEFAULT; + private final ServiceInvoker serviceInvoker; - public DefaultServiceProxyFactory(RemotingOperationsProvider remotingOperationsProvider, - ServiceInterfaceMetadataProvider metadataProvider, List interceptors) { + public DefaultServiceProxyFactory(ServiceInterfaceMetadataProvider metadataProvider, ServiceInvoker serviceInvoker) { + Assert.notNull(metadataProvider, "metadataProvider is required"); + Assert.notNull(serviceInvoker, "serviceInvoker is required"); this.metadataProvider = metadataProvider; - this.remotingOperationsProvider = remotingOperationsProvider; - this.interceptors = interceptors.toArray(new ClientInterceptor[0]); + this.serviceInvoker = serviceInvoker; } @Override @@ -56,7 +56,6 @@ public DefaultServiceProxyFactory(RemotingOperationsProvider remotingOperationsP public S getService(Class serviceInterface) { Assert.isTrue(serviceInterface.isInterface(), "service must be an interface"); var metadata = metadataProvider.getMetadata(serviceInterface); - ServiceInvoker serviceInvoker = new ServiceMethodInvoker(metadata, interceptors, remotingOperationsProvider, allocator); List serviceMethods = metadata.getServiceMethods(); return (S) Proxy.newProxyInstance(serviceInterface.getClassLoader(), new Class[] { serviceInterface }, @@ -78,9 +77,8 @@ public ServiceInvocationHandler(Class serviceInterface, List海子 Yang + * @since 1.0 2021/7/4 01:58 */ public class ServiceMethodInvoker implements ServiceInvoker { @@ -47,26 +53,24 @@ public class ServiceMethodInvoker implements ServiceInvoker { private final RemotingOperationsProvider remotingOperationsProvider; - private final ServiceInterfaceMetadata metadata; - private final ByteBufAllocator allocator; - private RequestSerializer requestSerializer; + private final RequestSerializer requestSerializer; - private ResponseDeserializer responseDeserializer; + private final ResponseDeserializer responseDeserializer; - ServiceMethodInvoker(ServiceInterfaceMetadata metadata, - ClientInterceptor[] interceptors, RemotingOperationsProvider remotingOperationsProvider, ByteBufAllocator allocator) { - this.metadata = metadata; - this.interceptors = interceptors; + public ServiceMethodInvoker(List interceptors, RemotingOperationsProvider remotingOperationsProvider, + ByteBufAllocator allocator, RequestSerializer requestSerializer, ResponseDeserializer responseDeserializer) { + this.interceptors = interceptors.toArray(new ClientInterceptor[0]); this.remotingOperationsProvider = remotingOperationsProvider; this.allocator = allocator; + this.requestSerializer = requestSerializer; + this.responseDeserializer = responseDeserializer; } @Override public InvocationResult invoke(ServiceInterfaceMethod serviceMethod, Object[] args) throws Throwable { MethodServiceInvocation invocation = new MethodServiceInvocation0(serviceMethod, args, interceptors); - return invocation.proceed(); } @@ -89,14 +93,9 @@ protected InvocationResult invokeRemoting() { private Mono createMonoPayload() { return Mono.defer(() -> { - RpcRequest request = new RpcRequest(); - request.setServiceClass(serviceMethod.getServiceInterface().getName()); - request.setMethodName(serviceMethod.getMethod().getName()); - ByteBuf buffer = allocator.ioBuffer(); - Payload payload = ByteBufPayload.create(buffer); - requestSerializer.serialize(request, buffer); - return Mono.just(payload); + requestSerializer.serialize(serviceMethod, getArguments(), new MessagePackWriter(buffer)); + return Mono.just(ByteBufPayload.create(buffer)); }); } diff --git a/today-service-client/src/main/java/infra/cloud/service/serialize/RequestSerializer.java b/today-service-client/src/main/java/infra/cloud/service/serialize/RequestSerializer.java index bc726c1..6e6a273 100644 --- a/today-service-client/src/main/java/infra/cloud/service/serialize/RequestSerializer.java +++ b/today-service-client/src/main/java/infra/cloud/service/serialize/RequestSerializer.java @@ -18,13 +18,10 @@ import java.util.List; -import infra.cloud.RpcRequest; -import infra.cloud.serialize.MessagePackWriter; +import infra.cloud.serialize.ArgumentSerialization; import infra.cloud.serialize.Writable; -import infra.cloud.serialize.RpcArgumentSerialization; -import infra.cloud.service.ServiceMethod; +import infra.cloud.service.ServiceInterfaceMethod; import infra.core.MethodParameter; -import io.netty.buffer.ByteBuf; /** * @author 海子 Yang @@ -33,31 +30,31 @@ @SuppressWarnings({ "unchecked", "rawtypes" }) public class RequestSerializer { - private final List argumentSerializations; + private final List argumentSerializations; - public RequestSerializer(List argumentSerializations) { + public RequestSerializer(List argumentSerializations) { this.argumentSerializations = argumentSerializations; } @SuppressWarnings("unchecked") - public void serialize(RpcRequest request, ByteBuf payload) { - Writable writable = new MessagePackWriter(payload); - request.writeTo(writable); - - ServiceMethod method = request.getMethod(); + public void serialize(ServiceInterfaceMethod serviceMethod, Object[] arguments, Writable writable) { + writable.write(serviceMethod.getServiceInterface().getName()); + writable.write(serviceMethod.getMethod().getName()); + writable.write(serviceMethod.getParameters(), parameter -> { + writable.write(parameter.getParameterType().getName()); + }); int idx = 0; - Object[] arguments = request.getArguments(); beforeSerializeArguments(writable, arguments); - for (MethodParameter parameter : method.getParameters()) { + for (MethodParameter parameter : serviceMethod.getParameters()) { var serialization = findArgumentSerialization(parameter); serialization.serialize(parameter, arguments[idx++], writable); } afterSerializeArguments(writable, arguments); } - private RpcArgumentSerialization findArgumentSerialization(MethodParameter parameter) { + private ArgumentSerialization findArgumentSerialization(MethodParameter parameter) { for (var argumentSerialization : argumentSerializations) { if (argumentSerialization.supportsArgument(parameter)) { return argumentSerialization; diff --git a/today-service-client/src/main/resources/META-INF/today.strategies b/today-service-client/src/main/resources/META-INF/today.strategies index 1aef7d7..63cd2ee 100644 --- a/today-service-client/src/main/resources/META-INF/today.strategies +++ b/today-service-client/src/main/resources/META-INF/today.strategies @@ -2,7 +2,7 @@ infra.beans.factory.support.DependencyResolvingStrategy=\ infra.cloud.client.annotation.ServiceDependencyResolvingStrategy -infra.cloud.serialize.RpcArgumentSerialization=\ +infra.cloud.serialize.ArgumentSerialization=\ infra.cloud.serialize.ProtobufArgumentSerialization,\ infra.cloud.serialize.SimpleValueArgumentSerialization diff --git a/today-service-provider/src/main/java/infra/cloud/provider/RpcRequestDeserializer.java b/today-service-provider/src/main/java/infra/cloud/provider/RpcRequestDeserializer.java index 94a591c..b81e724 100644 --- a/today-service-provider/src/main/java/infra/cloud/provider/RpcRequestDeserializer.java +++ b/today-service-provider/src/main/java/infra/cloud/provider/RpcRequestDeserializer.java @@ -22,10 +22,8 @@ import java.util.List; import java.util.Objects; -import infra.cloud.RpcRequest; +import infra.cloud.serialize.ArgumentSerialization; import infra.cloud.serialize.Readable; -import infra.cloud.serialize.MessagePackReader; -import infra.cloud.serialize.RpcArgumentSerialization; import infra.cloud.serialize.SerializationException; import infra.cloud.service.ServiceInterfaceMetadata; import infra.cloud.service.ServiceInterfaceMetadataProvider; @@ -33,7 +31,6 @@ import infra.lang.Assert; import infra.reflect.MethodInvoker; import infra.util.MapCache; -import io.netty.buffer.ByteBuf; /** * @author 海子 Yang @@ -42,7 +39,7 @@ @SuppressWarnings({ "unchecked", "rawtypes" }) public class RpcRequestDeserializer { - private final List argumentSerializations; + private final List argumentSerializations; /** fast method mapping cache */ private final MethodMapCache methodMapCache = new MethodMapCache(); @@ -51,21 +48,17 @@ public class RpcRequestDeserializer { private final LocalServiceHolder localServiceHolder; - public RpcRequestDeserializer(List argumentSerializations, + public RpcRequestDeserializer(List argumentSerializations, ServiceInterfaceMetadataProvider metadataProvider, LocalServiceHolder localServiceHolder) { this.argumentSerializations = argumentSerializations; this.metadataProvider = metadataProvider; this.localServiceHolder = localServiceHolder; } - public RemoteRequest deserialize(ByteBuf payload) throws SerializationException { - MessagePackReader input = new MessagePackReader(payload); - RpcRequest request = new RpcRequest(); - request.readFrom(input); - - String serviceClass = input.readString(); - String methodName = input.readString(); - String[] paramTypes = input.read(String.class, Readable::readString); + public RemoteRequest deserialize(Readable readable) throws SerializationException { + String serviceClass = readable.readString(); + String methodName = readable.readString(); + String[] paramTypes = readable.read(String.class, Readable::readString); var serviceInterface = localServiceHolder.getServiceInterface(serviceClass); Assert.state(serviceInterface != null, "service interface not found"); @@ -77,13 +70,13 @@ public RemoteRequest deserialize(ByteBuf payload) throws SerializationException int idx = 0; for (MethodParameter parameter : parameters) { var serialization = findArgumentSerialization(parameter); - args[idx++] = serialization.deserialize(parameter, input); + args[idx++] = serialization.deserialize(parameter, readable); } return new RemoteRequest(method, args, serviceInterface); } - private RpcArgumentSerialization findArgumentSerialization(MethodParameter parameter) { + private ArgumentSerialization findArgumentSerialization(MethodParameter parameter) { for (var argumentSerialization : argumentSerializations) { if (argumentSerialization.supportsArgument(parameter)) { return argumentSerialization; diff --git a/today-service-provider/src/main/java/infra/cloud/provider/ServiceChannelHandler.java b/today-service-provider/src/main/java/infra/cloud/provider/ServiceChannelHandler.java index 739f748..f025975 100644 --- a/today-service-provider/src/main/java/infra/cloud/provider/ServiceChannelHandler.java +++ b/today-service-provider/src/main/java/infra/cloud/provider/ServiceChannelHandler.java @@ -18,6 +18,7 @@ import org.reactivestreams.Publisher; +import infra.cloud.serialize.MessagePackReader; import infra.remoting.Channel; import infra.remoting.Payload; import reactor.core.publisher.Flux; @@ -41,7 +42,7 @@ public ServiceChannelHandler(LocalServiceHolder localServiceHolder) { @Override public Mono requestResponse(Payload payload) { - RemoteRequest request = requestDeserializer.deserialize(payload.data()); + RemoteRequest request = requestDeserializer.deserialize(new MessagePackReader(payload.data())); try { Object result = request.invoke(); return responseSerializer.serialize(request, result); From e6e7e07ca661b561730ecb6918c1cd0960f37cef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Mon, 16 Mar 2026 23:06:42 +0800 Subject: [PATCH 093/104] =?UTF-8?q?:art:=20=E4=BF=AE=E6=94=B9=E6=9C=8D?= =?UTF-8?q?=E5=8A=A1=E5=99=A8=E7=AB=AF=E5=8F=A3=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将服务器端口从 8080 更改为 8081 - 更新 application.yaml 中的 server.port 配置值 --- .../demo-user-service/src/main/resources/application.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/today-cloud-samples/demo-tests/demo-user-service/src/main/resources/application.yaml b/today-cloud-samples/demo-tests/demo-user-service/src/main/resources/application.yaml index 511396b..950d67a 100644 --- a/today-cloud-samples/demo-tests/demo-user-service/src/main/resources/application.yaml +++ b/today-cloud-samples/demo-tests/demo-user-service/src/main/resources/application.yaml @@ -8,7 +8,7 @@ today: auto-registration: fail-fast: true server: - port: 8080 + port: 8081 service-registry: simple: From 271ca0f00630f4c82661aa73bafd73eb864f5063 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Tue, 17 Mar 2026 22:53:12 +0800 Subject: [PATCH 094/104] =?UTF-8?q?:recycle:=20=E9=87=8D=E6=9E=84=E6=9C=8D?= =?UTF-8?q?=E5=8A=A1=E6=8F=90=E4=BE=9B=E8=80=85=E5=BA=8F=E5=88=97=E5=8C=96?= =?UTF-8?q?=E7=BB=84=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 重命名 RpcRequestDeserializer 为 RequestDeserializer - 为 ReturnValueSerializer 接口添加详细 JavaDoc 注释 - 更新 ServiceChannelHandler 构造函数注入序列化器依赖 - 在 ServiceProviderAutoConfiguration 中注册请求响应序列化器 - 修正 RequestSerializer 类的注释说明 - 优化 ArgumentSerialization 和 ReturnValueSerializer 的加载顺序 - 添加 ResponseSerializer 的原始类型注解抑制警告 --- .../serialize/ReturnValueSerializer.java | 20 +++++++++++++ .../ServiceClientAutoConfiguration.java | 2 +- .../service/serialize/RequestSerializer.java | 2 ++ ...rializer.java => RequestDeserializer.java} | 4 +-- .../cloud/provider/ResponseSerializer.java | 7 +++-- .../cloud/provider/ServiceChannelHandler.java | 11 ++++--- .../ServiceProviderAutoConfiguration.java | 30 +++++++++++++++++-- .../main/resources/META-INF/today.strategies | 2 ++ 8 files changed, 66 insertions(+), 12 deletions(-) rename today-service-provider/src/main/java/infra/cloud/provider/{RpcRequestDeserializer.java => RequestDeserializer.java} (97%) diff --git a/today-service-api/src/main/java/infra/cloud/serialize/ReturnValueSerializer.java b/today-service-api/src/main/java/infra/cloud/serialize/ReturnValueSerializer.java index 84bd4cb..9ca7171 100644 --- a/today-service-api/src/main/java/infra/cloud/serialize/ReturnValueSerializer.java +++ b/today-service-api/src/main/java/infra/cloud/serialize/ReturnValueSerializer.java @@ -19,13 +19,33 @@ import infra.cloud.service.ServiceMethod; /** + * A serializer responsible for converting the return value of a service method into a writable format. + *

              + * Implementations of this interface determine whether they support serializing the return value + * for a given {@link ServiceMethod} and perform the actual serialization process. + * + * @param the type of the return value to be serialized * @author 海子 Yang * @since 1.0 2025/8/20 21:56 */ public interface ReturnValueSerializer { + /** + * Checks if this serializer supports serializing the return value for the specified service method. + * + * @param method the service method to check + * @return {@code true} if this serializer can handle the return value of the given method, {@code false} otherwise + */ boolean supportsReturnValue(ServiceMethod method); + /** + * Serializes the return value of a service method into the provided writable target. + * + * @param method the service method whose return value is being serialized + * @param returnValue the return value to serialize + * @param writable the target to write the serialized data to + * @throws SerializationException if an error occurs during serialization + */ void serialize(ServiceMethod method, T returnValue, Writable writable) throws SerializationException; diff --git a/today-service-client/src/main/java/infra/cloud/client/annotation/config/ServiceClientAutoConfiguration.java b/today-service-client/src/main/java/infra/cloud/client/annotation/config/ServiceClientAutoConfiguration.java index 5b52831..cfc9580 100644 --- a/today-service-client/src/main/java/infra/cloud/client/annotation/config/ServiceClientAutoConfiguration.java +++ b/today-service-client/src/main/java/infra/cloud/client/annotation/config/ServiceClientAutoConfiguration.java @@ -88,7 +88,7 @@ public static ResponseDeserializer responseDeserializer(List argumentSerializations, ResourceLoader resourceLoader) { List serializations = TodayStrategies.find(ArgumentSerialization.class, resourceLoader.getClassLoader()); - argumentSerializations.addAll(serializations); // order after RpcArgumentSerialization beans + argumentSerializations.addAll(serializations); // order after ArgumentSerialization beans return new RequestSerializer(argumentSerializations); } diff --git a/today-service-client/src/main/java/infra/cloud/service/serialize/RequestSerializer.java b/today-service-client/src/main/java/infra/cloud/service/serialize/RequestSerializer.java index 6e6a273..c0fe65e 100644 --- a/today-service-client/src/main/java/infra/cloud/service/serialize/RequestSerializer.java +++ b/today-service-client/src/main/java/infra/cloud/service/serialize/RequestSerializer.java @@ -24,6 +24,8 @@ import infra.core.MethodParameter; /** + * Serializer for RPC request. + * * @author 海子 Yang * @since 1.0 2024/12/20 15:59 */ diff --git a/today-service-provider/src/main/java/infra/cloud/provider/RpcRequestDeserializer.java b/today-service-provider/src/main/java/infra/cloud/provider/RequestDeserializer.java similarity index 97% rename from today-service-provider/src/main/java/infra/cloud/provider/RpcRequestDeserializer.java rename to today-service-provider/src/main/java/infra/cloud/provider/RequestDeserializer.java index b81e724..2ec5f89 100644 --- a/today-service-provider/src/main/java/infra/cloud/provider/RpcRequestDeserializer.java +++ b/today-service-provider/src/main/java/infra/cloud/provider/RequestDeserializer.java @@ -37,7 +37,7 @@ * @since 1.0 2025/3/8 22:43 */ @SuppressWarnings({ "unchecked", "rawtypes" }) -public class RpcRequestDeserializer { +public class RequestDeserializer { private final List argumentSerializations; @@ -48,7 +48,7 @@ public class RpcRequestDeserializer { private final LocalServiceHolder localServiceHolder; - public RpcRequestDeserializer(List argumentSerializations, + public RequestDeserializer(List argumentSerializations, ServiceInterfaceMetadataProvider metadataProvider, LocalServiceHolder localServiceHolder) { this.argumentSerializations = argumentSerializations; this.metadataProvider = metadataProvider; diff --git a/today-service-provider/src/main/java/infra/cloud/provider/ResponseSerializer.java b/today-service-provider/src/main/java/infra/cloud/provider/ResponseSerializer.java index 7618ab9..e76a5a2 100644 --- a/today-service-provider/src/main/java/infra/cloud/provider/ResponseSerializer.java +++ b/today-service-provider/src/main/java/infra/cloud/provider/ResponseSerializer.java @@ -21,8 +21,8 @@ import java.util.List; import infra.cloud.serialize.MessagePackWriter; -import infra.cloud.serialize.Writable; import infra.cloud.serialize.ReturnValueSerializer; +import infra.cloud.serialize.Writable; import infra.cloud.service.ServiceMethod; import infra.remoting.Payload; import infra.remoting.util.ByteBufPayload; @@ -34,13 +34,14 @@ * @author 海子 Yang * @since 1.0 2025/8/31 16:21 */ +@SuppressWarnings("rawtypes") public class ResponseSerializer { - private final List> returnValueSerializers; + private final List returnValueSerializers; private final ByteBufAllocator allocator = ByteBufAllocator.DEFAULT; - public ResponseSerializer(List> returnValueSerializers) { + public ResponseSerializer(List returnValueSerializers) { this.returnValueSerializers = returnValueSerializers; } diff --git a/today-service-provider/src/main/java/infra/cloud/provider/ServiceChannelHandler.java b/today-service-provider/src/main/java/infra/cloud/provider/ServiceChannelHandler.java index f025975..100535c 100644 --- a/today-service-provider/src/main/java/infra/cloud/provider/ServiceChannelHandler.java +++ b/today-service-provider/src/main/java/infra/cloud/provider/ServiceChannelHandler.java @@ -30,14 +30,17 @@ */ public class ServiceChannelHandler implements Channel { - private RpcRequestDeserializer requestDeserializer; + private final LocalServiceHolder localServiceHolder; - private ResponseSerializer responseSerializer; + private final RequestDeserializer requestDeserializer; - private final LocalServiceHolder localServiceHolder; + private final ResponseSerializer responseSerializer; - public ServiceChannelHandler(LocalServiceHolder localServiceHolder) { + public ServiceChannelHandler(LocalServiceHolder localServiceHolder, + RequestDeserializer requestDeserializer, ResponseSerializer responseSerializer) { this.localServiceHolder = localServiceHolder; + this.requestDeserializer = requestDeserializer; + this.responseSerializer = responseSerializer; } @Override diff --git a/today-service-provider/src/main/java/infra/cloud/provider/config/ServiceProviderAutoConfiguration.java b/today-service-provider/src/main/java/infra/cloud/provider/config/ServiceProviderAutoConfiguration.java index 5c63f91..e502b9f 100644 --- a/today-service-provider/src/main/java/infra/cloud/provider/config/ServiceProviderAutoConfiguration.java +++ b/today-service-provider/src/main/java/infra/cloud/provider/config/ServiceProviderAutoConfiguration.java @@ -18,16 +18,22 @@ import org.jspecify.annotations.Nullable; +import java.util.List; + import infra.cloud.client.annotation.ConditionalOnDiscoveryEnabled; import infra.cloud.net.InetProperties; import infra.cloud.net.InetService; import infra.cloud.provider.DefaultServiceInterfaceMetadataProvider; import infra.cloud.provider.LocalServiceHolder; +import infra.cloud.provider.RequestDeserializer; +import infra.cloud.provider.ResponseSerializer; import infra.cloud.provider.ServerTransportFactory; import infra.cloud.provider.ServiceChannelHandler; import infra.cloud.provider.ServiceProviderServer; import infra.cloud.provider.ServiceServerProperties; import infra.cloud.provider.TcpServerTransportFactory; +import infra.cloud.serialize.ArgumentSerialization; +import infra.cloud.serialize.ReturnValueSerializer; import infra.cloud.service.DefaultServiceMetadataProvider; import infra.cloud.service.ServiceInterfaceMetadataProvider; import infra.cloud.service.ServiceMetadataProvider; @@ -37,6 +43,8 @@ import infra.context.condition.ConditionalOnBooleanProperty; import infra.context.condition.ConditionalOnMissingBean; import infra.context.properties.EnableConfigurationProperties; +import infra.core.io.ResourceLoader; +import infra.lang.TodayStrategies; import infra.remoting.Closeable; import infra.remoting.core.Resume; import infra.remoting.resume.InMemoryResumableFramesStoreFactory; @@ -51,6 +59,7 @@ * @author 海子 Yang * @since 1.0 2025/8/10 22:31 */ +@SuppressWarnings("rawtypes") @DisableDIAutoConfiguration @ConditionalOnDiscoveryEnabled @EnableConfigurationProperties({ InetProperties.class, ServiceServerProperties.class }) @@ -79,8 +88,25 @@ public static InetService inetService(InetProperties inetProperties) { } @Component - public static ServiceChannelHandler serviceChannelHandler(LocalServiceHolder localServiceHolder) { - return new ServiceChannelHandler(localServiceHolder); + public static RequestDeserializer requestDeserializer(List argumentSerializations, + ServiceInterfaceMetadataProvider serviceInterfaceMetadataProvider, + ResourceLoader resourceLoader, LocalServiceHolder localServiceHolder) { + List serializations = TodayStrategies.find(ArgumentSerialization.class, resourceLoader.getClassLoader()); + argumentSerializations.addAll(serializations); // order after ArgumentSerialization beans + return new RequestDeserializer(argumentSerializations, serviceInterfaceMetadataProvider, localServiceHolder); + } + + @Component + public static ResponseSerializer responseSerializer(List returnValueSerializers, ResourceLoader resourceLoader) { + List serializations = TodayStrategies.find(ReturnValueSerializer.class, resourceLoader.getClassLoader()); + returnValueSerializers.addAll(serializations); // order after ReturnValueSerializer beans + return new ResponseSerializer(returnValueSerializers); + } + + @Component + public static ServiceChannelHandler serviceChannelHandler(LocalServiceHolder localServiceHolder, + RequestDeserializer requestDeserializer, ResponseSerializer responseSerializer) { + return new ServiceChannelHandler(localServiceHolder, requestDeserializer, responseSerializer); } @Component diff --git a/today-service-provider/src/main/resources/META-INF/today.strategies b/today-service-provider/src/main/resources/META-INF/today.strategies index e69de29..e175bdd 100644 --- a/today-service-provider/src/main/resources/META-INF/today.strategies +++ b/today-service-provider/src/main/resources/META-INF/today.strategies @@ -0,0 +1,2 @@ +infra.cloud.serialize.ReturnValueSerializer=\ + infra.cloud.serialize.ProtobufArgumentSerialization \ No newline at end of file From fe41f29e8ba3621e464605fbd4a28978bba71426 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Tue, 17 Mar 2026 22:55:21 +0800 Subject: [PATCH 095/104] :art: --- .../infra/remoting/micrometer/MicrometerChannel.java | 4 ++-- .../infra/remoting/micrometer/MicrometerConnection.java | 4 ++-- .../observation/ObservationRequesterChannel.java | 6 +++--- .../observation/ObservationResponderChannel.java | 6 +++--- .../micrometer/integration/IntegrationTests.java | 6 +++--- .../micrometer/integration/TcpIntegrationTests.java | 4 ++-- .../java/infra/remoting/integration/FragmentTests.java | 4 ++-- .../{ChannelWrapper.java => DecoratingChannel.java} | 4 ++-- ...{ConnectionWrapper.java => DecoratingConnection.java} | 9 +++++++-- .../java/infra/remoting/lb/WeightedStatsChannel.java | 4 ++-- .../java/infra/remoting/plugins/RateLimitDecorator.java | 6 +++--- .../infra/remoting/core/DefaultChannelClientTests.java | 4 ++-- .../test/java/infra/remoting/lb/LoadbalanceTests.java | 4 ++-- 13 files changed, 35 insertions(+), 30 deletions(-) rename today-remoting/src/main/java/infra/remoting/{ChannelWrapper.java => DecoratingChannel.java} (95%) rename today-remoting/src/main/java/infra/remoting/{ConnectionWrapper.java => DecoratingConnection.java} (84%) diff --git a/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/MicrometerChannel.java b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/MicrometerChannel.java index f74254e..5bd611b 100644 --- a/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/MicrometerChannel.java +++ b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/MicrometerChannel.java @@ -23,7 +23,7 @@ import java.util.function.Consumer; import infra.remoting.Channel; -import infra.remoting.ChannelWrapper; +import infra.remoting.DecoratingChannel; import infra.remoting.Payload; import io.micrometer.core.instrument.Counter; import io.micrometer.core.instrument.Meter; @@ -50,7 +50,7 @@ * * @see Micrometer */ -final class MicrometerChannel extends ChannelWrapper { +final class MicrometerChannel extends DecoratingChannel { private final InteractionCounters metadataPush; diff --git a/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/MicrometerConnection.java b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/MicrometerConnection.java index 29edc9d..75925cb 100644 --- a/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/MicrometerConnection.java +++ b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/MicrometerConnection.java @@ -22,7 +22,7 @@ import infra.logging.Logger; import infra.logging.LoggerFactory; import infra.remoting.Connection; -import infra.remoting.ConnectionWrapper; +import infra.remoting.DecoratingConnection; import infra.remoting.frame.FrameHeaderCodec; import infra.remoting.frame.FrameType; import infra.remoting.plugins.ConnectionDecorator.Type; @@ -66,7 +66,7 @@ * * @see Micrometer */ -final class MicrometerConnection extends ConnectionWrapper { +final class MicrometerConnection extends DecoratingConnection { private final Counter close; diff --git a/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/ObservationRequesterChannel.java b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/ObservationRequesterChannel.java index 492a90c..d1346a1 100644 --- a/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/ObservationRequesterChannel.java +++ b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/ObservationRequesterChannel.java @@ -22,7 +22,7 @@ import java.util.function.Function; import infra.remoting.Channel; -import infra.remoting.ChannelWrapper; +import infra.remoting.DecoratingChannel; import infra.remoting.Payload; import infra.remoting.frame.FrameType; import io.micrometer.common.util.StringUtils; @@ -34,13 +34,13 @@ import reactor.util.context.ContextView; /** - * Tracing representation of a {@link ChannelWrapper} for the requester. + * Tracing representation of a {@link DecoratingChannel} for the requester. * * @author Marcin Grzejszczak * @author Oleh Dokuka * @author 海子 Yang */ -public class ObservationRequesterChannel extends ChannelWrapper { +public class ObservationRequesterChannel extends DecoratingChannel { /** * Aligned with ObservationThreadLocalAccessor#KEY diff --git a/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/ObservationResponderChannel.java b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/ObservationResponderChannel.java index 8014962..e4641f5 100644 --- a/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/ObservationResponderChannel.java +++ b/today-remoting-micrometer/src/main/java/infra/remoting/micrometer/observation/ObservationResponderChannel.java @@ -20,7 +20,7 @@ import org.reactivestreams.Publisher; import infra.remoting.Channel; -import infra.remoting.ChannelWrapper; +import infra.remoting.DecoratingChannel; import infra.remoting.Payload; import infra.remoting.frame.FrameType; import io.micrometer.common.util.StringUtils; @@ -31,12 +31,12 @@ import reactor.core.publisher.Mono; /** - * Tracing representation of a {@link ChannelWrapper} for the responder. + * Tracing representation of a {@link DecoratingChannel} for the responder. * * @author Marcin Grzejszczak * @author Oleh Dokuka */ -public class ObservationResponderChannel extends ChannelWrapper { +public class ObservationResponderChannel extends DecoratingChannel { /** Aligned with ObservationThreadLocalAccessor#KEY */ private static final String MICROMETER_OBSERVATION_KEY = "micrometer.observation"; diff --git a/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/IntegrationTests.java b/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/IntegrationTests.java index 466b13b..573bf58 100644 --- a/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/IntegrationTests.java +++ b/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/IntegrationTests.java @@ -27,7 +27,7 @@ import java.util.concurrent.atomic.AtomicInteger; import infra.remoting.Channel; -import infra.remoting.ChannelWrapper; +import infra.remoting.DecoratingChannel; import infra.remoting.Payload; import infra.remoting.core.ChannelConnector; import infra.remoting.core.RemotingServer; @@ -64,7 +64,7 @@ public class IntegrationTests { static { requesterInterceptor = channel -> - new ChannelWrapper(channel) { + new DecoratingChannel(channel) { @Override public Mono requestResponse(Payload payload) { calledRequester = true; @@ -73,7 +73,7 @@ public Mono requestResponse(Payload payload) { }; responderInterceptor = channel -> - new ChannelWrapper(channel) { + new DecoratingChannel(channel) { @Override public Mono requestResponse(Payload payload) { calledResponder = true; diff --git a/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/TcpIntegrationTests.java b/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/TcpIntegrationTests.java index 15ffaa9..fc60072 100644 --- a/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/TcpIntegrationTests.java +++ b/today-remoting-micrometer/src/test/java/infra/remoting/micrometer/integration/TcpIntegrationTests.java @@ -25,7 +25,7 @@ import java.util.concurrent.CountDownLatch; import infra.remoting.Channel; -import infra.remoting.ChannelWrapper; +import infra.remoting.DecoratingChannel; import infra.remoting.Payload; import infra.remoting.core.ChannelConnector; import infra.remoting.core.RemotingServer; @@ -48,7 +48,7 @@ public class TcpIntegrationTests { @BeforeEach public void startup() { - server = RemotingServer.create((setup, channel) -> Mono.just(new ChannelWrapper(handler))) + server = RemotingServer.create((setup, channel) -> Mono.just(new DecoratingChannel(handler))) .bind(TcpServerTransport.create("localhost", 0)) .block(); } diff --git a/today-remoting-transport-tcp/src/test/java/infra/remoting/integration/FragmentTests.java b/today-remoting-transport-tcp/src/test/java/infra/remoting/integration/FragmentTests.java index df9aae4..58fcd79 100644 --- a/today-remoting-transport-tcp/src/test/java/infra/remoting/integration/FragmentTests.java +++ b/today-remoting-transport-tcp/src/test/java/infra/remoting/integration/FragmentTests.java @@ -25,7 +25,7 @@ import java.util.stream.Stream; import infra.remoting.Channel; -import infra.remoting.ChannelWrapper; +import infra.remoting.DecoratingChannel; import infra.remoting.Payload; import infra.remoting.core.ChannelConnector; import infra.remoting.core.RemotingServer; @@ -65,7 +65,7 @@ public void startup(int frameSize) { TcpServerTransport serverTransport = TcpServerTransport.create("localhost", randomPort); server = - RemotingServer.create((setup, channel) -> Mono.just(new ChannelWrapper(handler))) + RemotingServer.create((setup, channel) -> Mono.just(new DecoratingChannel(handler))) .fragment(frameSize) .bind(serverTransport) .block(); diff --git a/today-remoting/src/main/java/infra/remoting/ChannelWrapper.java b/today-remoting/src/main/java/infra/remoting/DecoratingChannel.java similarity index 95% rename from today-remoting/src/main/java/infra/remoting/ChannelWrapper.java rename to today-remoting/src/main/java/infra/remoting/DecoratingChannel.java index f17099e..670e9ec 100644 --- a/today-remoting/src/main/java/infra/remoting/ChannelWrapper.java +++ b/today-remoting/src/main/java/infra/remoting/DecoratingChannel.java @@ -26,11 +26,11 @@ /** * Wrapper for a Channel. This is useful when we want to override a specific method. */ -public class ChannelWrapper implements Channel { +public class DecoratingChannel implements Channel { protected final Channel delegate; - public ChannelWrapper(Channel delegate) { + public DecoratingChannel(Channel delegate) { this.delegate = Objects.requireNonNull(delegate, "delegate is required"); } diff --git a/today-remoting/src/main/java/infra/remoting/ConnectionWrapper.java b/today-remoting/src/main/java/infra/remoting/DecoratingConnection.java similarity index 84% rename from today-remoting/src/main/java/infra/remoting/ConnectionWrapper.java rename to today-remoting/src/main/java/infra/remoting/DecoratingConnection.java index 36aa832..4732846 100644 --- a/today-remoting/src/main/java/infra/remoting/ConnectionWrapper.java +++ b/today-remoting/src/main/java/infra/remoting/DecoratingConnection.java @@ -25,14 +25,19 @@ import reactor.core.publisher.Mono; /** + * A decorator for {@link Connection} that delegates all method calls to the underlying connection. + *

              + * This class can be extended to add additional behavior or monitoring to a connection without + * modifying the original implementation. + * * @author 海子 Yang * @since 1.0 2025/8/3 11:25 */ -public class ConnectionWrapper implements Connection { +public class DecoratingConnection implements Connection { protected final Connection delegate; - public ConnectionWrapper(Connection delegate) { + public DecoratingConnection(Connection delegate) { this.delegate = Objects.requireNonNull(delegate, "delegate is required"); } diff --git a/today-remoting/src/main/java/infra/remoting/lb/WeightedStatsChannel.java b/today-remoting/src/main/java/infra/remoting/lb/WeightedStatsChannel.java index ad57e83..9f9177a 100644 --- a/today-remoting/src/main/java/infra/remoting/lb/WeightedStatsChannel.java +++ b/today-remoting/src/main/java/infra/remoting/lb/WeightedStatsChannel.java @@ -17,13 +17,13 @@ package infra.remoting.lb; import infra.remoting.Channel; -import infra.remoting.ChannelWrapper; +import infra.remoting.DecoratingChannel; /** * Package private {@code ChannelWrapper} used from {@link WeightedStats#wrap(Channel)} to attach a * {@link WeightedStats} instance to an {@code Channel}. */ -final class WeightedStatsChannel extends ChannelWrapper implements WeightedStats { +final class WeightedStatsChannel extends DecoratingChannel implements WeightedStats { private final WeightedStats weightedStats; diff --git a/today-remoting/src/main/java/infra/remoting/plugins/RateLimitDecorator.java b/today-remoting/src/main/java/infra/remoting/plugins/RateLimitDecorator.java index 0a51c21..33a3eca 100644 --- a/today-remoting/src/main/java/infra/remoting/plugins/RateLimitDecorator.java +++ b/today-remoting/src/main/java/infra/remoting/plugins/RateLimitDecorator.java @@ -19,7 +19,7 @@ import org.reactivestreams.Publisher; import infra.remoting.Channel; -import infra.remoting.ChannelWrapper; +import infra.remoting.DecoratingChannel; import infra.remoting.Payload; import reactor.core.publisher.Flux; @@ -107,7 +107,7 @@ public static RateLimitDecorator forRequester(int highTide, int lowTide) { /** * Responder side proxy, limits response streams. */ - private class ResponderChannel extends ChannelWrapper { + private class ResponderChannel extends DecoratingChannel { ResponderChannel(Channel source) { super(source); @@ -127,7 +127,7 @@ public Flux requestChannel(Publisher payloads) { /** * Requester side proxy, limits channel request stream. */ - private class RequesterChannel extends ChannelWrapper { + private class RequesterChannel extends DecoratingChannel { RequesterChannel(Channel source) { super(source); diff --git a/today-remoting/src/test/java/infra/remoting/core/DefaultChannelClientTests.java b/today-remoting/src/test/java/infra/remoting/core/DefaultChannelClientTests.java index 1992ab3..1fee968 100644 --- a/today-remoting/src/test/java/infra/remoting/core/DefaultChannelClientTests.java +++ b/today-remoting/src/test/java/infra/remoting/core/DefaultChannelClientTests.java @@ -39,7 +39,7 @@ import java.util.stream.Stream; import infra.remoting.Channel; -import infra.remoting.ChannelWrapper; +import infra.remoting.DecoratingChannel; import infra.remoting.FrameAssert; import infra.remoting.Payload; import infra.remoting.RaceTestConstants; @@ -512,7 +512,7 @@ public void shouldReceiveOnCloseNotificationOnDisposeOriginalSource() { new ClientChannelRule() { @Override protected Channel newChannel() { - return new ChannelWrapper(super.newChannel()) { + return new DecoratingChannel(super.newChannel()) { @Override public Mono onClose() { return super.onClose().and(onCloseDelayer.asMono()); diff --git a/today-remoting/src/test/java/infra/remoting/lb/LoadbalanceTests.java b/today-remoting/src/test/java/infra/remoting/lb/LoadbalanceTests.java index 1f726ce..4867b05 100644 --- a/today-remoting/src/test/java/infra/remoting/lb/LoadbalanceTests.java +++ b/today-remoting/src/test/java/infra/remoting/lb/LoadbalanceTests.java @@ -30,7 +30,7 @@ import java.util.concurrent.atomic.AtomicInteger; import infra.remoting.Channel; -import infra.remoting.ChannelWrapper; +import infra.remoting.DecoratingChannel; import infra.remoting.Payload; import infra.remoting.RaceTestConstants; import infra.remoting.core.ChannelConnector; @@ -404,7 +404,7 @@ public Mono fireAndForget(Payload payload) { Assertions.assertThat(counter.get()).isOne(); } - static class TestChannel extends ChannelWrapper { + static class TestChannel extends DecoratingChannel { final Sinks.Empty sink = Sinks.empty(); From 5909fd509ee01726223cb6a7f8a2b1712653e577 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Tue, 17 Mar 2026 22:56:01 +0800 Subject: [PATCH 096/104] :art: --- .../serialize/ReturnValueSerialization.java | 25 ------------------- 1 file changed, 25 deletions(-) delete mode 100644 today-service-api/src/main/java/infra/cloud/serialize/ReturnValueSerialization.java diff --git a/today-service-api/src/main/java/infra/cloud/serialize/ReturnValueSerialization.java b/today-service-api/src/main/java/infra/cloud/serialize/ReturnValueSerialization.java deleted file mode 100644 index 204ab77..0000000 --- a/today-service-api/src/main/java/infra/cloud/serialize/ReturnValueSerialization.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright 2021 - 2026 the TODAY 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 - * - * https://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 infra.cloud.serialize; - -/** - * @author 海子 Yang - * @since 1.0 2024/12/20 21:42 - */ -public interface ReturnValueSerialization extends ReturnValueSerializer, ReturnValueDeserializer { - -} From dd77caf8b4f77c06577267f49d82467d06102b12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Tue, 17 Mar 2026 23:33:38 +0800 Subject: [PATCH 097/104] =?UTF-8?q?:art:=20=20=E6=B7=BB=E5=8A=A0TCP?= =?UTF-8?q?=E4=BC=A0=E8=BE=93=E6=94=AF=E6=8C=81=E5=B9=B6=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E8=BF=9C=E7=A8=8B=E8=B0=83=E7=94=A8=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 集成 today-remoting-transport-tcp 模块以支持TCP传输协议 - 配置应用启用本地网络接口以优化服务发现 - 修复参数序列化错误消息中的类型名称显示问题 - 临时注释响应反序列化中的异常处理逻辑 - 优化负载均衡客户端创建过程中的调度机制 - 为方法调用参数添加空值注解支持 - 更新请求反序列化器以支持参数空值处理 - 添加请求反序列化器类的功能描述文档 - 修改策略配置文件以使用简化的参数序列化实现 --- .../demo-tests/demo-user-rest/build.gradle | 2 ++ .../src/main/resources/application.yaml | 4 ++++ .../service/DefaultRemotingOperationsProvider.java | 2 +- .../cloud/service/serialize/RequestSerializer.java | 2 +- .../service/serialize/ResponseDeserializer.java | 14 +++++++------- .../java/infra/cloud/provider/InvocableMethod.java | 2 +- .../java/infra/cloud/provider/RemoteRequest.java | 4 ++-- .../infra/cloud/provider/RequestDeserializer.java | 6 ++++-- .../src/main/resources/META-INF/today.strategies | 7 +++++-- 9 files changed, 27 insertions(+), 16 deletions(-) diff --git a/today-cloud-samples/demo-tests/demo-user-rest/build.gradle b/today-cloud-samples/demo-tests/demo-user-rest/build.gradle index 07801df..66e3760 100644 --- a/today-cloud-samples/demo-tests/demo-user-rest/build.gradle +++ b/today-cloud-samples/demo-tests/demo-user-rest/build.gradle @@ -3,6 +3,8 @@ description = "Demo Client" dependencies { implementation "cn.taketoday:today-service-client" + implementation "cn.taketoday:today-remoting-transport-tcp" + implementation project(":demo-tests:demo-user-api") implementation 'cn.taketoday:infra-starter-web' diff --git a/today-cloud-samples/demo-tests/demo-user-service/src/main/resources/application.yaml b/today-cloud-samples/demo-tests/demo-user-service/src/main/resources/application.yaml index 950d67a..4cddbb2 100644 --- a/today-cloud-samples/demo-tests/demo-user-service/src/main/resources/application.yaml +++ b/today-cloud-samples/demo-tests/demo-user-service/src/main/resources/application.yaml @@ -1,6 +1,9 @@ infra: profiles: active: dev + cloud: + inet: + use-only-site-local-interfaces: true today: @@ -14,6 +17,7 @@ today: simple: uri: http://localhost:9000 + logging: level: root: info diff --git a/today-service-client/src/main/java/infra/cloud/service/DefaultRemotingOperationsProvider.java b/today-service-client/src/main/java/infra/cloud/service/DefaultRemotingOperationsProvider.java index 16278a3..db79514 100644 --- a/today-service-client/src/main/java/infra/cloud/service/DefaultRemotingOperationsProvider.java +++ b/today-service-client/src/main/java/infra/cloud/service/DefaultRemotingOperationsProvider.java @@ -64,7 +64,7 @@ public RemotingOperations getRemotingOperations(ServiceMethod serviceMethod) { } public RemotingOperations getRemotingOperations(String serviceId) { - return remotingClientMap.computeIfAbsent(serviceId, name -> RemotingClient.forLoadBalance(Flux.interval(discoveryPeriod) + return remotingClientMap.computeIfAbsent(serviceId, name -> RemotingClient.forLoadBalance(Flux.interval(Duration.ZERO, discoveryPeriod) .map(i -> discoveryClient.getInstances(name)) .map(instances -> { var targets = new ArrayList(instances.size()); diff --git a/today-service-client/src/main/java/infra/cloud/service/serialize/RequestSerializer.java b/today-service-client/src/main/java/infra/cloud/service/serialize/RequestSerializer.java index c0fe65e..1602742 100644 --- a/today-service-client/src/main/java/infra/cloud/service/serialize/RequestSerializer.java +++ b/today-service-client/src/main/java/infra/cloud/service/serialize/RequestSerializer.java @@ -62,7 +62,7 @@ private ArgumentSerialization findArgumentSerialization(MethodParameter paramete return argumentSerialization; } } - throw new IllegalStateException("RpcArgumentSerialization for parameter %s not found".formatted(parameter)); + throw new IllegalStateException("ArgumentSerialization for parameter %s not found".formatted(parameter)); } protected void afterSerializeArguments(Writable writable, Object[] arguments) { diff --git a/today-service-client/src/main/java/infra/cloud/service/serialize/ResponseDeserializer.java b/today-service-client/src/main/java/infra/cloud/service/serialize/ResponseDeserializer.java index 4837ec2..7f65f60 100644 --- a/today-service-client/src/main/java/infra/cloud/service/serialize/ResponseDeserializer.java +++ b/today-service-client/src/main/java/infra/cloud/service/serialize/ResponseDeserializer.java @@ -48,18 +48,18 @@ public RpcResponse deserialize(ServiceInterfaceMethod method, ByteBuf body) thro RpcResponse response = new RpcResponse(); response.setMethod(method); - boolean hasError = body.readBoolean(); - if (hasError) { - Throwable deserialize = throwableSerialization.deserialize(body); - response.setException(deserialize); - } - else { +// boolean hasError = body.readBoolean(); +// if (hasError) { +// Throwable deserialize = throwableSerialization.deserialize(body); +// response.setException(deserialize); +// } +// else { Object result = input.readNullable(in -> { var deserializer = findDeserializer(method); return deserializer.deserialize(method, input); }); response.setResult(result); - } +// } return response; } diff --git a/today-service-provider/src/main/java/infra/cloud/provider/InvocableMethod.java b/today-service-provider/src/main/java/infra/cloud/provider/InvocableMethod.java index bc0414c..c4162b1 100644 --- a/today-service-provider/src/main/java/infra/cloud/provider/InvocableMethod.java +++ b/today-service-provider/src/main/java/infra/cloud/provider/InvocableMethod.java @@ -41,7 +41,7 @@ public InvocableMethod(ServiceInterfaceMetadata metadata, ServiceObject servi } @Nullable - public Object invoke(Object[] args) { + public Object invoke(@Nullable Object @Nullable [] args) { return invoker.invoke(instance, args); } diff --git a/today-service-provider/src/main/java/infra/cloud/provider/RemoteRequest.java b/today-service-provider/src/main/java/infra/cloud/provider/RemoteRequest.java index e308282..096ff2a 100644 --- a/today-service-provider/src/main/java/infra/cloud/provider/RemoteRequest.java +++ b/today-service-provider/src/main/java/infra/cloud/provider/RemoteRequest.java @@ -26,11 +26,11 @@ public class RemoteRequest { private final InvocableMethod method; - private final Object[] args; + private final @Nullable Object @Nullable [] args; private final ServiceObject serviceObject; - public RemoteRequest(InvocableMethod method, Object[] args, ServiceObject serviceObject) { + public RemoteRequest(InvocableMethod method, @Nullable Object @Nullable [] args, ServiceObject serviceObject) { this.method = method; this.args = args; this.serviceObject = serviceObject; diff --git a/today-service-provider/src/main/java/infra/cloud/provider/RequestDeserializer.java b/today-service-provider/src/main/java/infra/cloud/provider/RequestDeserializer.java index 2ec5f89..a830239 100644 --- a/today-service-provider/src/main/java/infra/cloud/provider/RequestDeserializer.java +++ b/today-service-provider/src/main/java/infra/cloud/provider/RequestDeserializer.java @@ -33,6 +33,8 @@ import infra.util.MapCache; /** + * Deserializes incoming remote requests + * * @author 海子 Yang * @since 1.0 2025/3/8 22:43 */ @@ -65,7 +67,7 @@ public RemoteRequest deserialize(Readable readable) throws SerializationExceptio InvocableMethod method = methodMapCache.get(new MethodKey(serviceClass, methodName, paramTypes), serviceInterface); MethodParameter[] parameters = method.getParameters(); - Object[] args = new Object[parameters.length]; + @Nullable Object[] args = new Object[parameters.length]; int idx = 0; for (MethodParameter parameter : parameters) { @@ -82,7 +84,7 @@ private ArgumentSerialization findArgumentSerialization(MethodParameter paramete return argumentSerialization; } } - throw new IllegalStateException("RpcArgumentSerialization for parameter %s not found".formatted(parameter)); + throw new IllegalStateException("ArgumentSerialization for parameter %s not found".formatted(parameter)); } private final class MethodMapCache extends MapCache { diff --git a/today-service-provider/src/main/resources/META-INF/today.strategies b/today-service-provider/src/main/resources/META-INF/today.strategies index e175bdd..377e287 100644 --- a/today-service-provider/src/main/resources/META-INF/today.strategies +++ b/today-service-provider/src/main/resources/META-INF/today.strategies @@ -1,2 +1,5 @@ -infra.cloud.serialize.ReturnValueSerializer=\ - infra.cloud.serialize.ProtobufArgumentSerialization \ No newline at end of file + +infra.cloud.serialize.ArgumentSerialization=\ + infra.cloud.serialize.SimpleValueArgumentSerialization + + From c519ee73ebc081a8fe7fb7219d907916acc6abe9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E5=AD=90=20Yang?= Date: Wed, 18 Mar 2026 11:11:55 +0800 Subject: [PATCH 098/104] :art: --- .../.run}/ClientApplication.run.xml | 0 .../.run}/RegistryApplication.run.xml | 0 .../.run}/UserServiceApplication.run.xml | 8 +------- 3 files changed, 1 insertion(+), 7 deletions(-) rename {.run => today-cloud-samples/.run}/ClientApplication.run.xml (100%) rename {.run => today-cloud-samples/.run}/RegistryApplication.run.xml (100%) rename {.run => today-cloud-samples/.run}/UserServiceApplication.run.xml (60%) diff --git a/.run/ClientApplication.run.xml b/today-cloud-samples/.run/ClientApplication.run.xml similarity index 100% rename from .run/ClientApplication.run.xml rename to today-cloud-samples/.run/ClientApplication.run.xml diff --git a/.run/RegistryApplication.run.xml b/today-cloud-samples/.run/RegistryApplication.run.xml similarity index 100% rename from .run/RegistryApplication.run.xml rename to today-cloud-samples/.run/RegistryApplication.run.xml diff --git a/.run/UserServiceApplication.run.xml b/today-cloud-samples/.run/UserServiceApplication.run.xml similarity index 60% rename from .run/UserServiceApplication.run.xml rename to today-cloud-samples/.run/UserServiceApplication.run.xml index 9e60420..926f65c 100644 --- a/.run/UserServiceApplication.run.xml +++ b/today-cloud-samples/.run/UserServiceApplication.run.xml @@ -1,14 +1,8 @@ - +