Skip to content

Commit 7ce8547

Browse files
committed
Propagate client properties
1 parent 6068940 commit 7ce8547

File tree

4 files changed

+136
-3
lines changed

4 files changed

+136
-3
lines changed

pom.xml

+8
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,14 @@
179179

180180
<build>
181181

182+
<!-- We store the client version in a Java properties file. -->
183+
<resources>
184+
<resource>
185+
<directory>${basedir}/src/main/resources</directory>
186+
<filtering>true</filtering>
187+
</resource>
188+
</resources>
189+
182190
<plugins>
183191

184192
<plugin>

src/main/java/com/rabbitmq/stream/Client.java

+36-3
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,8 @@ public class Client implements AutoCloseable {
9797

9898
private final ChunkChecksum chunkChecksum;
9999

100+
private final Map<String, String> clientProperties;
101+
100102
private final String NETTY_HANDLER_FLUSH_CONSOLIDATION = FlushConsolidationHandler.class.getSimpleName();
101103
private final String NETTY_HANDLER_FRAME_DECODER = LengthFieldBasedFrameDecoder.class.getSimpleName();
102104
private final String NETTY_HANDLER_STREAM = StreamHandler.class.getSimpleName();
@@ -154,6 +156,7 @@ public void initChannel(SocketChannel ch) {
154156

155157
this.channel = f.channel();
156158
this.tuneState = new TuneState(parameters.requestedMaxFrameSize, (int) parameters.requestedHeartbeat.getSeconds());
159+
this.clientProperties = clientProperties(parameters.clientProperties);
157160
authenticate();
158161
this.tuneState.await(Duration.ofSeconds(10));
159162
this.maxFrameSize = this.tuneState.getMaxFrameSize();
@@ -163,6 +166,13 @@ public void initChannel(SocketChannel ch) {
163166
open(parameters.virtualHost);
164167
}
165168

169+
private static Map<String, String> clientProperties(Map<String, String> fromParameters) {
170+
fromParameters = fromParameters == null ? Collections.emptyMap() : fromParameters;
171+
Map<String, String> clientProperties = new HashMap<>(fromParameters);
172+
clientProperties.putAll(ClientProperties.DEFAULT_CLIENT_PROPERTIES);
173+
return Collections.unmodifiableMap(clientProperties);
174+
}
175+
166176
static void handleMetadataUpdate(ByteBuf bb, int frameSize, Subscriptions subscriptions, SubscriptionListener subscriptionListener) {
167177
int read = 2 + 2; // already read the command id and version
168178
short code = bb.readShort();
@@ -573,7 +583,7 @@ private void authenticate() {
573583
boolean authDone = false;
574584
while (!authDone) {
575585
byte[] saslResponse = saslMechanism.handleChallenge(challenge, this.credentialsProvider);
576-
SaslAuthenticateResponse saslAuthenticateResponse = sendSaslAuthenticate(saslMechanism, saslResponse);
586+
SaslAuthenticateResponse saslAuthenticateResponse = sendSaslAuthenticate(this.clientProperties, saslMechanism, saslResponse);
577587
if (saslAuthenticateResponse.isOk()) {
578588
authDone = true;
579589
} else if (saslAuthenticateResponse.isChallenge()) {
@@ -586,8 +596,14 @@ private void authenticate() {
586596
}
587597
}
588598

589-
private SaslAuthenticateResponse sendSaslAuthenticate(SaslMechanism saslMechanism, byte[] challengeResponse) {
590-
int length = 2 + 2 + 4 + 2 + saslMechanism.getName().length() +
599+
private SaslAuthenticateResponse sendSaslAuthenticate(Map<String, String> clientProperties, SaslMechanism saslMechanism, byte[] challengeResponse) {
600+
int clientPropertiesSize = 4; // size of the map, always there
601+
if (!clientProperties.isEmpty()) {
602+
for (Map.Entry<String, String> entry : clientProperties.entrySet()) {
603+
clientPropertiesSize += 2 + entry.getKey().length() + 2 + entry.getValue().length();
604+
}
605+
}
606+
int length = 2 + 2 + 4 + +clientPropertiesSize + 2 + saslMechanism.getName().length() +
591607
4 + (challengeResponse == null ? 0 : challengeResponse.length);
592608
int correlationId = correlationSequence.incrementAndGet();
593609
try {
@@ -596,6 +612,11 @@ private SaslAuthenticateResponse sendSaslAuthenticate(SaslMechanism saslMechanis
596612
bb.writeShort(COMMAND_SASL_AUTHENTICATE);
597613
bb.writeShort(VERSION_0);
598614
bb.writeInt(correlationId);
615+
bb.writeInt(clientProperties.size());
616+
for (Map.Entry<String, String> entry : clientProperties.entrySet()) {
617+
bb.writeShort(entry.getKey().length()).writeBytes(entry.getKey().getBytes(StandardCharsets.UTF_8))
618+
.writeShort(entry.getValue().length()).writeBytes(entry.getValue().getBytes(StandardCharsets.UTF_8));
619+
}
599620
bb.writeShort(saslMechanism.getName().length());
600621
bb.writeBytes(saslMechanism.getName().getBytes(StandardCharsets.UTF_8));
601622
if (challengeResponse == null) {
@@ -1268,6 +1289,8 @@ public static class ClientParameters {
12681289

12691290
private ChunkChecksum chunkChecksum = JdkChunkChecksum.CRC32_SINGLETON;
12701291

1292+
private final Map<String, String> clientProperties = new HashMap<>();
1293+
12711294
public ClientParameters host(String host) {
12721295
this.host = host;
12731296
return this;
@@ -1371,6 +1394,16 @@ public ClientParameters chunkChecksum(ChunkChecksum chunkChecksum) {
13711394
this.chunkChecksum = chunkChecksum;
13721395
return this;
13731396
}
1397+
1398+
public ClientParameters clientProperties(Map<String, String> clientProperties) {
1399+
this.clientProperties.putAll(clientProperties);
1400+
return this;
1401+
}
1402+
1403+
public ClientParameters clientProperty(String key, String value) {
1404+
this.clientProperties.put(key, value);
1405+
return this;
1406+
}
13741407
}
13751408

13761409
private static final class BinaryOnlyMessage implements Message {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
// Copyright (c) 2020 VMware, Inc. or its affiliates. All rights reserved.
2+
//
3+
// This software, the RabbitMQ Java client library, is dual-licensed under the
4+
// Mozilla Public License 1.1 ("MPL"), and the Apache License version 2 ("ASL").
5+
// For the MPL, please see LICENSE-MPL-RabbitMQ. For the ASL,
6+
// please see LICENSE-APACHE2.
7+
//
8+
// This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND,
9+
// either express or implied. See the LICENSE file for specific language governing
10+
// rights and limitations of this software.
11+
//
12+
// If you have any questions regarding licensing, please contact us at
13+
14+
15+
package com.rabbitmq.stream;
16+
17+
import org.slf4j.Logger;
18+
import org.slf4j.LoggerFactory;
19+
20+
import java.io.InputStream;
21+
import java.util.Collections;
22+
import java.util.HashMap;
23+
import java.util.Map;
24+
import java.util.Properties;
25+
26+
public abstract class ClientProperties {
27+
28+
private static final Logger LOGGER = LoggerFactory.getLogger(ClientProperties.class);
29+
30+
// We store the version property in an unusual way because relocating the package can rewrite the key in the property
31+
// file, which results in spurious warnings being emitted at start-up.
32+
// see https://github.com/rabbitmq/rabbitmq-java-client/issues/436
33+
private static final char[] VERSION_PROPERTY = new char[]{'c', 'o', 'm', '.', 'r', 'a', 'b', 'b', 'i', 't', 'm', 'q', '.',
34+
's', 't', 'r', 'e', 'a', 'm', '.', 'c', 'l', 'i', 'e', 'n', 't', '.', 'v', 'e', 'r', 's', 'i', 'o', 'n'};
35+
36+
public static final String VERSION = getVersion();
37+
38+
public static final Map<String, String> DEFAULT_CLIENT_PROPERTIES = Collections.unmodifiableMap(new HashMap<String, String>() {{
39+
put("product", "RabbitMQ Stream");
40+
put("version", ClientProperties.VERSION);
41+
put("platform", "Java");
42+
put("copyright", "Copyright (c) 2020 VMware, Inc. or its affiliates.");
43+
put("information", "Licensed under the MPL 2.0. See https://www.rabbitmq.com/");
44+
}});
45+
46+
private static String getVersion() {
47+
String version;
48+
try {
49+
version = getVersionFromPropertyFile();
50+
} catch (Exception e1) {
51+
LOGGER.warn("Couldn't get version from property file", e1);
52+
try {
53+
version = getVersionFromPackage();
54+
} catch (Exception e2) {
55+
LOGGER.warn("Couldn't get version with Package#getImplementationVersion", e1);
56+
version = getDefaultVersion();
57+
}
58+
}
59+
return version;
60+
}
61+
62+
private static String getVersionFromPropertyFile() throws Exception {
63+
InputStream inputStream = ClientProperties.class.getClassLoader().getResourceAsStream("rabbitmq-stream-client.properties");
64+
java.util.Properties version = new Properties();
65+
try {
66+
version.load(inputStream);
67+
} finally {
68+
if (inputStream != null) {
69+
inputStream.close();
70+
}
71+
}
72+
String propertyName = new String(VERSION_PROPERTY);
73+
String versionProperty = version.getProperty(propertyName);
74+
if (versionProperty == null) {
75+
throw new IllegalStateException("Couldn't find version property in property file");
76+
}
77+
return versionProperty;
78+
}
79+
80+
private static String getVersionFromPackage() {
81+
if (ClientProperties.class.getPackage().getImplementationVersion() == null) {
82+
throw new IllegalStateException("Couldn't get version with Package#getImplementationVersion");
83+
}
84+
return ClientProperties.class.getPackage().getImplementationVersion();
85+
}
86+
87+
private static String getDefaultVersion() {
88+
return "0.0.0";
89+
}
90+
91+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
com.rabbitmq.stream.client.version = ${project.version}

0 commit comments

Comments
 (0)