2020import java .time .Duration ;
2121import java .util .*;
2222import java .util .concurrent .TimeUnit ;
23+ import java .util .regex .Matcher ;
24+ import java .util .regex .Pattern ;
2325
2426import org .apache .commons .logging .Log ;
2527import org .apache .commons .logging .LogFactory ;
@@ -178,8 +180,8 @@ public static Set<RedisClusterNode> toSetOfRedisClusterNodes(Collection<String>
178180 public static Set <RedisClusterNode > toSetOfRedisClusterNodes (String clusterNodes ) {
179181
180182 return StringUtils .hasText (clusterNodes )
181- ? toSetOfRedisClusterNodes (Arrays .asList (clusterNodes .split (CLUSTER_NODES_LINE_SEPARATOR )))
182- : Collections .emptySet ();
183+ ? toSetOfRedisClusterNodes (Arrays .asList (clusterNodes .split (CLUSTER_NODES_LINE_SEPARATOR )))
184+ : Collections .emptySet ();
183185 }
184186
185187 public static List <Object > toObjects (Set <Tuple > tuples ) {
@@ -386,8 +388,7 @@ public static Object parse(Object source, String sourcePath, Map<String, Class<?
386388
387389 if (targetType == null ) {
388390
389- String alternatePath = sourcePath .contains ("." )
390- ? sourcePath .substring (0 , sourcePath .lastIndexOf ("." )) + ".*"
391+ String alternatePath = sourcePath .contains ("." ) ? sourcePath .substring (0 , sourcePath .lastIndexOf ("." )) + ".*"
391392 : sourcePath ;
392393
393394 targetType = typeHintMap .get (alternatePath );
@@ -527,8 +528,9 @@ public GeoResults<GeoLocation<V>> convert(GeoResults<GeoLocation<byte[]>> source
527528 List <GeoResult <GeoLocation <V >>> values = new ArrayList <>(source .getContent ().size ());
528529
529530 for (GeoResult <GeoLocation <byte []>> value : source .getContent ()) {
530- values .add (new GeoResult <>(new GeoLocation <>(serializer .deserialize (value .getContent ().getName ()),
531- value .getContent ().getPoint ()), value .getDistance ()));
531+ values .add (new GeoResult <>(
532+ new GeoLocation <>(serializer .deserialize (value .getContent ().getName ()), value .getContent ().getPoint ()),
533+ value .getDistance ()));
532534 }
533535
534536 return new GeoResults <>(values , source .getAverageDistance ().getMetric ());
@@ -539,6 +541,16 @@ enum ClusterNodesConverter implements Converter<String, RedisClusterNode> {
539541
540542 INSTANCE ;
541543
544+ /**
545+ * Support following printf patterns:
546+ * <ul>
547+ * <li>{@code %s:%i} (Redis 3)</li>
548+ * <li>{@code %s:%i@%i} (Redis 4, with bus port)</li>
549+ * <li>{@code %s:%i@%i,%s} (Redis 7, with announced hostname)</li>
550+ * </ul>
551+ */
552+ static final Pattern clusterEndpointPattern = Pattern
553+ .compile ("\\ [?([0-9a-zA-Z\\ -_\\ .:]*)\\ ]?:([0-9]+)(?:@[0-9]+(?:,([^,].*))?)?" );
542554 private static final Map <String , Flag > flagLookupMap ;
543555
544556 static {
@@ -562,33 +574,29 @@ public RedisClusterNode convert(String source) {
562574
563575 String [] args = source .split (" " );
564576
565- int lastColonIndex = args [HOST_PORT_INDEX ]. lastIndexOf ( ":" );
577+ Matcher matcher = clusterEndpointPattern . matcher ( args [HOST_PORT_INDEX ]);
566578
567- Assert .isTrue (lastColonIndex >= 0 && lastColonIndex < args [HOST_PORT_INDEX ].length () - 1 ,
568- "ClusterNode information does not define host and port" );
579+ Assert .isTrue (matcher .matches (), "ClusterNode information does not define host and port" );
569580
570- String portPart = args [HOST_PORT_INDEX ].substring (lastColonIndex + 1 );
571- String hostPart = args [HOST_PORT_INDEX ].substring (0 , lastColonIndex );
581+ String addressPart = matcher .group (1 );
582+ String portPart = matcher .group (2 );
583+ String hostnamePart = matcher .group (3 );
572584
573585 SlotRange range = parseSlotRange (args );
574586 Set <Flag > flags = parseFlags (args );
575587
576- if (portPart .contains ("@" )) {
577- portPart = portPart .substring (0 , portPart .indexOf ('@' ));
578- }
579-
580- if (hostPart .startsWith ("[" ) && hostPart .endsWith ("]" )) {
581- hostPart = hostPart .substring (1 , hostPart .length () - 1 );
582- }
583-
584588 RedisClusterNodeBuilder nodeBuilder = RedisClusterNode .newRedisClusterNode ()
585- .listeningAt (hostPart , Integer .parseInt (portPart )) //
589+ .listeningAt (addressPart , Integer .parseInt (portPart )) //
586590 .withId (args [ID_INDEX ]) //
587591 .promotedAs (flags .contains (Flag .MASTER ) ? NodeType .MASTER : NodeType .REPLICA ) //
588592 .serving (range ) //
589593 .withFlags (flags ) //
590594 .linkState (parseLinkState (args ));
591595
596+ if (hostnamePart != null ) {
597+ nodeBuilder .withName (hostnamePart );
598+ }
599+
592600 if (!args [MASTER_ID_INDEX ].isEmpty () && !args [MASTER_ID_INDEX ].startsWith ("-" )) {
593601 nodeBuilder .replicaOf (args [MASTER_ID_INDEX ]);
594602 }
0 commit comments