public class IpAddressUtils extends Object
TODO: Support for reverse lookup with timeout isn't implemented. Hasn't been any need for it.
Modifier and Type | Class and Description |
---|---|
static class |
IpAddressUtils.IpTypePreference
Filters the result of a method according to IP protocol preference.
|
Modifier and Type | Method and Description |
---|---|
static boolean |
isValidIpv4Address(String ipAddressStr)
Validates if a string can be parsed as an IPv4 address.
|
static boolean |
looksLikeIpv4Literal(String ipAddressStr)
Does a shallow check if the argument looks like an IPv4 address as
opposed to a host name.
|
static boolean |
looksLikeIpv6Literal(String ipAddressStr)
Does a shallow check if the argument looks like an IPv6 address as
opposed to a host name.
|
static InetAddress |
nameResolve(String host,
int timeoutMs)
Performs a name service lookup with a timeout.
|
static InetAddress |
nameResolve(String host,
int timeoutMs,
IpAddressUtils.IpTypePreference ipTypePref)
Performs a name service lookup with a timeout.
|
static InetAddress[] |
nameResolveArr(String host,
int timeoutMs,
IpAddressUtils.IpTypePreference ipTypePref)
Performs a name service lookup with a timeout.
|
static String |
removeDomain(String hostname)
Strips the domain part from a host name.
|
static void |
removeLoopback(List<InetAddress> addresses)
Removes loopback addresses from the provided list.
|
static void |
sortIpAddresses(List<InetAddress> addresses,
boolean ip4BeforeIp6)
Sorts a list of IP addresses.
|
static void |
sortIpAddressesShallow(List<InetAddress> addresses,
boolean ip4BeforeIp6)
Sorts a list of IP addresses, but only with respect to IPv4 vs IPv6.
|
@NonNull public static InetAddress[] nameResolveArr(String host, int timeoutMs, IpAddressUtils.IpTypePreference ipTypePref) throws InterruptedException, UnknownHostException, TimeoutException
This method can be used when the JRE's default DNS timeout is not
acceptable. The method is essentially a wrapper around
InetAddress.getAllByName()
.
A reasonable timeout value is 4 seconds (4000 ms) as this value will - with the JRE's default settings - allow each DNS server in a list of 4 servers to be queried once.
If the host
is a literal representation
of an IPv4 address (using dot notation, for example "192.168.1.44"
)
or an IPv6 address (any form accepted by Inet6Address
),
then the method will convert the text into InetAddress
and
return immediately. The timeout does not apply to this case.
Java's default DNS timeout:
The default timeout DNS lookup is described in the documentation for JNDI in properties:
com.example.jndi.dns.timeout.initial
(defaults to 1 sec in Java 8)
com.example.jndi.dns.timeout.retries
(defaults to 4 in Java 8)
The defaults mean that if the host OS has two servers defined in its DNS
server search string (usually there's at least two) then - if both
servers do not respond - the call to
InetAddress.getByName(java.lang.String)
will block for
30 seconds! before it returns. With three servers it will be 45 seconds
and so forth. This wait may be unacceptable in some scenarios and this is
where this method is then a better alternative.
host
- either a host name or a literal IPv4
address in dot notation.timeoutMs
- Milliseconds to wait for the result from the name service
query before aborting. A value of 0 means not to use any timeout for
the background resolver task. In that case only the standard timeouts
as defined in the JRE will apply.ipTypePref
- IP protocol filterInterruptedException
- if the background task was interruptedTimeoutException
- if the timeout (timeoutMs
) expired
before a result was obtained.UnknownHostException
- if no IP address for the host could be
found.IpAddressUtils.nameResolve(String, int, IpTypePreference)
@NonNull public static InetAddress nameResolve(String host, int timeoutMs, IpAddressUtils.IpTypePreference ipTypePref) throws InterruptedException, UnknownHostException, TimeoutException
nameResolveArr()
but only returns a single address.host
- either a host name or a literal IPv4
address in dot notation.timeoutMs
- Milliseconds to wait for the result from the name service
query before aborting. A value of 0 means not to use any timeout for
the background resolver task. In that case only the standard timeouts
as defined in the JRE will apply.ipTypePref
- IP protocol filterInterruptedException
- if the background task was interruptedTimeoutException
- if the timeout (timeoutMs
) expired
before a result was obtained.UnknownHostException
- if no IP address for the host could be
found.IpAddressUtils.nameResolveArr(String, int, IpTypePreference)
@NonNull public static InetAddress nameResolve(String host, int timeoutMs) throws InterruptedException, UnknownHostException, TimeoutException
nameResolveArr()
but only returns a single address and uses
IpTypePreference.ANY_JDK_PREF
.
There are several overloaded forms of this method. If you don't need any specific filtering on the type of IP address returned then use this method!
host
- either a host name or a literal IPv4
address in dot notation.timeoutMs
- Milliseconds to wait for the result from the name service
query before aborting. A value of 0 means not to use any timeout for
the background resolver task. In that case only the standard timeouts
as defined in the JRE will apply.InterruptedException
- if the background task was interruptedTimeoutException
- if the timeout (timeoutMs
) expired
before a result was obtained.UnknownHostException
- if no IP address for the host could be
found.IpAddressUtils.nameResolveArr(String, int, IpTypePreference)
public static boolean isValidIpv4Address(String ipAddressStr)
The standard way to do this type of validation in Java is
InetAddress.getByName(java.lang.String)
but this method
will block if the string is not an IP address literal, because it
will query the name service. In contrast, this method relies solely on
pattern matching techniques and will never block. Return value
true
is a guarantee that the string can be parsed as an IPv4
address.
ipAddressStr
- input string to be evaluatedpublic static boolean looksLikeIpv6Literal(String ipAddressStr)
true
doesn't
guarantee that the argument is a valid IPv6 literal, but a return
value of false
is a guarantee that it is not.
The method is not meant as a validity check. It is mainly useful
for predicting if the JDK's InetAddress#get*ByName()
will block
or not.
ipAddressStr
- public static boolean looksLikeIpv4Literal(String ipAddressStr)
true
doesn't
guarantee that the argument is a valid IPv4 literal, but a return
value of false
is a guarantee that it is not.
The method is not meant as a validity check. It is mainly useful
for predicting if the JDK's InetAddress#get*ByName()
will block
or not.
Note, the method will err on the side of caution meaning return false
if in doubt. Java allows "123" as a valid IPv4 address
, but in this case it cannot be determined if the
input is a hostname or an IPv4 literal and therefore false
is
returned.
ipAddressStr
- IpAddressUtils.isValidIpv4Address(java.lang.String)
public static String removeDomain(String hostname)
"foo.bar.com"
then "foo"
will be returned.
The method is safe to use even if the input is an IPv4 literal or IPv6 literal. In this case the input will be returned unchanged.
hostname
- public static void removeLoopback(List<InetAddress> addresses)
addresses
- public static void sortIpAddresses(List<InetAddress> addresses, boolean ip4BeforeIp6)
addresses
- IP addressesip4BeforeIp6
- if IPv4 addresses are to come before IPv6 addresses
(true
) or not (false
).public static void sortIpAddressesShallow(List<InetAddress> addresses, boolean ip4BeforeIp6)
addresses
- IP addressesip4BeforeIp6
- if IPv4 addresses are to come before IPv6 addresses
(true
) or not (false
).