View Javadoc

1   /*
2    * Copyright 2015 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  package io.netty.resolver;
17  
18  import io.netty.util.concurrent.EventExecutor;
19  import io.netty.util.concurrent.Future;
20  import io.netty.util.concurrent.FutureListener;
21  import io.netty.util.concurrent.Promise;
22  
23  import java.util.Arrays;
24  import java.util.List;
25  
26  import static io.netty.util.internal.ObjectUtil.*;
27  
28  /**
29   * A composite [email protected] SimpleNameResolver} that resolves a host name against a sequence of [email protected] NameResolver}s.
30   *
31   * In case of a failure, only the last one will be reported.
32   */
33  public final class CompositeNameResolver<T> extends SimpleNameResolver<T> {
34  
35      private final NameResolver<T>[] resolvers;
36  
37      /**
38       * @param executor the [email protected] EventExecutor} which is used to notify the listeners of the [email protected] Future} returned
39       *                 by [email protected] #resolve(String)}
40       * @param resolvers the [email protected] NameResolver}s to be tried sequentially
41       */
42      public CompositeNameResolver(EventExecutor executor, NameResolver<T>... resolvers) {
43          super(executor);
44          checkNotNull(resolvers, "resolvers");
45          for (int i = 0; i < resolvers.length; i++) {
46              if (resolvers[i] == null) {
47                  throw new NullPointerException("resolvers[" + i + ']');
48              }
49          }
50          if (resolvers.length < 2) {
51              throw new IllegalArgumentException("resolvers: " + Arrays.asList(resolvers) +
52                      " (expected: at least 2 resolvers)");
53          }
54          this.resolvers = resolvers.clone();
55      }
56  
57      @Override
58      protected void doResolve(String inetHost, Promise<T> promise) throws Exception {
59          doResolveRec(inetHost, promise, 0, null);
60      }
61  
62      private void doResolveRec(final String inetHost,
63                                final Promise<T> promise,
64                                final int resolverIndex,
65                                Throwable lastFailure) throws Exception {
66          if (resolverIndex >= resolvers.length) {
67              promise.setFailure(lastFailure);
68          } else {
69              NameResolver resolver = resolvers[resolverIndex];
70              resolver.resolve(inetHost).addListener(new FutureListener<T>() {
71                  @Override
72                  public void operationComplete(Future<T> future) throws Exception {
73                      if (future.isSuccess()) {
74                          promise.setSuccess(future.getNow());
75                      } else {
76                          doResolveRec(inetHost, promise, resolverIndex + 1, future.cause());
77                      }
78                  }
79              });
80          }
81      }
82  
83      @Override
84      protected void doResolveAll(String inetHost, Promise<List<T>> promise) throws Exception {
85          doResolveAllRec(inetHost, promise, 0, null);
86      }
87  
88      private void doResolveAllRec(final String inetHost,
89                                final Promise<List<T>> promise,
90                                final int resolverIndex,
91                                Throwable lastFailure) throws Exception {
92          if (resolverIndex >= resolvers.length) {
93              promise.setFailure(lastFailure);
94          } else {
95              NameResolver resolver = resolvers[resolverIndex];
96              resolver.resolveAll(inetHost).addListener(new FutureListener<List<T>>() {
97                  @Override
98                  public void operationComplete(Future<List<T>> future) throws Exception {
99                      if (future.isSuccess()) {
100                         promise.setSuccess(future.getNow());
101                     } else {
102                         doResolveAllRec(inetHost, promise, resolverIndex + 1, future.cause());
103                     }
104                 }
105             });
106         }
107     }
108 }