1 /* 2 * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package java.net.spi; 27 28 import sun.net.ResolverProviderConfiguration; 29 30 import java.net.InetAddress; 31 import java.util.ServiceLoader; 32 33 /** 34 * Service-provider class for {@linkplain InetAddressResolver InetAddress resolvers}. 35 * 36 * <p> A resolver provider is a factory for custom implementations of {@linkplain 37 * InetAddressResolver InetAddress resolvers}. A resolver defines operations for 38 * looking up (resolving) host names and IP addresses. 39 * <p>A resolver provider is a concrete subclass of this class that has a 40 * zero-argument constructor and implements the abstract methods specified below. 41 * 42 * <p> A given invocation of the Java virtual machine maintains a single 43 * system-wide resolver instance, which is used by 44 * <a href="{@docRoot}/java.base/java/net/InetAddress.html#host-name-resolution"> 45 * InetAddress</a>. It is set after the VM is fully initialized and when an 46 * invocation of a method in {@link InetAddress} class triggers the first lookup 47 * operation. 48 * 49 * <p id="system-wide-resolver"> A resolver provider is located and loaded by 50 * {@link InetAddress} to create the system-wide resolver as follows: 51 * <ol> 52 * <li>The {@link ServiceLoader} mechanism is used to locate an 53 * {@code InetAddressResolverProvider} using the 54 * system class loader. The order in which providers are located is 55 * {@linkplain ServiceLoader#load(java.lang.Class, java.lang.ClassLoader) 56 * implementation specific}. 57 * The first provider found will be used to instantiate the 58 * {@link InetAddressResolver InetAddressResolver} by invoking the 59 * {@link InetAddressResolverProvider#get(InetAddressResolverProvider.Configuration)} 60 * method. The returned {@code InetAddressResolver} will be set as the 61 * system-wide resolver. 62 * <li>If the previous step fails to find any resolver provider the 63 * <a href="{@docRoot}/java.base/java/net/InetAddress.html#built-in-resolver"> 64 * built-in resolver</a> will be set as the system-wide resolver. 65 * </ol> 66 * 67 * <p> If instantiating a custom resolver from a provider discovered in 68 * step 1 throws an error or exception, the system-wide resolver will not be 69 * set and the error or exception will be propagated to the calling thread. 70 * Otherwise, any lookup operation will be performed using the 71 * <i>system-wide resolver</i>. 72 * 73 * @implNote {@link InetAddress} will use the <i>built-in resolver</i> for any lookup operation 74 * that might occur before the VM is fully booted. 75 * 76 * @since 18 77 */ 78 public abstract class InetAddressResolverProvider { 79 80 /** 81 * Initialize and return an {@link InetAddressResolver} provided by 82 * this provider. This method is called by {@link InetAddress} when 83 * <a href="#system-wide-resolver">installing</a> 84 * the system-wide resolver implementation. 85 * 86 * <p> Any error or exception thrown by this method is considered as 87 * a failure of {@code InetAddressResolver} instantiation and will be propagated to 88 * the calling thread. 89 * @param configuration a {@link Configuration} instance containing platform built-in address 90 * resolution configuration. 91 * @return the resolver provided by this provider 92 */ 93 public abstract InetAddressResolver get(Configuration configuration); 94 95 /** 96 * {@return the name of this provider, or {@code null} if unnamed} 97 */ 98 public abstract String name(); 99 100 /** 101 * The {@code RuntimePermission("inetAddressResolverProvider")} is 102 * necessary to subclass and instantiate the {@code InetAddressResolverProvider} class, 103 * as well as to obtain resolver from an instance of that class, 104 * and it is also required to obtain the operating system name resolution configurations. 105 */ 106 private static final RuntimePermission INET_ADDRESS_RESOLVER_PERMISSION = 107 new RuntimePermission("inetAddressResolverProvider"); 108 109 /** 110 * Creates a new instance of {@code InetAddressResolverProvider}. 111 * 112 * @throws SecurityException if a security manager is present and its 113 * {@code checkPermission} method doesn't allow the 114 * {@code RuntimePermission("inetAddressResolverProvider")}. 115 * @implNote It is recommended that an {@code InetAddressResolverProvider} service 116 * implementation initialization should be as simple as possible, in order to avoid 117 * possible risks of deadlock or class loading cycles during the instantiation of the 118 * service provider. 119 */ 120 protected InetAddressResolverProvider() { 121 this(checkPermission()); 122 } 123 124 private InetAddressResolverProvider(Void unused) { 125 } 126 127 @SuppressWarnings("removal") 128 private static Void checkPermission() { 129 final SecurityManager sm = System.getSecurityManager(); 130 if (sm != null) { 131 sm.checkPermission(INET_ADDRESS_RESOLVER_PERMISSION); 132 } 133 return null; 134 } 135 136 /** 137 * A {@code Configuration} object is supplied to the 138 * {@link InetAddressResolverProvider#get(Configuration)} method when 139 * setting the system-wide resolver. 140 * A resolver implementation can then delegate to the built-in resolver 141 * provided by this interface if it needs to. 142 * 143 * @since 18 144 */ 145 public sealed interface Configuration permits ResolverProviderConfiguration { 146 /** 147 * Returns the built-in {@linkplain InetAddressResolver resolver}. 148 * 149 * @return the JDK built-in resolver. 150 */ 151 InetAddressResolver builtinResolver(); 152 153 /** 154 * Reads the localhost name from the system configuration. 155 * 156 * @return the localhost name. 157 */ 158 String lookupLocalHostName(); 159 } 160 }