Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -547,6 +547,9 @@
<include>**/*CompareCondition*.java</include>
<include>**/*MSetExParams*.java</include>
<include>**/*UnitTest.java</include>
<include>**/DriverInfo.java</include>
<include>**/ClientSetInfo*.java</include>
<include>**/ClientCommandsTest*.java</include>
</includes>
</configuration>
<executions>
Expand Down
128 changes: 96 additions & 32 deletions src/main/java/redis/clients/jedis/ClientSetInfoConfig.java
Original file line number Diff line number Diff line change
@@ -1,68 +1,132 @@
package redis.clients.jedis;

import java.util.Arrays;
import java.util.HashSet;
import redis.clients.jedis.exceptions.JedisValidationException;

/**
* Configuration for CLIENT SETINFO command behaviour.
* <p>
* This class supports two modes of operation:
* <ul>
* <li>Advanced mode: Using {@link #withLibNameSuffix(String)} for advanced suffix customization,
* where the provided string is already preformatted according to the rules of the `CLIENT SETINFO`
* command</li>
* <li>Simple mode: Using {@link #ClientSetInfoConfig(DriverInfo)} used when the command parameter
* will be built by the driver based on the {@link DriverInfo} provided</li>
* </ul>
* <p>
* For backward compatibility, {@link #getUpstreamDrivers()} returns the upstream drivers string
* when using driver info mode.
* @see DriverInfo
* @see <a href="https://redis.io/docs/latest/commands/client-setinfo/">CLIENT SETINFO</a>
*/
public final class ClientSetInfoConfig {

private final boolean disabled;

private final String libNameSuffix;
private final DriverInfo driverInfo;

/**
* Creates a new ClientSetInfoConfig with default settings.
* <p>
* The default configuration uses the "jedis" library name without any upstream drivers.
*/
public ClientSetInfoConfig() {
this(false, null);
this(false);
}

/**
* Creates a new ClientSetInfoConfig with the specified disabled state.
* <p>
* When disabled, the CLIENT SETINFO command will not be sent to Redis.
* @param disabled {@code true} to disable CLIENT SETINFO, {@code false} otherwise
*/
public ClientSetInfoConfig(boolean disabled) {
this(disabled, null);
this.disabled = disabled;
this.driverInfo = DriverInfo.builder().build();
}

/**
* @param libNameSuffix must not have braces ({@code ()[]{}}) and spaces will be replaced with hyphens
* Creates a new ClientSetInfoConfig with a library name suffix.
* <p>
* This constructor is for legacy compatibility. The suffix will be appended to "jedis" in
* parentheses, resulting in a format like: {@code jedis(suffix)}.
* <p>
* For adding upstream driver information, use {@link #ClientSetInfoConfig(DriverInfo)} with a
* {@link DriverInfo} that has upstream drivers.
* @param libNameSuffix the suffix to append to "jedis" (will be placed in parentheses)
* @throws JedisValidationException if libNameSuffix contains braces
*/
public ClientSetInfoConfig(String libNameSuffix) {
this(false, libNameSuffix);
this.disabled = false;
this.driverInfo = DriverInfo.builder().addUpstreamDriver(libNameSuffix).build();
}

private ClientSetInfoConfig(boolean disabled, String libNameSuffix) {
this.disabled = disabled;
this.libNameSuffix = validateLibNameSuffix(libNameSuffix);
}

private static final HashSet<Character> BRACES = new HashSet<>(Arrays.asList('(', ')', '[', ']', '{', '}'));

private static String validateLibNameSuffix(String suffix) {
if (suffix == null || suffix.trim().isEmpty()) {
return null;
}

for (int i = 0; i < suffix.length(); i++) {
char c = suffix.charAt(i);
if (c < ' ' || c > '~' || BRACES.contains(c)) {
throw new JedisValidationException("lib-name suffix cannot contain braces, newlines or "
+ "special characters.");
}
/**
* Creates a new ClientSetInfoConfig with the specified driver information.
* <p>
* This is the recommended constructor for setting up driver information with upstream drivers.
* The driver information can optionally override the library name completely.
* @param driverInfo the driver information, must not be {@code null}
* @throws JedisValidationException if driverInfo is {@code null}
*/
public ClientSetInfoConfig(DriverInfo driverInfo) {
if (driverInfo == null) {
throw new JedisValidationException("DriverInfo must not be null");
}

return suffix.replaceAll("\\s", "-");
this.disabled = false;
this.driverInfo = driverInfo;
}

public final boolean isDisabled() {
/**
* @return {@code true} if CLIENT SETINFO is disabled, {@code false} otherwise
*/
public boolean isDisabled() {
return disabled;
}

public final String getLibNameSuffix() {
return libNameSuffix;
/**
* @return the driver information
*/
public DriverInfo getDriverInfo() {
return driverInfo;
}

/**
* Returns the formatted upstream drivers string.
* <p>
* Multiple drivers are separated by semicolons, with the most recently added driver appearing
* first.
* <p>
* Examples:
* <ul>
* <li>{@code "spring-data-redis_v3.2.0"} - single upstream driver</li>
* <li>{@code "lettuce-core_v6.4.1;spring-data-redis_v3.2.0"} - multiple upstream drivers</li>
* </ul>
* @return the formatted upstream drivers string, or {@code null} if no upstream drivers are set
*/
public String getUpstreamDrivers() {
return driverInfo.getUpstreamDrivers();
}

/**
* Default configuration that uses the Jedis library name without any upstream drivers.
*/
public static final ClientSetInfoConfig DEFAULT = new ClientSetInfoConfig();

/**
* Configuration that disables CLIENT SETINFO command.
*/
public static final ClientSetInfoConfig DISABLED = new ClientSetInfoConfig(true);

/**
* @param suffix must not have braces ({@code ()[]{}}) and spaces will be replaced with hyphens
* @return config
* Creates a new ClientSetInfoConfig with a library name suffix.
* <p>
* This is the legacy method for simple name customization. The provided suffix will be appended
* to "jedis" in parentheses, resulting in a format like: {@code jedis(suffix)}. For adding
* upstream driver information, use {@link #ClientSetInfoConfig(DriverInfo)} with a *
* {@link DriverInfo} that has upstream drivers.
* @param suffix the suffix to append to "jedis" (will be placed in parentheses)
* @return a new ClientSetInfoConfig with the library name suffix
*/
public static ClientSetInfoConfig withLibNameSuffix(String suffix) {
return new ClientSetInfoConfig(suffix);
Expand Down
17 changes: 6 additions & 11 deletions src/main/java/redis/clients/jedis/Connection.java
Original file line number Diff line number Diff line change
Expand Up @@ -542,20 +542,15 @@ protected void initializeFromClientConfig(final JedisClientConfig config) {
}

if (!setInfoConfig.isDisabled()) {
String libName = JedisMetaInfo.getArtifactId();
if (libName != null && validateClientInfo(libName)) {
String libNameSuffix = setInfoConfig.getLibNameSuffix();
if (libNameSuffix != null) { // validation is moved into ClientSetInfoConfig constructor
libName = libName + '(' + libNameSuffix + ')';
}
fireAndForgetMsg.add(new CommandArguments(Command.CLIENT).add(Keyword.SETINFO)
.add(ClientAttributeOption.LIB_NAME.getRaw()).add(libName));
}
fireAndForgetMsg.add(
new CommandArguments(Command.CLIENT).add(Keyword.SETINFO).add(ClientAttributeOption.LIB_NAME.getRaw())
.add(setInfoConfig.getDriverInfo().getFormattedName()));

String libVersion = JedisMetaInfo.getVersion();
if (libVersion != null && validateClientInfo(libVersion)) {
fireAndForgetMsg.add(new CommandArguments(Command.CLIENT).add(Keyword.SETINFO)
.add(ClientAttributeOption.LIB_VER.getRaw()).add(libVersion));
fireAndForgetMsg.add(
new CommandArguments(Command.CLIENT).add(Keyword.SETINFO).add(ClientAttributeOption.LIB_VER.getRaw())
.add(libVersion));
}
}

Expand Down
Loading
Loading