Java tutorial
/* * Copyright 2012 CoreMedia AG * * This file is part of Joala. * * Joala is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Joala is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Joala. If not, see <http://www.gnu.org/licenses/>. */ package net.joala.dns; import com.google.common.base.Function; import com.google.common.base.MoreObjects; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.collect.Sets; import org.xbill.DNS.Address; import org.xbill.DNS.Name; import org.xbill.DNS.TextParseException; import javax.annotation.Nonnull; import javax.annotation.Nullable; import javax.annotation.concurrent.ThreadSafe; import java.net.InetAddress; import java.net.UnknownHostException; import java.util.Arrays; import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Set; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; import static java.lang.String.format; /** * <p> * This store is responsible for overriding calls for resolving host names. It allows you to manually * add and remove known hosts during your tests. * </p> * * @deprecated Will be removed soon. */ @SuppressWarnings("deprecation") @Deprecated @ThreadSafe public final class NameStore { /** * A logger using System-PrintStreams. */ private static final SystemLogger LOG = SystemLogger.getLogger(NameStore.class); /** * Mapper to map a string to an {@code InetAddress}. */ private static final Function<String, InetAddress> STRING_TO_INET_ADDRESS = new String2InetAddress(); private static final String CHECK_NAME_MUST_NOT_BE_NULL = "Name must not be null."; private static final String CHECK_ADDRESSES_MUST_NOT_BE_NULL = "Addresses must not be null."; private static final String CHECK_ADDRESSES_MUST_NOT_BE_EMPTY = "Addresses must not be empty."; /** * Store which contains the hosts to map to specified internet addresses. */ private final Map<Name, Set<InetAddress>> store = Maps.newHashMap(); /** * Singleton instance. */ private static final NameStore OUR_INSTANCE = new NameStore(); /** * Use {@link #nameStore()} to get an instance. */ private NameStore() { } /** * <p> * Get singleton instance of name store. * </p> * * @return name store instance */ @Nonnull public static NameStore nameStore() { return OUR_INSTANCE; } /** * <p> * Register name with the given addresses. * If name is already registered for some inet addresses * the given addresses will be added to the known ones. * </p> * * @param name host name representation * @param addresses list of addresses to register for name */ private void register(@Nonnull final Name name, @Nonnull final Collection<InetAddress> addresses) { checkNotNull(name, CHECK_NAME_MUST_NOT_BE_NULL); final String errorMessage = CHECK_ADDRESSES_MUST_NOT_BE_NULL; checkNotNull(addresses, errorMessage); checkArgument(!addresses.isEmpty(), CHECK_ADDRESSES_MUST_NOT_BE_EMPTY); synchronized (store) { if (store.containsKey(name)) { final Set<InetAddress> set = store.get(name); set.addAll(addresses); LOG.info(format("Updated registration for %s to %s.", name, store.get(name))); } else { store.put(name, Sets.newHashSet(addresses)); LOG.info(format("Registered %s with %s.", name, store.get(name))); } } } /** * <p> * Register name with the given addresses. * If name is already registered for some inet addresses * the given addresses will be added to the known ones. * </p> * * @param name host name * @param addresses list of addresses to register for name */ public void register(@Nonnull final String name, @Nonnull final InetAddress... addresses) { checkNotNull(name, CHECK_NAME_MUST_NOT_BE_NULL); try { register(Name.fromString(name), Arrays.asList(addresses)); } catch (TextParseException e) { throw new IllegalArgumentException("Unable to parse name.", e); } } /** * <p> * Register name with the given addresses. * If name is already registered for some inet addresses * the given addresses will be added to the known ones. * </p> * * @param name host name * @param addresses list of addresses to register for name */ public void register(@Nonnull final String name, @Nonnull final String... addresses) { checkNotNull(name, CHECK_NAME_MUST_NOT_BE_NULL); final List<InetAddress> inetAddresses = Lists.transform(Arrays.asList(addresses), STRING_TO_INET_ADDRESS); try { register(Name.fromString(name), inetAddresses); } catch (TextParseException e) { throw new IllegalArgumentException("Unable to parse name.", e); } } /** * <p> * Unregister name with all its addresses. Requires DNS cache to be disabled. * </p> * * @param name host name */ public void unregister(@Nonnull final String name) { checkNotNull(name, CHECK_NAME_MUST_NOT_BE_NULL); try { synchronized (store) { if (null != store.remove(Name.fromString(name))) { LOG.info(format("Unregistered %s.", name)); } } } catch (TextParseException e) { throw new IllegalArgumentException("Invalid name.", e); } } /** * Clear the complete name store. Recommended before and after running the tests * in order to prevent that tests influence each other. */ public void clear() { synchronized (store) { store.clear(); LOG.info("Cleared name store."); } } /** * <p> * Try to find a host name in the store based on the given address. * </p> * * @param inetAddress the internet address to search the host name for * @return the name found – or {@code null}, if the internet address could not be found in store */ @Nullable Name reverseLookup(@Nullable final InetAddress inetAddress) { synchronized (store) { final Set<Map.Entry<Name, Set<InetAddress>>> entries = store.entrySet(); for (final Map.Entry<Name, Set<InetAddress>> entry : entries) { if (entry.getValue().contains(inetAddress)) { return entry.getKey(); } } } return null; } /** * <p> * Lookup registered inet addresses for given name. * </p> * * @param name the host name * @return the inet addresses found for the given name; empty list if none */ @Nonnull InetAddress[] lookup(@Nonnull final String name) { checkNotNull(name, CHECK_NAME_MUST_NOT_BE_NULL); final Name someName; try { someName = Name.fromString(name); } catch (TextParseException e) { throw new IllegalArgumentException("Unable to parse name.", e); } return lookup(someName); } /** * <p> * Lookup registered inet addresses for given name. * </p> * * @param name the host name * @return the inet addresses found for the given name; empty list if none */ @Nonnull InetAddress[] lookup(@Nonnull final Name name) { checkNotNull(name, CHECK_NAME_MUST_NOT_BE_NULL); synchronized (store) { if (store.containsKey(name)) { LOG.info(format("Succeeded to lookup %s.", name)); return Iterables.toArray(store.get(name), InetAddress.class); } } LOG.info(format("Failed to lookup %s.", name)); return new InetAddress[0]; } /** * <p> * Mapper to create InetAddresses from Strings. * </p> */ private static class String2InetAddress implements Function<String, InetAddress> { @Override @Nonnull public InetAddress apply(final String input) { try { checkNotNull(input, "Address must not be null."); return Address.getByAddress(input); } catch (UnknownHostException e) { throw new IllegalArgumentException("Failed to create InetAddress.", e); } } } @Override public String toString() { return MoreObjects.toStringHelper(this).add("store", store).toString(); } }