diff --git a/artemis-core-client/src/main/java/org/apache/activemq/artemis/uri/TCPServerLocatorSchema.java b/artemis-core-client/src/main/java/org/apache/activemq/artemis/uri/TCPServerLocatorSchema.java index c4701a709b..47500477b3 100644 --- a/artemis-core-client/src/main/java/org/apache/activemq/artemis/uri/TCPServerLocatorSchema.java +++ b/artemis-core-client/src/main/java/org/apache/activemq/artemis/uri/TCPServerLocatorSchema.java @@ -27,8 +27,26 @@ import org.apache.activemq.artemis.utils.uri.URISchema; import java.net.URI; import java.util.List; import java.util.Map; +import java.util.regex.Pattern; public class TCPServerLocatorSchema extends AbstractServerLocatorSchema { + // regex from http://stackoverflow.com/questions/53497/regular-expression-that-matches-valid-ipv6-addresses + private static final Pattern IPV6 = Pattern.compile("(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|" + // 1:2:3:4:5:6:7:8 + "([0-9a-fA-F]{1,4}:){1,7}:|" + // 1:: 1:2:3:4:5:6:7:: + "([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|" + // 1::8 1:2:3:4:5:6::8 1:2:3:4:5:6::8 + "([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|" + // 1::7:8 1:2:3:4:5::7:8 1:2:3:4:5::8 + "([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|" + // 1::6:7:8 1:2:3:4::6:7:8 1:2:3:4::8 + "([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|" + // 1::5:6:7:8 1:2:3::5:6:7:8 1:2:3::8 + "([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|" + // 1::4:5:6:7:8 1:2::4:5:6:7:8 1:2::8 + "[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|" + // 1::3:4:5:6:7:8 1::3:4:5:6:7:8 1::8 + ":((:[0-9a-fA-F]{1,4}){1,7}|:)|" + // ::2:3:4:5:6:7:8 ::2:3:4:5:6:7:8 ::8 :: + "[fF][eE]80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|" + // fe80::7:8%eth0 fe80::7:8%1 (link-local IPv6 addresses with zone index) + "::([fF]{4}(:0{1,4}){0,1}:){0,1}" + + "((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}" + + "(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|" + // ::255.255.255.255 ::ffff:255.255.255.255 ::ffff:0:255.255.255.255 (IPv4-mapped IPv6 addresses and IPv4-translated addresses) + "([0-9a-fA-F]{1,4}:){1,4}:" + + "((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}" + + "(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))"); // 2001:db8:3:4::192.0.2.33 64:ff9b::192.0.2.33 (IPv4-Embedded IPv6 Address) @Override public String getSchemaName() { @@ -64,7 +82,7 @@ public class TCPServerLocatorSchema extends AbstractServerLocatorSchema { StringBuilder fragment = new StringBuilder(); for (int i = 1; i < staticConnectors.length; i++) { TransportConfiguration connector = staticConnectors[i]; - Map params = connector.getParams(); + Map params = escapeIPv6Host(connector.getParams()); URI extraUri = new URI(SchemaConstants.TCP, null, getHost(params), getPort(params), null, createQuery(params, null), null); if (i > 1) { fragment.append(","); @@ -72,10 +90,20 @@ public class TCPServerLocatorSchema extends AbstractServerLocatorSchema { fragment.append(extraUri.toASCIIString()); } - Map params = staticConnectors[0].getParams(); + Map params = escapeIPv6Host(staticConnectors[0].getParams()); return new URI(SchemaConstants.TCP, null, getHost(params), getPort(params), null, createQuery(params, query), fragment.toString()); } + private static Map escapeIPv6Host(Map params) { + String host = (String) params.get("host"); + + if (host != null && IPV6.matcher(host).matches()) { + params.put("host", "[" + host + "]"); + } + + return params; + } + private static int getPort(Map params) { Object port = params.get("port"); if (port instanceof String) { diff --git a/artemis-jms-client/src/test/java/org/apache/activemq/artemis/uri/ConnectionFactoryURITest.java b/artemis-jms-client/src/test/java/org/apache/activemq/artemis/uri/ConnectionFactoryURITest.java index 8169553fba..827a894243 100644 --- a/artemis-jms-client/src/test/java/org/apache/activemq/artemis/uri/ConnectionFactoryURITest.java +++ b/artemis-jms-client/src/test/java/org/apache/activemq/artemis/uri/ConnectionFactoryURITest.java @@ -18,6 +18,10 @@ package org.apache.activemq.artemis.uri; import java.beans.PropertyDescriptor; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; import java.lang.reflect.InvocationTargetException; import java.net.URI; import java.util.HashMap; @@ -49,6 +53,28 @@ public class ConnectionFactoryURITest { ConnectionFactoryParser parser = new ConnectionFactoryParser(); + @Test + public void testIPv6() throws Exception { + String ipv6 = "fe80::baf6:b1ff:fe12:daf7%eth0"; + Map params = new HashMap<>(); + params.put("host", ipv6); + params.put("port", 5445); + TransportConfiguration transport = new TransportConfiguration(NettyConnectorFactory.class.getName(), params); + ActiveMQConnectionFactory factory = ActiveMQJMSClient.createConnectionFactoryWithoutHA(JMSFactoryType.CF, transport); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ObjectOutputStream outStream = new ObjectOutputStream(baos); + outStream.writeObject(factory); + outStream.close(); + baos.close(); + ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); + ObjectInputStream in = new ObjectInputStream(bais); + factory = (ActiveMQConnectionFactory) in.readObject(); + in.close(); + bais.close(); + Assert.assertEquals("[" + ipv6 + "]", factory.getStaticConnectors()[0].getParams().get("host")); + } + @Test public void testQUEUE_XA_CF() throws Exception { ActiveMQConnectionFactory factory = parser.newObject(new URI("tcp://localhost:3030?ha=true&type=QUEUE_XA_CF"), null);