/*
 * Copyright 2015 The Netty Project
 *
 * The Netty Project licenses this file to you under the Apache License,
 * version 2.0 (the "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at:
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations
 * under the License.
 */

package io.netty.resolver;

import io.netty.util.concurrent.EventExecutor;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.Promise;
import io.netty.util.internal.TypeParameterMatcher;
import io.netty.util.internal.UnstableApi;

import java.net.SocketAddress;
import java.nio.channels.UnsupportedAddressTypeException;
import java.util.Collections;
import java.util.List;

import static io.netty.util.internal.ObjectUtil.checkNotNull;

A skeletal AddressResolver implementation.
/** * A skeletal {@link AddressResolver} implementation. */
@UnstableApi public abstract class AbstractAddressResolver<T extends SocketAddress> implements AddressResolver<T> { private final EventExecutor executor; private final TypeParameterMatcher matcher;
Params:
/** * @param executor the {@link EventExecutor} which is used to notify the listeners of the {@link Future} returned * by {@link #resolve(SocketAddress)} */
protected AbstractAddressResolver(EventExecutor executor) { this.executor = checkNotNull(executor, "executor"); matcher = TypeParameterMatcher.find(this, AbstractAddressResolver.class, "T"); }
Params:
/** * @param executor the {@link EventExecutor} which is used to notify the listeners of the {@link Future} returned * by {@link #resolve(SocketAddress)} * @param addressType the type of the {@link SocketAddress} supported by this resolver */
protected AbstractAddressResolver(EventExecutor executor, Class<? extends T> addressType) { this.executor = checkNotNull(executor, "executor"); matcher = TypeParameterMatcher.get(addressType); }
Returns the EventExecutor which is used to notify the listeners of the Future returned by resolve(SocketAddress).
/** * Returns the {@link EventExecutor} which is used to notify the listeners of the {@link Future} returned * by {@link #resolve(SocketAddress)}. */
protected EventExecutor executor() { return executor; } @Override public boolean isSupported(SocketAddress address) { return matcher.match(address); } @Override public final boolean isResolved(SocketAddress address) { if (!isSupported(address)) { throw new UnsupportedAddressTypeException(); } @SuppressWarnings("unchecked") final T castAddress = (T) address; return doIsResolved(castAddress); }
Invoked by isResolved(SocketAddress) to check if the specified address has been resolved already.
/** * Invoked by {@link #isResolved(SocketAddress)} to check if the specified {@code address} has been resolved * already. */
protected abstract boolean doIsResolved(T address); @Override public final Future<T> resolve(SocketAddress address) { if (!isSupported(checkNotNull(address, "address"))) { // Address type not supported by the resolver return executor().newFailedFuture(new UnsupportedAddressTypeException()); } if (isResolved(address)) { // Resolved already; no need to perform a lookup @SuppressWarnings("unchecked") final T cast = (T) address; return executor.newSucceededFuture(cast); } try { @SuppressWarnings("unchecked") final T cast = (T) address; final Promise<T> promise = executor().newPromise(); doResolve(cast, promise); return promise; } catch (Exception e) { return executor().newFailedFuture(e); } } @Override public final Future<T> resolve(SocketAddress address, Promise<T> promise) { checkNotNull(address, "address"); checkNotNull(promise, "promise"); if (!isSupported(address)) { // Address type not supported by the resolver return promise.setFailure(new UnsupportedAddressTypeException()); } if (isResolved(address)) { // Resolved already; no need to perform a lookup @SuppressWarnings("unchecked") final T cast = (T) address; return promise.setSuccess(cast); } try { @SuppressWarnings("unchecked") final T cast = (T) address; doResolve(cast, promise); return promise; } catch (Exception e) { return promise.setFailure(e); } } @Override public final Future<List<T>> resolveAll(SocketAddress address) { if (!isSupported(checkNotNull(address, "address"))) { // Address type not supported by the resolver return executor().newFailedFuture(new UnsupportedAddressTypeException()); } if (isResolved(address)) { // Resolved already; no need to perform a lookup @SuppressWarnings("unchecked") final T cast = (T) address; return executor.newSucceededFuture(Collections.singletonList(cast)); } try { @SuppressWarnings("unchecked") final T cast = (T) address; final Promise<List<T>> promise = executor().newPromise(); doResolveAll(cast, promise); return promise; } catch (Exception e) { return executor().newFailedFuture(e); } } @Override public final Future<List<T>> resolveAll(SocketAddress address, Promise<List<T>> promise) { checkNotNull(address, "address"); checkNotNull(promise, "promise"); if (!isSupported(address)) { // Address type not supported by the resolver return promise.setFailure(new UnsupportedAddressTypeException()); } if (isResolved(address)) { // Resolved already; no need to perform a lookup @SuppressWarnings("unchecked") final T cast = (T) address; return promise.setSuccess(Collections.singletonList(cast)); } try { @SuppressWarnings("unchecked") final T cast = (T) address; doResolveAll(cast, promise); return promise; } catch (Exception e) { return promise.setFailure(e); } }
Invoked by resolve(SocketAddress) to perform the actual name resolution.
/** * Invoked by {@link #resolve(SocketAddress)} to perform the actual name * resolution. */
protected abstract void doResolve(T unresolvedAddress, Promise<T> promise) throws Exception;
Invoked by resolveAll(SocketAddress) to perform the actual name resolution.
/** * Invoked by {@link #resolveAll(SocketAddress)} to perform the actual name * resolution. */
protected abstract void doResolveAll(T unresolvedAddress, Promise<List<T>> promise) throws Exception; @Override public void close() { } }