mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 14:54:52 +02:00
8244202: Implementation of JEP 418: Internet-Address Resolution SPI
Co-authored-by: Chris Hegarty <chegar@openjdk.org> Co-authored-by: Daniel Fuchs <dfuchs@openjdk.org> Co-authored-by: Alan Bateman <alanb@openjdk.org> Reviewed-by: dfuchs, alanb, michaelm, chegar
This commit is contained in:
parent
c29cab8ab4
commit
2ca4ff87b7
56 changed files with 2986 additions and 293 deletions
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -378,6 +378,16 @@ import java.lang.module.ModuleFinder;
|
||||||
* {@linkplain ModuleFinder#ofSystem system modules} in the runtime image.</td>
|
* {@linkplain ModuleFinder#ofSystem system modules} in the runtime image.</td>
|
||||||
* </tr>
|
* </tr>
|
||||||
*
|
*
|
||||||
|
* <tr>
|
||||||
|
* <th scope="row">inetAddressResolverProvider</th>
|
||||||
|
* <td>This {@code RuntimePermission} is required to be granted to
|
||||||
|
* classes which subclass and implement {@code java.net.spi.InetAddressResolverProvider}.
|
||||||
|
* The permission is checked during invocation of the abstract base class constructor.
|
||||||
|
* This permission ensures trust in classes which provide resolvers used by
|
||||||
|
* {@link java.net.InetAddress} hostname and address resolution methods.</td>
|
||||||
|
* <td>See {@link java.net.spi.InetAddressResolverProvider} for more information.</td>
|
||||||
|
* </tr>
|
||||||
|
*
|
||||||
* </tbody>
|
* </tbody>
|
||||||
* </table>
|
* </table>
|
||||||
*
|
*
|
||||||
|
|
|
@ -24,6 +24,9 @@
|
||||||
*/
|
*/
|
||||||
package java.net;
|
package java.net;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.net.spi.InetAddressResolver.LookupPolicy;
|
||||||
|
|
||||||
|
import static java.net.spi.InetAddressResolver.LookupPolicy.IPV4;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Package private implementation of InetAddressImpl for IPv4.
|
* Package private implementation of InetAddressImpl for IPv4.
|
||||||
|
@ -32,8 +35,14 @@ import java.io.IOException;
|
||||||
*/
|
*/
|
||||||
final class Inet4AddressImpl implements InetAddressImpl {
|
final class Inet4AddressImpl implements InetAddressImpl {
|
||||||
public native String getLocalHostName() throws UnknownHostException;
|
public native String getLocalHostName() throws UnknownHostException;
|
||||||
public native InetAddress[]
|
public InetAddress[] lookupAllHostAddr(String hostname, LookupPolicy lookupPolicy)
|
||||||
lookupAllHostAddr(String hostname) throws UnknownHostException;
|
throws UnknownHostException {
|
||||||
|
if ((lookupPolicy.characteristics() & IPV4) == 0) {
|
||||||
|
throw new UnknownHostException(hostname);
|
||||||
|
}
|
||||||
|
return lookupAllHostAddr(hostname);
|
||||||
|
}
|
||||||
|
private native InetAddress[] lookupAllHostAddr(String hostname) throws UnknownHostException;
|
||||||
public native String getHostByAddr(byte[] addr) throws UnknownHostException;
|
public native String getHostByAddr(byte[] addr) throws UnknownHostException;
|
||||||
private native boolean isReachable0(byte[] addr, int timeout, byte[] ifaddr, int ttl) throws IOException;
|
private native boolean isReachable0(byte[] addr, int timeout, byte[] ifaddr, int ttl) throws IOException;
|
||||||
|
|
||||||
|
|
|
@ -25,10 +25,9 @@
|
||||||
package java.net;
|
package java.net;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.net.spi.InetAddressResolver.LookupPolicy;
|
||||||
|
|
||||||
import static java.net.InetAddress.IPv6;
|
import static java.net.InetAddress.PLATFORM_LOOKUP_POLICY;
|
||||||
import static java.net.InetAddress.PREFER_IPV6_VALUE;
|
|
||||||
import static java.net.InetAddress.PREFER_SYSTEM_VALUE;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Package private implementation of InetAddressImpl for dual
|
* Package private implementation of InetAddressImpl for dual
|
||||||
|
@ -48,8 +47,13 @@ final class Inet6AddressImpl implements InetAddressImpl {
|
||||||
|
|
||||||
public native String getLocalHostName() throws UnknownHostException;
|
public native String getLocalHostName() throws UnknownHostException;
|
||||||
|
|
||||||
public native InetAddress[] lookupAllHostAddr(String hostname)
|
public InetAddress[] lookupAllHostAddr(String hostname, LookupPolicy lookupPolicy)
|
||||||
throws UnknownHostException;
|
throws UnknownHostException {
|
||||||
|
return lookupAllHostAddr(hostname, lookupPolicy.characteristics());
|
||||||
|
}
|
||||||
|
|
||||||
|
private native InetAddress[] lookupAllHostAddr(String hostname, int characteristics)
|
||||||
|
throws UnknownHostException;
|
||||||
|
|
||||||
public native String getHostByAddr(byte[] addr) throws UnknownHostException;
|
public native String getHostByAddr(byte[] addr) throws UnknownHostException;
|
||||||
|
|
||||||
|
@ -96,8 +100,9 @@ final class Inet6AddressImpl implements InetAddressImpl {
|
||||||
|
|
||||||
public synchronized InetAddress anyLocalAddress() {
|
public synchronized InetAddress anyLocalAddress() {
|
||||||
if (anyLocalAddress == null) {
|
if (anyLocalAddress == null) {
|
||||||
if (InetAddress.preferIPv6Address == PREFER_IPV6_VALUE ||
|
int flags = PLATFORM_LOOKUP_POLICY.characteristics();
|
||||||
InetAddress.preferIPv6Address == PREFER_SYSTEM_VALUE) {
|
if (InetAddress.ipv6AddressesFirst(flags) ||
|
||||||
|
InetAddress.systemAddressesOrder(flags)) {
|
||||||
anyLocalAddress = new Inet6Address();
|
anyLocalAddress = new Inet6Address();
|
||||||
anyLocalAddress.holder().hostName = "::";
|
anyLocalAddress.holder().hostName = "::";
|
||||||
} else {
|
} else {
|
||||||
|
@ -109,9 +114,9 @@ final class Inet6AddressImpl implements InetAddressImpl {
|
||||||
|
|
||||||
public synchronized InetAddress loopbackAddress() {
|
public synchronized InetAddress loopbackAddress() {
|
||||||
if (loopbackAddress == null) {
|
if (loopbackAddress == null) {
|
||||||
boolean preferIPv6Address =
|
int flags = PLATFORM_LOOKUP_POLICY.characteristics();
|
||||||
InetAddress.preferIPv6Address == PREFER_IPV6_VALUE ||
|
boolean preferIPv6Address = InetAddress.ipv6AddressesFirst(flags) ||
|
||||||
InetAddress.preferIPv6Address == PREFER_SYSTEM_VALUE;
|
InetAddress.systemAddressesOrder(flags);
|
||||||
|
|
||||||
for (int i = 0; i < 2; i++) {
|
for (int i = 0; i < 2; i++) {
|
||||||
InetAddress address;
|
InetAddress address;
|
||||||
|
|
|
@ -25,6 +25,11 @@
|
||||||
|
|
||||||
package java.net;
|
package java.net;
|
||||||
|
|
||||||
|
import java.net.spi.InetAddressResolver;
|
||||||
|
import java.net.spi.InetAddressResolverProvider;
|
||||||
|
import java.net.spi.InetAddressResolver.LookupPolicy;
|
||||||
|
import java.security.AccessController;
|
||||||
|
import java.security.PrivilegedAction;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.NavigableSet;
|
import java.util.NavigableSet;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
@ -40,19 +45,31 @@ import java.io.ObjectInputStream.GetField;
|
||||||
import java.io.ObjectOutputStream;
|
import java.io.ObjectOutputStream;
|
||||||
import java.io.ObjectOutputStream.PutField;
|
import java.io.ObjectOutputStream.PutField;
|
||||||
import java.lang.annotation.Native;
|
import java.lang.annotation.Native;
|
||||||
|
import java.util.ServiceLoader;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.ConcurrentMap;
|
import java.util.concurrent.ConcurrentMap;
|
||||||
import java.util.concurrent.ConcurrentSkipListSet;
|
import java.util.concurrent.ConcurrentSkipListSet;
|
||||||
import java.util.concurrent.atomic.AtomicLong;
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import jdk.internal.misc.VM;
|
||||||
|
|
||||||
import jdk.internal.access.JavaNetInetAddressAccess;
|
import jdk.internal.access.JavaNetInetAddressAccess;
|
||||||
import jdk.internal.access.SharedSecrets;
|
import jdk.internal.access.SharedSecrets;
|
||||||
|
import jdk.internal.vm.annotation.Stable;
|
||||||
|
import sun.net.ResolverProviderConfiguration;
|
||||||
import sun.security.action.*;
|
import sun.security.action.*;
|
||||||
import sun.net.InetAddressCachePolicy;
|
import sun.net.InetAddressCachePolicy;
|
||||||
import sun.net.util.IPAddressUtil;
|
import sun.net.util.IPAddressUtil;
|
||||||
import sun.nio.cs.UTF_8;
|
import sun.nio.cs.UTF_8;
|
||||||
|
|
||||||
|
import static java.net.spi.InetAddressResolver.LookupPolicy.IPV4;
|
||||||
|
import static java.net.spi.InetAddressResolver.LookupPolicy.IPV4_FIRST;
|
||||||
|
import static java.net.spi.InetAddressResolver.LookupPolicy.IPV6;
|
||||||
|
import static java.net.spi.InetAddressResolver.LookupPolicy.IPV6_FIRST;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class represents an Internet Protocol (IP) address.
|
* This class represents an Internet Protocol (IP) address.
|
||||||
*
|
*
|
||||||
|
@ -128,25 +145,35 @@ import sun.nio.cs.UTF_8;
|
||||||
* address format, please refer to <A
|
* address format, please refer to <A
|
||||||
* HREF="Inet6Address.html#format">Inet6Address#format</A>.
|
* HREF="Inet6Address.html#format">Inet6Address#format</A>.
|
||||||
*
|
*
|
||||||
* <P>There is a <a href="doc-files/net-properties.html#Ipv4IPv6">couple of
|
* <p> There is a <a href="doc-files/net-properties.html#Ipv4IPv6">couple of
|
||||||
* System Properties</a> affecting how IPv4 and IPv6 addresses are used.</P>
|
* System Properties</a> affecting how IPv4 and IPv6 addresses are used.
|
||||||
*
|
*
|
||||||
* <h3> Host Name Resolution </h3>
|
* <h2 id="host-name-resolution"> Host Name Resolution </h2>
|
||||||
*
|
*
|
||||||
* Host name-to-IP address <i>resolution</i> is accomplished through
|
* <p> The InetAddress class provides methods to resolve host names to
|
||||||
* the use of a combination of local machine configuration information
|
* their IP addresses and vice versa. The actual resolution is delegated to an
|
||||||
* and network naming services such as the Domain Name System (DNS)
|
* {@linkplain InetAddressResolver InetAddress resolver}.
|
||||||
* and Network Information Service(NIS). The particular naming
|
*
|
||||||
* services(s) being used is by default the local machine configured
|
* <p> <i>Host name-to-IP address resolution</i> maps a host name to an IP address.
|
||||||
* one. For any host name, its corresponding IP address is returned.
|
* For any host name, its corresponding IP address is returned.
|
||||||
*
|
*
|
||||||
* <p> <i>Reverse name resolution</i> means that for any IP address,
|
* <p> <i>Reverse name resolution</i> means that for any IP address,
|
||||||
* the host associated with the IP address is returned.
|
* the host associated with the IP address is returned.
|
||||||
*
|
*
|
||||||
* <p> The InetAddress class provides methods to resolve host names to
|
* <p id="built-in-resolver"> The built-in InetAddress resolver implementation does
|
||||||
* their IP addresses and vice versa.
|
* host name-to-IP address resolution and vice versa through the use of
|
||||||
|
* a combination of local machine configuration information and network
|
||||||
|
* naming services such as the Domain Name System (DNS) and the Lightweight Directory
|
||||||
|
* Access Protocol (LDAP).
|
||||||
|
* The particular naming services that the built-in resolver uses by default
|
||||||
|
* depends on the configuration of the local machine.
|
||||||
*
|
*
|
||||||
* <h3> InetAddress Caching </h3>
|
* <p> {@code InetAddress} has a service provider mechanism for InetAddress resolvers
|
||||||
|
* that allows a custom InetAddress resolver to be used instead of the built-in implementation.
|
||||||
|
* {@link InetAddressResolverProvider} is the service provider class. Its API docs provide all the
|
||||||
|
* details on this mechanism.
|
||||||
|
*
|
||||||
|
* <h2> InetAddress Caching </h2>
|
||||||
*
|
*
|
||||||
* The InetAddress class has a cache to store successful as well as
|
* The InetAddress class has a cache to store successful as well as
|
||||||
* unsuccessful host name resolutions.
|
* unsuccessful host name resolutions.
|
||||||
|
@ -198,10 +225,6 @@ import sun.nio.cs.UTF_8;
|
||||||
*/
|
*/
|
||||||
public class InetAddress implements java.io.Serializable {
|
public class InetAddress implements java.io.Serializable {
|
||||||
|
|
||||||
@Native static final int PREFER_IPV4_VALUE = 0;
|
|
||||||
@Native static final int PREFER_IPV6_VALUE = 1;
|
|
||||||
@Native static final int PREFER_SYSTEM_VALUE = 2;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specify the address family: Internet Protocol, Version 4
|
* Specify the address family: Internet Protocol, Version 4
|
||||||
* @since 1.4
|
* @since 1.4
|
||||||
|
@ -214,9 +237,6 @@ public class InetAddress implements java.io.Serializable {
|
||||||
*/
|
*/
|
||||||
@Native static final int IPv6 = 2;
|
@Native static final int IPv6 = 2;
|
||||||
|
|
||||||
/* Specify address family preference */
|
|
||||||
static final transient int preferIPv6Address;
|
|
||||||
|
|
||||||
static class InetAddressHolder {
|
static class InetAddressHolder {
|
||||||
/**
|
/**
|
||||||
* Reserve the original application specified hostname.
|
* Reserve the original application specified hostname.
|
||||||
|
@ -288,8 +308,11 @@ public class InetAddress implements java.io.Serializable {
|
||||||
return holder;
|
return holder;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Used to store the name service provider */
|
/* Used to store the system-wide resolver */
|
||||||
private static transient NameService nameService;
|
@Stable
|
||||||
|
private static volatile InetAddressResolver resolver;
|
||||||
|
|
||||||
|
private static final InetAddressResolver BUILTIN_RESOLVER;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to store the best available hostname.
|
* Used to store the best available hostname.
|
||||||
|
@ -301,22 +324,25 @@ public class InetAddress implements java.io.Serializable {
|
||||||
@java.io.Serial
|
@java.io.Serial
|
||||||
private static final long serialVersionUID = 3286316764910316507L;
|
private static final long serialVersionUID = 3286316764910316507L;
|
||||||
|
|
||||||
|
// "java.net.preferIPv4Stack" system property value
|
||||||
|
private static final String PREFER_IPV4_STACK_VALUE;
|
||||||
|
|
||||||
|
// "java.net.preferIPv6Addresses" system property value
|
||||||
|
private static final String PREFER_IPV6_ADDRESSES_VALUE;
|
||||||
|
|
||||||
|
// "jdk.net.hosts.file" system property value
|
||||||
|
private static final String HOSTS_FILE_NAME;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Load net library into runtime, and perform initializations.
|
* Load net library into runtime, and perform initializations.
|
||||||
*/
|
*/
|
||||||
static {
|
static {
|
||||||
String str = GetPropertyAction.privilegedGetProperty("java.net.preferIPv6Addresses");
|
PREFER_IPV4_STACK_VALUE =
|
||||||
if (str == null) {
|
GetPropertyAction.privilegedGetProperty("java.net.preferIPv4Stack");
|
||||||
preferIPv6Address = PREFER_IPV4_VALUE;
|
PREFER_IPV6_ADDRESSES_VALUE =
|
||||||
} else if (str.equalsIgnoreCase("true")) {
|
GetPropertyAction.privilegedGetProperty("java.net.preferIPv6Addresses");
|
||||||
preferIPv6Address = PREFER_IPV6_VALUE;
|
HOSTS_FILE_NAME =
|
||||||
} else if (str.equalsIgnoreCase("false")) {
|
GetPropertyAction.privilegedGetProperty("jdk.net.hosts.file");
|
||||||
preferIPv6Address = PREFER_IPV4_VALUE;
|
|
||||||
} else if (str.equalsIgnoreCase("system")) {
|
|
||||||
preferIPv6Address = PREFER_SYSTEM_VALUE;
|
|
||||||
} else {
|
|
||||||
preferIPv6Address = PREFER_IPV4_VALUE;
|
|
||||||
}
|
|
||||||
jdk.internal.loader.BootLoader.loadLibrary("net");
|
jdk.internal.loader.BootLoader.loadLibrary("net");
|
||||||
SharedSecrets.setJavaNetInetAddressAccess(
|
SharedSecrets.setJavaNetInetAddressAccess(
|
||||||
new JavaNetInetAddressAccess() {
|
new JavaNetInetAddressAccess() {
|
||||||
|
@ -324,13 +350,6 @@ public class InetAddress implements java.io.Serializable {
|
||||||
return ia.holder.getOriginalHostName();
|
return ia.holder.getOriginalHostName();
|
||||||
}
|
}
|
||||||
|
|
||||||
public InetAddress getByName(String hostName,
|
|
||||||
InetAddress hostAddress)
|
|
||||||
throws UnknownHostException
|
|
||||||
{
|
|
||||||
return InetAddress.getByName(hostName, hostAddress);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int addressValue(Inet4Address inet4Address) {
|
public int addressValue(Inet4Address inet4Address) {
|
||||||
return inet4Address.addressValue();
|
return inet4Address.addressValue();
|
||||||
}
|
}
|
||||||
|
@ -343,6 +362,131 @@ public class InetAddress implements java.io.Serializable {
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an address lookup policy from {@code "java.net.preferIPv4Stack"},
|
||||||
|
* {@code "java.net.preferIPv6Addresses"} system property values, and O/S configuration.
|
||||||
|
*/
|
||||||
|
private static final LookupPolicy initializePlatformLookupPolicy() {
|
||||||
|
// Calculate AddressFamily value first
|
||||||
|
boolean ipv4Available = isIPv4Available();
|
||||||
|
if ("true".equals(PREFER_IPV4_STACK_VALUE) && ipv4Available) {
|
||||||
|
return LookupPolicy.of(IPV4);
|
||||||
|
}
|
||||||
|
// Check if IPv6 is not supported
|
||||||
|
if (InetAddress.impl instanceof Inet4AddressImpl) {
|
||||||
|
return LookupPolicy.of(IPV4);
|
||||||
|
}
|
||||||
|
// Check if system supports IPv4, if not use IPv6
|
||||||
|
if (!ipv4Available) {
|
||||||
|
return LookupPolicy.of(IPV6);
|
||||||
|
}
|
||||||
|
// If both address families are needed - check preferIPv6Addresses value
|
||||||
|
if (PREFER_IPV6_ADDRESSES_VALUE != null) {
|
||||||
|
if (PREFER_IPV6_ADDRESSES_VALUE.equalsIgnoreCase("true")) {
|
||||||
|
return LookupPolicy.of(IPV4 | IPV6 | IPV6_FIRST);
|
||||||
|
}
|
||||||
|
if (PREFER_IPV6_ADDRESSES_VALUE.equalsIgnoreCase("false")) {
|
||||||
|
return LookupPolicy.of(IPV4 | IPV6 | IPV4_FIRST);
|
||||||
|
}
|
||||||
|
if (PREFER_IPV6_ADDRESSES_VALUE.equalsIgnoreCase("system")) {
|
||||||
|
return LookupPolicy.of(IPV4 | IPV6);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Default value with both address families needed - IPv4 addresses come first
|
||||||
|
return LookupPolicy.of(IPV4 | IPV6 | IPV4_FIRST);
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean systemAddressesOrder(int lookupCharacteristics) {
|
||||||
|
return (lookupCharacteristics & (IPV4_FIRST | IPV6_FIRST)) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean ipv4AddressesFirst(int lookupCharacteristics) {
|
||||||
|
return (lookupCharacteristics & IPV4_FIRST) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean ipv6AddressesFirst(int lookupCharacteristics) {
|
||||||
|
return (lookupCharacteristics & IPV6_FIRST) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Native method to check if IPv4 is available
|
||||||
|
private static native boolean isIPv4Available();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@code RuntimePermission("inetAddressResolverProvider")} is
|
||||||
|
* necessary to subclass and instantiate the {@code InetAddressResolverProvider}
|
||||||
|
* class, as well as to obtain resolver from an instance of that class,
|
||||||
|
* and it is also required to obtain the operating system name resolution configurations.
|
||||||
|
*/
|
||||||
|
private static final RuntimePermission INET_ADDRESS_RESOLVER_PERMISSION =
|
||||||
|
new RuntimePermission("inetAddressResolverProvider");
|
||||||
|
|
||||||
|
private static final ReentrantLock RESOLVER_LOCK = new ReentrantLock();
|
||||||
|
private static volatile InetAddressResolver bootstrapResolver;
|
||||||
|
|
||||||
|
@SuppressWarnings("removal")
|
||||||
|
private static InetAddressResolver resolver() {
|
||||||
|
InetAddressResolver cns = resolver;
|
||||||
|
if (cns != null) {
|
||||||
|
return cns;
|
||||||
|
}
|
||||||
|
if (VM.isBooted()) {
|
||||||
|
RESOLVER_LOCK.lock();
|
||||||
|
boolean bootstrapSet = false;
|
||||||
|
try {
|
||||||
|
cns = resolver;
|
||||||
|
if (cns != null) {
|
||||||
|
return cns;
|
||||||
|
}
|
||||||
|
// Protection against provider calling InetAddress APIs during initialization
|
||||||
|
if (bootstrapResolver != null) {
|
||||||
|
return bootstrapResolver;
|
||||||
|
}
|
||||||
|
bootstrapResolver = BUILTIN_RESOLVER;
|
||||||
|
bootstrapSet = true;
|
||||||
|
|
||||||
|
if (HOSTS_FILE_NAME != null) {
|
||||||
|
// The default resolver service is already host file resolver
|
||||||
|
cns = BUILTIN_RESOLVER;
|
||||||
|
} else if (System.getSecurityManager() != null) {
|
||||||
|
PrivilegedAction<InetAddressResolver> pa = InetAddress::loadResolver;
|
||||||
|
cns = AccessController.doPrivileged(
|
||||||
|
pa, null, INET_ADDRESS_RESOLVER_PERMISSION);
|
||||||
|
} else {
|
||||||
|
cns = loadResolver();
|
||||||
|
}
|
||||||
|
|
||||||
|
InetAddress.resolver = cns;
|
||||||
|
return cns;
|
||||||
|
} finally {
|
||||||
|
// We want to clear bootstrap resolver reference only after an attempt to
|
||||||
|
// instantiate a resolver has been completed.
|
||||||
|
if (bootstrapSet) {
|
||||||
|
bootstrapResolver = null;
|
||||||
|
}
|
||||||
|
RESOLVER_LOCK.unlock();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return BUILTIN_RESOLVER;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static InetAddressResolver loadResolver() {
|
||||||
|
return ServiceLoader.load(InetAddressResolverProvider.class)
|
||||||
|
.findFirst()
|
||||||
|
.map(nsp -> nsp.get(builtinConfiguration()))
|
||||||
|
.orElse(BUILTIN_RESOLVER);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static InetAddressResolverProvider.Configuration builtinConfiguration() {
|
||||||
|
return new ResolverProviderConfiguration(BUILTIN_RESOLVER, () -> {
|
||||||
|
try {
|
||||||
|
return impl.getLocalHostName();
|
||||||
|
} catch (UnknownHostException unknownHostException) {
|
||||||
|
return "localhost";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor for the Socket.accept() method.
|
* Constructor for the Socket.accept() method.
|
||||||
* This creates an empty InetAddress, which is filled in by
|
* This creates an empty InetAddress, which is filled in by
|
||||||
|
@ -555,7 +699,7 @@ public class InetAddress implements java.io.Serializable {
|
||||||
* this host name will be remembered and returned;
|
* this host name will be remembered and returned;
|
||||||
* otherwise, a reverse name lookup will be performed
|
* otherwise, a reverse name lookup will be performed
|
||||||
* and the result will be returned based on the system
|
* and the result will be returned based on the system
|
||||||
* configured name lookup service. If a lookup of the name service
|
* configured resolver. If a lookup of the name service
|
||||||
* is required, call
|
* is required, call
|
||||||
* {@link #getCanonicalHostName() getCanonicalHostName}.
|
* {@link #getCanonicalHostName() getCanonicalHostName}.
|
||||||
*
|
*
|
||||||
|
@ -656,10 +800,11 @@ public class InetAddress implements java.io.Serializable {
|
||||||
* @see SecurityManager#checkConnect
|
* @see SecurityManager#checkConnect
|
||||||
*/
|
*/
|
||||||
private static String getHostFromNameService(InetAddress addr, boolean check) {
|
private static String getHostFromNameService(InetAddress addr, boolean check) {
|
||||||
String host = null;
|
String host;
|
||||||
|
var resolver = resolver();
|
||||||
try {
|
try {
|
||||||
// first lookup the hostname
|
// first lookup the hostname
|
||||||
host = nameService.getHostByAddr(addr.getAddress());
|
host = resolver.lookupByAddress(addr.getAddress());
|
||||||
|
|
||||||
/* check to see if calling code is allowed to know
|
/* check to see if calling code is allowed to know
|
||||||
* the hostname for this IP address, ie, connect to the host
|
* the hostname for this IP address, ie, connect to the host
|
||||||
|
@ -691,11 +836,12 @@ public class InetAddress implements java.io.Serializable {
|
||||||
host = addr.getHostAddress();
|
host = addr.getHostAddress();
|
||||||
return host;
|
return host;
|
||||||
}
|
}
|
||||||
} catch (SecurityException e) {
|
} catch (RuntimeException | UnknownHostException e) {
|
||||||
|
// 'resolver.lookupByAddress' and 'InetAddress.getAllByName0' delegate to
|
||||||
|
// the system-wide resolver, which could be a custom one. At that point we
|
||||||
|
// treat any unexpected RuntimeException thrown by the resolver as we would
|
||||||
|
// treat an UnknownHostException or an unmatched host name.
|
||||||
host = addr.getHostAddress();
|
host = addr.getHostAddress();
|
||||||
} catch (UnknownHostException e) {
|
|
||||||
host = addr.getHostAddress();
|
|
||||||
// let next provider resolve the hostname
|
|
||||||
}
|
}
|
||||||
return host;
|
return host;
|
||||||
}
|
}
|
||||||
|
@ -755,8 +901,9 @@ public class InetAddress implements java.io.Serializable {
|
||||||
* string returned is of the form: hostname / literal IP
|
* string returned is of the form: hostname / literal IP
|
||||||
* address.
|
* address.
|
||||||
*
|
*
|
||||||
* If the host name is unresolved, no reverse name service lookup
|
* If the host name is unresolved, no reverse lookup
|
||||||
* is performed. The hostname part will be represented by an empty string.
|
* is performed. The hostname part will be represented
|
||||||
|
* by an empty string.
|
||||||
*
|
*
|
||||||
* @return a string representation of this IP address.
|
* @return a string representation of this IP address.
|
||||||
*/
|
*/
|
||||||
|
@ -821,11 +968,9 @@ public class InetAddress implements java.io.Serializable {
|
||||||
// in cache when the result is obtained
|
// in cache when the result is obtained
|
||||||
private static final class NameServiceAddresses implements Addresses {
|
private static final class NameServiceAddresses implements Addresses {
|
||||||
private final String host;
|
private final String host;
|
||||||
private final InetAddress reqAddr;
|
|
||||||
|
|
||||||
NameServiceAddresses(String host, InetAddress reqAddr) {
|
NameServiceAddresses(String host) {
|
||||||
this.host = host;
|
this.host = host;
|
||||||
this.reqAddr = reqAddr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -849,7 +994,7 @@ public class InetAddress implements java.io.Serializable {
|
||||||
UnknownHostException ex;
|
UnknownHostException ex;
|
||||||
int cachePolicy;
|
int cachePolicy;
|
||||||
try {
|
try {
|
||||||
inetAddresses = getAddressesFromNameService(host, reqAddr);
|
inetAddresses = getAddressesFromNameService(host);
|
||||||
ex = null;
|
ex = null;
|
||||||
cachePolicy = InetAddressCachePolicy.get();
|
cachePolicy = InetAddressCachePolicy.get();
|
||||||
} catch (UnknownHostException uhe) {
|
} catch (UnknownHostException uhe) {
|
||||||
|
@ -875,7 +1020,7 @@ public class InetAddress implements java.io.Serializable {
|
||||||
expirySet.add(cachedAddresses);
|
expirySet.add(cachedAddresses);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (inetAddresses == null) {
|
if (inetAddresses == null || inetAddresses.length == 0) {
|
||||||
throw ex == null ? new UnknownHostException(host) : ex;
|
throw ex == null ? new UnknownHostException(host) : ex;
|
||||||
}
|
}
|
||||||
return inetAddresses;
|
return inetAddresses;
|
||||||
|
@ -889,81 +1034,48 @@ public class InetAddress implements java.io.Serializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* NameService provides host and address lookup service
|
* The default InetAddressResolver implementation, which delegates to the underlying
|
||||||
*
|
|
||||||
* @since 9
|
|
||||||
*/
|
|
||||||
private interface NameService {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Lookup a host mapping by name. Retrieve the IP addresses
|
|
||||||
* associated with a host
|
|
||||||
*
|
|
||||||
* @param host the specified hostname
|
|
||||||
* @return array of IP addresses for the requested host
|
|
||||||
* @throws UnknownHostException
|
|
||||||
* if no IP address for the {@code host} could be found
|
|
||||||
*/
|
|
||||||
InetAddress[] lookupAllHostAddr(String host)
|
|
||||||
throws UnknownHostException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Lookup the host corresponding to the IP address provided
|
|
||||||
*
|
|
||||||
* @param addr byte array representing an IP address
|
|
||||||
* @return {@code String} representing the host name mapping
|
|
||||||
* @throws UnknownHostException
|
|
||||||
* if no host found for the specified IP address
|
|
||||||
*/
|
|
||||||
String getHostByAddr(byte[] addr) throws UnknownHostException;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The default NameService implementation, which delegates to the underlying
|
|
||||||
* OS network libraries to resolve host address mappings.
|
* OS network libraries to resolve host address mappings.
|
||||||
*
|
*
|
||||||
* @since 9
|
* @since 9
|
||||||
*/
|
*/
|
||||||
private static final class PlatformNameService implements NameService {
|
private static final class PlatformResolver implements InetAddressResolver {
|
||||||
|
|
||||||
public InetAddress[] lookupAllHostAddr(String host)
|
public Stream<InetAddress> lookupByName(String host, LookupPolicy policy)
|
||||||
throws UnknownHostException
|
throws UnknownHostException {
|
||||||
{
|
Objects.requireNonNull(host);
|
||||||
return impl.lookupAllHostAddr(host);
|
Objects.requireNonNull(policy);
|
||||||
|
return Arrays.stream(impl.lookupAllHostAddr(host, policy));
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getHostByAddr(byte[] addr)
|
public String lookupByAddress(byte[] addr)
|
||||||
throws UnknownHostException
|
throws UnknownHostException {
|
||||||
{
|
Objects.requireNonNull(addr);
|
||||||
|
if (addr.length != Inet4Address.INADDRSZ && addr.length != Inet6Address.INADDRSZ) {
|
||||||
|
throw new IllegalArgumentException("Invalid address length");
|
||||||
|
}
|
||||||
return impl.getHostByAddr(addr);
|
return impl.getHostByAddr(addr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The HostsFileNameService provides host address mapping
|
* The HostsFileResolver provides host address mapping
|
||||||
* by reading the entries in a hosts file, which is specified by
|
* by reading the entries in a hosts file, which is specified by
|
||||||
* {@code jdk.net.hosts.file} system property
|
* {@code jdk.net.hosts.file} system property
|
||||||
*
|
*
|
||||||
* <p>The file format is that which corresponds with the /etc/hosts file
|
* <p>The file format is that which corresponds with the /etc/hosts file
|
||||||
* IP Address host alias list.
|
* IP Address host alias list.
|
||||||
*
|
*
|
||||||
* <p>When the file lookup is enabled it replaces the default NameService
|
* <p>When the file lookup is enabled it replaces the default InetAddressResolver
|
||||||
* implementation
|
* implementation
|
||||||
*
|
*
|
||||||
* @since 9
|
* @since 9
|
||||||
*/
|
*/
|
||||||
private static final class HostsFileNameService implements NameService {
|
private static final class HostsFileResolver implements InetAddressResolver {
|
||||||
|
|
||||||
private static final InetAddress[] EMPTY_ARRAY = new InetAddress[0];
|
|
||||||
|
|
||||||
// Specify if only IPv4 addresses should be returned by HostsFileService implementation
|
|
||||||
private static final boolean preferIPv4Stack = Boolean.parseBoolean(
|
|
||||||
GetPropertyAction.privilegedGetProperty("java.net.preferIPv4Stack"));
|
|
||||||
|
|
||||||
private final String hostsFile;
|
private final String hostsFile;
|
||||||
|
|
||||||
public HostsFileNameService(String hostsFileName) {
|
public HostsFileResolver(String hostsFileName) {
|
||||||
this.hostsFile = hostsFileName;
|
this.hostsFile = hostsFileName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -974,17 +1086,22 @@ public class InetAddress implements java.io.Serializable {
|
||||||
*
|
*
|
||||||
* @param addr byte array representing an IP address
|
* @param addr byte array representing an IP address
|
||||||
* @return {@code String} representing the host name mapping
|
* @return {@code String} representing the host name mapping
|
||||||
* @throws UnknownHostException
|
* @throws UnknownHostException if no host found for the specified IP address
|
||||||
* if no host found for the specified IP address
|
* @throws IllegalArgumentException if IP address is of illegal length
|
||||||
|
* @throws NullPointerException if addr is {@code null}
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public String getHostByAddr(byte[] addr) throws UnknownHostException {
|
public String lookupByAddress(byte[] addr) throws UnknownHostException {
|
||||||
String hostEntry;
|
String hostEntry;
|
||||||
String host = null;
|
String host = null;
|
||||||
|
Objects.requireNonNull(addr);
|
||||||
|
// Check the length of the address array
|
||||||
|
if (addr.length != Inet4Address.INADDRSZ && addr.length != Inet6Address.INADDRSZ) {
|
||||||
|
throw new IllegalArgumentException("Invalid address length");
|
||||||
|
}
|
||||||
|
|
||||||
try (Scanner hostsFileScanner = new Scanner(new File(hostsFile),
|
try (Scanner hostsFileScanner = new Scanner(new File(hostsFile),
|
||||||
UTF_8.INSTANCE))
|
UTF_8.INSTANCE)) {
|
||||||
{
|
|
||||||
while (hostsFileScanner.hasNextLine()) {
|
while (hostsFileScanner.hasNextLine()) {
|
||||||
hostEntry = hostsFileScanner.nextLine();
|
hostEntry = hostsFileScanner.nextLine();
|
||||||
if (!hostEntry.startsWith("#")) {
|
if (!hostEntry.startsWith("#")) {
|
||||||
|
@ -1020,22 +1137,31 @@ public class InetAddress implements java.io.Serializable {
|
||||||
* with the specified host name.
|
* with the specified host name.
|
||||||
*
|
*
|
||||||
* @param host the specified hostname
|
* @param host the specified hostname
|
||||||
* @return array of IP addresses for the requested host
|
* @param lookupPolicy IP addresses lookup policy which specifies addresses
|
||||||
|
* family and their order
|
||||||
|
* @return stream of IP addresses for the requested host
|
||||||
|
* @throws NullPointerException if either parameter is {@code null}
|
||||||
* @throws UnknownHostException
|
* @throws UnknownHostException
|
||||||
* if no IP address for the {@code host} could be found
|
* if no IP address for the {@code host} could be found
|
||||||
*/
|
*/
|
||||||
public InetAddress[] lookupAllHostAddr(String host)
|
public Stream<InetAddress> lookupByName(String host, LookupPolicy lookupPolicy)
|
||||||
throws UnknownHostException {
|
throws UnknownHostException {
|
||||||
String hostEntry;
|
String hostEntry;
|
||||||
String addrStr;
|
String addrStr;
|
||||||
byte addr[];
|
byte addr[];
|
||||||
|
|
||||||
|
Objects.requireNonNull(host);
|
||||||
|
Objects.requireNonNull(lookupPolicy);
|
||||||
List<InetAddress> inetAddresses = new ArrayList<>();
|
List<InetAddress> inetAddresses = new ArrayList<>();
|
||||||
List<InetAddress> inet4Addresses = new ArrayList<>();
|
List<InetAddress> inet4Addresses = new ArrayList<>();
|
||||||
List<InetAddress> inet6Addresses = new ArrayList<>();
|
List<InetAddress> inet6Addresses = new ArrayList<>();
|
||||||
|
int flags = lookupPolicy.characteristics();
|
||||||
|
boolean needIPv4 = (flags & IPv4) != 0;
|
||||||
|
boolean needIPv6 = (flags & IPv6) != 0;
|
||||||
|
|
||||||
// lookup the file and create a list InetAddress for the specified host
|
// lookup the file and create a list InetAddress for the specified host
|
||||||
try (Scanner hostsFileScanner = new Scanner(new File(hostsFile),
|
try (Scanner hostsFileScanner = new Scanner(new File(hostsFile),
|
||||||
UTF_8.INSTANCE)) {
|
UTF_8.INSTANCE)) {
|
||||||
while (hostsFileScanner.hasNextLine()) {
|
while (hostsFileScanner.hasNextLine()) {
|
||||||
hostEntry = hostsFileScanner.nextLine();
|
hostEntry = hostsFileScanner.nextLine();
|
||||||
if (!hostEntry.startsWith("#")) {
|
if (!hostEntry.startsWith("#")) {
|
||||||
|
@ -1047,10 +1173,10 @@ public class InetAddress implements java.io.Serializable {
|
||||||
if (addr != null) {
|
if (addr != null) {
|
||||||
InetAddress address = InetAddress.getByAddress(host, addr);
|
InetAddress address = InetAddress.getByAddress(host, addr);
|
||||||
inetAddresses.add(address);
|
inetAddresses.add(address);
|
||||||
if (address instanceof Inet4Address) {
|
if (address instanceof Inet4Address && needIPv4) {
|
||||||
inet4Addresses.add(address);
|
inet4Addresses.add(address);
|
||||||
}
|
}
|
||||||
if (address instanceof Inet6Address) {
|
if (address instanceof Inet6Address && needIPv6) {
|
||||||
inet6Addresses.add(address);
|
inet6Addresses.add(address);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1062,33 +1188,38 @@ public class InetAddress implements java.io.Serializable {
|
||||||
throw new UnknownHostException("Unable to resolve host " + host
|
throw new UnknownHostException("Unable to resolve host " + host
|
||||||
+ " as hosts file " + hostsFile + " not found ");
|
+ " as hosts file " + hostsFile + " not found ");
|
||||||
}
|
}
|
||||||
|
// Check if only IPv4 addresses are requested
|
||||||
List<InetAddress> res;
|
if (needIPv4 && !needIPv6) {
|
||||||
// If "preferIPv4Stack" system property is set to "true" then return
|
checkResultsList(inet4Addresses, host);
|
||||||
// only IPv4 addresses
|
return inet4Addresses.stream();
|
||||||
if (preferIPv4Stack) {
|
|
||||||
res = inet4Addresses;
|
|
||||||
} else {
|
|
||||||
// Otherwise, analyse "preferIPv6Addresses" value
|
|
||||||
res = switch (preferIPv6Address) {
|
|
||||||
case PREFER_IPV4_VALUE -> concatAddresses(inet4Addresses, inet6Addresses);
|
|
||||||
case PREFER_IPV6_VALUE -> concatAddresses(inet6Addresses, inet4Addresses);
|
|
||||||
default -> inetAddresses;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
// Check if only IPv6 addresses are requested
|
||||||
if (res.isEmpty()) {
|
if (!needIPv4 && needIPv6) {
|
||||||
throw new UnknownHostException("Unable to resolve host " + host
|
checkResultsList(inet6Addresses, host);
|
||||||
+ " in hosts file " + hostsFile);
|
return inet6Addresses.stream();
|
||||||
}
|
}
|
||||||
return res.toArray(EMPTY_ARRAY);
|
// If both type of addresses are requested:
|
||||||
|
// First, check if there is any results. Then arrange
|
||||||
|
// addresses according to LookupPolicy value.
|
||||||
|
checkResultsList(inetAddresses, host);
|
||||||
|
if (ipv6AddressesFirst(flags)) {
|
||||||
|
return Stream.concat(inet6Addresses.stream(), inet4Addresses.stream());
|
||||||
|
} else if (ipv4AddressesFirst(flags)) {
|
||||||
|
return Stream.concat(inet4Addresses.stream(), inet6Addresses.stream());
|
||||||
|
}
|
||||||
|
// Only "system" addresses order is possible at this stage
|
||||||
|
assert systemAddressesOrder(flags);
|
||||||
|
return inetAddresses.stream();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<InetAddress> concatAddresses(List<InetAddress> firstPart,
|
// Checks if result list with addresses is not empty.
|
||||||
List<InetAddress> secondPart) {
|
// If it is empty throw an UnknownHostException.
|
||||||
List<InetAddress> result = new ArrayList<>(firstPart);
|
private void checkResultsList(List<InetAddress> addressesList, String hostName)
|
||||||
result.addAll(secondPart);
|
throws UnknownHostException {
|
||||||
return result;
|
if (addressesList.isEmpty()) {
|
||||||
|
throw new UnknownHostException("Unable to resolve host " + hostName
|
||||||
|
+ " in hosts file " + hostsFile);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private String removeComments(String hostsEntry) {
|
private String removeComments(String hostsEntry) {
|
||||||
|
@ -1130,45 +1261,52 @@ public class InetAddress implements java.io.Serializable {
|
||||||
|
|
||||||
static final InetAddressImpl impl;
|
static final InetAddressImpl impl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Platform-wide {@code LookupPolicy} initialized from {@code "java.net.preferIPv4Stack"},
|
||||||
|
* {@code "java.net.preferIPv6Addresses"} system properties.
|
||||||
|
*/
|
||||||
|
static final LookupPolicy PLATFORM_LOOKUP_POLICY;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
// create the impl
|
// create the impl
|
||||||
impl = InetAddressImplFactory.create();
|
impl = InetAddressImplFactory.create();
|
||||||
|
|
||||||
// create name service
|
// impl must be initialized before calling this method
|
||||||
nameService = createNameService();
|
PLATFORM_LOOKUP_POLICY = initializePlatformLookupPolicy();
|
||||||
|
|
||||||
|
// create built-in resolver
|
||||||
|
BUILTIN_RESOLVER = createBuiltinInetAddressResolver();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create an instance of the NameService interface based on
|
* Create an instance of the InetAddressResolver interface based on
|
||||||
* the setting of the {@code jdk.net.hosts.file} system property.
|
* the setting of the {@code jdk.net.hosts.file} system property.
|
||||||
*
|
*
|
||||||
* <p>The default NameService is the PlatformNameService, which typically
|
* <p>The default InetAddressResolver is the PlatformResolver, which typically
|
||||||
* delegates name and address resolution calls to the underlying
|
* delegates name and address resolution calls to the underlying
|
||||||
* OS network libraries.
|
* OS network libraries.
|
||||||
*
|
*
|
||||||
* <p> A HostsFileNameService is created if the {@code jdk.net.hosts.file}
|
* <p> A HostsFileResolver is created if the {@code jdk.net.hosts.file}
|
||||||
* system property is set. If the specified file doesn't exist, the name or
|
* system property is set. If the specified file doesn't exist, the name or
|
||||||
* address lookup will result in an UnknownHostException. Thus, non existent
|
* address lookup will result in an UnknownHostException. Thus, non existent
|
||||||
* hosts file is handled as if the file is empty.
|
* hosts file is handled as if the file is empty.
|
||||||
*
|
*
|
||||||
* @return a NameService
|
* @return an InetAddressResolver
|
||||||
*/
|
*/
|
||||||
private static NameService createNameService() {
|
private static InetAddressResolver createBuiltinInetAddressResolver() {
|
||||||
|
InetAddressResolver theResolver;
|
||||||
String hostsFileName =
|
if (HOSTS_FILE_NAME != null) {
|
||||||
GetPropertyAction.privilegedGetProperty("jdk.net.hosts.file");
|
theResolver = new HostsFileResolver(HOSTS_FILE_NAME);
|
||||||
NameService theNameService;
|
|
||||||
if (hostsFileName != null) {
|
|
||||||
theNameService = new HostsFileNameService(hostsFileName);
|
|
||||||
} else {
|
} else {
|
||||||
theNameService = new PlatformNameService();
|
theResolver = new PlatformResolver();
|
||||||
}
|
}
|
||||||
return theNameService;
|
return theResolver;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an InetAddress based on the provided host name and IP address.
|
* Creates an InetAddress based on the provided host name and IP address.
|
||||||
* No name service is checked for the validity of the address.
|
* The system-wide {@linkplain InetAddressResolver resolver} is not used to check
|
||||||
|
* the validity of the address.
|
||||||
*
|
*
|
||||||
* <p> The host name can either be a machine name, such as
|
* <p> The host name can either be a machine name, such as
|
||||||
* "{@code www.example.com}", or a textual representation of its IP
|
* "{@code www.example.com}", or a textual representation of its IP
|
||||||
|
@ -1251,15 +1389,9 @@ public class InetAddress implements java.io.Serializable {
|
||||||
return InetAddress.getAllByName(host)[0];
|
return InetAddress.getAllByName(host)[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
// called from deployment cache manager
|
|
||||||
private static InetAddress getByName(String host, InetAddress reqAddr)
|
|
||||||
throws UnknownHostException {
|
|
||||||
return InetAddress.getAllByName(host, reqAddr)[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Given the name of a host, returns an array of its IP addresses,
|
* Given the name of a host, returns an array of its IP addresses,
|
||||||
* based on the configured name service on the system.
|
* based on the configured system {@linkplain InetAddressResolver resolver}.
|
||||||
*
|
*
|
||||||
* <p> The host name can either be a machine name, such as
|
* <p> The host name can either be a machine name, such as
|
||||||
* "{@code www.example.com}", or a textual representation of its IP
|
* "{@code www.example.com}", or a textual representation of its IP
|
||||||
|
@ -1298,11 +1430,6 @@ public class InetAddress implements java.io.Serializable {
|
||||||
*/
|
*/
|
||||||
public static InetAddress[] getAllByName(String host)
|
public static InetAddress[] getAllByName(String host)
|
||||||
throws UnknownHostException {
|
throws UnknownHostException {
|
||||||
return getAllByName(host, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static InetAddress[] getAllByName(String host, InetAddress reqAddr)
|
|
||||||
throws UnknownHostException {
|
|
||||||
|
|
||||||
if (host == null || host.isEmpty()) {
|
if (host == null || host.isEmpty()) {
|
||||||
InetAddress[] ret = new InetAddress[1];
|
InetAddress[] ret = new InetAddress[1];
|
||||||
|
@ -1364,7 +1491,7 @@ public class InetAddress implements java.io.Serializable {
|
||||||
// We were expecting an IPv6 Literal, but got something else
|
// We were expecting an IPv6 Literal, but got something else
|
||||||
throw new UnknownHostException("["+host+"]");
|
throw new UnknownHostException("["+host+"]");
|
||||||
}
|
}
|
||||||
return getAllByName0(host, reqAddr, true, true);
|
return getAllByName0(host, true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1414,25 +1541,18 @@ public class InetAddress implements java.io.Serializable {
|
||||||
return zone;
|
return zone;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static InetAddress[] getAllByName0 (String host)
|
|
||||||
throws UnknownHostException
|
|
||||||
{
|
|
||||||
return getAllByName0(host, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* package private so SocketPermission can call it
|
* package private so SocketPermission can call it
|
||||||
*/
|
*/
|
||||||
static InetAddress[] getAllByName0 (String host, boolean check)
|
static InetAddress[] getAllByName0 (String host, boolean check)
|
||||||
throws UnknownHostException {
|
throws UnknownHostException {
|
||||||
return getAllByName0 (host, null, check, true);
|
return getAllByName0(host, check, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Designated lookup method.
|
* Designated lookup method.
|
||||||
*
|
*
|
||||||
* @param host host name to look up
|
* @param host host name to look up
|
||||||
* @param reqAddr requested address to be the 1st in returned array
|
|
||||||
* @param check perform security check
|
* @param check perform security check
|
||||||
* @param useCache use cached value if not expired else always
|
* @param useCache use cached value if not expired else always
|
||||||
* perform name service lookup (and cache the result)
|
* perform name service lookup (and cache the result)
|
||||||
|
@ -1440,7 +1560,6 @@ public class InetAddress implements java.io.Serializable {
|
||||||
* @throws UnknownHostException if host name is not found
|
* @throws UnknownHostException if host name is not found
|
||||||
*/
|
*/
|
||||||
private static InetAddress[] getAllByName0(String host,
|
private static InetAddress[] getAllByName0(String host,
|
||||||
InetAddress reqAddr,
|
|
||||||
boolean check,
|
boolean check,
|
||||||
boolean useCache)
|
boolean useCache)
|
||||||
throws UnknownHostException {
|
throws UnknownHostException {
|
||||||
|
@ -1498,7 +1617,7 @@ public class InetAddress implements java.io.Serializable {
|
||||||
// the name service and install it within cache...
|
// the name service and install it within cache...
|
||||||
Addresses oldAddrs = cache.putIfAbsent(
|
Addresses oldAddrs = cache.putIfAbsent(
|
||||||
host,
|
host,
|
||||||
addrs = new NameServiceAddresses(host, reqAddr)
|
addrs = new NameServiceAddresses(host)
|
||||||
);
|
);
|
||||||
if (oldAddrs != null) { // lost putIfAbsent race
|
if (oldAddrs != null) { // lost putIfAbsent race
|
||||||
addrs = oldAddrs;
|
addrs = oldAddrs;
|
||||||
|
@ -1509,47 +1628,30 @@ public class InetAddress implements java.io.Serializable {
|
||||||
return addrs.get().clone();
|
return addrs.get().clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
static InetAddress[] getAddressesFromNameService(String host, InetAddress reqAddr)
|
static InetAddress[] getAddressesFromNameService(String host)
|
||||||
throws UnknownHostException {
|
throws UnknownHostException {
|
||||||
InetAddress[] addresses = null;
|
Stream<InetAddress> addresses = null;
|
||||||
UnknownHostException ex = null;
|
UnknownHostException ex = null;
|
||||||
|
|
||||||
|
var resolver = resolver();
|
||||||
try {
|
try {
|
||||||
addresses = nameService.lookupAllHostAddr(host);
|
addresses = resolver.lookupByName(host, PLATFORM_LOOKUP_POLICY);
|
||||||
} catch (UnknownHostException uhe) {
|
} catch (RuntimeException | UnknownHostException x) {
|
||||||
if (host.equalsIgnoreCase("localhost")) {
|
if (host.equalsIgnoreCase("localhost")) {
|
||||||
addresses = new InetAddress[]{impl.loopbackAddress()};
|
addresses = Stream.of(impl.loopbackAddress());
|
||||||
} else {
|
} else if (x instanceof UnknownHostException uhe) {
|
||||||
ex = uhe;
|
ex = uhe;
|
||||||
|
} else {
|
||||||
|
ex = new UnknownHostException();
|
||||||
|
ex.initCause(x);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
InetAddress[] result = addresses == null ? null
|
||||||
if (addresses == null) {
|
: addresses.toArray(InetAddress[]::new);
|
||||||
|
if (result == null || result.length == 0) {
|
||||||
throw ex == null ? new UnknownHostException(host) : ex;
|
throw ex == null ? new UnknownHostException(host) : ex;
|
||||||
}
|
}
|
||||||
|
return result;
|
||||||
// More to do?
|
|
||||||
if (reqAddr != null && addresses.length > 1 && !addresses[0].equals(reqAddr)) {
|
|
||||||
// Find it?
|
|
||||||
int i = 1;
|
|
||||||
for (; i < addresses.length; i++) {
|
|
||||||
if (addresses[i].equals(reqAddr)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Rotate
|
|
||||||
if (i < addresses.length) {
|
|
||||||
InetAddress tmp, tmp2 = reqAddr;
|
|
||||||
for (int j = 0; j < i; j++) {
|
|
||||||
tmp = addresses[j];
|
|
||||||
addresses[j] = tmp2;
|
|
||||||
tmp2 = tmp;
|
|
||||||
}
|
|
||||||
addresses[i] = tmp2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return addresses;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1557,8 +1659,7 @@ public class InetAddress implements java.io.Serializable {
|
||||||
* The argument is in network byte order: the highest order
|
* The argument is in network byte order: the highest order
|
||||||
* byte of the address is in {@code getAddress()[0]}.
|
* byte of the address is in {@code getAddress()[0]}.
|
||||||
*
|
*
|
||||||
* <p> This method doesn't block, i.e. no reverse name service lookup
|
* <p> This method doesn't block, i.e. no reverse lookup is performed.
|
||||||
* is performed.
|
|
||||||
*
|
*
|
||||||
* <p> IPv4 address byte array must be 4 bytes long and IPv6 byte array
|
* <p> IPv4 address byte array must be 4 bytes long and IPv6 byte array
|
||||||
* must be 16 bytes long
|
* must be 16 bytes long
|
||||||
|
@ -1637,7 +1738,7 @@ public class InetAddress implements java.io.Serializable {
|
||||||
// call getAllByName0 without security checks and
|
// call getAllByName0 without security checks and
|
||||||
// without using cached data
|
// without using cached data
|
||||||
try {
|
try {
|
||||||
localAddr = getAllByName0(local, null, false, false)[0];
|
localAddr = getAllByName0(local, false, false)[0];
|
||||||
} catch (UnknownHostException uhe) {
|
} catch (UnknownHostException uhe) {
|
||||||
// Rethrow with a more informative error message.
|
// Rethrow with a more informative error message.
|
||||||
UnknownHostException uhe2 =
|
UnknownHostException uhe2 =
|
||||||
|
|
|
@ -24,7 +24,10 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package java.net;
|
package java.net;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.net.spi.InetAddressResolver.LookupPolicy;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Package private interface to "implementation" used by
|
* Package private interface to "implementation" used by
|
||||||
* {@link InetAddress}.
|
* {@link InetAddress}.
|
||||||
|
@ -38,7 +41,7 @@ sealed interface InetAddressImpl permits Inet4AddressImpl, Inet6AddressImpl {
|
||||||
|
|
||||||
String getLocalHostName() throws UnknownHostException;
|
String getLocalHostName() throws UnknownHostException;
|
||||||
InetAddress[]
|
InetAddress[]
|
||||||
lookupAllHostAddr(String hostname) throws UnknownHostException;
|
lookupAllHostAddr(String hostname, LookupPolicy lookupPolicy) throws UnknownHostException;
|
||||||
String getHostByAddr(byte[] addr) throws UnknownHostException;
|
String getHostByAddr(byte[] addr) throws UnknownHostException;
|
||||||
|
|
||||||
InetAddress anyLocalAddress();
|
InetAddress anyLocalAddress();
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<!DOCTYPE HTML>
|
<!DOCTYPE HTML>
|
||||||
<!--
|
<!--
|
||||||
Copyright (c) 1998, 2020, Oracle and/or its affiliates. All rights reserved.
|
Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||||
DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
|
||||||
This code is free software; you can redistribute it and/or modify it
|
This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -61,7 +61,7 @@ If there is no special note, a property value is checked every time it is used.<
|
||||||
(e.g. 192.168.1.1). This property can be set to <B>true</B> to
|
(e.g. 192.168.1.1). This property can be set to <B>true</B> to
|
||||||
change that preference and use IPv6 addresses over IPv4 ones where
|
change that preference and use IPv6 addresses over IPv4 ones where
|
||||||
possible, or <B>system</B> to preserve the order of the addresses as
|
possible, or <B>system</B> to preserve the order of the addresses as
|
||||||
returned by the operating system.</P>
|
returned by the system-wide {@linkplain java.net.spi.InetAddressResolver resolver}.</P>
|
||||||
</UL>
|
</UL>
|
||||||
<P>Both of these properties are checked only once, at startup.</P>
|
<P>Both of these properties are checked only once, at startup.</P>
|
||||||
<a id="Proxies"></a>
|
<a id="Proxies"></a>
|
||||||
|
|
|
@ -0,0 +1,201 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation. Oracle designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Oracle in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package java.net.spi;
|
||||||
|
|
||||||
|
import java.lang.annotation.Native;
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.net.UnknownHostException;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This interface defines operations for looking up host names and IP addresses.
|
||||||
|
* {@link InetAddress} delegates all lookup operations to the <i>system-wide
|
||||||
|
* resolver</i>.
|
||||||
|
*
|
||||||
|
* <p> The <i>system-wide resolver</i> can be customized by
|
||||||
|
* <a href="InetAddressResolverProvider.html#system-wide-resolver">
|
||||||
|
* deploying an implementation</a> of {@link InetAddressResolverProvider}.
|
||||||
|
*
|
||||||
|
* @since 18
|
||||||
|
*/
|
||||||
|
public interface InetAddressResolver {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given the name of a host, returns a stream of IP addresses of the requested
|
||||||
|
* address family associated with a provided hostname.
|
||||||
|
*
|
||||||
|
* <p> {@code host} should be a machine name, such as "{@code www.example.com}",
|
||||||
|
* not a textual representation of its IP address. No validation is performed on
|
||||||
|
* the given {@code host} name: if a textual representation is supplied, the name
|
||||||
|
* resolution is likely to fail and {@link UnknownHostException} may be thrown.
|
||||||
|
*
|
||||||
|
* <p> The address family type and addresses order are specified by the
|
||||||
|
* {@code LookupPolicy} instance. Lookup operation characteristics could be
|
||||||
|
* acquired with {@link LookupPolicy#characteristics()}.
|
||||||
|
* If {@link InetAddressResolver.LookupPolicy#IPV4} and
|
||||||
|
* {@link InetAddressResolver.LookupPolicy#IPV6} characteristics provided then this
|
||||||
|
* method returns addresses of both IPV4 and IPV6 families.
|
||||||
|
*
|
||||||
|
* @param host the specified hostname
|
||||||
|
* @param lookupPolicy the address lookup policy
|
||||||
|
* @return a stream of IP addresses for the requested host
|
||||||
|
* @throws NullPointerException if either parameter is {@code null}
|
||||||
|
* @throws UnknownHostException if no IP address for the {@code host} could be found
|
||||||
|
* @see LookupPolicy
|
||||||
|
*/
|
||||||
|
Stream<InetAddress> lookupByName(String host, LookupPolicy lookupPolicy) throws UnknownHostException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lookup the host name corresponding to the raw IP address provided.
|
||||||
|
*
|
||||||
|
* <p> {@code addr} argument is in network byte order: the highest order byte of the address
|
||||||
|
* is in {@code addr[0]}.
|
||||||
|
*
|
||||||
|
* <p> IPv4 address byte array must be 4 bytes long and IPv6 byte array
|
||||||
|
* must be 16 bytes long.
|
||||||
|
*
|
||||||
|
* @param addr byte array representing a raw IP address
|
||||||
|
* @return {@code String} representing the host name mapping
|
||||||
|
* @throws UnknownHostException if no host name is found for the specified IP address
|
||||||
|
* @throws IllegalArgumentException if the length of the provided byte array doesn't correspond
|
||||||
|
* to a valid IP address length
|
||||||
|
* @throws NullPointerException if addr is {@code null}
|
||||||
|
*/
|
||||||
|
String lookupByAddress(byte[] addr) throws UnknownHostException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A {@code LookupPolicy} object describes characteristics that can be applied to a lookup operation.
|
||||||
|
* In particular, it is used to specify the ordering and which filtering should be performed when
|
||||||
|
* {@linkplain InetAddressResolver#lookupByName(String, LookupPolicy) looking up host addresses}.
|
||||||
|
*
|
||||||
|
* <p> The default platform-wide lookup policy is constructed by consulting
|
||||||
|
* <a href="doc-files/net-properties.html#Ipv4IPv6">System Properties</a> which affect
|
||||||
|
* how IPv4 and IPv6 addresses are returned.
|
||||||
|
*
|
||||||
|
* @since 18
|
||||||
|
*/
|
||||||
|
final class LookupPolicy {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Characteristic value signifying if IPv4 addresses need to be queried during lookup.
|
||||||
|
*/
|
||||||
|
@Native
|
||||||
|
public static final int IPV4 = 1 << 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Characteristic value signifying if IPv6 addresses need to be queried during lookup.
|
||||||
|
*/
|
||||||
|
@Native
|
||||||
|
public static final int IPV6 = 1 << 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Characteristic value signifying if IPv4 addresses should be returned
|
||||||
|
* first by {@code InetAddressResolver}.
|
||||||
|
*/
|
||||||
|
@Native
|
||||||
|
public static final int IPV4_FIRST = 1 << 2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Characteristic value signifying if IPv6 addresses should be returned
|
||||||
|
* first by {@code InetAddressResolver}.
|
||||||
|
*/
|
||||||
|
@Native
|
||||||
|
public static final int IPV6_FIRST = 1 << 3;
|
||||||
|
|
||||||
|
private final int characteristics;
|
||||||
|
|
||||||
|
private LookupPolicy(int characteristics) {
|
||||||
|
this.characteristics = characteristics;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This factory method creates a {@link LookupPolicy LookupPolicy} instance with
|
||||||
|
* the given {@code characteristics} value.
|
||||||
|
*
|
||||||
|
* <p> The {@code characteristics} value is an integer bit mask which defines
|
||||||
|
* parameters of a forward lookup operation. These parameters define at least:
|
||||||
|
* <ul>
|
||||||
|
* <li>the family type of the returned addresses</li>
|
||||||
|
* <li>the order in which a {@linkplain InetAddressResolver resolver}
|
||||||
|
* implementation should return its results</li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* <p> To request addresses of specific family types the following bit masks can be combined:
|
||||||
|
* <ul>
|
||||||
|
* <li>{@link LookupPolicy#IPV4}: to request IPv4 addresses</li>
|
||||||
|
* <li>{@link LookupPolicy#IPV6}: to request IPv6 addresses</li>
|
||||||
|
* </ul>
|
||||||
|
* <br>It is an error if neither {@link LookupPolicy#IPV4} or {@link LookupPolicy#IPV6} are set.
|
||||||
|
*
|
||||||
|
* <p> To request a specific ordering of the results:
|
||||||
|
* <ul>
|
||||||
|
* <li>{@link LookupPolicy#IPV4_FIRST}: return IPv4 addresses before any IPv6 address</li>
|
||||||
|
* <li>{@link LookupPolicy#IPV6_FIRST}: return IPv6 addresses before any IPv4 address</li>
|
||||||
|
* </ul>
|
||||||
|
* <br>If neither {@link LookupPolicy#IPV4_FIRST} or {@link LookupPolicy#IPV6_FIRST} are set it
|
||||||
|
* implies <a href="{@docRoot}/java.base/java/net/doc-files/net-properties.html#Ipv4IPv6">"system"</a>
|
||||||
|
* order of addresses.
|
||||||
|
* It is an error to request both {@link LookupPolicy#IPV4_FIRST} and {@link LookupPolicy#IPV6_FIRST}.
|
||||||
|
*
|
||||||
|
* @param characteristics a value which represents the set of lookup characteristics
|
||||||
|
* @return an instance of {@code InetAddressResolver.LookupPolicy}
|
||||||
|
* @throws IllegalArgumentException if an illegal characteristics bit mask is provided
|
||||||
|
* @see InetAddressResolver#lookupByName(String, LookupPolicy)
|
||||||
|
*/
|
||||||
|
public static LookupPolicy of(int characteristics) {
|
||||||
|
// At least one type of addresses should be requested
|
||||||
|
if ((characteristics & IPV4) == 0 && (characteristics & IPV6) == 0) {
|
||||||
|
throw new IllegalArgumentException("No address type specified");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Requested order of addresses couldn't be determined
|
||||||
|
if ((characteristics & IPV4_FIRST) != 0 && (characteristics & IPV6_FIRST) != 0) {
|
||||||
|
throw new IllegalArgumentException("Addresses order cannot be determined");
|
||||||
|
}
|
||||||
|
|
||||||
|
// If IPv4 addresses requested to be returned first then they should be requested too
|
||||||
|
if ((characteristics & IPV4_FIRST) != 0 && (characteristics & IPV4) == 0) {
|
||||||
|
throw new IllegalArgumentException("Addresses order and type do not match");
|
||||||
|
}
|
||||||
|
|
||||||
|
// If IPv6 addresses requested to be returned first then they should be requested too
|
||||||
|
if ((characteristics & IPV6_FIRST) != 0 && (characteristics & IPV6) == 0) {
|
||||||
|
throw new IllegalArgumentException("Addresses order and type do not match");
|
||||||
|
}
|
||||||
|
return new LookupPolicy(characteristics);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the set of characteristics of this lookup policy.
|
||||||
|
*
|
||||||
|
* @return a characteristics value
|
||||||
|
* @see InetAddressResolver#lookupByName(String, LookupPolicy)
|
||||||
|
*/
|
||||||
|
public int characteristics() {
|
||||||
|
return characteristics;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,160 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation. Oracle designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Oracle in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package java.net.spi;
|
||||||
|
|
||||||
|
import sun.net.ResolverProviderConfiguration;
|
||||||
|
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.util.ServiceLoader;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Service-provider class for {@linkplain InetAddressResolver InetAddress resolvers}.
|
||||||
|
*
|
||||||
|
* <p> A resolver provider is a factory for custom implementations of {@linkplain
|
||||||
|
* InetAddressResolver InetAddress resolvers}. A resolver defines operations for
|
||||||
|
* looking up (resolving) host names and IP addresses.
|
||||||
|
* <p>A resolver provider is a concrete subclass of this class that has a
|
||||||
|
* zero-argument constructor and implements the abstract methods specified below.
|
||||||
|
*
|
||||||
|
* <p> A given invocation of the Java virtual machine maintains a single
|
||||||
|
* system-wide resolver instance, which is used by
|
||||||
|
* <a href="{@docRoot}/java.base/java/net/InetAddress.html#host-name-resolution">
|
||||||
|
* InetAddress</a>. It is set after the VM is fully initialized and when an
|
||||||
|
* invocation of a method in {@link InetAddress} class triggers the first lookup
|
||||||
|
* operation.
|
||||||
|
*
|
||||||
|
* <p id="system-wide-resolver"> A resolver provider is located and loaded by
|
||||||
|
* {@link InetAddress} to create the system-wide resolver as follows:
|
||||||
|
* <ol>
|
||||||
|
* <li>The {@link ServiceLoader} mechanism is used to locate an
|
||||||
|
* {@code InetAddressResolverProvider} using the
|
||||||
|
* system class loader. The order in which providers are located is
|
||||||
|
* {@linkplain ServiceLoader#load(java.lang.Class, java.lang.ClassLoader)
|
||||||
|
* implementation specific}.
|
||||||
|
* The first provider found will be used to instantiate the
|
||||||
|
* {@link InetAddressResolver InetAddressResolver} by invoking the
|
||||||
|
* {@link InetAddressResolverProvider#get(InetAddressResolverProvider.Configuration)}
|
||||||
|
* method. The returned {@code InetAddressResolver} will be set as the
|
||||||
|
* system-wide resolver.
|
||||||
|
* <li>If the previous step fails to find any resolver provider the
|
||||||
|
* <a href="{@docRoot}/java.base/java/net/InetAddress.html#built-in-resolver">
|
||||||
|
* built-in resolver</a> will be set as the system-wide resolver.
|
||||||
|
* </ol>
|
||||||
|
*
|
||||||
|
* <p> If instantiating a custom resolver from a provider discovered in
|
||||||
|
* step 1 throws an error or exception, the system-wide resolver will not be
|
||||||
|
* set and the error or exception will be propagated to the calling thread.
|
||||||
|
* Otherwise, any lookup operation will be performed using the
|
||||||
|
* <i>system-wide resolver</i>.
|
||||||
|
*
|
||||||
|
* @implNote {@link InetAddress} will use the <i>built-in resolver</i> for any lookup operation
|
||||||
|
* that might occur before the VM is fully booted.
|
||||||
|
*
|
||||||
|
* @since 18
|
||||||
|
*/
|
||||||
|
public abstract class InetAddressResolverProvider {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize and return an {@link InetAddressResolver} provided by
|
||||||
|
* this provider. This method is called by {@link InetAddress} when
|
||||||
|
* <a href="#system-wide-resolver">installing</a>
|
||||||
|
* the system-wide resolver implementation.
|
||||||
|
*
|
||||||
|
* <p> Any error or exception thrown by this method is considered as
|
||||||
|
* a failure of {@code InetAddressResolver} instantiation and will be propagated to
|
||||||
|
* the calling thread.
|
||||||
|
* @param configuration a {@link Configuration} instance containing platform built-in address
|
||||||
|
* resolution configuration.
|
||||||
|
* @return the resolver provided by this provider
|
||||||
|
*/
|
||||||
|
public abstract InetAddressResolver get(Configuration configuration);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@return the name of this provider, or {@code null} if unnamed}
|
||||||
|
*/
|
||||||
|
public abstract String name();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@code RuntimePermission("inetAddressResolverProvider")} is
|
||||||
|
* necessary to subclass and instantiate the {@code InetAddressResolverProvider} class,
|
||||||
|
* as well as to obtain resolver from an instance of that class,
|
||||||
|
* and it is also required to obtain the operating system name resolution configurations.
|
||||||
|
*/
|
||||||
|
private static final RuntimePermission INET_ADDRESS_RESOLVER_PERMISSION =
|
||||||
|
new RuntimePermission("inetAddressResolverProvider");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new instance of {@code InetAddressResolverProvider}.
|
||||||
|
*
|
||||||
|
* @throws SecurityException if a security manager is present and its
|
||||||
|
* {@code checkPermission} method doesn't allow the
|
||||||
|
* {@code RuntimePermission("inetAddressResolverProvider")}.
|
||||||
|
* @implNote It is recommended that an {@code InetAddressResolverProvider} service
|
||||||
|
* implementation initialization should be as simple as possible, in order to avoid
|
||||||
|
* possible risks of deadlock or class loading cycles during the instantiation of the
|
||||||
|
* service provider.
|
||||||
|
*/
|
||||||
|
protected InetAddressResolverProvider() {
|
||||||
|
this(checkPermission());
|
||||||
|
}
|
||||||
|
|
||||||
|
private InetAddressResolverProvider(Void unused) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("removal")
|
||||||
|
private static Void checkPermission() {
|
||||||
|
final SecurityManager sm = System.getSecurityManager();
|
||||||
|
if (sm != null) {
|
||||||
|
sm.checkPermission(INET_ADDRESS_RESOLVER_PERMISSION);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A {@code Configuration} object is supplied to the
|
||||||
|
* {@link InetAddressResolverProvider#get(Configuration)} method when
|
||||||
|
* setting the system-wide resolver.
|
||||||
|
* A resolver implementation can then delegate to the built-in resolver
|
||||||
|
* provided by this interface if it needs to.
|
||||||
|
*
|
||||||
|
* @since 18
|
||||||
|
*/
|
||||||
|
public sealed interface Configuration permits ResolverProviderConfiguration {
|
||||||
|
/**
|
||||||
|
* Returns the built-in {@linkplain InetAddressResolver resolver}.
|
||||||
|
*
|
||||||
|
* @return the JDK built-in resolver.
|
||||||
|
*/
|
||||||
|
InetAddressResolver builtinResolver();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads the localhost name from the system configuration.
|
||||||
|
*
|
||||||
|
* @return the localhost name.
|
||||||
|
*/
|
||||||
|
String lookupLocalHostName();
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -26,8 +26,8 @@
|
||||||
/**
|
/**
|
||||||
* Service-provider classes for the {@link java.net} package.
|
* Service-provider classes for the {@link java.net} package.
|
||||||
*
|
*
|
||||||
* <p> Only developers who are defining new URL stream handler providers
|
* <p> Only developers who are defining new URL stream handler providers or implementing
|
||||||
* should need to make direct use of this package.
|
* a custom resolver provider should need to make direct use of this package.
|
||||||
*
|
*
|
||||||
* @since 9
|
* @since 9
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -28,7 +28,6 @@ package jdk.internal.access;
|
||||||
import java.net.Inet4Address;
|
import java.net.Inet4Address;
|
||||||
import java.net.Inet6Address;
|
import java.net.Inet6Address;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.net.UnknownHostException;
|
|
||||||
|
|
||||||
public interface JavaNetInetAddressAccess {
|
public interface JavaNetInetAddressAccess {
|
||||||
/**
|
/**
|
||||||
|
@ -37,15 +36,6 @@ public interface JavaNetInetAddressAccess {
|
||||||
*/
|
*/
|
||||||
String getOriginalHostName(InetAddress ia);
|
String getOriginalHostName(InetAddress ia);
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the InetAddress of the provided host. If an InetAddress is provided
|
|
||||||
* then it will be the default address returned for all calls to either
|
|
||||||
* form of getByName. This is required to maintain consistency when
|
|
||||||
* caching addresses and hostnames.
|
|
||||||
*/
|
|
||||||
InetAddress getByName(String hostName, InetAddress hostAddress)
|
|
||||||
throws UnknownHostException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the 32-bit IPv4 address.
|
* Returns the 32-bit IPv4 address.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -369,6 +369,7 @@ module java.base {
|
||||||
|
|
||||||
uses java.lang.System.LoggerFinder;
|
uses java.lang.System.LoggerFinder;
|
||||||
uses java.net.ContentHandlerFactory;
|
uses java.net.ContentHandlerFactory;
|
||||||
|
uses java.net.spi.InetAddressResolverProvider;
|
||||||
uses java.net.spi.URLStreamHandlerProvider;
|
uses java.net.spi.URLStreamHandlerProvider;
|
||||||
uses java.nio.channels.spi.AsynchronousChannelProvider;
|
uses java.nio.channels.spi.AsynchronousChannelProvider;
|
||||||
uses java.nio.channels.spi.SelectorProvider;
|
uses java.nio.channels.spi.SelectorProvider;
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation. Oracle designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Oracle in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package sun.net;
|
||||||
|
|
||||||
|
import java.net.spi.InetAddressResolver;
|
||||||
|
import java.net.spi.InetAddressResolverProvider;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
public final class ResolverProviderConfiguration implements
|
||||||
|
InetAddressResolverProvider.Configuration {
|
||||||
|
|
||||||
|
private final InetAddressResolver builtinResolver;
|
||||||
|
private final Supplier<String> localHostNameSupplier;
|
||||||
|
|
||||||
|
public ResolverProviderConfiguration(InetAddressResolver builtinResolver,
|
||||||
|
Supplier<String> localHostNameSupplier) {
|
||||||
|
this.builtinResolver = builtinResolver;
|
||||||
|
this.localHostNameSupplier = localHostNameSupplier;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InetAddressResolver builtinResolver() {
|
||||||
|
return builtinResolver;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String lookupLocalHostName() {
|
||||||
|
return localHostNameSupplier.get();
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -39,7 +39,6 @@ jfieldID iac_addressID;
|
||||||
jfieldID iac_familyID;
|
jfieldID iac_familyID;
|
||||||
jfieldID iac_hostNameID;
|
jfieldID iac_hostNameID;
|
||||||
jfieldID iac_origHostNameID;
|
jfieldID iac_origHostNameID;
|
||||||
jfieldID ia_preferIPv6AddressID;
|
|
||||||
|
|
||||||
static int ia_initialized = 0;
|
static int ia_initialized = 0;
|
||||||
|
|
||||||
|
@ -61,8 +60,6 @@ Java_java_net_InetAddress_init(JNIEnv *env, jclass cls) {
|
||||||
CHECK_NULL(iac_class);
|
CHECK_NULL(iac_class);
|
||||||
ia_holderID = (*env)->GetFieldID(env, ia_class, "holder", "Ljava/net/InetAddress$InetAddressHolder;");
|
ia_holderID = (*env)->GetFieldID(env, ia_class, "holder", "Ljava/net/InetAddress$InetAddressHolder;");
|
||||||
CHECK_NULL(ia_holderID);
|
CHECK_NULL(ia_holderID);
|
||||||
ia_preferIPv6AddressID = (*env)->GetStaticFieldID(env, ia_class, "preferIPv6Address", "I");
|
|
||||||
CHECK_NULL(ia_preferIPv6AddressID);
|
|
||||||
|
|
||||||
iac_addressID = (*env)->GetFieldID(env, iac_class, "address", "I");
|
iac_addressID = (*env)->GetFieldID(env, iac_class, "address", "I");
|
||||||
CHECK_NULL(iac_addressID);
|
CHECK_NULL(iac_addressID);
|
||||||
|
@ -75,3 +72,12 @@ Java_java_net_InetAddress_init(JNIEnv *env, jclass cls) {
|
||||||
ia_initialized = 1;
|
ia_initialized = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Class: java_net_InetAddress
|
||||||
|
* Method: isIPv4Available
|
||||||
|
*/
|
||||||
|
JNIEXPORT jboolean JNICALL
|
||||||
|
Java_java_net_InetAddress_isIPv4Available(JNIEnv *env, jclass clazz) {
|
||||||
|
return ipv4_available();
|
||||||
|
}
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include "net_util.h"
|
#include "net_util.h"
|
||||||
|
|
||||||
#include "java_net_InetAddress.h"
|
#include "java_net_InetAddress.h"
|
||||||
|
#include "java_net_spi_InetAddressResolver_LookupPolicy.h"
|
||||||
|
|
||||||
int IPv4_supported();
|
int IPv4_supported();
|
||||||
int IPv6_supported();
|
int IPv6_supported();
|
||||||
|
@ -332,3 +333,23 @@ in_cksum(unsigned short *addr, int len) {
|
||||||
answer = ~sum;
|
answer = ~sum;
|
||||||
return (answer);
|
return (answer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int lookupCharacteristicsToAddressFamily(int characteristics) {
|
||||||
|
int ipv4 = characteristics & java_net_spi_InetAddressResolver_LookupPolicy_IPV4;
|
||||||
|
int ipv6 = characteristics & java_net_spi_InetAddressResolver_LookupPolicy_IPV6;
|
||||||
|
|
||||||
|
if (ipv4 != 0 && ipv6 == 0) {
|
||||||
|
return AF_INET;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ipv4 == 0 && ipv6 != 0) {
|
||||||
|
return AF_INET6;
|
||||||
|
}
|
||||||
|
return AF_UNSPEC;
|
||||||
|
}
|
||||||
|
|
||||||
|
int addressesInSystemOrder(int characteristics) {
|
||||||
|
return (characteristics &
|
||||||
|
(java_net_spi_InetAddressResolver_LookupPolicy_IPV4_FIRST |
|
||||||
|
java_net_spi_InetAddressResolver_LookupPolicy_IPV6_FIRST)) == 0;
|
||||||
|
}
|
||||||
|
|
|
@ -51,7 +51,6 @@ extern jfieldID iac_addressID;
|
||||||
extern jfieldID iac_familyID;
|
extern jfieldID iac_familyID;
|
||||||
extern jfieldID iac_hostNameID;
|
extern jfieldID iac_hostNameID;
|
||||||
extern jfieldID iac_origHostNameID;
|
extern jfieldID iac_origHostNameID;
|
||||||
extern jfieldID ia_preferIPv6AddressID;
|
|
||||||
|
|
||||||
JNIEXPORT void JNICALL initInetAddressIDs(JNIEnv *env);
|
JNIEXPORT void JNICALL initInetAddressIDs(JNIEnv *env);
|
||||||
|
|
||||||
|
@ -192,4 +191,8 @@ unsigned short in_cksum(unsigned short *addr, int len);
|
||||||
|
|
||||||
jint NET_Wait(JNIEnv *env, jint fd, jint flags, jint timeout);
|
jint NET_Wait(JNIEnv *env, jint fd, jint flags, jint timeout);
|
||||||
|
|
||||||
|
int lookupCharacteristicsToAddressFamily(int characteristics);
|
||||||
|
|
||||||
|
int addressesInSystemOrder(int characteristics);
|
||||||
|
|
||||||
#endif /* NET_UTILS_H */
|
#endif /* NET_UTILS_H */
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -36,9 +36,11 @@
|
||||||
#include "net_util.h"
|
#include "net_util.h"
|
||||||
|
|
||||||
#include "java_net_Inet4AddressImpl.h"
|
#include "java_net_Inet4AddressImpl.h"
|
||||||
|
#include "java_net_spi_InetAddressResolver_LookupPolicy.h"
|
||||||
|
|
||||||
#if defined(MACOSX)
|
#if defined(MACOSX)
|
||||||
extern jobjectArray lookupIfLocalhost(JNIEnv *env, const char *hostname, jboolean includeV6);
|
extern jobjectArray lookupIfLocalhost(JNIEnv *env, const char *hostname, jboolean includeV6,
|
||||||
|
int addressesOrder);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define SET_NONBLOCKING(fd) { \
|
#define SET_NONBLOCKING(fd) { \
|
||||||
|
@ -111,7 +113,9 @@ Java_java_net_Inet4AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this,
|
||||||
if (error) {
|
if (error) {
|
||||||
#if defined(MACOSX)
|
#if defined(MACOSX)
|
||||||
// If getaddrinfo fails try getifaddrs, see bug 8170910.
|
// If getaddrinfo fails try getifaddrs, see bug 8170910.
|
||||||
ret = lookupIfLocalhost(env, hostname, JNI_FALSE);
|
// java_net_spi_InetAddressResolver_LookupPolicy_IPV4_FIRST and no ordering is ok
|
||||||
|
// here since only AF_INET addresses will be returned.
|
||||||
|
ret = lookupIfLocalhost(env, hostname, JNI_FALSE, java_net_spi_InetAddressResolver_LookupPolicy_IPV4);
|
||||||
if (ret != NULL || (*env)->ExceptionCheck(env)) {
|
if (ret != NULL || (*env)->ExceptionCheck(env)) {
|
||||||
goto cleanupAndReturn;
|
goto cleanupAndReturn;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -41,6 +41,8 @@
|
||||||
#include "java_net_InetAddress.h"
|
#include "java_net_InetAddress.h"
|
||||||
#include "java_net_Inet4AddressImpl.h"
|
#include "java_net_Inet4AddressImpl.h"
|
||||||
#include "java_net_Inet6AddressImpl.h"
|
#include "java_net_Inet6AddressImpl.h"
|
||||||
|
#include "java_net_spi_InetAddressResolver_LookupPolicy.h"
|
||||||
|
|
||||||
|
|
||||||
#define SET_NONBLOCKING(fd) { \
|
#define SET_NONBLOCKING(fd) { \
|
||||||
int flags = fcntl(fd, F_GETFL); \
|
int flags = fcntl(fd, F_GETFL); \
|
||||||
|
@ -74,7 +76,7 @@ Java_java_net_Inet6AddressImpl_getLocalHostName(JNIEnv *env, jobject this) {
|
||||||
#if defined(MACOSX)
|
#if defined(MACOSX)
|
||||||
/* also called from Inet4AddressImpl.c */
|
/* also called from Inet4AddressImpl.c */
|
||||||
__private_extern__ jobjectArray
|
__private_extern__ jobjectArray
|
||||||
lookupIfLocalhost(JNIEnv *env, const char *hostname, jboolean includeV6)
|
lookupIfLocalhost(JNIEnv *env, const char *hostname, jboolean includeV6, int characteristics)
|
||||||
{
|
{
|
||||||
jobjectArray result = NULL;
|
jobjectArray result = NULL;
|
||||||
char myhostname[NI_MAXHOST + 1];
|
char myhostname[NI_MAXHOST + 1];
|
||||||
|
@ -151,7 +153,7 @@ lookupIfLocalhost(JNIEnv *env, const char *hostname, jboolean includeV6)
|
||||||
result = (*env)->NewObjectArray(env, arraySize, ia_class, NULL);
|
result = (*env)->NewObjectArray(env, arraySize, ia_class, NULL);
|
||||||
if (!result) goto done;
|
if (!result) goto done;
|
||||||
|
|
||||||
if ((*env)->GetStaticBooleanField(env, ia_class, ia_preferIPv6AddressID)) {
|
if ((characteristics & java_net_spi_InetAddressResolver_LookupPolicy_IPV6_FIRST) != 0) {
|
||||||
i = includeLoopback ? addrs6 : (addrs6 - numV6Loopbacks);
|
i = includeLoopback ? addrs6 : (addrs6 - numV6Loopbacks);
|
||||||
j = 0;
|
j = 0;
|
||||||
} else {
|
} else {
|
||||||
|
@ -204,7 +206,7 @@ lookupIfLocalhost(JNIEnv *env, const char *hostname, jboolean includeV6)
|
||||||
*/
|
*/
|
||||||
JNIEXPORT jobjectArray JNICALL
|
JNIEXPORT jobjectArray JNICALL
|
||||||
Java_java_net_Inet6AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this,
|
Java_java_net_Inet6AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this,
|
||||||
jstring host) {
|
jstring host, jint characteristics) {
|
||||||
jobjectArray ret = NULL;
|
jobjectArray ret = NULL;
|
||||||
const char *hostname;
|
const char *hostname;
|
||||||
int error = 0;
|
int error = 0;
|
||||||
|
@ -224,14 +226,14 @@ Java_java_net_Inet6AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this,
|
||||||
// try once, with our static buffer
|
// try once, with our static buffer
|
||||||
memset(&hints, 0, sizeof(hints));
|
memset(&hints, 0, sizeof(hints));
|
||||||
hints.ai_flags = AI_CANONNAME;
|
hints.ai_flags = AI_CANONNAME;
|
||||||
hints.ai_family = AF_UNSPEC;
|
hints.ai_family = lookupCharacteristicsToAddressFamily(characteristics);
|
||||||
|
|
||||||
error = getaddrinfo(hostname, NULL, &hints, &res);
|
error = getaddrinfo(hostname, NULL, &hints, &res);
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
#if defined(MACOSX)
|
#if defined(MACOSX)
|
||||||
// if getaddrinfo fails try getifaddrs
|
// if getaddrinfo fails try getifaddrs
|
||||||
ret = lookupIfLocalhost(env, hostname, JNI_TRUE);
|
ret = lookupIfLocalhost(env, hostname, JNI_TRUE, characteristics);
|
||||||
if (ret != NULL || (*env)->ExceptionCheck(env)) {
|
if (ret != NULL || (*env)->ExceptionCheck(env)) {
|
||||||
goto cleanupAndReturn;
|
goto cleanupAndReturn;
|
||||||
}
|
}
|
||||||
|
@ -242,8 +244,6 @@ Java_java_net_Inet6AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this,
|
||||||
} else {
|
} else {
|
||||||
int i = 0, inetCount = 0, inet6Count = 0, inetIndex = 0,
|
int i = 0, inetCount = 0, inet6Count = 0, inetIndex = 0,
|
||||||
inet6Index = 0, originalIndex = 0;
|
inet6Index = 0, originalIndex = 0;
|
||||||
int addressPreference =
|
|
||||||
(*env)->GetStaticIntField(env, ia_class, ia_preferIPv6AddressID);;
|
|
||||||
iterator = res;
|
iterator = res;
|
||||||
while (iterator != NULL) {
|
while (iterator != NULL) {
|
||||||
// skip duplicates
|
// skip duplicates
|
||||||
|
@ -322,13 +322,13 @@ Java_java_net_Inet6AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this,
|
||||||
goto cleanupAndReturn;
|
goto cleanupAndReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (addressPreference == java_net_InetAddress_PREFER_IPV6_VALUE) {
|
if ((characteristics & java_net_spi_InetAddressResolver_LookupPolicy_IPV6_FIRST) != 0) {
|
||||||
inetIndex = inet6Count;
|
inetIndex = inet6Count;
|
||||||
inet6Index = 0;
|
inet6Index = 0;
|
||||||
} else if (addressPreference == java_net_InetAddress_PREFER_IPV4_VALUE) {
|
} else if ((characteristics & java_net_spi_InetAddressResolver_LookupPolicy_IPV4_FIRST) != 0) {
|
||||||
inetIndex = 0;
|
inetIndex = 0;
|
||||||
inet6Index = inetCount;
|
inet6Index = inetCount;
|
||||||
} else if (addressPreference == java_net_InetAddress_PREFER_SYSTEM_VALUE) {
|
} else {
|
||||||
inetIndex = inet6Index = originalIndex = 0;
|
inetIndex = inet6Index = originalIndex = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -371,7 +371,8 @@ Java_java_net_Inet6AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this,
|
||||||
(*env)->SetObjectArrayElement(env, ret, (inet6Index | originalIndex), iaObj);
|
(*env)->SetObjectArrayElement(env, ret, (inet6Index | originalIndex), iaObj);
|
||||||
inet6Index++;
|
inet6Index++;
|
||||||
}
|
}
|
||||||
if (addressPreference == java_net_InetAddress_PREFER_SYSTEM_VALUE) {
|
// Check if addresses are requested to be returned in SYSTEM order
|
||||||
|
if (addressesInSystemOrder(characteristics)) {
|
||||||
originalIndex++;
|
originalIndex++;
|
||||||
inetIndex = inet6Index = 0;
|
inetIndex = inet6Index = 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -29,6 +29,7 @@
|
||||||
#include "java_net_InetAddress.h"
|
#include "java_net_InetAddress.h"
|
||||||
#include "java_net_Inet4AddressImpl.h"
|
#include "java_net_Inet4AddressImpl.h"
|
||||||
#include "java_net_Inet6AddressImpl.h"
|
#include "java_net_Inet6AddressImpl.h"
|
||||||
|
#include "java_net_spi_InetAddressResolver_LookupPolicy.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Inet6AddressImpl
|
* Inet6AddressImpl
|
||||||
|
@ -56,7 +57,7 @@ Java_java_net_Inet6AddressImpl_getLocalHostName(JNIEnv *env, jobject this) {
|
||||||
*/
|
*/
|
||||||
JNIEXPORT jobjectArray JNICALL
|
JNIEXPORT jobjectArray JNICALL
|
||||||
Java_java_net_Inet6AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this,
|
Java_java_net_Inet6AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this,
|
||||||
jstring host) {
|
jstring host, jint characteristics) {
|
||||||
jobjectArray ret = NULL;
|
jobjectArray ret = NULL;
|
||||||
const char *hostname;
|
const char *hostname;
|
||||||
int error = 0;
|
int error = 0;
|
||||||
|
@ -76,7 +77,7 @@ Java_java_net_Inet6AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this,
|
||||||
// try once, with our static buffer
|
// try once, with our static buffer
|
||||||
memset(&hints, 0, sizeof(hints));
|
memset(&hints, 0, sizeof(hints));
|
||||||
hints.ai_flags = AI_CANONNAME;
|
hints.ai_flags = AI_CANONNAME;
|
||||||
hints.ai_family = AF_UNSPEC;
|
hints.ai_family = lookupCharacteristicsToAddressFamily(characteristics);
|
||||||
|
|
||||||
error = getaddrinfo(hostname, NULL, &hints, &res);
|
error = getaddrinfo(hostname, NULL, &hints, &res);
|
||||||
|
|
||||||
|
@ -88,8 +89,6 @@ Java_java_net_Inet6AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this,
|
||||||
} else {
|
} else {
|
||||||
int i = 0, inetCount = 0, inet6Count = 0, inetIndex = 0,
|
int i = 0, inetCount = 0, inet6Count = 0, inetIndex = 0,
|
||||||
inet6Index = 0, originalIndex = 0;
|
inet6Index = 0, originalIndex = 0;
|
||||||
int addressPreference =
|
|
||||||
(*env)->GetStaticIntField(env, ia_class, ia_preferIPv6AddressID);
|
|
||||||
iterator = res;
|
iterator = res;
|
||||||
while (iterator != NULL) {
|
while (iterator != NULL) {
|
||||||
// skip duplicates
|
// skip duplicates
|
||||||
|
@ -168,13 +167,13 @@ Java_java_net_Inet6AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this,
|
||||||
goto cleanupAndReturn;
|
goto cleanupAndReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (addressPreference == java_net_InetAddress_PREFER_IPV6_VALUE) {
|
if ((characteristics & java_net_spi_InetAddressResolver_LookupPolicy_IPV6_FIRST) != 0) {
|
||||||
inetIndex = inet6Count;
|
inetIndex = inet6Count;
|
||||||
inet6Index = 0;
|
inet6Index = 0;
|
||||||
} else if (addressPreference == java_net_InetAddress_PREFER_IPV4_VALUE) {
|
} else if ((characteristics & java_net_spi_InetAddressResolver_LookupPolicy_IPV4_FIRST) != 0) {
|
||||||
inetIndex = 0;
|
inetIndex = 0;
|
||||||
inet6Index = inetCount;
|
inet6Index = inetCount;
|
||||||
} else if (addressPreference == java_net_InetAddress_PREFER_SYSTEM_VALUE) {
|
} else {
|
||||||
inetIndex = inet6Index = originalIndex = 0;
|
inetIndex = inet6Index = originalIndex = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -217,7 +216,8 @@ Java_java_net_Inet6AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this,
|
||||||
(*env)->SetObjectArrayElement(env, ret, (inet6Index | originalIndex), iaObj);
|
(*env)->SetObjectArrayElement(env, ret, (inet6Index | originalIndex), iaObj);
|
||||||
inet6Index++;
|
inet6Index++;
|
||||||
}
|
}
|
||||||
if (addressPreference == java_net_InetAddress_PREFER_SYSTEM_VALUE) {
|
// Check if addresses are requested to be returned in SYSTEM order
|
||||||
|
if (addressesInSystemOrder(characteristics)) {
|
||||||
originalIndex++;
|
originalIndex++;
|
||||||
inetIndex = inet6Index = 0;
|
inetIndex = inet6Index = 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,104 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.net.UnknownHostException;
|
||||||
|
|
||||||
|
import org.testng.Assert;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import impl.SimpleResolverProviderImpl;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @test
|
||||||
|
* @summary Test that InetAddress caching security properties work as expected
|
||||||
|
* when a custom resolver is installed.
|
||||||
|
* @library lib providers/simple
|
||||||
|
* @build test.library/testlib.ResolutionRegistry
|
||||||
|
* simple.provider/impl.SimpleResolverProviderImpl AddressesCachingTest
|
||||||
|
* @run testng/othervm -Djava.security.properties=${test.src}/NeverCache.props
|
||||||
|
* -Dtest.cachingDisabled=true AddressesCachingTest
|
||||||
|
* @run testng/othervm -Djava.security.properties=${test.src}/ForeverCache.props
|
||||||
|
* -Dtest.cachingDisabled=false AddressesCachingTest
|
||||||
|
*/
|
||||||
|
public class AddressesCachingTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPositiveCaching() {
|
||||||
|
boolean observedTwoLookups = performLookups(false);
|
||||||
|
if (CACHING_DISABLED) {
|
||||||
|
Assert.assertTrue(observedTwoLookups,
|
||||||
|
"Two positive lookups are expected with caching disabled");
|
||||||
|
} else {
|
||||||
|
Assert.assertFalse(observedTwoLookups,
|
||||||
|
"Only one positive lookup is expected with caching enabled");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNegativeCaching() {
|
||||||
|
boolean observedTwoLookups = performLookups(true);
|
||||||
|
if (CACHING_DISABLED) {
|
||||||
|
Assert.assertTrue(observedTwoLookups,
|
||||||
|
"Two negative lookups are expected with caching disabled");
|
||||||
|
} else {
|
||||||
|
Assert.assertFalse(observedTwoLookups,
|
||||||
|
"Only one negative lookup is expected with caching enabled");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Performs two subsequent positive or negative lookups.
|
||||||
|
* Returns true if the timestamp of this lookups differs,
|
||||||
|
* false otherwise.
|
||||||
|
*/
|
||||||
|
private static boolean performLookups(boolean performNegativeLookup) {
|
||||||
|
doLookup(performNegativeLookup);
|
||||||
|
long firstTimestamp = SimpleResolverProviderImpl.getLastLookupTimestamp();
|
||||||
|
doLookup(performNegativeLookup);
|
||||||
|
long secondTimestamp = SimpleResolverProviderImpl.getLastLookupTimestamp();
|
||||||
|
return firstTimestamp != secondTimestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Performs negative or positive lookup.
|
||||||
|
// It is a test error if UnknownHostException is thrown during positive lookup.
|
||||||
|
// It is a test error if UnknownHostException is NOT thrown during negative lookup.
|
||||||
|
private static void doLookup(boolean performNegativeLookup) {
|
||||||
|
String hostName = performNegativeLookup ? "notKnowHost.org" : "javaTest.org";
|
||||||
|
try {
|
||||||
|
InetAddress.getByName(hostName);
|
||||||
|
if (performNegativeLookup) {
|
||||||
|
Assert.fail("Host name is expected to get unresolved");
|
||||||
|
}
|
||||||
|
} catch (UnknownHostException uhe) {
|
||||||
|
if (!performNegativeLookup) {
|
||||||
|
Assert.fail("Host name is expected to get resolved");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper system property that signals to the test if both negative and positive
|
||||||
|
// caches are disabled.
|
||||||
|
private static final boolean CACHING_DISABLED = Boolean.getBoolean("test.cachingDisabled");
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.net.InetAddress;
|
||||||
|
|
||||||
|
import org.testng.Assert;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import static impl.WithBootstrapResolverUsageProvider.numberOfGetCalls;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
* @summary Test that InetAddress class properly avoids stack-overflow by
|
||||||
|
* correctly tracking the bootstrap resolver instance when
|
||||||
|
* InetAddressResolverProvider.get method uses InetAddress lookup API.
|
||||||
|
* @library providers/bootstrapUsage
|
||||||
|
* @build bootstrap.usage.provider/impl.WithBootstrapResolverUsageProvider
|
||||||
|
* @run testng/othervm BootstrapResolverUsageTest
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class BootstrapResolverUsageTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSuccessfulProviderInstantiationTest() throws Exception {
|
||||||
|
System.err.println(InetAddress.getAllByName(InetAddress.getLocalHost().getHostName()));
|
||||||
|
Assert.assertEquals(numberOfGetCalls, 1,
|
||||||
|
"InetAddressResolverProvider.get was called more than once");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,79 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import org.testng.annotations.BeforeTest;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.net.UnknownHostException;
|
||||||
|
import java.net.spi.InetAddressResolver;
|
||||||
|
|
||||||
|
import static org.testng.Assert.*;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @test
|
||||||
|
* @summary white-box test to check that the built-in resolver
|
||||||
|
* is used by default.
|
||||||
|
* @modules java.base/java.net:open
|
||||||
|
* @run testng/othervm BuiltInResolverTest
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class BuiltInResolverTest {
|
||||||
|
|
||||||
|
private Field builtInResolverField, resolverField;
|
||||||
|
|
||||||
|
@BeforeTest
|
||||||
|
public void beforeTest() throws NoSuchFieldException {
|
||||||
|
Class<InetAddress> inetAddressClass = InetAddress.class;
|
||||||
|
// Needs to happen for InetAddress.resolver to be initialized
|
||||||
|
try {
|
||||||
|
InetAddress.getByName("test");
|
||||||
|
} catch (UnknownHostException e) {
|
||||||
|
// Do nothing, only want to assign resolver
|
||||||
|
}
|
||||||
|
builtInResolverField = inetAddressClass.getDeclaredField("BUILTIN_RESOLVER");
|
||||||
|
builtInResolverField.setAccessible(true);
|
||||||
|
resolverField = inetAddressClass.getDeclaredField("resolver");
|
||||||
|
resolverField.setAccessible(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDefaultNSContext() throws IllegalAccessException {
|
||||||
|
// Test that the resolver used by default is the BUILTIN_RESOLVER
|
||||||
|
Object defaultResolverObject = builtInResolverField.get(InetAddressResolver.class);
|
||||||
|
Object usedResolverObject = resolverField.get(InetAddressResolver.class);
|
||||||
|
|
||||||
|
assertTrue(defaultResolverObject == usedResolverObject);
|
||||||
|
|
||||||
|
String defaultClassName = defaultResolverObject.getClass().getCanonicalName();
|
||||||
|
String currentClassName = usedResolverObject.getClass().getCanonicalName();
|
||||||
|
|
||||||
|
assertNotNull(defaultClassName, "defaultClassName not set");
|
||||||
|
assertNotNull(currentClassName, "currentClassName name not set");
|
||||||
|
|
||||||
|
assertEquals(currentClassName, defaultClassName,
|
||||||
|
"BUILTIN_RESOLVER resolver was not used.");
|
||||||
|
System.err.println("Resolver used by default is the built-in resolver");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import org.testng.Assert;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.net.UnknownHostException;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @test
|
||||||
|
* @summary checks that InetAddress forward lookup API throw UnknownHostException
|
||||||
|
* when resolver returns empty address stream.
|
||||||
|
* @library providers/empty
|
||||||
|
* @build empty.results.provider/impl.EmptyResultsProviderImpl
|
||||||
|
* @run testng/othervm EmptyResultsStreamTest
|
||||||
|
*/
|
||||||
|
public class EmptyResultsStreamTest {
|
||||||
|
|
||||||
|
@Test(expectedExceptions = UnknownHostException.class)
|
||||||
|
public void getAllByNameTest() throws UnknownHostException {
|
||||||
|
System.err.println("getAllByName unexpectedly completed: " +
|
||||||
|
Arrays.deepToString(InetAddress.getAllByName("test1.org")));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expectedExceptions = UnknownHostException.class)
|
||||||
|
public void getByNameTest() throws UnknownHostException {
|
||||||
|
System.err.println("getByName unexpectedly completed: " +
|
||||||
|
InetAddress.getByName("test2.org"));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,2 @@
|
||||||
|
networkaddress.cache.ttl=-1
|
||||||
|
networkaddress.cache.negative.ttl=-1
|
|
@ -0,0 +1,44 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import org.testng.Assert;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import java.net.InetAddress;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
* @summary Test that provider which uses InetAddress APIs during its initialization
|
||||||
|
* wouldn't cause stack overflow and will be successfully installed.
|
||||||
|
* @library providers/recursive
|
||||||
|
* @build recursive.init.provider/impl.InetAddressUsageInGetProviderImpl
|
||||||
|
* @run testng/othervm InetAddressUsageInGetProviderTest
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class InetAddressUsageInGetProviderTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSuccessfulProviderInstantiationTest() throws Exception {
|
||||||
|
System.err.println(InetAddress.getAllByName(InetAddress.getLocalHost().getHostName()));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,172 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import static java.net.spi.InetAddressResolver.LookupPolicy.IPV4;
|
||||||
|
import static java.net.spi.InetAddressResolver.LookupPolicy.IPV4_FIRST;
|
||||||
|
import static java.net.spi.InetAddressResolver.LookupPolicy.IPV6;
|
||||||
|
import static java.net.spi.InetAddressResolver.LookupPolicy.IPV6_FIRST;
|
||||||
|
|
||||||
|
import jdk.test.lib.net.IPSupport;
|
||||||
|
import jdk.test.lib.NetworkConfiguration;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
import org.testng.Assert;
|
||||||
|
import org.testng.SkipException;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @test
|
||||||
|
* @summary Test that platform lookup characteristic value is correctly initialized from
|
||||||
|
* system properties affecting order and type of queried addresses.
|
||||||
|
* @library lib providers/simple /test/lib
|
||||||
|
* @build test.library/testlib.ResolutionRegistry simple.provider/impl.SimpleResolverProviderImpl
|
||||||
|
* jdk.test.lib.net.IPSupport LookupPolicyMappingTest
|
||||||
|
* @run testng/othervm LookupPolicyMappingTest
|
||||||
|
* @run testng/othervm -Djava.net.preferIPv4Stack=true -Djava.net.preferIPv6Addresses=true LookupPolicyMappingTest
|
||||||
|
* @run testng/othervm -Djava.net.preferIPv4Stack=true -Djava.net.preferIPv6Addresses=false LookupPolicyMappingTest
|
||||||
|
* @run testng/othervm -Djava.net.preferIPv4Stack=true -Djava.net.preferIPv6Addresses=system LookupPolicyMappingTest
|
||||||
|
* @run testng/othervm -Djava.net.preferIPv4Stack=true -Djava.net.preferIPv6Addresses LookupPolicyMappingTest
|
||||||
|
* @run testng/othervm -Djava.net.preferIPv4Stack=true LookupPolicyMappingTest
|
||||||
|
* @run testng/othervm -Djava.net.preferIPv4Stack=false -Djava.net.preferIPv6Addresses=true LookupPolicyMappingTest
|
||||||
|
* @run testng/othervm -Djava.net.preferIPv4Stack=false -Djava.net.preferIPv6Addresses=false LookupPolicyMappingTest
|
||||||
|
* @run testng/othervm -Djava.net.preferIPv4Stack=false -Djava.net.preferIPv6Addresses=system LookupPolicyMappingTest
|
||||||
|
* @run testng/othervm -Djava.net.preferIPv4Stack=false -Djava.net.preferIPv6Addresses LookupPolicyMappingTest
|
||||||
|
* @run testng/othervm -Djava.net.preferIPv4Stack=false LookupPolicyMappingTest
|
||||||
|
* @run testng/othervm -Djava.net.preferIPv4Stack -Djava.net.preferIPv6Addresses=true LookupPolicyMappingTest
|
||||||
|
* @run testng/othervm -Djava.net.preferIPv4Stack -Djava.net.preferIPv6Addresses=false LookupPolicyMappingTest
|
||||||
|
* @run testng/othervm -Djava.net.preferIPv4Stack -Djava.net.preferIPv6Addresses=system LookupPolicyMappingTest
|
||||||
|
* @run testng/othervm -Djava.net.preferIPv4Stack -Djava.net.preferIPv6Addresses LookupPolicyMappingTest
|
||||||
|
* @run testng/othervm -Djava.net.preferIPv4Stack LookupPolicyMappingTest
|
||||||
|
* @run testng/othervm -Djava.net.preferIPv6Addresses=true LookupPolicyMappingTest
|
||||||
|
* @run testng/othervm -Djava.net.preferIPv6Addresses=false LookupPolicyMappingTest
|
||||||
|
* @run testng/othervm -Djava.net.preferIPv6Addresses=system LookupPolicyMappingTest
|
||||||
|
* @run testng/othervm -Djava.net.preferIPv6Addresses LookupPolicyMappingTest
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class LookupPolicyMappingTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSystemProperties() throws Exception {
|
||||||
|
|
||||||
|
// Check if platform network configuration matches the test requirements,
|
||||||
|
// if not throw a SkipException
|
||||||
|
checkPlatformNetworkConfiguration();
|
||||||
|
|
||||||
|
System.err.println("javaTest.org resolved to:" + Arrays.deepToString(
|
||||||
|
InetAddress.getAllByName("javaTest.org")));
|
||||||
|
|
||||||
|
// Acquire runtime characteristics from the test NSP
|
||||||
|
int runtimeCharacteristics = impl.SimpleResolverProviderImpl.lastLookupPolicy().characteristics();
|
||||||
|
|
||||||
|
// Calculate expected lookup policy characteristic
|
||||||
|
String preferIPv4Stack = System.getProperty("java.net.preferIPv4Stack");
|
||||||
|
String preferIPv6Addresses = System.getProperty("java.net.preferIPv6Addresses");
|
||||||
|
String expectedResultsKey = calculateMapKey(preferIPv4Stack, preferIPv6Addresses);
|
||||||
|
int expectedCharacteristics = EXPECTED_RESULTS_MAP.get(expectedResultsKey);
|
||||||
|
|
||||||
|
Assert.assertTrue(characteristicsMatch(
|
||||||
|
runtimeCharacteristics, expectedCharacteristics), "Unexpected LookupPolicy observed");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Throws SkipException if platform doesn't support required IP address types
|
||||||
|
static void checkPlatformNetworkConfiguration() {
|
||||||
|
IPSupport.throwSkippedExceptionIfNonOperational();
|
||||||
|
IPSupport.printPlatformSupport(System.err);
|
||||||
|
NetworkConfiguration.printSystemConfiguration(System.err);
|
||||||
|
// If preferIPv4=true and no IPv4 - skip
|
||||||
|
if (IPSupport.preferIPv4Stack()) {
|
||||||
|
if (!IPSupport.hasIPv4()) {
|
||||||
|
throw new SkipException("Skip tests - IPv4 support required");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
record ExpectedResult(String ipv4stack, String ipv6addresses, int characteristics) {
|
||||||
|
ExpectedResult {
|
||||||
|
if (!IPSupport.hasIPv4()) {
|
||||||
|
characteristics = IPV6;
|
||||||
|
} else if (!IPSupport.hasIPv6()) {
|
||||||
|
characteristics = IPV4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String key() {
|
||||||
|
return calculateMapKey(ipv4stack, ipv6addresses);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Each row describes a combination of 'preferIPv4Stack', 'preferIPv6Addresses'
|
||||||
|
* values and the expected characteristic value
|
||||||
|
*/
|
||||||
|
private static List<ExpectedResult> EXPECTED_RESULTS_TABLE = List.of(
|
||||||
|
new ExpectedResult("true", "true", IPV4),
|
||||||
|
new ExpectedResult("true", "false", IPV4),
|
||||||
|
new ExpectedResult("true", "system", IPV4),
|
||||||
|
new ExpectedResult("true", "", IPV4),
|
||||||
|
new ExpectedResult("true", null, IPV4),
|
||||||
|
|
||||||
|
new ExpectedResult("false", "true", IPV4 | IPV6 | IPV6_FIRST),
|
||||||
|
new ExpectedResult("false", "false", IPV4 | IPV6 | IPV4_FIRST),
|
||||||
|
new ExpectedResult("false", "system", IPV4 | IPV6),
|
||||||
|
new ExpectedResult("false", "", IPV4 | IPV6 | IPV4_FIRST),
|
||||||
|
new ExpectedResult("false", null, IPV4 | IPV6 | IPV4_FIRST),
|
||||||
|
|
||||||
|
new ExpectedResult("", "true", IPV4 | IPV6 | IPV6_FIRST),
|
||||||
|
new ExpectedResult("", "false", IPV4 | IPV6 | IPV4_FIRST),
|
||||||
|
new ExpectedResult("", "system", IPV4 | IPV6),
|
||||||
|
new ExpectedResult("", "", IPV4 | IPV6 | IPV4_FIRST),
|
||||||
|
new ExpectedResult("", null, IPV4 | IPV6 | IPV4_FIRST),
|
||||||
|
|
||||||
|
new ExpectedResult(null, "true", IPV4 | IPV6 | IPV6_FIRST),
|
||||||
|
new ExpectedResult(null, "false", IPV4 | IPV6 | IPV4_FIRST),
|
||||||
|
new ExpectedResult(null, "system", IPV4 | IPV6),
|
||||||
|
new ExpectedResult(null, "", IPV4 | IPV6 | IPV4_FIRST),
|
||||||
|
new ExpectedResult(null, null, IPV4 | IPV6 | IPV4_FIRST));
|
||||||
|
|
||||||
|
private static final Map<String, Integer> EXPECTED_RESULTS_MAP = calculateExpectedCharacteristics();
|
||||||
|
|
||||||
|
private static Map<String, Integer> calculateExpectedCharacteristics() {
|
||||||
|
return EXPECTED_RESULTS_TABLE.stream()
|
||||||
|
.collect(Collectors.toUnmodifiableMap(
|
||||||
|
ExpectedResult::key,
|
||||||
|
ExpectedResult::characteristics)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String calculateMapKey(String ipv4stack, String ipv6addresses) {
|
||||||
|
return ipv4stack + "_" + ipv6addresses;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean characteristicsMatch(int actual, int expected) {
|
||||||
|
System.err.printf("Comparing characteristics:%n\tActual: %s%n\tExpected: %s%n",
|
||||||
|
Integer.toBinaryString(actual),
|
||||||
|
Integer.toBinaryString(expected));
|
||||||
|
return (actual & (IPV4 | IPV6 | IPV4_FIRST | IPV6_FIRST)) == expected;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,88 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @test
|
||||||
|
* @summary check if LookupPolicy.of correctly handles valid and illegal
|
||||||
|
* combinations of characteristics bit mask flags.
|
||||||
|
* @run testng LookupPolicyOfTest
|
||||||
|
*/
|
||||||
|
|
||||||
|
import org.testng.annotations.DataProvider;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import java.net.spi.InetAddressResolver.LookupPolicy;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static java.net.spi.InetAddressResolver.LookupPolicy.IPV4;
|
||||||
|
import static java.net.spi.InetAddressResolver.LookupPolicy.IPV4_FIRST;
|
||||||
|
import static java.net.spi.InetAddressResolver.LookupPolicy.IPV6;
|
||||||
|
import static java.net.spi.InetAddressResolver.LookupPolicy.IPV6_FIRST;
|
||||||
|
|
||||||
|
public class LookupPolicyOfTest {
|
||||||
|
|
||||||
|
@Test(dataProvider = "validCharacteristics")
|
||||||
|
public void testValidCharacteristicCombinations(List<Integer> validCombination) {
|
||||||
|
LookupPolicy.of(bitFlagsToCharacteristicsValue(validCombination));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(dataProvider = "invalidCharacteristics", expectedExceptions = IllegalArgumentException.class)
|
||||||
|
public void testInvalidCharacteristicCombinations(List<Integer> invalidCombination) {
|
||||||
|
LookupPolicy.of(bitFlagsToCharacteristicsValue(invalidCombination));
|
||||||
|
}
|
||||||
|
|
||||||
|
@DataProvider(name = "validCharacteristics")
|
||||||
|
public Object[][] validCharacteristicValue() {
|
||||||
|
return new Object[][]{
|
||||||
|
{List.of(IPV4)},
|
||||||
|
{List.of(IPV4, IPV4_FIRST)},
|
||||||
|
{List.of(IPV6)},
|
||||||
|
{List.of(IPV6, IPV6_FIRST)},
|
||||||
|
{List.of(IPV4, IPV6)},
|
||||||
|
{List.of(IPV4, IPV6, IPV4_FIRST)},
|
||||||
|
{List.of(IPV4, IPV6, IPV6_FIRST)},
|
||||||
|
// Custom flag values alongside to address type flags
|
||||||
|
// that could be used by custom providers
|
||||||
|
{List.of(IPV4, IPV6, 0x10)},
|
||||||
|
{List.of(IPV4, IPV6, 0x20)},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@DataProvider(name = "invalidCharacteristics")
|
||||||
|
public Object[][] illegalCharacteristicValue() {
|
||||||
|
return new Object[][]{
|
||||||
|
{List.of()},
|
||||||
|
{List.of(IPV4_FIRST)},
|
||||||
|
{List.of(IPV6_FIRST)},
|
||||||
|
{List.of(IPV4_FIRST, IPV6_FIRST)},
|
||||||
|
{List.of(IPV4, IPV6_FIRST)},
|
||||||
|
{List.of(IPV6, IPV4_FIRST)},
|
||||||
|
{List.of(IPV4, IPV6, IPV4_FIRST, IPV6_FIRST)},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int bitFlagsToCharacteristicsValue(List<Integer> bitFlagsList) {
|
||||||
|
return bitFlagsList.stream()
|
||||||
|
.reduce(0, (flag1, flag2) -> flag1 | flag2);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,2 @@
|
||||||
|
networkaddress.cache.ttl=0
|
||||||
|
networkaddress.cache.negative.ttl=0
|
|
@ -0,0 +1,63 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
import org.testng.Assert;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import static impl.FaultyResolverProviderGetImpl.EXCEPTION_MESSAGE;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @test
|
||||||
|
* @summary Test that InetAddress fast-fails if custom provider fails to
|
||||||
|
* instantiate a resolver.
|
||||||
|
* @library providers/faulty
|
||||||
|
* @build faulty.provider/impl.FaultyResolverProviderGetImpl
|
||||||
|
* @run testng/othervm ProviderGetExceptionTest
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class ProviderGetExceptionTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getByNameExceptionTest() {
|
||||||
|
String hostName = "test.host";
|
||||||
|
System.out.println("Looking up address for the following host name:" + hostName);
|
||||||
|
callInetAddressAndCheckException(() -> InetAddress.getByName(hostName));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getByAddressExceptionTest() {
|
||||||
|
byte[] address = new byte[]{1, 2, 3, 4};
|
||||||
|
System.out.println("Looking up host name for the following address:" + Arrays.toString(address));
|
||||||
|
callInetAddressAndCheckException(() -> InetAddress.getByAddress(address).getHostName());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void callInetAddressAndCheckException(Assert.ThrowingRunnable apiCall) {
|
||||||
|
IllegalArgumentException iae = Assert.expectThrows(IllegalArgumentException.class, apiCall);
|
||||||
|
System.out.println("Got exception of expected type:" + iae);
|
||||||
|
Assert.assertNull(iae.getCause(), "cause is not null");
|
||||||
|
Assert.assertEquals(iae.getMessage(), EXCEPTION_MESSAGE);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,94 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.net.UnknownHostException;
|
||||||
|
|
||||||
|
import impl.ThrowingLookupsProviderImpl;
|
||||||
|
|
||||||
|
import static impl.ThrowingLookupsProviderImpl.RUNTIME_EXCEPTION_MESSAGE;
|
||||||
|
|
||||||
|
import org.testng.Assert;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @test
|
||||||
|
* @summary Test that only UnknownHostException is thrown if resolver
|
||||||
|
* implementation throws RuntimeException during forward or reverse lookup.
|
||||||
|
* @library providers/throwing
|
||||||
|
* @build throwing.lookups.provider/impl.ThrowingLookupsProviderImpl
|
||||||
|
* @run testng/othervm ResolutionWithExceptionTest
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class ResolutionWithExceptionTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getByNameUnknownHostException() {
|
||||||
|
ThrowingLookupsProviderImpl.throwRuntimeException = false;
|
||||||
|
runGetByNameTest();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getByNameRuntimeException() {
|
||||||
|
ThrowingLookupsProviderImpl.throwRuntimeException = true;
|
||||||
|
runGetByNameTest();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getByAddressUnknownHostException() throws UnknownHostException {
|
||||||
|
ThrowingLookupsProviderImpl.throwRuntimeException = false;
|
||||||
|
runGetByAddressTest();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getByAddressRuntimeException() throws UnknownHostException {
|
||||||
|
ThrowingLookupsProviderImpl.throwRuntimeException = true;
|
||||||
|
runGetByAddressTest();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void runGetByNameTest() {
|
||||||
|
// InetAddress.getByName() is expected to throw UnknownHostException in all cases
|
||||||
|
UnknownHostException uhe = Assert.expectThrows(UnknownHostException.class,
|
||||||
|
() -> InetAddress.getByName("doesnt.matter.com"));
|
||||||
|
// If provider is expected to throw RuntimeException - check that UnknownHostException
|
||||||
|
// is set as its cause
|
||||||
|
if (ThrowingLookupsProviderImpl.throwRuntimeException) {
|
||||||
|
Throwable cause = uhe.getCause();
|
||||||
|
if (cause instanceof RuntimeException re) {
|
||||||
|
// Check RuntimeException message
|
||||||
|
Assert.assertEquals(re.getMessage(), RUNTIME_EXCEPTION_MESSAGE,
|
||||||
|
"incorrect exception message");
|
||||||
|
} else {
|
||||||
|
Assert.fail("UnknownHostException cause is not RuntimeException");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void runGetByAddressTest() throws UnknownHostException {
|
||||||
|
// getCanonicalHostName is not expected to throw an exception:
|
||||||
|
// if there is an error during reverse lookup operation the literal IP
|
||||||
|
// address String will be returned.
|
||||||
|
String literalIP = InetAddress.getByAddress(new byte[]{1, 2, 3, 4}).getCanonicalHostName();
|
||||||
|
Assert.assertEquals(literalIP, "1.2.3.4");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,95 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.net.SocketPermission;
|
||||||
|
import java.net.UnknownHostException;
|
||||||
|
import java.security.Permission;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import org.testng.Assert;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @test
|
||||||
|
* @summary Test that resolution of host name requires SocketPermission("resolve", <host name>)
|
||||||
|
* permission when running with security manager and custom resolver provider installed.
|
||||||
|
* @library lib providers/simple
|
||||||
|
* @build test.library/testlib.ResolutionRegistry simple.provider/impl.SimpleResolverProviderImpl
|
||||||
|
* ResolvePermissionTest
|
||||||
|
* @run testng/othervm -Dtest.dataFileName=nonExistentFile -Djava.security.manager=allow
|
||||||
|
* ResolvePermissionTest
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class ResolvePermissionTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void withResolvePermission() throws Exception {
|
||||||
|
testResolvePermission(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void noResolvePermission() throws Exception {
|
||||||
|
testResolvePermission(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("removal")
|
||||||
|
private void testResolvePermission(boolean grantResolvePermission) throws Exception {
|
||||||
|
// Set security manager which grants or denies permission to resolve 'javaTest.org' host
|
||||||
|
var securityManager = new ResolvePermissionTest.TestSecurityManager(grantResolvePermission);
|
||||||
|
try {
|
||||||
|
System.setSecurityManager(securityManager);
|
||||||
|
Class expectedExceptionClass = grantResolvePermission ?
|
||||||
|
UnknownHostException.class : SecurityException.class;
|
||||||
|
var exception = Assert.expectThrows(expectedExceptionClass, () -> InetAddress.getByName("javaTest.org"));
|
||||||
|
LOGGER.info("Got expected exception: " + exception);
|
||||||
|
} finally {
|
||||||
|
System.setSecurityManager(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class TestSecurityManager extends SecurityManager {
|
||||||
|
final boolean allowJavaTestOrgResolve;
|
||||||
|
|
||||||
|
public TestSecurityManager(boolean allowJavaTestOrgResolve) {
|
||||||
|
this.allowJavaTestOrgResolve = allowJavaTestOrgResolve;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void checkPermission(Permission permission) {
|
||||||
|
if (permission instanceof java.net.SocketPermission) {
|
||||||
|
SocketPermission sockPerm = (SocketPermission) permission;
|
||||||
|
if ("resolve".equals(sockPerm.getActions())) {
|
||||||
|
String host = sockPerm.getName();
|
||||||
|
LOGGER.info("Checking 'resolve' SocketPermission: " + permission);
|
||||||
|
if ("javaTest.org".equals(host) && !allowJavaTestOrgResolve) {
|
||||||
|
LOGGER.info("Denying 'resolve' permission for 'javaTest.org'");
|
||||||
|
throw new SecurityException("Access Denied");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final Logger LOGGER = Logger.getLogger(ResolvePermissionTest.class.getName());
|
||||||
|
}
|
|
@ -0,0 +1,62 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import impl.DelegatingProviderImpl;
|
||||||
|
import org.testng.Assert;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.net.UnknownHostException;
|
||||||
|
|
||||||
|
import static impl.DelegatingProviderImpl.changeReverseLookupAddress;
|
||||||
|
import static impl.DelegatingProviderImpl.lastReverseLookupThrowable;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @test
|
||||||
|
* @summary checks delegation of illegal reverse lookup request to the built-in
|
||||||
|
* InetAddressResolver.
|
||||||
|
* @library providers/delegating
|
||||||
|
* @build delegating.provider/impl.DelegatingProviderImpl
|
||||||
|
* @run testng/othervm ReverseLookupDelegationTest
|
||||||
|
*/
|
||||||
|
public class ReverseLookupDelegationTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void delegateHostNameLookupWithWrongByteArray() throws UnknownHostException {
|
||||||
|
// The underlying resolver implementation will ignore the supplied
|
||||||
|
// byte array and will replace it with byte array of incorrect size.
|
||||||
|
changeReverseLookupAddress = true;
|
||||||
|
String canonicalHostName = InetAddress.getByAddress(new byte[]{1, 2, 3, 4}).getCanonicalHostName();
|
||||||
|
// Output canonical host name and the exception thrown by the built-in resolver
|
||||||
|
System.err.println("Canonical host name:" + canonicalHostName);
|
||||||
|
System.err.println("Exception thrown by the built-in resolver:" + lastReverseLookupThrowable);
|
||||||
|
|
||||||
|
// Check that originally supplied byte array was used to construct canonical host name after
|
||||||
|
// failed reverse lookup.
|
||||||
|
Assert.assertEquals("1.2.3.4", canonicalHostName, "unexpected canonical hostname");
|
||||||
|
|
||||||
|
// Check that on a provider side the IllegalArgumentException has been thrown by the built-in resolver
|
||||||
|
Assert.assertTrue(lastReverseLookupThrowable instanceof IllegalArgumentException,
|
||||||
|
"wrong exception type is thrown by the built-in resolver");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,100 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import org.testng.Assert;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.security.Permission;
|
||||||
|
import java.util.ServiceConfigurationError;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @test
|
||||||
|
* @summary Test that instantiation of InetAddressResolverProvider requires "inetAddressResolverProvider"
|
||||||
|
* RuntimePermission when running with security manager.
|
||||||
|
* @library lib providers/simple
|
||||||
|
* @build test.library/testlib.ResolutionRegistry simple.provider/impl.SimpleResolverProviderImpl
|
||||||
|
* RuntimePermissionTest
|
||||||
|
* @run testng/othervm -Djava.security.manager=allow RuntimePermissionTest
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class RuntimePermissionTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void withRuntimePermission() throws Exception {
|
||||||
|
testRuntimePermission(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void noRuntimePermission() throws Exception {
|
||||||
|
testRuntimePermission(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("removal")
|
||||||
|
private void testRuntimePermission(boolean permitInetAddressResolver) throws Exception {
|
||||||
|
// Set security manager which grants all permissions + RuntimePermission("inetAddressResolverProvider")
|
||||||
|
var securityManager = new TestSecurityManager(permitInetAddressResolver);
|
||||||
|
try {
|
||||||
|
System.setSecurityManager(securityManager);
|
||||||
|
if (permitInetAddressResolver) {
|
||||||
|
InetAddress.getByName("javaTest.org");
|
||||||
|
} else {
|
||||||
|
ServiceConfigurationError sce =
|
||||||
|
Assert.expectThrows(ServiceConfigurationError.class,
|
||||||
|
() -> InetAddress.getByName("javaTest.org"));
|
||||||
|
LOGGER.info("Got ServiceConfigurationError: " + sce);
|
||||||
|
Throwable cause = sce.getCause();
|
||||||
|
Assert.assertTrue(cause instanceof SecurityException);
|
||||||
|
Assert.assertTrue(cause.getMessage().contains(RUNTIME_PERMISSION_NAME));
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
System.setSecurityManager(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class TestSecurityManager extends SecurityManager {
|
||||||
|
final boolean permitInetAddressResolver;
|
||||||
|
|
||||||
|
public TestSecurityManager(boolean permitInetAddressResolver) {
|
||||||
|
this.permitInetAddressResolver = permitInetAddressResolver;
|
||||||
|
LOGGER.info("inetAddressResolverProvider permission is " +
|
||||||
|
(permitInetAddressResolver ? "granted" : "not granted"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void checkPermission(Permission permission) {
|
||||||
|
if (permission instanceof RuntimePermission) {
|
||||||
|
LOGGER.info("Checking RuntimePermission: " + permission);
|
||||||
|
if (RUNTIME_PERMISSION_NAME.equals(permission.getName()) && !permitInetAddressResolver) {
|
||||||
|
LOGGER.info("Denying '" + RUNTIME_PERMISSION_NAME + "' permission");
|
||||||
|
throw new SecurityException("Access Denied: " + RUNTIME_PERMISSION_NAME);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final String RUNTIME_PERMISSION_NAME = "inetAddressResolverProvider";
|
||||||
|
private static final Logger LOGGER = Logger.getLogger(RuntimePermissionTest.class.getName());
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
# Test data file for InetAddressResolverProvider SPI tests
|
||||||
|
# Format: <IP address> <Host Name>
|
||||||
|
# If multiple IP addresses are required for host:
|
||||||
|
# multiple lines could be added
|
||||||
|
|
||||||
|
1.2.3.4 javaTest.org
|
||||||
|
[ca:fe:ba:be::1] javaTest.org
|
|
@ -0,0 +1,27 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
module test.library {
|
||||||
|
exports testlib;
|
||||||
|
requires java.logging;
|
||||||
|
}
|
|
@ -0,0 +1,239 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation. Oracle designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Oracle in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package testlib;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.net.UnknownHostException;
|
||||||
|
import java.net.spi.InetAddressResolver.LookupPolicy;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
import java.util.Comparator;
|
||||||
|
|
||||||
|
import static java.net.spi.InetAddressResolver.LookupPolicy.*;
|
||||||
|
|
||||||
|
public class ResolutionRegistry {
|
||||||
|
|
||||||
|
// Map to store hostName -> InetAddress mappings
|
||||||
|
private final Map<String, List<byte[]>> registry;
|
||||||
|
private static final int IPV4_RAW_LEN = 4;
|
||||||
|
private static final int IPV6_RAW_LEN = 16;
|
||||||
|
|
||||||
|
private static final Logger LOGGER = Logger.getLogger(ResolutionRegistry.class.getName());
|
||||||
|
|
||||||
|
public ResolutionRegistry() {
|
||||||
|
|
||||||
|
// Populate registry from test data file
|
||||||
|
String fileName = System.getProperty("test.dataFileName", "addresses.txt");
|
||||||
|
Path addressesFile = Paths.get(System.getProperty("test.src", ".")).resolve(fileName);
|
||||||
|
LOGGER.info("Creating ResolutionRegistry instance from file:" + addressesFile);
|
||||||
|
registry = parseDataFile(addressesFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<String, List<byte[]>> parseDataFile(Path addressesFile) {
|
||||||
|
try {
|
||||||
|
if (addressesFile.toFile().isFile()) {
|
||||||
|
Map<String, List<byte[]>> resReg = new ConcurrentHashMap<>();
|
||||||
|
// Prepare list of hostname/address entries
|
||||||
|
List<String[]> entriesList = Files.readAllLines(addressesFile).stream()
|
||||||
|
.map(String::trim)
|
||||||
|
.filter(Predicate.not(String::isBlank))
|
||||||
|
.filter(s -> !s.startsWith("#"))
|
||||||
|
.map(s -> s.split("\\s+"))
|
||||||
|
.filter(sarray -> sarray.length == 2)
|
||||||
|
.filter(ResolutionRegistry::hasLiteralAddress)
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
// Convert list of entries into registry Map
|
||||||
|
for (var entry : entriesList) {
|
||||||
|
String ipAddress = entry[0].trim();
|
||||||
|
String hostName = entry[1].trim();
|
||||||
|
byte[] addrBytes = toByteArray(ipAddress);
|
||||||
|
if (addrBytes != null) {
|
||||||
|
var list = resReg.containsKey(hostName) ? resReg.get(hostName) : new ArrayList();
|
||||||
|
list.add(addrBytes);
|
||||||
|
if (!resReg.containsKey(hostName)) {
|
||||||
|
resReg.put(hostName, list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resReg.replaceAll((k, v) -> Collections.unmodifiableList(v));
|
||||||
|
// Print constructed registry
|
||||||
|
StringBuilder sb = new StringBuilder("Constructed addresses registry:" + System.lineSeparator());
|
||||||
|
for (var entry : resReg.entrySet()) {
|
||||||
|
sb.append("\t" + entry.getKey() + ": ");
|
||||||
|
for (byte[] addr : entry.getValue()) {
|
||||||
|
sb.append(addressBytesToString(addr) + " ");
|
||||||
|
}
|
||||||
|
sb.append(System.lineSeparator());
|
||||||
|
}
|
||||||
|
LOGGER.info(sb.toString());
|
||||||
|
return resReg;
|
||||||
|
} else {
|
||||||
|
// If file doesn't exist - return empty map
|
||||||
|
return Collections.emptyMap();
|
||||||
|
}
|
||||||
|
} catch (IOException ioException) {
|
||||||
|
// If any problems parsing the file - log a warning and return an empty map
|
||||||
|
LOGGER.log(Level.WARNING, "Error reading data file", ioException);
|
||||||
|
return Collections.emptyMap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Line is not a blank and not a comment
|
||||||
|
private static boolean hasLiteralAddress(String[] lineFields) {
|
||||||
|
String addressString = lineFields[0].trim();
|
||||||
|
return addressString.charAt(0) == '[' ||
|
||||||
|
Character.digit(addressString.charAt(0), 16) != -1 ||
|
||||||
|
(addressString.charAt(0) == ':');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Line is not blank and not comment
|
||||||
|
private static byte[] toByteArray(String addressString) {
|
||||||
|
InetAddress address;
|
||||||
|
// Will reuse InetAddress functionality to parse literal IP address
|
||||||
|
// strings. This call is guarded by 'hasLiteralAddress' method.
|
||||||
|
try {
|
||||||
|
address = InetAddress.getByName(addressString);
|
||||||
|
} catch (UnknownHostException unknownHostException) {
|
||||||
|
LOGGER.warning("Can't parse address string:'" + addressString + "'");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return address.getAddress();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Stream<InetAddress> lookupHost(String host, LookupPolicy lookupPolicy)
|
||||||
|
throws UnknownHostException {
|
||||||
|
LOGGER.info("Looking-up '" + host + "' address");
|
||||||
|
if (!registry.containsKey(host)) {
|
||||||
|
LOGGER.info("Registry doesn't contain addresses for '" + host + "'");
|
||||||
|
throw new UnknownHostException(host);
|
||||||
|
}
|
||||||
|
|
||||||
|
int characteristics = lookupPolicy.characteristics();
|
||||||
|
// Filter IPV4 or IPV6 as needed. Then sort with
|
||||||
|
// comparator for IPV4_FIRST or IPV6_FIRST.
|
||||||
|
return registry.get(host)
|
||||||
|
.stream()
|
||||||
|
.filter(ba -> filterAddressByLookupPolicy(ba, characteristics))
|
||||||
|
.sorted(new AddressOrderPref(characteristics))
|
||||||
|
.map(ba -> constructInetAddress(host, ba))
|
||||||
|
.filter(Objects::nonNull);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean filterAddressByLookupPolicy(byte[] ba, int ch) {
|
||||||
|
// If 0011, return both. If 0001, IPv4. If 0010, IPv6
|
||||||
|
boolean ipv4Flag = (ch & IPV4) == IPV4;
|
||||||
|
boolean ipv6Flag = (ch & IPV6) == IPV6;
|
||||||
|
|
||||||
|
if (ipv4Flag && ipv6Flag)
|
||||||
|
return true; // Return regardless of length
|
||||||
|
else if (ipv4Flag)
|
||||||
|
return (ba.length == IPV4_RAW_LEN);
|
||||||
|
else if (ipv6Flag)
|
||||||
|
return (ba.length == IPV6_RAW_LEN);
|
||||||
|
|
||||||
|
throw new RuntimeException("Lookup policy characteristics were improperly set. " +
|
||||||
|
"Characteristics: " + Integer.toString(ch, 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static InetAddress constructInetAddress(String host, byte[] address) {
|
||||||
|
try {
|
||||||
|
return InetAddress.getByAddress(host, address);
|
||||||
|
} catch (UnknownHostException unknownHostException) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String lookupAddress(byte[] addressBytes) {
|
||||||
|
for (var entry : registry.entrySet()) {
|
||||||
|
if (entry.getValue()
|
||||||
|
.stream()
|
||||||
|
.filter(ba -> Arrays.equals(ba, addressBytes))
|
||||||
|
.findAny()
|
||||||
|
.isPresent()) {
|
||||||
|
return entry.getKey();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return InetAddress.getByAddress(addressBytes).getHostAddress();
|
||||||
|
} catch (UnknownHostException unknownHostException) {
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean containsAddressMapping(InetAddress address) {
|
||||||
|
String hostName = address.getHostName();
|
||||||
|
if (registry.containsKey(hostName)) {
|
||||||
|
var mappedBytes = registry.get(address.getHostName());
|
||||||
|
for (byte[] mappedAddr : mappedBytes) {
|
||||||
|
if (Arrays.equals(mappedAddr, address.getAddress())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String addressBytesToString(byte[] bytes) {
|
||||||
|
try {
|
||||||
|
return InetAddress.getByAddress(bytes).toString();
|
||||||
|
} catch (UnknownHostException unknownHostException) {
|
||||||
|
return Arrays.toString(bytes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class AddressOrderPref implements Comparator<byte[]> {
|
||||||
|
|
||||||
|
private final int ch;
|
||||||
|
|
||||||
|
AddressOrderPref(int ch) {
|
||||||
|
this.ch = ch;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compare(byte[] o1, byte[] o2) {
|
||||||
|
// Compares based on address length, 4 bytes for IPv4,
|
||||||
|
// 16 bytes for IPv6.
|
||||||
|
return ((ch & IPV4_FIRST) == IPV4_FIRST) ?
|
||||||
|
Integer.compare(o1.length, o2.length) :
|
||||||
|
Integer.compare(o2.length, o1.length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,76 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package impl;
|
||||||
|
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.net.UnknownHostException;
|
||||||
|
import java.net.spi.InetAddressResolver;
|
||||||
|
import java.net.spi.InetAddressResolverProvider;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
public class WithBootstrapResolverUsageProvider extends InetAddressResolverProvider {
|
||||||
|
|
||||||
|
public static volatile long numberOfGetCalls;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InetAddressResolver get(Configuration configuration) {
|
||||||
|
numberOfGetCalls++;
|
||||||
|
System.out.println("The following provider will be used by current test:" +
|
||||||
|
this.getClass().getCanonicalName());
|
||||||
|
System.out.println("InetAddressResolverProvider::get() called " + numberOfGetCalls + " times");
|
||||||
|
|
||||||
|
// We use different names to avoid InetAddress-level caching
|
||||||
|
doLookup("foo" + numberOfGetCalls + ".A.org");
|
||||||
|
|
||||||
|
// We need second call to test how InetAddress internals maintain reference to a bootstrap resolver
|
||||||
|
doLookup("foo" + numberOfGetCalls + ".B.org");
|
||||||
|
|
||||||
|
return new InetAddressResolver() {
|
||||||
|
@Override
|
||||||
|
public Stream<InetAddress> lookupByName(String host, LookupPolicy lookupPolicy)
|
||||||
|
throws UnknownHostException {
|
||||||
|
return Stream.of(InetAddress.getByAddress(host, new byte[]{127, 0, 2, 1}));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String lookupByAddress(byte[] addr) throws UnknownHostException {
|
||||||
|
return configuration.builtinResolver().lookupByAddress(addr);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Perform an InetAddress resolution lookup operation
|
||||||
|
private static void doLookup(String hostName) {
|
||||||
|
try {
|
||||||
|
InetAddress.getByName(hostName);
|
||||||
|
} catch (UnknownHostException e) {
|
||||||
|
// Ignore UHE since the bootstrap resolver is used here
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String name() {
|
||||||
|
return "WithBootstrapResolverUsageProvider";
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.net.spi.InetAddressResolverProvider;
|
||||||
|
|
||||||
|
module bootstrap.usage.provider {
|
||||||
|
exports impl;
|
||||||
|
requires java.logging;
|
||||||
|
provides InetAddressResolverProvider with impl.WithBootstrapResolverUsageProvider;
|
||||||
|
}
|
|
@ -0,0 +1,68 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package impl;
|
||||||
|
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.net.UnknownHostException;
|
||||||
|
import java.net.spi.InetAddressResolver;
|
||||||
|
import java.net.spi.InetAddressResolverProvider;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
public class DelegatingProviderImpl extends InetAddressResolverProvider {
|
||||||
|
|
||||||
|
public static volatile boolean changeReverseLookupAddress;
|
||||||
|
public static volatile Throwable lastReverseLookupThrowable;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InetAddressResolver get(Configuration configuration) {
|
||||||
|
System.out.println("The following provider will be used by current test:" +
|
||||||
|
this.getClass().getCanonicalName());
|
||||||
|
return new InetAddressResolver() {
|
||||||
|
@Override
|
||||||
|
public Stream<InetAddress> lookupByName(String host, LookupPolicy lookupPolicy) throws UnknownHostException {
|
||||||
|
return configuration.builtinResolver().lookupByName(host, lookupPolicy);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String lookupByAddress(byte[] addr) throws UnknownHostException {
|
||||||
|
try {
|
||||||
|
if (!changeReverseLookupAddress) {
|
||||||
|
return configuration.builtinResolver().lookupByAddress(addr);
|
||||||
|
} else {
|
||||||
|
// Deliberately supply address bytes array with wrong size
|
||||||
|
return configuration.builtinResolver().lookupByAddress(new byte[]{1, 2, 3});
|
||||||
|
}
|
||||||
|
} catch (Throwable t) {
|
||||||
|
lastReverseLookupThrowable = t;
|
||||||
|
throw t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String name() {
|
||||||
|
return "DelegatingProvider";
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.net.spi.InetAddressResolverProvider;
|
||||||
|
|
||||||
|
module delegating.provider {
|
||||||
|
exports impl;
|
||||||
|
provides InetAddressResolverProvider with impl.DelegatingProviderImpl;
|
||||||
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package impl;
|
||||||
|
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.net.UnknownHostException;
|
||||||
|
import java.net.spi.InetAddressResolver;
|
||||||
|
import java.net.spi.InetAddressResolverProvider;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
public class EmptyResultsProviderImpl extends InetAddressResolverProvider {
|
||||||
|
@Override
|
||||||
|
public InetAddressResolver get(Configuration configuration) {
|
||||||
|
System.out.println("The following provider will be used by current test:" +
|
||||||
|
this.getClass().getCanonicalName());
|
||||||
|
|
||||||
|
return new InetAddressResolver() {
|
||||||
|
@Override
|
||||||
|
public Stream<InetAddress> lookupByName(String host, LookupPolicy lookupPolicy)
|
||||||
|
throws UnknownHostException {
|
||||||
|
return Stream.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String lookupByAddress(byte[] addr) throws UnknownHostException {
|
||||||
|
return configuration.builtinResolver().lookupByAddress(addr);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String name() {
|
||||||
|
return "EmptyForwardLookupResultsProvider";
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.net.spi.InetAddressResolverProvider;
|
||||||
|
|
||||||
|
module empty.results.provider {
|
||||||
|
exports impl;
|
||||||
|
provides InetAddressResolverProvider with impl.EmptyResultsProviderImpl;
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package impl;
|
||||||
|
|
||||||
|
import java.net.spi.InetAddressResolverProvider;
|
||||||
|
import java.net.spi.InetAddressResolver;
|
||||||
|
|
||||||
|
public class FaultyResolverProviderGetImpl extends InetAddressResolverProvider {
|
||||||
|
public static final String EXCEPTION_MESSAGE = "This provider provides nothing";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InetAddressResolver get(Configuration configuration) {
|
||||||
|
System.out.println("The following provider will be used by current test:" + this.getClass().getCanonicalName());
|
||||||
|
throw new IllegalArgumentException(EXCEPTION_MESSAGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String name() {
|
||||||
|
return "faultyInetAddressResolverGet";
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.net.spi.InetAddressResolverProvider;
|
||||||
|
|
||||||
|
module faulty.provider {
|
||||||
|
exports impl;
|
||||||
|
requires java.logging;
|
||||||
|
provides InetAddressResolverProvider with impl.FaultyResolverProviderGetImpl;
|
||||||
|
}
|
|
@ -0,0 +1,63 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package impl;
|
||||||
|
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.net.UnknownHostException;
|
||||||
|
import java.net.spi.InetAddressResolver;
|
||||||
|
import java.net.spi.InetAddressResolverProvider;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
public class InetAddressUsageInGetProviderImpl extends InetAddressResolverProvider {
|
||||||
|
@Override
|
||||||
|
public InetAddressResolver get(Configuration configuration) {
|
||||||
|
System.out.println("The following provider will be used by current test:" + this.getClass().getCanonicalName());
|
||||||
|
String localHostName;
|
||||||
|
try {
|
||||||
|
localHostName = InetAddress.getLocalHost().getHostName();
|
||||||
|
} catch (UnknownHostException e) {
|
||||||
|
throw new RuntimeException("Provider failed to initialize");
|
||||||
|
}
|
||||||
|
return new InetAddressResolver() {
|
||||||
|
@Override
|
||||||
|
public Stream<InetAddress> lookupByName(String host, LookupPolicy lookupPolicy) throws UnknownHostException {
|
||||||
|
if (host.equals(localHostName)) {
|
||||||
|
return configuration.builtinResolver().lookupByName(host, lookupPolicy);
|
||||||
|
} else {
|
||||||
|
throw new UnknownHostException(host);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String lookupByAddress(byte[] addr) throws UnknownHostException {
|
||||||
|
return configuration.builtinResolver().lookupByAddress(addr);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String name() {
|
||||||
|
return "ProviderWithInetAddressUsageInGet";
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.net.spi.InetAddressResolverProvider;
|
||||||
|
|
||||||
|
module recursive.init.provider {
|
||||||
|
exports impl;
|
||||||
|
requires java.logging;
|
||||||
|
provides InetAddressResolverProvider with impl.InetAddressUsageInGetProviderImpl;
|
||||||
|
}
|
|
@ -0,0 +1,91 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package impl;
|
||||||
|
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.net.UnknownHostException;
|
||||||
|
import java.net.spi.InetAddressResolver;
|
||||||
|
import java.net.spi.InetAddressResolver.LookupPolicy;
|
||||||
|
import java.net.spi.InetAddressResolverProvider;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import testlib.ResolutionRegistry;
|
||||||
|
|
||||||
|
public class SimpleResolverProviderImpl extends InetAddressResolverProvider {
|
||||||
|
|
||||||
|
public static ResolutionRegistry registry = new ResolutionRegistry();
|
||||||
|
private static List<LookupPolicy> LOOKUP_HISTORY = Collections.synchronizedList(new ArrayList<>());
|
||||||
|
private static volatile long LAST_LOOKUP_TIMESTAMP;
|
||||||
|
private static Logger LOGGER = Logger.getLogger(SimpleResolverProviderImpl.class.getName());
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InetAddressResolver get(Configuration configuration) {
|
||||||
|
System.out.println("The following provider will be used by current test:" + this.getClass().getCanonicalName());
|
||||||
|
return new InetAddressResolver() {
|
||||||
|
@Override
|
||||||
|
public Stream<InetAddress> lookupByName(String host, LookupPolicy lookupPolicy) throws UnknownHostException {
|
||||||
|
LOGGER.info("Looking-up addresses for '" + host + "'. Lookup characteristics:" +
|
||||||
|
Integer.toString(lookupPolicy.characteristics(), 2));
|
||||||
|
LOOKUP_HISTORY.add(lookupPolicy);
|
||||||
|
LAST_LOOKUP_TIMESTAMP = System.nanoTime();
|
||||||
|
return registry.lookupHost(host, lookupPolicy);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String lookupByAddress(byte[] addr) throws UnknownHostException {
|
||||||
|
LOGGER.info("Looking host name for the following address:" + ResolutionRegistry.addressBytesToString(addr));
|
||||||
|
return registry.lookupAddress(addr);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Utility methods
|
||||||
|
public static LookupPolicy lastLookupPolicy() {
|
||||||
|
return lookupPolicyHistory(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static long getLastLookupTimestamp() {
|
||||||
|
return LAST_LOOKUP_TIMESTAMP;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static LookupPolicy lookupPolicyHistory(int position) {
|
||||||
|
if (LOOKUP_HISTORY.isEmpty()) {
|
||||||
|
throw new RuntimeException("No registered lookup policies");
|
||||||
|
}
|
||||||
|
if (position >= LOOKUP_HISTORY.size()) {
|
||||||
|
throw new IllegalArgumentException("No element available with provided position");
|
||||||
|
}
|
||||||
|
return LOOKUP_HISTORY.get(LOOKUP_HISTORY.size() - position - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String name() {
|
||||||
|
return "simpleInetAddressResolver";
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.net.spi.InetAddressResolverProvider;
|
||||||
|
|
||||||
|
module simple.provider {
|
||||||
|
exports impl;
|
||||||
|
requires java.logging;
|
||||||
|
requires test.library;
|
||||||
|
provides InetAddressResolverProvider with impl.SimpleResolverProviderImpl;
|
||||||
|
}
|
|
@ -0,0 +1,73 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package impl;
|
||||||
|
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.net.UnknownHostException;
|
||||||
|
import java.net.spi.InetAddressResolver;
|
||||||
|
import java.net.spi.InetAddressResolverProvider;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
public class ThrowingLookupsProviderImpl extends InetAddressResolverProvider {
|
||||||
|
@Override
|
||||||
|
public InetAddressResolver get(Configuration configuration) {
|
||||||
|
System.out.println("The following provider will be used by current test:" +
|
||||||
|
this.getClass().getCanonicalName());
|
||||||
|
|
||||||
|
return new InetAddressResolver() {
|
||||||
|
@Override
|
||||||
|
public Stream<InetAddress> lookupByName(String host, LookupPolicy lookupPolicy)
|
||||||
|
throws UnknownHostException {
|
||||||
|
if (throwRuntimeException) {
|
||||||
|
System.err.println(name()+" forward lookup: throwing RuntimeException");
|
||||||
|
throw new RuntimeException(RUNTIME_EXCEPTION_MESSAGE);
|
||||||
|
} else {
|
||||||
|
System.err.println(name()+" forward lookup: throwing UnknownHostException");
|
||||||
|
throw new UnknownHostException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String lookupByAddress(byte[] addr) throws UnknownHostException {
|
||||||
|
if (throwRuntimeException) {
|
||||||
|
System.err.println(name()+" reverse lookup: throwing RuntimeException");
|
||||||
|
throw new RuntimeException(RUNTIME_EXCEPTION_MESSAGE);
|
||||||
|
} else {
|
||||||
|
System.err.println(name()+" reverse lookup: throwing UnknownHostException");
|
||||||
|
throw new UnknownHostException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String name() {
|
||||||
|
return "ThrowingLookupsProvider";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Indicates if provider need to throw RuntimeException for forward and reverse lookup operations.
|
||||||
|
// If it is set to 'false' then UnknownHostException will thrown for each operation.
|
||||||
|
public static volatile boolean throwRuntimeException;
|
||||||
|
public static final String RUNTIME_EXCEPTION_MESSAGE = "This provider only throws exceptions";
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.net.spi.InetAddressResolverProvider;
|
||||||
|
|
||||||
|
module throwing.lookups.provider {
|
||||||
|
exports impl;
|
||||||
|
provides InetAddressResolverProvider with impl.ThrowingLookupsProviderImpl;
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.net.InetAddress;
|
||||||
|
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import static org.testng.Assert.assertThrows;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @test
|
||||||
|
* @summary Test that InetAddressResolverProvider implementation can be installed to a class path.
|
||||||
|
* @library ../../lib
|
||||||
|
* @build test.library/testlib.ResolutionRegistry ClasspathResolverProviderImpl
|
||||||
|
* @run testng/othervm ClasspathProviderTest
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class ClasspathProviderTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testResolution() throws Exception {
|
||||||
|
InetAddress inetAddress = InetAddress.getByName("classpath-provider-test.org");
|
||||||
|
System.err.println("Resolved address:" + inetAddress);
|
||||||
|
|
||||||
|
if (!ClasspathResolverProviderImpl.registry.containsAddressMapping(inetAddress)) {
|
||||||
|
throw new RuntimeException("InetAddressResolverProvider was not properly installed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,67 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.net.UnknownHostException;
|
||||||
|
import java.net.spi.InetAddressResolverProvider;
|
||||||
|
import java.net.spi.InetAddressResolver;
|
||||||
|
import java.net.spi.InetAddressResolver.LookupPolicy;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import testlib.ResolutionRegistry;
|
||||||
|
|
||||||
|
public class ClasspathResolverProviderImpl extends InetAddressResolverProvider {
|
||||||
|
|
||||||
|
public static ResolutionRegistry registry = new ResolutionRegistry();
|
||||||
|
private static List<LookupPolicy> LOOKUP_HISTORY = Collections.synchronizedList(new ArrayList<>());
|
||||||
|
private static Logger LOGGER = Logger.getLogger(ClasspathResolverProviderImpl.class.getName());
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InetAddressResolver get(Configuration configuration) {
|
||||||
|
System.out.println("The following provider will be used by current test:" + this.getClass().getCanonicalName());
|
||||||
|
return new InetAddressResolver() {
|
||||||
|
@Override
|
||||||
|
public Stream<InetAddress> lookupByName(String host, LookupPolicy lookupPolicy) throws UnknownHostException {
|
||||||
|
LOGGER.info("Looking-up addresses for '" + host + "'. Lookup characteristics:" +
|
||||||
|
Integer.toString(lookupPolicy.characteristics(), 2));
|
||||||
|
LOOKUP_HISTORY.add(lookupPolicy);
|
||||||
|
return registry.lookupHost(host, lookupPolicy);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String lookupByAddress(byte[] addr) throws UnknownHostException {
|
||||||
|
LOGGER.info("Looking host name for the following address:" + ResolutionRegistry.addressBytesToString(addr));
|
||||||
|
return registry.lookupAddress(addr);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String name() {
|
||||||
|
return "classpathINSP";
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
ClasspathResolverProviderImpl
|
|
@ -0,0 +1,7 @@
|
||||||
|
# Test data file for classpath origin type tests.
|
||||||
|
# Format: <IP address> <Host Name>
|
||||||
|
# If multiple IP addresses are required for host:
|
||||||
|
# multiple lines could be added
|
||||||
|
|
||||||
|
1.2.3.4 classpath-provider-test.org
|
||||||
|
[ca:fe:ba:be::1] classpath-provider-test.org
|
|
@ -0,0 +1,49 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.net.InetAddress;
|
||||||
|
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @test
|
||||||
|
* @summary Test that implementation of InetAddressResolverProvider can be installed to a module path.
|
||||||
|
* @library ../../lib ../../providers/simple
|
||||||
|
* @build test.library/testlib.ResolutionRegistry simple.provider/impl.SimpleResolverProviderImpl
|
||||||
|
* ModularProviderTest
|
||||||
|
* @run testng/othervm ModularProviderTest
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
public class ModularProviderTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testResolution() throws Exception {
|
||||||
|
InetAddress inetAddress = InetAddress.getByName("modular-provider-test.org");
|
||||||
|
System.err.println("Resolved address:" + inetAddress);
|
||||||
|
|
||||||
|
if (!impl.SimpleResolverProviderImpl.registry.containsAddressMapping(inetAddress)) {
|
||||||
|
throw new RuntimeException("InetAddressResolverProvider was not properly installed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
# Test data file for tests in modularTests directory
|
||||||
|
# Format: <IP address> <Host Name>
|
||||||
|
# If multiple IP addresses are required for host:
|
||||||
|
# multiple lines could be added
|
||||||
|
|
||||||
|
1.2.3.4 modular-provider-test.org
|
||||||
|
[ca:fe:ba:be::1] modular-provider-test.org
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -27,11 +27,12 @@ import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.PrintStream;
|
import java.io.PrintStream;
|
||||||
import java.io.UncheckedIOException;
|
import java.io.UncheckedIOException;
|
||||||
|
import java.net.Inet4Address;
|
||||||
|
import java.net.Inet6Address;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.ProtocolFamily;
|
||||||
import java.net.Socket;
|
import java.net.StandardProtocolFamily;
|
||||||
import java.net.SocketException;
|
import java.nio.channels.SocketChannel;
|
||||||
import java.net.UnknownHostException;
|
|
||||||
import java.security.AccessController;
|
import java.security.AccessController;
|
||||||
import java.security.PrivilegedActionException;
|
import java.security.PrivilegedActionException;
|
||||||
import java.security.PrivilegedExceptionAction;
|
import java.security.PrivilegedExceptionAction;
|
||||||
|
@ -49,19 +50,8 @@ public class IPSupport {
|
||||||
private static final boolean preferIPv6Addresses;
|
private static final boolean preferIPv6Addresses;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
try {
|
hasIPv4 = runPrivilegedAction(() -> isSupported(Inet4Address.class));
|
||||||
InetAddress loopbackIPv4 = InetAddress.getByAddress(
|
hasIPv6 = runPrivilegedAction(() -> isSupported(Inet6Address.class));
|
||||||
new byte[] {0x7F, 0x00, 0x00, 0x01});
|
|
||||||
|
|
||||||
InetAddress loopbackIPv6 = InetAddress.getByAddress(
|
|
||||||
new byte[] {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01});
|
|
||||||
|
|
||||||
hasIPv4 = runPrivilegedAction(() -> hasAddress(loopbackIPv4));
|
|
||||||
hasIPv6 = runPrivilegedAction(() -> hasAddress(loopbackIPv6));
|
|
||||||
} catch (UnknownHostException e) {
|
|
||||||
throw new AssertionError(e);
|
|
||||||
}
|
|
||||||
preferIPv4Stack = runPrivilegedAction(() -> Boolean.parseBoolean(
|
preferIPv4Stack = runPrivilegedAction(() -> Boolean.parseBoolean(
|
||||||
System.getProperty("java.net.preferIPv4Stack")));
|
System.getProperty("java.net.preferIPv4Stack")));
|
||||||
preferIPv6Addresses = runPrivilegedAction(() -> Boolean.parseBoolean(
|
preferIPv6Addresses = runPrivilegedAction(() -> Boolean.parseBoolean(
|
||||||
|
@ -71,14 +61,13 @@ public class IPSupport {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean hasAddress(InetAddress address) {
|
private static boolean isSupported(Class<? extends InetAddress> addressType) {
|
||||||
try (Socket socket = new Socket()) {
|
ProtocolFamily family = addressType == Inet4Address.class ?
|
||||||
socket.bind(new InetSocketAddress(address, 0));
|
StandardProtocolFamily.INET : StandardProtocolFamily.INET6;
|
||||||
|
try (var sc = SocketChannel.open(family)) {
|
||||||
return true;
|
return true;
|
||||||
} catch (SocketException se) {
|
} catch (IOException | UnsupportedOperationException ex) {
|
||||||
return false;
|
return false;
|
||||||
} catch (IOException e) {
|
|
||||||
throw new UncheckedIOException(e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue