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  * A resolver provider class is a factory for custom implementations of {@linkplain
 35  * InetAddressResolver resolvers} which define operations for looking-up (resolving) host names
 36  * and IP addresses.
 37  * Resolver providers are <a href="{@docRoot}/java.base/java/net/InetAddress.html#resolverProviders">
 38  * discovered</a> by {@link InetAddress} to instantiate and install a <i>system-wide resolver</i>.
 39  * <p>
 40  * A resolver provider is a concrete subclass of this class that has a zero-argument
 41  * constructor and implements the abstract methods specified below.
 42  * <p>
 43  * Resolver providers are located using the {@link ServiceLoader} facility, as specified by
 44  * {@link InetAddress}.
 45  */
 46 public abstract class InetAddressResolverProvider {
 47 
 48     /**
 49      * Initialise and return the {@link InetAddressResolver} provided by
 50      * this provider. This method is called by {@link InetAddress} when
 51      * <a href="{@docRoot}/java.base/java/net/InetAddress.html#resolverProviders">installing</a>
 52      * the system-wide resolver implementation.
 53      * <p>
 54      * Any error or exception thrown by this method is considered as
 55      * a failure of {@code InetAddressResolver} instantiation and will be propagated to
 56      * the calling thread.
 57      * @param configuration a {@link Configuration} instance containing platform built-in address
 58      *                     resolution configuration.
 59      * @return the resolver provided by this provider
 60      */
 61     public abstract InetAddressResolver get(Configuration configuration);
 62 
 63     /**
 64      * Returns the name of this provider.
 65      *
 66      * @return the resolver provider name
 67      */
 68     public abstract String name();
 69 
 70     /**
 71      * The {@code RuntimePermission("inetAddressResolverProvider")} is
 72      * necessary to subclass and instantiate the {@code InetAddressResolverProvider} class,
 73      * as well as to obtain resolver from an instance of that class,
 74      * and it is also required to obtain the operating system name resolution configurations.
 75      */
 76     private static final RuntimePermission INET_ADDRESS_RESOLVER_PERMISSION =
 77             new RuntimePermission("inetAddressResolverProvider");
 78 
 79     /**
 80      * Creates a new instance of {@code InetAddressResolverProvider}.
 81      *
 82      * @throws SecurityException if a security manager is present and its
 83      *                           {@code checkPermission} method doesn't allow the
 84      *                           {@code RuntimePermission("inetAddressResolverProvider")}.
 85      * @implNote It is recommended that an {@code InetAddressResolverProvider} service
 86      * implementation does not perform any heavy initialization in its
 87      * constructor, in order to avoid possible risks of deadlock or class
 88      * loading cycles during the instantiation of the service provider.
 89      */
 90     protected InetAddressResolverProvider() {
 91         this(checkPermission());
 92     }
 93 
 94     private InetAddressResolverProvider(Void unused) {
 95     }
 96 
 97     @SuppressWarnings("removal")
 98     private static Void checkPermission() {
 99         final SecurityManager sm = System.getSecurityManager();
100         if (sm != null) {
101             sm.checkPermission(INET_ADDRESS_RESOLVER_PERMISSION);
102         }
103         return null;
104     }
105 
106     /**
107      * A {@code Configuration} interface is supplied to the
108      * {@link InetAddressResolverProvider#get(Configuration)} method when installing a
109      * system-wide custom resolver implementation.
110      * The custom resolver implementation can then delegate to the built-in resolver
111      * provided by this interface if it needs to.
112      */
113     public sealed interface Configuration permits ResolverProviderConfiguration {
114         /**
115          * Returns platform built-in {@linkplain InetAddressResolver resolver}.
116          *
117          * @return the JDK built-in resolver.
118          */
119         InetAddressResolver builtinResolver();
120 
121         /**
122          * Reads the localhost name from the system configuration.
123          *
124          * @return the localhost name.
125          */
126         String lookupLocalHostName();
127     }
128 }