View Javadoc
1   /*
2    * Copyright 2014 The Netty Project
3    *
4    * The Netty Project licenses this file to you under the Apache License,
5    * version 2.0 (the "License"); you may not use this file except in compliance
6    * with the License. You may obtain a copy of the License at:
7    *
8    *   http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13   * License for the specific language governing permissions and limitations
14   * under the License.
15   */
16  
17  package io.netty.resolver.dns;
18  
19  import io.netty.util.internal.UnstableApi;
20  
21  import java.net.InetSocketAddress;
22  import java.util.ArrayList;
23  import java.util.Collection;
24  import java.util.List;
25  
26  /**
27   * Provides an infinite sequence of DNS server addresses to {@link DnsNameResolver}.
28   */
29  @UnstableApi
30  @SuppressWarnings("IteratorNextCanNotThrowNoSuchElementException")
31  public abstract class DnsServerAddresses {
32      /**
33       * @deprecated Use {@link DefaultDnsServerAddressStreamProvider#defaultAddressList()}.
34       * <p>
35       * Returns the list of the system DNS server addresses. If it failed to retrieve the list of the system DNS server
36       * addresses from the environment, it will return {@code "8.8.8.8"} and {@code "8.8.4.4"}, the addresses of the
37       * Google public DNS servers.
38       */
39      @Deprecated
40      public static List<InetSocketAddress> defaultAddressList() {
41          return DefaultDnsServerAddressStreamProvider.defaultAddressList();
42      }
43  
44      /**
45       * @deprecated Use {@link DefaultDnsServerAddressStreamProvider#defaultAddresses()}.
46       * <p>
47       * Returns the {@link DnsServerAddresses} that yields the system DNS server addresses sequentially. If it failed to
48       * retrieve the list of the system DNS server addresses from the environment, it will use {@code "8.8.8.8"} and
49       * {@code "8.8.4.4"}, the addresses of the Google public DNS servers.
50       * <p>
51       * This method has the same effect with the following code:
52       * <pre>
53       * DnsServerAddresses.sequential(DnsServerAddresses.defaultAddressList());
54       * </pre>
55       * </p>
56       */
57      @Deprecated
58      public static DnsServerAddresses defaultAddresses() {
59          return DefaultDnsServerAddressStreamProvider.defaultAddresses();
60      }
61  
62      /**
63       * Returns the {@link DnsServerAddresses} that yields the specified {@code addresses} sequentially. Once the
64       * last address is yielded, it will start again from the first address.
65       */
66      public static DnsServerAddresses sequential(Iterable<? extends InetSocketAddress> addresses) {
67          return sequential0(sanitize(addresses));
68      }
69  
70      /**
71       * Returns the {@link DnsServerAddresses} that yields the specified {@code addresses} sequentially. Once the
72       * last address is yielded, it will start again from the first address.
73       */
74      public static DnsServerAddresses sequential(InetSocketAddress... addresses) {
75          return sequential0(sanitize(addresses));
76      }
77  
78      private static DnsServerAddresses sequential0(final List<InetSocketAddress> addresses) {
79          if (addresses.size() == 1) {
80              return singleton(addresses.get(0));
81          }
82  
83          return new DefaultDnsServerAddresses("sequential", addresses) {
84              @Override
85              public DnsServerAddressStream stream() {
86                  return new SequentialDnsServerAddressStream(addresses, 0);
87              }
88          };
89      }
90  
91      /**
92       * Returns the {@link DnsServerAddresses} that yields the specified {@code address} in a shuffled order. Once all
93       * addresses are yielded, the addresses are shuffled again.
94       */
95      public static DnsServerAddresses shuffled(Iterable<? extends InetSocketAddress> addresses) {
96          return shuffled0(sanitize(addresses));
97      }
98  
99      /**
100      * Returns the {@link DnsServerAddresses} that yields the specified {@code addresses} in a shuffled order. Once all
101      * addresses are yielded, the addresses are shuffled again.
102      */
103     public static DnsServerAddresses shuffled(InetSocketAddress... addresses) {
104         return shuffled0(sanitize(addresses));
105     }
106 
107     private static DnsServerAddresses shuffled0(List<InetSocketAddress> addresses) {
108         if (addresses.size() == 1) {
109             return singleton(addresses.get(0));
110         }
111 
112         return new DefaultDnsServerAddresses("shuffled", addresses) {
113             @Override
114             public DnsServerAddressStream stream() {
115                 return new ShuffledDnsServerAddressStream(addresses);
116             }
117         };
118     }
119 
120     /**
121      * Returns the {@link DnsServerAddresses} that yields the specified {@code addresses} in a rotational sequential
122      * order. It is similar to {@link #sequential(Iterable)}, but each {@link DnsServerAddressStream} starts from
123      * a different starting point.  For example, the first {@link #stream()} will start from the first address, the
124      * second one will start from the second address, and so on.
125      */
126     public static DnsServerAddresses rotational(Iterable<? extends InetSocketAddress> addresses) {
127         return rotational0(sanitize(addresses));
128     }
129 
130     /**
131      * Returns the {@link DnsServerAddresses} that yields the specified {@code addresses} in a rotational sequential
132      * order. It is similar to {@link #sequential(Iterable)}, but each {@link DnsServerAddressStream} starts from
133      * a different starting point.  For example, the first {@link #stream()} will start from the first address, the
134      * second one will start from the second address, and so on.
135      */
136     public static DnsServerAddresses rotational(InetSocketAddress... addresses) {
137         return rotational0(sanitize(addresses));
138     }
139 
140     private static DnsServerAddresses rotational0(List<InetSocketAddress> addresses) {
141         if (addresses.size() == 1) {
142             return singleton(addresses.get(0));
143         }
144 
145         return new RotationalDnsServerAddresses(addresses);
146     }
147 
148     /**
149      * Returns the {@link DnsServerAddresses} that yields only a single {@code address}.
150      */
151     public static DnsServerAddresses singleton(final InetSocketAddress address) {
152         if (address == null) {
153             throw new NullPointerException("address");
154         }
155         if (address.isUnresolved()) {
156             throw new IllegalArgumentException("cannot use an unresolved DNS server address: " + address);
157         }
158 
159         return new SingletonDnsServerAddresses(address);
160     }
161 
162     private static List<InetSocketAddress> sanitize(Iterable<? extends InetSocketAddress> addresses) {
163         if (addresses == null) {
164             throw new NullPointerException("addresses");
165         }
166 
167         final List<InetSocketAddress> list;
168         if (addresses instanceof Collection) {
169             list = new ArrayList<InetSocketAddress>(((Collection<?>) addresses).size());
170         } else {
171             list = new ArrayList<InetSocketAddress>(4);
172         }
173 
174         for (InetSocketAddress a : addresses) {
175             if (a == null) {
176                 break;
177             }
178             if (a.isUnresolved()) {
179                 throw new IllegalArgumentException("cannot use an unresolved DNS server address: " + a);
180             }
181             list.add(a);
182         }
183 
184         if (list.isEmpty()) {
185             throw new IllegalArgumentException("empty addresses");
186         }
187 
188         return list;
189     }
190 
191     private static List<InetSocketAddress> sanitize(InetSocketAddress[] addresses) {
192         if (addresses == null) {
193             throw new NullPointerException("addresses");
194         }
195 
196         List<InetSocketAddress> list = new ArrayList<InetSocketAddress>(addresses.length);
197         for (InetSocketAddress a: addresses) {
198             if (a == null) {
199                 break;
200             }
201             if (a.isUnresolved()) {
202                 throw new IllegalArgumentException("cannot use an unresolved DNS server address: " + a);
203             }
204             list.add(a);
205         }
206 
207         if (list.isEmpty()) {
208             return DefaultDnsServerAddressStreamProvider.defaultAddressList();
209         }
210 
211         return list;
212     }
213 
214     /**
215      * Starts a new infinite stream of DNS server addresses. This method is invoked by {@link DnsNameResolver} on every
216      * uncached {@link DnsNameResolver#resolve(String)}or {@link DnsNameResolver#resolveAll(String)}.
217      */
218     public abstract DnsServerAddressStream stream();
219 }