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 java.lang.annotation.Native;
 29 import java.net.InetAddress;
 30 import java.net.UnknownHostException;
 31 import java.util.stream.Stream;
 32 
 33 /**
 34  * This interface defines operations for looking up host names and IP addresses.
 35  * {@link InetAddress} delegates all lookup operations to the <i>system-wide
 36  * resolver</i>.
 37  *
 38  * <p> The <i>system-wide resolver</i> can be customized by
 39  * <a href="InetAddressResolverProvider.html#system-wide-resolver">
 40  * deploying an implementation</a> of {@link InetAddressResolverProvider}.
 41  *
 42  * @since 18
 43  */
 44 public interface InetAddressResolver {
 45 
 46     /**
 47      * Given the name of a host, returns a stream of IP addresses of the requested
 48      * address family associated with a provided hostname.
 49      *
 50      * <p> {@code host} should be a machine name, such as "{@code www.example.com}",
 51      * not a textual representation of its IP address. No validation is performed on
 52      * the given {@code host} name: if a textual representation is supplied, the name
 53      * resolution is likely to fail and {@link UnknownHostException} may be thrown.
 54      *
 55      * <p> The address family type and addresses order are specified by the
 56      * {@code LookupPolicy} instance. Lookup operation characteristics could be
 57      * acquired with {@link LookupPolicy#characteristics()}.
 58      * If {@link InetAddressResolver.LookupPolicy#IPV4} and
 59      * {@link InetAddressResolver.LookupPolicy#IPV6} characteristics provided then this
 60      * method returns addresses of both IPV4 and IPV6 families.
 61      *
 62      * @param host         the specified hostname
 63      * @param lookupPolicy the address lookup policy
 64      * @return a stream of IP addresses for the requested host
 65      * @throws NullPointerException if either parameter is {@code null}
 66      * @throws UnknownHostException if no IP address for the {@code host} could be found
 67      * @see LookupPolicy
 68      */
 69     Stream<InetAddress> lookupByName(String host, LookupPolicy lookupPolicy) throws UnknownHostException;
 70 
 71     /**
 72      * Lookup the host name corresponding to the raw IP address provided.
 73      *
 74      * <p> {@code addr} argument is in network byte order: the highest order byte of the address
 75      * is in {@code addr[0]}.
 76      *
 77      * <p> IPv4 address byte array must be 4 bytes long and IPv6 byte array
 78      * must be 16 bytes long.
 79      *
 80      * @param addr byte array representing a raw IP address
 81      * @return {@code String} representing the host name mapping
 82      * @throws UnknownHostException     if no host name is found for the specified IP address
 83      * @throws IllegalArgumentException if the length of the provided byte array doesn't correspond
 84      *                                  to a valid IP address length
 85      * @throws NullPointerException     if addr is {@code null}
 86      */
 87     String lookupByAddress(byte[] addr) throws UnknownHostException;
 88 
 89     /**
 90      * A {@code LookupPolicy} object describes characteristics that can be applied to a lookup operation.
 91      * In particular, it is used to specify the ordering and which filtering should be performed when
 92      * {@linkplain InetAddressResolver#lookupByName(String, LookupPolicy) looking up host addresses}.
 93      *
 94      * <p> The default platform-wide lookup policy is constructed by consulting
 95      * <a href="doc-files/net-properties.html#Ipv4IPv6">System Properties</a> which affect
 96      * how IPv4 and IPv6 addresses are returned.
 97      *
 98      * @since 18
 99      */
100     final class LookupPolicy {
101 
102         /**
103          * Characteristic value signifying if IPv4 addresses need to be queried during lookup.
104          */
105         @Native
106         public static final int IPV4 = 1 << 0;
107 
108         /**
109          * Characteristic value signifying if IPv6 addresses need to be queried during lookup.
110          */
111         @Native
112         public static final int IPV6 = 1 << 1;
113 
114         /**
115          * Characteristic value signifying if IPv4 addresses should be returned
116          * first by {@code InetAddressResolver}.
117          */
118         @Native
119         public static final int IPV4_FIRST = 1 << 2;
120 
121         /**
122          * Characteristic value signifying if IPv6 addresses should be returned
123          * first by {@code InetAddressResolver}.
124          */
125         @Native
126         public static final int IPV6_FIRST = 1 << 3;
127 
128         private final int characteristics;
129 
130         private LookupPolicy(int characteristics) {
131             this.characteristics = characteristics;
132         }
133 
134         /**
135          * This factory method creates a {@link LookupPolicy LookupPolicy} instance with
136          * the given {@code characteristics} value.
137          *
138          * <p> The {@code characteristics} value is an integer bit mask which defines
139          * parameters of a forward lookup operation. These parameters define at least:
140          * <ul>
141          *     <li>the family type of the returned addresses</li>
142          *     <li>the order in which a {@linkplain InetAddressResolver resolver}
143          *         implementation should return its results</li>
144          * </ul>
145          *
146          * <p> To request addresses of specific family types the following bit masks can be combined:
147          * <ul>
148          *     <li>{@link LookupPolicy#IPV4}: to request IPv4 addresses</li>
149          *     <li>{@link LookupPolicy#IPV6}: to request IPv6 addresses</li>
150          * </ul>
151          * <br>It is an error if neither {@link LookupPolicy#IPV4} or {@link LookupPolicy#IPV6} are set.
152          *
153          * <p> To request a specific ordering of the results:
154          * <ul>
155          *     <li>{@link LookupPolicy#IPV4_FIRST}: return IPv4 addresses before any IPv6 address</li>
156          *     <li>{@link LookupPolicy#IPV6_FIRST}: return IPv6 addresses before any IPv4 address</li>
157          * </ul>
158          * <br>If neither {@link LookupPolicy#IPV4_FIRST} or {@link LookupPolicy#IPV6_FIRST} are set it
159          * implies <a href="{@docRoot}/java.base/java/net/doc-files/net-properties.html#Ipv4IPv6">"system"</a>
160          * order of addresses.
161          * It is an error to request both {@link LookupPolicy#IPV4_FIRST} and {@link LookupPolicy#IPV6_FIRST}.
162          *
163          * @param characteristics a value which represents the set of lookup characteristics
164          * @return an instance of {@code InetAddressResolver.LookupPolicy}
165          * @throws IllegalArgumentException if an illegal characteristics bit mask is provided
166          * @see InetAddressResolver#lookupByName(String, LookupPolicy)
167          */
168         public static LookupPolicy of(int characteristics) {
169             // At least one type of addresses should be requested
170             if ((characteristics & IPV4) == 0 && (characteristics & IPV6) == 0) {
171                 throw new IllegalArgumentException("No address type specified");
172             }
173 
174             // Requested order of addresses couldn't be determined
175             if ((characteristics & IPV4_FIRST) != 0 && (characteristics & IPV6_FIRST) != 0) {
176                 throw new IllegalArgumentException("Addresses order cannot be determined");
177             }
178 
179             // If IPv4 addresses requested to be returned first then they should be requested too
180             if ((characteristics & IPV4_FIRST) != 0 && (characteristics & IPV4) == 0) {
181                 throw new IllegalArgumentException("Addresses order and type do not match");
182             }
183 
184             // If IPv6 addresses requested to be returned first then they should be requested too
185             if ((characteristics & IPV6_FIRST) != 0 && (characteristics & IPV6) == 0) {
186                 throw new IllegalArgumentException("Addresses order and type do not match");
187             }
188             return new LookupPolicy(characteristics);
189         }
190 
191         /**
192          * Returns the set of characteristics of this lookup policy.
193          *
194          * @return a characteristics value
195          * @see InetAddressResolver#lookupByName(String, LookupPolicy)
196          */
197         public int characteristics() {
198             return characteristics;
199         }
200     }
201 }