
com.lambdaworks.redis.RedisURI Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of lettuce Show documentation
Show all versions of lettuce Show documentation
Advanced and thread-safe Java Redis client for synchronous, asynchronous, and
reactive usage. Supports Cluster, Sentinel, Pipelining, Auto-Reconnect, Codecs
and much more.
The newest version!
/*
* Copyright 2011-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.lambdaworks.redis;
import static com.lambdaworks.redis.LettuceStrings.isEmpty;
import static com.lambdaworks.redis.LettuceStrings.isNotEmpty;
import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.net.URI;
import java.net.URLEncoder;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import com.lambdaworks.redis.internal.HostAndPort;
import com.lambdaworks.redis.internal.LettuceAssert;
import com.lambdaworks.redis.internal.LettuceSets;
import com.lambdaworks.redis.protocol.LettuceCharsets;
/**
* Redis URI. Contains connection details for the Redis/Sentinel connections. You can provide the database, password and
* timeouts within the RedisURI.
*
* You have following possibilities to create a {@link RedisURI}:
*
*
* - Use an URI:
*
* {@code RedisURI.create("redis://localhost/");}
*
* See {@link #create(String)} for more options
* - Use the Builder:
*
* {@code RedisURI.Builder.redis("localhost", 6379).withPassword("password").withDatabase(1).build(); }
*
* See {@link com.lambdaworks.redis.RedisURI.Builder#redis(String)} and
* {@link com.lambdaworks.redis.RedisURI.Builder#sentinel(String)} for more options.
* - Construct your own instance:
*
* {@code new RedisURI("localhost", 6379, 60, TimeUnit.SECONDS);}
*
* or
*
* {@code RedisURI uri = new RedisURI();
* uri.setHost("localhost");
* }
*
*
*
*
* URI syntax
*
* Redis Standalone redis{@code ://}[password@]host [{@code :}
* port][{@code /}database][{@code ?} [timeout=timeout[d|h|m|s|ms|us|ns]] [
* &database=database]]
*
* Redis Standalone (SSL) rediss{@code ://}[password@]host [{@code :}
* port][{@code /}database][{@code ?} [timeout=timeout[d|h|m|s|ms|us|ns]] [
* &database=database]]
*
* Redis Standalone (Unix Domain Sockets) redis-socket{@code ://} [password@]path[
* {@code ?}[timeout=timeout[d|h|m|s|ms|us|ns]][&database=database]]
*
* Redis Sentinel redis-sentinel{@code ://}[password@]host1 [{@code :}
* port1][, host2 [{@code :}port2]][, hostN [{@code :}portN]][{@code /}
* database][{@code ?} [timeout=timeout[d|h|m|s|ms|us|ns]] [
* &sentinelMasterId=sentinelMasterId] [&database=database]]
*
*
* Schemes
*
*
* - redis Redis Standalone
* - rediss Redis Standalone SSL
* - redis-socket Redis Standalone Unix Domain Socket
* - redis-sentinel Redis Sentinel
*
*
*
* Timeout units
*
*
* - d Days
* - h Hours
* - m Minutes
* - s Seconds
* - ms Milliseconds
* - us Microseconds
* - ns Nanoseconds
*
*
*
* Hint: The database parameter within the query part has higher precedence than the database in the path.
*
*
*
* RedisURI supports Redis Standalone, Redis Sentinel and Redis Cluster with plain, SSL, TLS and unix domain socket connections.
*
* @author Mark Paluch
* @since 3.0
*/
@SuppressWarnings("serial")
public class RedisURI implements Serializable, ConnectionPoint {
public static final String URI_SCHEME_REDIS_SENTINEL = "redis-sentinel";
public static final String URI_SCHEME_REDIS = "redis";
public static final String URI_SCHEME_REDIS_SECURE = "rediss";
public static final String URI_SCHEME_REDIS_SECURE_ALT = "redis+ssl";
public static final String URI_SCHEME_REDIS_TLS_ALT = "redis+tls";
public static final String URI_SCHEME_REDIS_SOCKET = "redis-socket";
public static final String URI_SCHEME_REDIS_SOCKET_ALT = "redis+socket";
public static final String PARAMETER_NAME_TIMEOUT = "timeout";
public static final String PARAMETER_NAME_DATABASE = "database";
public static final String PARAMETER_NAME_DATABASE_ALT = "db";
public static final String PARAMETER_NAME_SENTINEL_MASTER_ID = "sentinelMasterId";
public static final Map TIME_UNIT_MAP;
static {
Map unitMap = new HashMap();
unitMap.put("ns", TimeUnit.NANOSECONDS);
unitMap.put("us", TimeUnit.MICROSECONDS);
unitMap.put("ms", TimeUnit.MILLISECONDS);
unitMap.put("s", TimeUnit.SECONDS);
unitMap.put("m", TimeUnit.MINUTES);
unitMap.put("h", TimeUnit.HOURS);
unitMap.put("d", TimeUnit.DAYS);
TIME_UNIT_MAP = Collections.unmodifiableMap(unitMap);
}
/**
* The default sentinel port.
*/
public static final int DEFAULT_SENTINEL_PORT = 26379;
/**
* The default redis port.
*/
public static final int DEFAULT_REDIS_PORT = 6379;
/**
* Default timeout: 60 sec
*/
public static final long DEFAULT_TIMEOUT = 60;
public static final TimeUnit DEFAULT_TIMEOUT_UNIT = TimeUnit.SECONDS;
private String host;
private String socket;
private String sentinelMasterId;
private int port;
private int database;
private char[] password;
private boolean ssl = false;
private boolean verifyPeer = true;
private boolean startTls = false;
private long timeout = 60;
private TimeUnit unit = TimeUnit.SECONDS;
private final List sentinels = new ArrayList<>();
/**
* Default empty constructor.
*/
public RedisURI() {
}
/**
* Constructor with host/port and timeout.
*
* @param host the host
* @param port the port
* @param timeout timeout value
* @param unit unit of the timeout value
*/
public RedisURI(String host, int port, long timeout, TimeUnit unit) {
this.host = host;
this.port = port;
this.timeout = timeout;
this.unit = unit;
}
/**
* Returns a new {@link RedisURI.Builder} to construct a {@link RedisURI}.
*
* @return a new {@link RedisURI.Builder} to construct a {@link RedisURI}.
*/
public static RedisURI.Builder builder() {
return new Builder();
}
/**
* Create a Redis URI from host and port.
*
* @param host the host
* @param port the port
* @return An instance of {@link RedisURI} containing details from the {@code host} and {@code port}.
*/
public static RedisURI create(String host, int port) {
return Builder.redis(host, port).build();
}
/**
* Create a Redis URI from an URI string.
*
* The uri must follow conventions of {@link java.net.URI}
*
* @param uri The URI string.
* @return An instance of {@link RedisURI} containing details from the URI.
*/
public static RedisURI create(String uri) {
LettuceAssert.notEmpty(uri, "URI must not be empty");
return create(URI.create(uri));
}
/**
* Create a Redis URI from an URI string:
*
* The uri must follow conventions of {@link java.net.URI}
*
* @param uri The URI.
* @return An instance of {@link RedisURI} containing details from the URI.
*/
public static RedisURI create(URI uri) {
return buildRedisUriFromUri(uri);
}
/**
* Returns the host.
*
* @return the host.
*/
public String getHost() {
return host;
}
/**
* Sets the Redis host.
*
* @param host the host
*/
public void setHost(String host) {
this.host = host;
}
/**
* Returns the Sentinel Master Id.
*
* @return the Sentinel Master Id.
*/
public String getSentinelMasterId() {
return sentinelMasterId;
}
/**
* Sets the Sentinel Master Id.
*
* @param sentinelMasterId the Sentinel Master Id.
*/
public void setSentinelMasterId(String sentinelMasterId) {
this.sentinelMasterId = sentinelMasterId;
}
/**
* Returns the Redis port.
*
* @return the Redis port
*/
public int getPort() {
return port;
}
/**
* Sets the Redis port. Defaults to {@link #DEFAULT_REDIS_PORT}.
*
* @param port the Redis port
*/
public void setPort(int port) {
this.port = port;
}
/**
* Returns the Unix Domain Socket path.
*
* @return the Unix Domain Socket path.
*/
public String getSocket() {
return socket;
}
/**
* Sets the Unix Domain Socket path.
*
* @param socket the Unix Domain Socket path.
*/
public void setSocket(String socket) {
this.socket = socket;
}
/**
* Returns the password.
*
* @return the password
*/
public char[] getPassword() {
return password;
}
/**
* Sets the password. Use empty string to skip authentication.
*
* @param password the password, must not be {@literal null}.
*/
public void setPassword(String password) {
LettuceAssert.notNull(password, "Password must not be null");
this.password = password.toCharArray();
}
/**
* Returns the command timeout for synchronous command execution.
*
* @return the Timeout
*/
public long getTimeout() {
return timeout;
}
/**
* Sets the command timeout for synchronous command execution.
*
* @param timeout the command timeout for synchronous command execution.
*/
public void setTimeout(long timeout) {
this.timeout = timeout;
}
/**
* Returns the {@link TimeUnit} for the command timeout.
*
* @return the {@link TimeUnit} for the command timeout.
*/
public TimeUnit getUnit() {
return unit;
}
/**
* Sets the {@link TimeUnit} for the command timeout.
*
* @param unit the {@link TimeUnit} for the command timeout, must not be {@literal null}
*/
public void setUnit(TimeUnit unit) {
LettuceAssert.notNull(unit, "TimeUnit must not be null");
this.unit = unit;
}
/**
* Returns the Redis database number. Databases are only available for Redis Standalone and Redis Master/Slave.
*
* @return
*/
public int getDatabase() {
return database;
}
/**
* Sets the Redis database number. Databases are only available for Redis Standalone and Redis Master/Slave.
*
* @param database the Redis database number.
*/
public void setDatabase(int database) {
this.database = database;
}
/**
* Returns {@literal true} if SSL mode is enabled.
*
* @return {@literal true} if SSL mode is enabled.
*/
public boolean isSsl() {
return ssl;
}
/**
* Sets whether to use SSL model.
*
* @param ssl
*/
public void setSsl(boolean ssl) {
this.ssl = ssl;
}
/**
* Sets whether to verify peers when using {@link #isSsl() SSL}.
*
* @return {@literal true} to verify peers when using {@link #isSsl() SSL}.
*/
public boolean isVerifyPeer() {
return verifyPeer;
}
/**
* Sets whether to verify peers when using {@link #isSsl() SSL}.
*
* @param verifyPeer {@literal true} to verify peers when using {@link #isSsl() SSL}.
*/
public void setVerifyPeer(boolean verifyPeer) {
this.verifyPeer = verifyPeer;
}
/**
* Returns {@literal true} if StartTLS is enabled.
*
* @return {@literal true} if StartTLS is enabled.
*/
public boolean isStartTls() {
return startTls;
}
/**
* Returns whether StartTLS is enabled.
*
* @param startTls {@literal true} if StartTLS is enabled.
*/
public void setStartTls(boolean startTls) {
this.startTls = startTls;
}
/**
*
* @return the list of {@link RedisURI Redis Sentinel URIs}.
*/
public List getSentinels() {
return sentinels;
}
/**
* Creates an URI based on the RedisURI.
*
* @return URI based on the RedisURI
*/
public URI toURI() {
String scheme = getScheme();
String authority = getAuthority(scheme);
String queryString = getQueryString();
String uri = scheme + "://" + authority;
if (!queryString.isEmpty()) {
uri += "?" + queryString;
}
return URI.create(uri);
}
private static RedisURI buildRedisUriFromUri(URI uri) {
Builder builder;
if (uri.getScheme().equals(URI_SCHEME_REDIS_SENTINEL)) {
builder = configureSentinel(uri);
} else {
builder = configureStandalone(uri);
}
String userInfo = uri.getUserInfo();
if (isEmpty(userInfo) && isNotEmpty(uri.getAuthority()) && uri.getAuthority().indexOf('@') > 0) {
userInfo = uri.getAuthority().substring(0, uri.getAuthority().indexOf('@'));
}
if (isNotEmpty(userInfo)) {
String password = userInfo;
if (password.startsWith(":")) {
password = password.substring(1);
} else {
int index = password.indexOf(':');
if (index > 0) {
password = password.substring(index + 1);
}
}
if (password != null && !password.equals("")) {
builder.withPassword(password);
}
}
if (isNotEmpty(uri.getPath()) && builder.socket == null) {
String pathSuffix = uri.getPath().substring(1);
if (isNotEmpty(pathSuffix)) {
builder.withDatabase(Integer.parseInt(pathSuffix));
}
}
if (isNotEmpty(uri.getQuery())) {
StringTokenizer st = new StringTokenizer(uri.getQuery(), "&;");
while (st.hasMoreTokens()) {
String queryParam = st.nextToken();
String forStartWith = queryParam.toLowerCase();
if (forStartWith.startsWith(PARAMETER_NAME_TIMEOUT + "=")) {
parseTimeout(builder, queryParam.toLowerCase());
}
if (forStartWith.startsWith(PARAMETER_NAME_DATABASE + "=")
|| queryParam.startsWith(PARAMETER_NAME_DATABASE_ALT + "=")) {
parseDatabase(builder, queryParam);
}
if (forStartWith.startsWith(PARAMETER_NAME_SENTINEL_MASTER_ID.toLowerCase() + "=")) {
parseSentinelMasterId(builder, queryParam);
}
}
}
if (uri.getScheme().equals(URI_SCHEME_REDIS_SENTINEL)) {
LettuceAssert.notEmpty(builder.sentinelMasterId, "URI must contain the sentinelMasterId");
}
return builder.build();
}
private String getAuthority(final String scheme) {
String authority = null;
if (host != null) {
authority = urlEncode(host) + getPortPart(port, scheme);
}
if (sentinels.size() != 0) {
String joinedSentinels = sentinels.stream()
.map(redisURI -> urlEncode(redisURI.getHost()) + getPortPart(redisURI.getPort(), scheme))
.collect(Collectors.joining(","));
authority = joinedSentinels;
}
if (socket != null) {
authority = urlEncode(socket);
}
if (password != null && password.length != 0) {
authority = urlEncode(new String(password)) + "@" + authority;
}
return authority;
}
private String getQueryString() {
List queryPairs = new ArrayList<>();
if (database != 0) {
queryPairs.add(PARAMETER_NAME_DATABASE + "=" + database);
}
if (sentinelMasterId != null) {
queryPairs.add(PARAMETER_NAME_SENTINEL_MASTER_ID + "=" + urlEncode(sentinelMasterId));
}
if (timeout != 0 && unit != null && (timeout != DEFAULT_TIMEOUT && !unit.equals(DEFAULT_TIMEOUT_UNIT))) {
queryPairs.add(PARAMETER_NAME_TIMEOUT + "=" + timeout + toQueryParamUnit(unit));
}
return queryPairs.stream().collect(Collectors.joining("&"));
}
private String getPortPart(int port, String scheme) {
if (URI_SCHEME_REDIS_SENTINEL.equals(scheme) && port == DEFAULT_SENTINEL_PORT) {
return "";
}
if (URI_SCHEME_REDIS.equals(scheme) && port == DEFAULT_REDIS_PORT) {
return "";
}
return ":" + port;
}
private String getScheme() {
String scheme = URI_SCHEME_REDIS;
if (isSsl()) {
if (isStartTls()) {
scheme = URI_SCHEME_REDIS_TLS_ALT;
} else {
scheme = URI_SCHEME_REDIS_SECURE;
}
}
if (socket != null) {
scheme = URI_SCHEME_REDIS_SOCKET;
}
if (host == null && !sentinels.isEmpty()) {
scheme = URI_SCHEME_REDIS_SENTINEL;
}
return scheme;
}
private String toQueryParamUnit(TimeUnit unit) {
for (Map.Entry entry : TIME_UNIT_MAP.entrySet()) {
if (entry.getValue().equals(unit)) {
return entry.getKey();
}
}
return "";
}
/**
* URL encode the {@code str} without slash escaping {@code %2F}
*
* @param str
* @return the URL-encoded string
*/
private String urlEncode(String str) {
try {
return URLEncoder.encode(str, LettuceCharsets.UTF8.name()).replaceAll("%2F", "/");
} catch (UnsupportedEncodingException e) {
throw new IllegalStateException(e);
}
}
/**
*
* @return the resolved {@link SocketAddress} based either on host/port or the socket.
*/
public SocketAddress getResolvedAddress() {
if (getSocket() != null) {
return EpollProvider.newSocketAddress(getSocket());
}
InetSocketAddress socketAddress = new InetSocketAddress(host, port);
return socketAddress;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder();
sb.append(getClass().getSimpleName());
sb.append(" [");
if (host != null) {
sb.append("host='").append(host).append('\'');
sb.append(", port=").append(port);
}
if (socket != null) {
sb.append("socket='").append(socket).append('\'');
}
if (sentinelMasterId != null) {
sb.append("sentinels=").append(getSentinels());
sb.append(", sentinelMasterId=").append(sentinelMasterId);
}
sb.append(']');
return sb.toString();
}
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (!(o instanceof RedisURI))
return false;
RedisURI redisURI = (RedisURI) o;
if (port != redisURI.port)
return false;
if (database != redisURI.database)
return false;
if (host != null ? !host.equals(redisURI.host) : redisURI.host != null)
return false;
if (socket != null ? !socket.equals(redisURI.socket) : redisURI.socket != null)
return false;
if (sentinelMasterId != null ? !sentinelMasterId.equals(redisURI.sentinelMasterId) : redisURI.sentinelMasterId != null)
return false;
return !(sentinels != null ? !sentinels.equals(redisURI.sentinels) : redisURI.sentinels != null);
}
@Override
public int hashCode() {
int result = host != null ? host.hashCode() : 0;
result = 31 * result + (socket != null ? socket.hashCode() : 0);
result = 31 * result + (sentinelMasterId != null ? sentinelMasterId.hashCode() : 0);
result = 31 * result + port;
result = 31 * result + database;
result = 31 * result + (sentinels != null ? sentinels.hashCode() : 0);
return result;
}
private static void parseTimeout(Builder builder, String queryParam) {
int index = queryParam.indexOf('=');
if (index < 0) {
return;
}
String timeoutString = queryParam.substring(index + 1);
int numbersEnd = 0;
while (numbersEnd < timeoutString.length() && Character.isDigit(timeoutString.charAt(numbersEnd))) {
numbersEnd++;
}
if (numbersEnd == 0) {
if (timeoutString.startsWith("-")) {
builder.withTimeout(0, TimeUnit.MILLISECONDS);
} else {
// no-op, leave defaults
}
} else {
String timeoutValueString = timeoutString.substring(0, numbersEnd);
long timeoutValue = Long.parseLong(timeoutValueString);
builder.withTimeout(timeoutValue, TimeUnit.MILLISECONDS);
String suffix = timeoutString.substring(numbersEnd);
TimeUnit timeoutUnit = TIME_UNIT_MAP.get(suffix);
if (timeoutUnit == null) {
timeoutUnit = TimeUnit.MILLISECONDS;
}
builder.withTimeout(timeoutValue, timeoutUnit);
}
}
private static void parseDatabase(Builder builder, String queryParam) {
int index = queryParam.indexOf('=');
if (index < 0) {
return;
}
String databaseString = queryParam.substring(index + 1);
int numbersEnd = 0;
while (numbersEnd < databaseString.length() && Character.isDigit(databaseString.charAt(numbersEnd))) {
numbersEnd++;
}
if (numbersEnd != 0) {
String databaseValueString = databaseString.substring(0, numbersEnd);
int value = Integer.parseInt(databaseValueString);
builder.withDatabase(value);
}
}
private static void parseSentinelMasterId(Builder builder, String queryParam) {
int index = queryParam.indexOf('=');
if (index < 0) {
return;
}
String masterIdString = queryParam.substring(index + 1);
if (isNotEmpty(masterIdString)) {
builder.withSentinelMasterId(masterIdString);
}
}
private static Builder configureStandalone(URI uri) {
Builder builder;
Set allowedSchemes = LettuceSets.unmodifiableSet(URI_SCHEME_REDIS, URI_SCHEME_REDIS_SECURE,
URI_SCHEME_REDIS_SOCKET, URI_SCHEME_REDIS_SOCKET_ALT, URI_SCHEME_REDIS_SECURE_ALT, URI_SCHEME_REDIS_TLS_ALT);
if (!allowedSchemes.contains(uri.getScheme())) {
throw new IllegalArgumentException("Scheme " + uri.getScheme() + " not supported");
}
if (URI_SCHEME_REDIS_SOCKET.equals(uri.getScheme()) || URI_SCHEME_REDIS_SOCKET_ALT.equals(uri.getScheme())) {
builder = Builder.socket(uri.getPath());
} else {
if (uri.getPort() > 0) {
builder = Builder.redis(uri.getHost(), uri.getPort());
} else {
builder = Builder.redis(uri.getHost());
}
}
if (URI_SCHEME_REDIS_SECURE.equals(uri.getScheme()) || URI_SCHEME_REDIS_SECURE_ALT.equals(uri.getScheme())) {
builder.withSsl(true);
}
if (URI_SCHEME_REDIS_TLS_ALT.equals(uri.getScheme())) {
builder.withSsl(true);
builder.withStartTls(true);
}
return builder;
}
private static RedisURI.Builder configureSentinel(URI uri) {
String masterId = uri.getFragment();
RedisURI.Builder builder = null;
if (isNotEmpty(uri.getHost())) {
if (uri.getPort() != -1) {
builder = RedisURI.Builder.sentinel(uri.getHost(), uri.getPort());
} else {
builder = RedisURI.Builder.sentinel(uri.getHost());
}
}
if (builder == null && isNotEmpty(uri.getAuthority())) {
String authority = uri.getAuthority();
if (authority.indexOf('@') > -1) {
authority = authority.substring(authority.indexOf('@') + 1);
}
String[] hosts = authority.split("\\,");
for (String host : hosts) {
HostAndPort hostAndPort = HostAndPort.parse(host);
if (builder == null) {
if (hostAndPort.hasPort()) {
builder = RedisURI.Builder.sentinel(hostAndPort.getHostText(), hostAndPort.getPort());
} else {
builder = RedisURI.Builder.sentinel(hostAndPort.getHostText());
}
} else {
if (hostAndPort.hasPort()) {
builder.withSentinel(hostAndPort.getHostText(), hostAndPort.getPort());
} else {
builder.withSentinel(hostAndPort.getHostText());
}
}
}
}
if (isNotEmpty(masterId)) {
builder.withSentinelMasterId(masterId);
}
LettuceAssert.notNull(builder, "Invalid URI, cannot get host part");
return builder;
}
/**
* Builder for Redis URI.
*/
public static class Builder {
private String host;
private String socket;
private String sentinelMasterId;
private int port;
private int database;
private char[] password;
private boolean ssl = false;
private boolean verifyPeer = true;
private boolean startTls = false;
private long timeout = 60;
private TimeUnit unit = TimeUnit.SECONDS;
private final List sentinels = new ArrayList<>();
private Builder() {
}
/**
* Set Redis socket. Creates a new builder.
*
* @param socket the host name
* @return New builder with Redis socket.
*/
public static Builder socket(String socket) {
LettuceAssert.notNull(socket, "Socket must not be null");
Builder builder = RedisURI.builder();
builder.socket = socket;
return builder;
}
/**
* Set Redis host. Creates a new builder.
*
* @param host the host name
* @return New builder with Redis host/port.
*/
public static Builder redis(String host) {
return redis(host, DEFAULT_REDIS_PORT);
}
/**
* Set Redis host and port. Creates a new builder
*
* @param host the host name
* @param port the port
* @return New builder with Redis host/port.
*/
public static Builder redis(String host, int port) {
LettuceAssert.notEmpty(host, "Host must not be empty");
LettuceAssert.isTrue(isValidPort(port), String.format("Port out of range: %s", port));
Builder builder = RedisURI.builder();
return builder.withHost(host).withPort(port);
}
/**
* Set Sentinel host. Creates a new builder.
*
* @param host the host name
* @return New builder with Sentinel host/port.
*/
public static Builder sentinel(String host) {
LettuceAssert.notEmpty(host, "Host must not be empty");
Builder builder = RedisURI.builder();
return builder.withSentinel(host);
}
/**
* Set Sentinel host and port. Creates a new builder.
*
* @param host the host name
* @param port the port
* @return New builder with Sentinel host/port.
*/
public static Builder sentinel(String host, int port) {
LettuceAssert.notEmpty(host, "Host must not be empty");
LettuceAssert.isTrue(isValidPort(port), String.format("Port out of range: %s", port));
Builder builder = RedisURI.builder();
return builder.withSentinel(host, port);
}
/**
* Set Sentinel host and master id. Creates a new builder.
*
* @param host the host name
* @param masterId sentinel master id
* @return New builder with Sentinel host/port.
*/
public static Builder sentinel(String host, String masterId) {
return sentinel(host, DEFAULT_SENTINEL_PORT, masterId);
}
/**
* Set Sentinel host, port and master id. Creates a new builder.
*
* @param host the host name
* @param port the port
* @param masterId sentinel master id
* @return New builder with Sentinel host/port.
*/
public static Builder sentinel(String host, int port, String masterId) {
LettuceAssert.notEmpty(host, "Host must not be empty");
LettuceAssert.isTrue(isValidPort(port), String.format("Port out of range: %s", port));
Builder builder = RedisURI.builder();
return builder.withSentinelMasterId(masterId).withSentinel(host, port);
}
/**
* Add a withSentinel host to the existing builder.
*
* @param host the host name
* @return the builder
*/
public Builder withSentinel(String host) {
return withSentinel(host, DEFAULT_SENTINEL_PORT);
}
/**
* Add a withSentinel host/port to the existing builder.
*
* @param host the host name
* @param port the port
* @return the builder
*/
public Builder withSentinel(String host, int port) {
LettuceAssert.assertState(this.host == null, "Cannot use with Redis mode.");
LettuceAssert.notEmpty(host, "Host must not be empty");
LettuceAssert.isTrue(isValidPort(port), String.format("Port out of range: %s", port));
sentinels.add(HostAndPort.of(host, port));
return this;
}
/**
* Adds host information to the builder. Does only affect Redis URI, cannot be used with Sentinel connections.
*
* @param host the port
* @return the builder
*/
public Builder withHost(String host) {
LettuceAssert.assertState(this.sentinels.isEmpty(), "Sentinels are non-empty. Cannot use in Sentinel mode.");
LettuceAssert.notEmpty(host, "Host must not be empty");
this.host = host;
return this;
}
/**
* Adds port information to the builder. Does only affect Redis URI, cannot be used with Sentinel connections.
*
* @param port the port
* @return the builder
*/
public Builder withPort(int port) {
LettuceAssert.assertState(this.host != null, "Host is null. Cannot use in Sentinel mode.");
LettuceAssert.isTrue(isValidPort(port), String.format("Port out of range: %s", port));
this.port = port;
return this;
}
/**
* Adds ssl information to the builder. Does only affect Redis URI, cannot be used with Sentinel connections.
*
* @param ssl {@literal true} if use SSL
* @return the builder
*/
public Builder withSsl(boolean ssl) {
LettuceAssert.assertState(this.host != null, "Host is null. Cannot use in Sentinel mode.");
this.ssl = ssl;
return this;
}
/**
* Enables/disables StartTLS when using SSL. Does only affect Redis URI, cannot be used with Sentinel connections.
*
* @param startTls {@literal true} if use StartTLS
* @return the builder
*/
public Builder withStartTls(boolean startTls) {
LettuceAssert.assertState(this.host != null, "Host is null. Cannot use in Sentinel mode.");
this.startTls = startTls;
return this;
}
/**
* Enables/disables peer verification. Does only affect Redis URI, cannot be used with Sentinel connections.
*
* @param verifyPeer {@literal true} to verify hosts when using SSL
* @return the builder
*/
public Builder withVerifyPeer(boolean verifyPeer) {
LettuceAssert.assertState(this.host != null, "Host is null. Cannot use in Sentinel mode.");
this.verifyPeer = verifyPeer;
return this;
}
/**
* Adds database selection.
*
* @param database the database number
* @return the builder
*/
public Builder withDatabase(int database) {
LettuceAssert.isTrue(database >= 0 && database <= 15, "Invalid database number: " + database);
this.database = database;
return this;
}
/**
* Adds authentication.
*
* @param password the password
* @return the builder
*/
public Builder withPassword(String password) {
LettuceAssert.notNull(password, "Password must not be null");
this.password = password.toCharArray();
return this;
}
/**
* Adds timeout.
*
* @param timeout must be greater or equal 0"
* @param unit the timeout time unit.
* @return the builder
*/
public Builder withTimeout(long timeout, TimeUnit unit) {
LettuceAssert.notNull(unit, "TimeUnit must not be null");
LettuceAssert.isTrue(timeout >= 0, "Timeout must be greater or equal 0");
this.timeout = timeout;
this.unit = unit;
return this;
}
/**
* Adds a sentinel master Id.
*
* @param sentinelMasterId sentinel master id, must not be empty or {@literal null}
* @return the builder
*/
public Builder withSentinelMasterId(String sentinelMasterId) {
LettuceAssert.notEmpty(sentinelMasterId, "Sentinel master id must not empty");
this.sentinelMasterId = sentinelMasterId;
return this;
}
/**
*
* @return the RedisURI.
*/
public RedisURI build() {
if (sentinels.isEmpty() && LettuceStrings.isEmpty(host) && LettuceStrings.isEmpty(socket)) {
throw new IllegalStateException(
"Cannot build a RedisURI. One of the following must be provided Host, Socket or Sentinel");
}
RedisURI redisURI = new RedisURI();
redisURI.setHost(host);
redisURI.setPort(port);
redisURI.password = password;
redisURI.setDatabase(database);
redisURI.setSentinelMasterId(sentinelMasterId);
for (HostAndPort sentinel : sentinels) {
redisURI.getSentinels().add(new RedisURI(sentinel.getHostText(), sentinel.getPort(), timeout, unit));
}
redisURI.setSocket(socket);
redisURI.setSsl(ssl);
redisURI.setStartTls(startTls);
redisURI.setVerifyPeer(verifyPeer);
redisURI.setTimeout(timeout);
redisURI.setUnit(unit);
return redisURI;
}
}
/** Return true for valid port numbers. */
private static boolean isValidPort(int port) {
return port >= 0 && port <= 65535;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy