[TEXT-170] Add String lookup for host names and IP addresses (#118)
Merge remote-tracking branch 'origin/master'.
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index b66bb0a..b0b2a60 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -49,6 +49,7 @@
<action issue="TEXT-167" type="fix" dev="ggregory" due-to="Larry West">commons-text web page missing "RELEASE-NOTES-1.7.txt"</action>
<action issue="TEXT-168" type="fix" dev="ggregory" due-to="luksan47">(doc) Fixed wrong value for Jaro-Winkler example #117</action>
<action issue="TEXT-169" type="add" dev="ggregory" due-to="Gary Gregory">Add helper factory method org.apache.commons.text.StringSubstitutor.createInterpolator().</action>
+ <action issue="TEXT-170" type="add" dev="ggregory" due-to="Gary Gregory">Add String lookup for host names and IP addresses (DnsStringLookup).</action>
</release>
<release version="1.7" date="2019-06-30" description="Release 1.7">
diff --git a/src/main/java/org/apache/commons/text/lookup/DefaultStringLookup.java b/src/main/java/org/apache/commons/text/lookup/DefaultStringLookup.java
index ba57578..c9632fa 100644
--- a/src/main/java/org/apache/commons/text/lookup/DefaultStringLookup.java
+++ b/src/main/java/org/apache/commons/text/lookup/DefaultStringLookup.java
@@ -49,6 +49,13 @@
DATE(StringLookupFactory.KEY_DATE, StringLookupFactory.INSTANCE.dateStringLookup()),
/**
+ * The lookup for DNS.
+ *
+ * @since 1.8
+ */
+ DNS(StringLookupFactory.KEY_DNS, StringLookupFactory.INSTANCE.dnsStringLookup()),
+
+ /**
* The lookup for environment properties.
*/
ENVIRONMENT(StringLookupFactory.KEY_ENV, StringLookupFactory.INSTANCE.environmentVariableStringLookup()),
diff --git a/src/main/java/org/apache/commons/text/lookup/DnsStringLookup.java b/src/main/java/org/apache/commons/text/lookup/DnsStringLookup.java
new file mode 100644
index 0000000..ba89418
--- /dev/null
+++ b/src/main/java/org/apache/commons/text/lookup/DnsStringLookup.java
@@ -0,0 +1,85 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.commons.text.lookup;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+/**
+ * Looks up keys related to DNS entries like host name, canonical host name, host address.
+ * <p>
+ * The lookup keys are:
+ * </p>
+ * <ul>
+ * <li><b>name|<em>address</em></b>: for the host name, for example {@code "name|93.184.216.34"} ->
+ * {@code "example.com"}.</li>
+ * <li><b>canonical-name|<em>address</em></b>: for the canonical host name, for example {@code "name|93.184.216.34"} ->
+ * {@code "example.com"}.</li>
+ * <li><b>address|<em>hostname</em></b>: for the host address, for example {@code "address|example.com"} ->
+ * {@code "93.184.216.34"}.</li>
+ * <li><b><em>address</em></b>: same as {@code address|hostname}.</li>
+ * </ul>
+ *
+ * @since 1.8
+ */
+final class DnsStringLookup extends AbstractStringLookup {
+
+ /**
+ * Defines the singleton for this class.
+ */
+ static final DnsStringLookup INSTANCE = new DnsStringLookup();
+
+ /**
+ * No need to build instances for now.
+ */
+ private DnsStringLookup() {
+ // empty
+ }
+
+ /**
+ * Looks up the DNS value of the key.
+ *
+ * @param key the key to be looked up, may be null
+ * @return The DNS value.
+ */
+ @Override
+ public String lookup(final String key) {
+ if (key == null) {
+ return null;
+ }
+ final String[] keys = key.trim().split("\\|");
+ final int keyLen = keys.length;
+ final String subKey = keys[0].trim();
+ final String subValue = keyLen < 2 ? key : keys[1].trim();
+ try {
+ final InetAddress inetAddress = InetAddress.getByName(subValue);
+ switch (subKey) {
+ case InetAddressKeys.KEY_NAME:
+ return inetAddress.getHostName();
+ case InetAddressKeys.KEY_CANONICAL_NAME:
+ return inetAddress.getCanonicalHostName();
+ case InetAddressKeys.KEY_ADDRESS:
+ return inetAddress.getHostAddress();
+ default:
+ return inetAddress.getHostAddress();
+ }
+ } catch (final UnknownHostException e) {
+ return null;
+ }
+ }
+
+}
diff --git a/src/main/java/org/apache/commons/text/lookup/InetAddressKeys.java b/src/main/java/org/apache/commons/text/lookup/InetAddressKeys.java
new file mode 100644
index 0000000..2465614
--- /dev/null
+++ b/src/main/java/org/apache/commons/text/lookup/InetAddressKeys.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.commons.text.lookup;
+
+import java.net.InetAddress;
+
+/**
+ * Constants for referring to {@link InetAddress} APIs.
+ *
+ * @since 1.8
+ */
+class InetAddressKeys {
+
+ /**
+ * Constants for referring to {@link InetAddress#getAddress()}.
+ */
+ static final String KEY_ADDRESS = "address";
+
+ /**
+ * Constants for referring to {@link InetAddress#getCanonicalAddress()}.
+ */
+ static final String KEY_CANONICAL_NAME = "canonical-name";
+
+ /**
+ * Constants for referring to {@link InetAddress#getName()}.
+ */
+ static final String KEY_NAME = "name";
+
+}
diff --git a/src/main/java/org/apache/commons/text/lookup/LocalHostStringLookup.java b/src/main/java/org/apache/commons/text/lookup/LocalHostStringLookup.java
index 9f4ee34..8bdc24d 100644
--- a/src/main/java/org/apache/commons/text/lookup/LocalHostStringLookup.java
+++ b/src/main/java/org/apache/commons/text/lookup/LocalHostStringLookup.java
@@ -59,11 +59,11 @@
}
try {
switch (key) {
- case "name":
+ case InetAddressKeys.KEY_NAME:
return InetAddress.getLocalHost().getHostName();
- case "canonical-name":
+ case InetAddressKeys.KEY_CANONICAL_NAME:
return InetAddress.getLocalHost().getCanonicalHostName();
- case "address":
+ case InetAddressKeys.KEY_ADDRESS:
return InetAddress.getLocalHost().getHostAddress();
default:
throw new IllegalArgumentException(key);
diff --git a/src/main/java/org/apache/commons/text/lookup/StringLookupFactory.java b/src/main/java/org/apache/commons/text/lookup/StringLookupFactory.java
index 693eedb..7cfc90b 100644
--- a/src/main/java/org/apache/commons/text/lookup/StringLookupFactory.java
+++ b/src/main/java/org/apache/commons/text/lookup/StringLookupFactory.java
@@ -59,6 +59,12 @@
* <td>1.5</td>
* </tr>
* <tr>
+ * <td>{@value #KEY_DNS}</td>
+ * <td>{@link DnsStringLookup}</td>
+ * <td>{@link #dnsStringLookup()}</td>
+ * <td>1.8</td>
+ * </tr>
+ * <tr>
* <td>{@value #KEY_ENV}</td>
* <td>{@link EnvironmentVariableStringLookup}</td>
* <td>{@link #environmentVariableStringLookup()}</td>
@@ -172,6 +178,13 @@
/**
* Default lookup key for interpolation.
*
+ * @since 1.8
+ */
+ public static final String KEY_DNS = "dns";
+
+ /**
+ * Default lookup key for interpolation.
+ *
* @since 1.6
*/
public static final String KEY_ENV = "env";
@@ -592,6 +605,21 @@
}
/**
+ * Returns the DnsStringLookup singleton instance where the lookup key is one of:
+ * <ul>
+ * <li><b>name</b>: for the local host name, for example {@code EXAMPLE} but also {@code EXAMPLE.apache.org}.</li>
+ * <li><b>canonical-name</b>: for the local canonical host name, for example {@code EXAMPLE.apache.org}.</li>
+ * <li><b>address</b>: for the local host address, for example {@code 192.168.56.1}.</li>
+ * </ul>
+ *
+ * @return the DateStringLookup singleton instance.
+ * @since 1.8
+ */
+ public StringLookup dnsStringLookup() {
+ return DnsStringLookup.INSTANCE;
+ }
+
+ /**
* Returns a new map-based lookup where the request for a lookup is answered with the value for that key.
*
* @param <V> the map value type.
diff --git a/src/test/java/org/apache/commons/text/StringSubstitutorWithInterpolatorStringLookupTest.java b/src/test/java/org/apache/commons/text/StringSubstitutorWithInterpolatorStringLookupTest.java
index f05b2c7..ed4dc03 100644
--- a/src/test/java/org/apache/commons/text/StringSubstitutorWithInterpolatorStringLookupTest.java
+++ b/src/test/java/org/apache/commons/text/StringSubstitutorWithInterpolatorStringLookupTest.java
@@ -45,7 +45,7 @@
final Map<String, StringLookup> stringLookupMap = new HashMap<>();
stringLookupMap.put("customLookup", mapStringLookup);
final StringSubstitutor strSubst = new StringSubstitutor(
- StringLookupFactory.INSTANCE.interpolatorStringLookup(stringLookupMap, null, addDefaultLookups));
+ StringLookupFactory.INSTANCE.interpolatorStringLookup(stringLookupMap, null, addDefaultLookups));
if (addDefaultLookups) {
final String spKey = "user.name";
Assertions.assertEquals(System.getProperty(spKey), strSubst.replace("${sys:" + spKey + "}"));
@@ -61,7 +61,7 @@
@Test
public void testDefaultValueForMissingKeyInResourceBundle() {
final StringLookup interpolatorStringLookup = StringLookupFactory.INSTANCE.interpolatorStringLookup(
- StringLookupFactory.INSTANCE.resourceBundleStringLookup("testResourceBundleLookup"));
+ StringLookupFactory.INSTANCE.resourceBundleStringLookup("testResourceBundleLookup"));
assertEquals("${missingKey:-defaultValue}", interpolatorStringLookup.lookup("keyWithMissingKey"));
final StringSubstitutor stringSubstitutor = new StringSubstitutor(interpolatorStringLookup);
// The following would throw a MissingResourceException before TEXT-165.
@@ -69,19 +69,50 @@
}
@Test
- void testAll() {
- // @formatter:off
- StringSubstitutor.createInterpolator().replace(
- "OS name: ${sys:os.name}, " +
- "3 + 4 = ${script:javascript:3 + 4}");
- // @formatter:on
+ public void testDnsLookup() throws UnknownHostException {
+ final StringSubstitutor strSubst = StringSubstitutor.createInterpolator();
+ final String hostName = InetAddress.getLocalHost().getHostName();
+ Assertions.assertEquals(InetAddress.getByName(hostName).getHostAddress(),
+ strSubst.replace("${dns:" + hostName + "}"));
}
@Test
- public void testJavaScript() {
- Assertions.assertEquals("Hello World!",
- StringSubstitutor.createInterpolator().replace("${script:javascript:\"Hello World!\"}"));
- Assertions.assertEquals("7", StringSubstitutor.createInterpolator().replace("${script:javascript:3 + 4}"));
+ public void testDnsLookupAddress() throws UnknownHostException {
+ final StringSubstitutor strSubst = StringSubstitutor.createInterpolator();
+ Assertions.assertEquals(InetAddress.getByName("apache.org").getHostAddress(),
+ strSubst.replace("${dns:address|apache.org}"));
+ }
+
+ @Test
+ public void testDnsLookupCanonicalName() throws UnknownHostException {
+ final StringSubstitutor strSubst = StringSubstitutor.createInterpolator();
+ final String address = InetAddress.getLocalHost().getHostAddress();
+ final InetAddress inetAddress = InetAddress.getByName(address);
+ Assertions.assertEquals(inetAddress.getCanonicalHostName(),
+ strSubst.replace("${dns:canonical-name|" + address + "}"));
+ }
+
+ @Test
+ public void testDnsLookupName() throws UnknownHostException {
+ final StringSubstitutor strSubst = StringSubstitutor.createInterpolator();
+ final String address = InetAddress.getLocalHost().getHostAddress();
+ final InetAddress inetAddress = InetAddress.getByName(address);
+ Assertions.assertEquals(inetAddress.getHostName(), strSubst.replace("${dns:name|" + address + "}"));
+ }
+
+ @Test
+ public void testDnsLookupNameUntrimmed() throws UnknownHostException {
+ final StringSubstitutor strSubst = StringSubstitutor.createInterpolator();
+ final String address = InetAddress.getLocalHost().getHostAddress();
+ final InetAddress inetAddress = InetAddress.getByName(address);
+ Assertions.assertEquals(inetAddress.getHostName(), strSubst.replace("${dns:name| " + address + " }"));
+ }
+
+ @Test
+ public void testDnsLookupUnknown() {
+ final StringSubstitutor strSubst = StringSubstitutor.createInterpolator();
+ final String unknown = "${dns: u n k n o w n}";
+ Assertions.assertEquals(unknown, strSubst.replace(unknown));
}
@Test
@@ -94,7 +125,7 @@
public void testLocalHostLookup_CanonicalName() throws UnknownHostException {
final StringSubstitutor strSubst = StringSubstitutor.createInterpolator();
Assertions.assertEquals(InetAddress.getLocalHost().getCanonicalHostName(),
- strSubst.replace("${localhost:canonical-name}"));
+ strSubst.replace("${localhost:canonical-name}"));
}
@Test
@@ -110,13 +141,21 @@
final Map<String, String> map = new HashMap<>();
map.put(key, value);
final StringSubstitutor strSubst = new StringSubstitutor(
- StringLookupFactory.INSTANCE.interpolatorStringLookup(map));
+ StringLookupFactory.INSTANCE.interpolatorStringLookup(map));
final String spKey = "user.name";
Assertions.assertEquals(System.getProperty(spKey), strSubst.replace("${sys:" + spKey + "}"));
Assertions.assertEquals(value, strSubst.replace("${" + key + "}"));
}
@Test
+ void testJavaScript() {
+ Assertions.assertEquals("Hello World!",
+ StringSubstitutor.createInterpolator().replace("${script:javascript:\"Hello World!\"}"));
+ Assertions.assertEquals("7",
+ StringSubstitutor.createInterpolator().replace("${script:javascript:3 + 4}"));
+ }
+
+ @Test
public void testSystemProperty() {
final StringSubstitutor strSubst = StringSubstitutor.createInterpolator();
final String spKey = "user.name";
diff --git a/src/test/java/org/apache/commons/text/lookup/DefaultStringLookupTest.java b/src/test/java/org/apache/commons/text/lookup/DefaultStringLookupTest.java
index 2302dd3..0fa967a 100644
--- a/src/test/java/org/apache/commons/text/lookup/DefaultStringLookupTest.java
+++ b/src/test/java/org/apache/commons/text/lookup/DefaultStringLookupTest.java
@@ -46,6 +46,7 @@
StringLookupFactory.INSTANCE.base64EncoderStringLookup());
assertSame(DefaultStringLookup.CONST.getStringLookup(), StringLookupFactory.INSTANCE.constantStringLookup());
assertSame(DefaultStringLookup.DATE.getStringLookup(), StringLookupFactory.INSTANCE.dateStringLookup());
+ assertSame(DefaultStringLookup.DNS.getStringLookup(), StringLookupFactory.INSTANCE.dnsStringLookup());
assertSame(DefaultStringLookup.ENVIRONMENT.getStringLookup(),
StringLookupFactory.INSTANCE.environmentVariableStringLookup());
assertSame(DefaultStringLookup.FILE.getStringLookup(), StringLookupFactory.INSTANCE.fileStringLookup());
diff --git a/src/test/java/org/apache/commons/text/lookup/DnsStringLookupTest.java b/src/test/java/org/apache/commons/text/lookup/DnsStringLookupTest.java
new file mode 100644
index 0000000..fed3797
--- /dev/null
+++ b/src/test/java/org/apache/commons/text/lookup/DnsStringLookupTest.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.commons.text.lookup;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+/**
+ * Tests {@link DnsStringLookup}.
+ */
+public class DnsStringLookupTest {
+
+ @Test
+ public void testAddressFromHostAddress() throws UnknownHostException {
+ final InetAddress localHost = InetAddress.getLocalHost();
+ Assertions.assertEquals(localHost.getHostAddress(),
+ DnsStringLookup.INSTANCE.lookup("address|" + localHost.getHostAddress()));
+ }
+
+ @Test
+ public void testAddressFromHostName() throws UnknownHostException {
+ final InetAddress localHost = InetAddress.getLocalHost();
+ Assertions.assertEquals(localHost.getHostAddress(),
+ DnsStringLookup.INSTANCE.lookup("address|" + localHost.getHostName()));
+ }
+
+ @Test
+ public void testCanonicalNameFromHostAddress() throws UnknownHostException {
+ final InetAddress localHost = InetAddress.getLocalHost();
+ Assertions.assertEquals(localHost.getCanonicalHostName(),
+ DnsStringLookup.INSTANCE.lookup("canonical-name|" + localHost.getHostAddress()));
+ }
+
+ @Test
+ public void testCanonicalNameFromHostName() throws UnknownHostException {
+ final InetAddress localHost = InetAddress.getLocalHost();
+ Assertions.assertEquals(localHost.getCanonicalHostName(),
+ DnsStringLookup.INSTANCE.lookup("canonical-name|" + localHost.getHostName()));
+ }
+
+ @Test
+ public void testName() throws UnknownHostException {
+ final String address = InetAddress.getLocalHost().getHostAddress();
+ final InetAddress localHost = InetAddress.getByName(address);
+ Assertions.assertEquals(localHost.getHostName(), DnsStringLookup.INSTANCE.lookup("name|" + address + ""));
+ }
+
+ @Test
+ public void testNull() {
+ Assertions.assertNull(DnsStringLookup.INSTANCE.lookup(null));
+ }
+
+}
diff --git a/src/test/java/org/apache/commons/text/lookup/StringLookupFactoryTest.java b/src/test/java/org/apache/commons/text/lookup/StringLookupFactoryTest.java
index 46893fd..e7731e7 100644
--- a/src/test/java/org/apache/commons/text/lookup/StringLookupFactoryTest.java
+++ b/src/test/java/org/apache/commons/text/lookup/StringLookupFactoryTest.java
@@ -34,6 +34,7 @@
assertTrue(stringLookupMap.containsKey(StringLookupFactory.KEY_BASE64_ENCODER));
assertTrue(stringLookupMap.containsKey(StringLookupFactory.KEY_CONST));
assertTrue(stringLookupMap.containsKey(StringLookupFactory.KEY_DATE));
+ assertTrue(stringLookupMap.containsKey(StringLookupFactory.KEY_DNS));
assertTrue(stringLookupMap.containsKey(StringLookupFactory.KEY_ENV));
assertTrue(stringLookupMap.containsKey(StringLookupFactory.KEY_FILE));
assertTrue(stringLookupMap.containsKey(StringLookupFactory.KEY_JAVA));
@@ -70,6 +71,7 @@
Assertions.assertSame(Base64EncoderStringLookup.INSTANCE, stringLookupFactory.base64EncoderStringLookup());
Assertions.assertSame(ConstantStringLookup.INSTANCE, stringLookupFactory.constantStringLookup());
Assertions.assertSame(DateStringLookup.INSTANCE, stringLookupFactory.dateStringLookup());
+ Assertions.assertSame(DnsStringLookup.INSTANCE, stringLookupFactory.dnsStringLookup());
Assertions.assertSame(EnvironmentVariableStringLookup.INSTANCE,
stringLookupFactory.environmentVariableStringLookup());
Assertions.assertSame(InterpolatorStringLookup.INSTANCE, stringLookupFactory.interpolatorStringLookup());