13742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman// Copyright 2003-2005 Arthur van Hoff Rick Blair
23742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman// Licensed under Apache License version 2.0
33742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman// Original license LGPL
43742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
53742d9db8b6edb10627b0f89336cca5249f1d15aManuel Romanpackage javax.jmdns.impl;
63742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
73742d9db8b6edb10627b0f89336cca5249f1d15aManuel Romanimport java.util.AbstractMap;
83742d9db8b6edb10627b0f89336cca5249f1d15aManuel Romanimport java.util.ArrayList;
93742d9db8b6edb10627b0f89336cca5249f1d15aManuel Romanimport java.util.Collection;
103742d9db8b6edb10627b0f89336cca5249f1d15aManuel Romanimport java.util.Collections;
113742d9db8b6edb10627b0f89336cca5249f1d15aManuel Romanimport java.util.HashSet;
123742d9db8b6edb10627b0f89336cca5249f1d15aManuel Romanimport java.util.Iterator;
133742d9db8b6edb10627b0f89336cca5249f1d15aManuel Romanimport java.util.List;
143742d9db8b6edb10627b0f89336cca5249f1d15aManuel Romanimport java.util.Map;
153742d9db8b6edb10627b0f89336cca5249f1d15aManuel Romanimport java.util.Set;
163742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
173742d9db8b6edb10627b0f89336cca5249f1d15aManuel Romanimport javax.jmdns.impl.constants.DNSRecordClass;
183742d9db8b6edb10627b0f89336cca5249f1d15aManuel Romanimport javax.jmdns.impl.constants.DNSRecordType;
193742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
203742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman/**
213742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman * A table of DNS entries. This is a map table which can handle multiple entries with the same name.
223742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman * <p/>
233742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman * Storing multiple entries with the same name is implemented using a linked list. This is hidden from the user and can change in later implementation.
243742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman * <p/>
253742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman * Here's how to iterate over all entries:
263742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman *
273742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman * <pre>
283742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman *       for (Iterator i=dnscache.allValues().iterator(); i.hasNext(); ) {
293742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman *             DNSEntry entry = i.next();
303742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman *             ...do something with entry...
313742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman *       }
323742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman * </pre>
333742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman * <p/>
343742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman * And here's how to iterate over all entries having a given name:
353742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman *
363742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman * <pre>
373742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman *       for (Iterator i=dnscache.getDNSEntryList(name).iterator(); i.hasNext(); ) {
383742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman *             DNSEntry entry = i.next();
393742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman *           ...do something with entry...
403742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman *       }
413742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman * </pre>
423742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman *
433742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman * @author Arthur van Hoff, Werner Randelshofer, Rick Blair, Pierre Frisch
443742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman */
453742d9db8b6edb10627b0f89336cca5249f1d15aManuel Romanpublic class DNSCache extends AbstractMap<String, List<? extends DNSEntry>> {
463742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
473742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    // private static Logger logger = Logger.getLogger(DNSCache.class.getName());
483742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
493742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    private transient Set<Map.Entry<String, List<? extends DNSEntry>>> _entrySet  = null;
503742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
513742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    /**
523742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     *
533742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     */
543742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    public static final DNSCache                                       EmptyCache = new _EmptyCache();
553742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
563742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    static final class _EmptyCache extends DNSCache {
573742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
583742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        /**
593742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman         * {@inheritDoc}
603742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman         */
613742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        @Override
623742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        public int size() {
633742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            return 0;
643742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        }
653742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
663742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        /**
673742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman         * {@inheritDoc}
683742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman         */
693742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        @Override
703742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        public boolean isEmpty() {
713742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            return true;
723742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        }
733742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
743742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        /**
753742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman         * {@inheritDoc}
763742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman         */
773742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        @Override
783742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        public boolean containsKey(Object key) {
793742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            return false;
803742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        }
813742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
823742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        /**
833742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman         * {@inheritDoc}
843742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman         */
853742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        @Override
863742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        public boolean containsValue(Object value) {
873742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            return false;
883742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        }
893742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
903742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        /**
913742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman         * {@inheritDoc}
923742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman         */
933742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        @Override
943742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        public List<DNSEntry> get(Object key) {
953742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            return null;
963742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        }
973742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
983742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        /**
993742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman         * {@inheritDoc}
1003742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman         */
1013742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        @Override
1023742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        public Set<String> keySet() {
1033742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            return Collections.emptySet();
1043742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        }
1053742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
1063742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        /**
1073742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman         * {@inheritDoc}
1083742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman         */
1093742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        @Override
1103742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        public Collection<List<? extends DNSEntry>> values() {
1113742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            return Collections.emptySet();
1123742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        }
1133742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
1143742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        /**
1153742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman         * {@inheritDoc}
1163742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman         */
1173742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        @Override
1183742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        public Set<Map.Entry<String, List<? extends DNSEntry>>> entrySet() {
1193742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            return Collections.emptySet();
1203742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        }
1213742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
1223742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        /**
1233742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman         * {@inheritDoc}
1243742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman         */
1253742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        @Override
1263742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        public boolean equals(Object o) {
1273742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            return (o instanceof Map) && ((Map<?, ?>) o).size() == 0;
1283742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        }
1293742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
1303742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        /**
1313742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman         * {@inheritDoc}
1323742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman         */
1333742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        @Override
1343742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        public List<? extends DNSEntry> put(String key, List<? extends DNSEntry> value) {
1353742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            return null;
1363742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        }
1373742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
1383742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        /**
1393742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman         * {@inheritDoc}
1403742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman         */
1413742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        @Override
1423742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        public int hashCode() {
1433742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            return 0;
1443742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        }
1453742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
1463742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    }
1473742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
1483742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    /**
1493742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     *
1503742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     */
1513742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    protected static class _CacheEntry extends Object implements Map.Entry<String, List<? extends DNSEntry>> {
1523742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
1533742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        private List<? extends DNSEntry> _value;
1543742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
1553742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        private String                   _key;
1563742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
1573742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        /**
1583742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman         * @param key
1593742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman         * @param value
1603742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman         */
1613742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        protected _CacheEntry(String key, List<? extends DNSEntry> value) {
1623742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            super();
1633742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            _key = (key != null ? key.trim().toLowerCase() : null);
1643742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            _value = value;
1653742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        }
1663742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
1673742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        /**
1683742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman         * @param entry
1693742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman         */
1703742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        protected _CacheEntry(Map.Entry<String, List<? extends DNSEntry>> entry) {
1713742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            super();
1723742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            if (entry instanceof _CacheEntry) {
1733742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman                _key = ((_CacheEntry) entry).getKey();
1743742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman                _value = ((_CacheEntry) entry).getValue();
1753742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            }
1763742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        }
1773742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
1783742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        /**
1793742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman         * {@inheritDoc}
1803742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman         */
1813742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        @Override
1823742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        public String getKey() {
1833742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            return (_key != null ? _key : "");
1843742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        }
1853742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
1863742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        /**
1873742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman         * {@inheritDoc}
1883742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman         */
1893742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        @Override
1903742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        public List<? extends DNSEntry> getValue() {
1913742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            return _value;
1923742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        }
1933742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
1943742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        /**
1953742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman         * {@inheritDoc}
1963742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman         */
1973742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        @Override
1983742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        public List<? extends DNSEntry> setValue(List<? extends DNSEntry> value) {
1993742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            List<? extends DNSEntry> oldValue = _value;
2003742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            _value = value;
2013742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            return oldValue;
2023742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        }
2033742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
2043742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        /**
2053742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman         * Returns <tt>true</tt> if this list contains no elements.
2063742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman         *
2073742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman         * @return <tt>true</tt> if this list contains no elements
2083742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman         */
2093742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        public boolean isEmpty() {
2103742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            return this.getValue().isEmpty();
2113742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        }
2123742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
2133742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        /**
2143742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman         * {@inheritDoc}
2153742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman         */
2163742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        @Override
2173742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        public boolean equals(Object entry) {
2183742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            if (!(entry instanceof Map.Entry)) {
2193742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman                return false;
2203742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            }
2213742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            return this.getKey().equals(((Map.Entry<?, ?>) entry).getKey()) && this.getValue().equals(((Map.Entry<?, ?>) entry).getValue());
2223742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        }
2233742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
2243742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        /**
2253742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman         * {@inheritDoc}
2263742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman         */
2273742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        @Override
2283742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        public int hashCode() {
2293742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            return (_key == null ? 0 : _key.hashCode());
2303742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        }
2313742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
2323742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        /**
2333742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman         * {@inheritDoc}
2343742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman         */
2353742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        @Override
2363742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        public synchronized String toString() {
2373742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            StringBuffer aLog = new StringBuffer(200);
2383742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            aLog.append("\n\t\tname '");
2393742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            aLog.append(_key);
2403742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            aLog.append("' ");
2413742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            if ((_value != null) && (!_value.isEmpty())) {
2423742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman                for (DNSEntry entry : _value) {
2433742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman                    aLog.append("\n\t\t\t");
2443742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman                    aLog.append(entry.toString());
2453742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman                }
2463742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            } else {
2473742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman                aLog.append(" no entries");
2483742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            }
2493742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            return aLog.toString();
2503742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        }
2513742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    }
2523742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
2533742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    /**
2543742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     *
2553742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     */
2563742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    public DNSCache() {
2573742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        this(1024);
2583742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    }
2593742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
2603742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    /**
2613742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * @param map
2623742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     */
2633742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    public DNSCache(DNSCache map) {
2643742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        this(map != null ? map.size() : 1024);
2653742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        if (map != null) {
2663742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            this.putAll(map);
2673742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        }
2683742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    }
2693742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
2703742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    /**
2713742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * Create a table with a given initial size.
2723742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     *
2733742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * @param initialCapacity
2743742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     */
2753742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    public DNSCache(int initialCapacity) {
2763742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        super();
2773742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        _entrySet = new HashSet<Map.Entry<String, List<? extends DNSEntry>>>(initialCapacity);
2783742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    }
2793742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
2803742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    // ====================================================================
2813742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    // Map
2823742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
2833742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    /*
2843742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * (non-Javadoc)
2853742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * @see java.util.AbstractMap#entrySet()
2863742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     */
2873742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    @Override
2883742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    public Set<Map.Entry<String, List<? extends DNSEntry>>> entrySet() {
2893742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        if (_entrySet == null) {
2903742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            _entrySet = new HashSet<Map.Entry<String, List<? extends DNSEntry>>>();
2913742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        }
2923742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        return _entrySet;
2933742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    }
2943742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
2953742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    /**
2963742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * @param key
2973742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * @return map entry for the key
2983742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     */
2993742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    protected Map.Entry<String, List<? extends DNSEntry>> getEntry(String key) {
3003742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        String stringKey = (key != null ? key.trim().toLowerCase() : null);
3013742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        for (Map.Entry<String, List<? extends DNSEntry>> entry : this.entrySet()) {
3023742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            if (stringKey != null) {
3033742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman                if (stringKey.equals(entry.getKey())) {
3043742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman                    return entry;
3053742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman                }
3063742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            } else {
3073742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman                if (entry.getKey() == null) {
3083742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman                    return entry;
3093742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman                }
3103742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            }
3113742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        }
3123742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        return null;
3133742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    }
3143742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
3153742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    /**
3163742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * {@inheritDoc}
3173742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     */
3183742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    @Override
3193742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    public List<? extends DNSEntry> put(String key, List<? extends DNSEntry> value) {
3203742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        synchronized (this) {
3213742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            List<? extends DNSEntry> oldValue = null;
3223742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            Map.Entry<String, List<? extends DNSEntry>> oldEntry = this.getEntry(key);
3233742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            if (oldEntry != null) {
3243742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman                oldValue = oldEntry.setValue(value);
3253742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            } else {
3263742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman                this.entrySet().add(new _CacheEntry(key, value));
3273742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            }
3283742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            return oldValue;
3293742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        }
3303742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    }
3313742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
3323742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    /**
3333742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * {@inheritDoc}
3343742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     */
3353742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    @Override
3363742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    protected Object clone() throws CloneNotSupportedException {
3373742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        return new DNSCache(this);
3383742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    }
3393742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
3403742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    // ====================================================================
3413742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
3423742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    /**
3433742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * Returns all entries in the cache
3443742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     *
3453742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * @return all entries in the cache
3463742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     */
3473742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    public synchronized Collection<DNSEntry> allValues() {
3483742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        List<DNSEntry> allValues = new ArrayList<DNSEntry>();
3493742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        for (List<? extends DNSEntry> entry : this.values()) {
3503742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            if (entry != null) {
3513742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman                allValues.addAll(entry);
3523742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            }
3533742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        }
3543742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        return allValues;
3553742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    }
3563742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
3573742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    /**
3583742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * Iterate only over items with matching name. Returns an list of DNSEntry or null. To retrieve all entries, one must iterate over this linked list.
3593742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     *
3603742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * @param name
3613742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * @return list of DNSEntries
3623742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     */
3633742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    public synchronized Collection<? extends DNSEntry> getDNSEntryList(String name) {
3643742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        Collection<? extends DNSEntry> entryList = this._getDNSEntryList(name);
3653742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        if (entryList != null) {
3663742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            entryList = new ArrayList<DNSEntry>(entryList);
3673742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        } else {
3683742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            entryList = Collections.emptyList();
3693742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        }
3703742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        return entryList;
3713742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    }
3723742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
3733742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    private Collection<? extends DNSEntry> _getDNSEntryList(String name) {
3743742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        return this.get(name != null ? name.toLowerCase() : null);
3753742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    }
3763742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
3773742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    /**
3783742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * Get a matching DNS entry from the table (using isSameEntry). Returns the entry that was found.
3793742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     *
3803742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * @param dnsEntry
3813742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * @return DNSEntry
3823742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     */
3833742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    public synchronized DNSEntry getDNSEntry(DNSEntry dnsEntry) {
3843742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        DNSEntry result = null;
3853742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        if (dnsEntry != null) {
3863742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            Collection<? extends DNSEntry> entryList = this._getDNSEntryList(dnsEntry.getKey());
3873742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            if (entryList != null) {
3883742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman                for (DNSEntry testDNSEntry : entryList) {
3893742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman                    if (testDNSEntry.isSameEntry(dnsEntry)) {
3903742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman                        result = testDNSEntry;
3913742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman                        break;
3923742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman                    }
3933742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman                }
3943742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            }
3953742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        }
3963742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        return result;
3973742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    }
3983742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
3993742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    /**
4003742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * Get a matching DNS entry from the table.
4013742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     *
4023742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * @param name
4033742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * @param type
4043742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * @param recordClass
4053742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * @return DNSEntry
4063742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     */
4073742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    public synchronized DNSEntry getDNSEntry(String name, DNSRecordType type, DNSRecordClass recordClass) {
4083742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        DNSEntry result = null;
4093742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        Collection<? extends DNSEntry> entryList = this._getDNSEntryList(name);
4103742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        if (entryList != null) {
4113742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            for (DNSEntry testDNSEntry : entryList) {
4123742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman                if (testDNSEntry.getRecordType().equals(type) && ((DNSRecordClass.CLASS_ANY == recordClass) || testDNSEntry.getRecordClass().equals(recordClass))) {
4133742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman                    result = testDNSEntry;
4143742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman                    break;
4153742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman                }
4163742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            }
4173742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        }
4183742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        return result;
4193742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    }
4203742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
4213742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    /**
4223742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * Get all matching DNS entries from the table.
4233742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     *
4243742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * @param name
4253742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * @param type
4263742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * @param recordClass
4273742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * @return list of entries
4283742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     */
4293742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    public synchronized Collection<? extends DNSEntry> getDNSEntryList(String name, DNSRecordType type, DNSRecordClass recordClass) {
4303742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        Collection<? extends DNSEntry> entryList = this._getDNSEntryList(name);
4313742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        if (entryList != null) {
4323742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            entryList = new ArrayList<DNSEntry>(entryList);
4333742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            for (Iterator<? extends DNSEntry> i = entryList.iterator(); i.hasNext();) {
4343742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman                DNSEntry testDNSEntry = i.next();
4353742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman                if (!testDNSEntry.getRecordType().equals(type) || ((DNSRecordClass.CLASS_ANY != recordClass) && !testDNSEntry.getRecordClass().equals(recordClass))) {
4363742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman                    i.remove();
4373742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman                }
4383742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            }
4393742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        } else {
4403742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            entryList = Collections.emptyList();
4413742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        }
4423742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        return entryList;
4433742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    }
4443742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
4453742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    /**
4463742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * Adds an entry to the table.
4473742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     *
4483742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * @param dnsEntry
4493742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * @return true if the entry was added
4503742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     */
4513742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    public synchronized boolean addDNSEntry(final DNSEntry dnsEntry) {
4523742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        boolean result = false;
4533742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        if (dnsEntry != null) {
4543742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            Map.Entry<String, List<? extends DNSEntry>> oldEntry = this.getEntry(dnsEntry.getKey());
4553742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
4563742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            List<DNSEntry> aNewValue = null;
4573742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            if (oldEntry != null) {
4583742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman                aNewValue = new ArrayList<DNSEntry>(oldEntry.getValue());
4593742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            } else {
4603742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman                aNewValue = new ArrayList<DNSEntry>();
4613742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            }
4623742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            aNewValue.add(dnsEntry);
4633742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
4643742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            if (oldEntry != null) {
4653742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman                oldEntry.setValue(aNewValue);
4663742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            } else {
4673742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman                this.entrySet().add(new _CacheEntry(dnsEntry.getKey(), aNewValue));
4683742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            }
4693742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            // This is probably not very informative
4703742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            result = true;
4713742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        }
4723742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        return result;
4733742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    }
4743742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
4753742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    /**
4763742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * Removes a specific entry from the table. Returns true if the entry was found.
4773742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     *
4783742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * @param dnsEntry
4793742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * @return true if the entry was removed
4803742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     */
4813742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    public synchronized boolean removeDNSEntry(DNSEntry dnsEntry) {
4823742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        boolean result = false;
4833742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        if (dnsEntry != null) {
4843742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            Map.Entry<String, List<? extends DNSEntry>> existingEntry = this.getEntry(dnsEntry.getKey());
4853742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            if (existingEntry != null) {
4863742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman                result = existingEntry.getValue().remove(dnsEntry);
4873742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman                // If we just removed the last one we need to get rid of the entry
4883742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman                if (existingEntry.getValue().isEmpty()) {
4893742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman                    this.entrySet().remove(existingEntry);
4903742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman                }
4913742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            }
4923742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        }
4933742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        return result;
4943742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    }
4953742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
4963742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    /**
4973742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * Replace an existing entry by a new one.<br/>
4983742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * <b>Note:</b> the 2 entries must have the same key.
4993742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     *
5003742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * @param newDNSEntry
5013742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * @param existingDNSEntry
5023742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * @return <code>true</code> if the entry has been replace, <code>false</code> otherwise.
5033742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     */
5043742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    public synchronized boolean replaceDNSEntry(DNSEntry newDNSEntry, DNSEntry existingDNSEntry) {
5053742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        boolean result = false;
5063742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        if ((newDNSEntry != null) && (existingDNSEntry != null) && (newDNSEntry.getKey().equals(existingDNSEntry.getKey()))) {
5073742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            Map.Entry<String, List<? extends DNSEntry>> oldEntry = this.getEntry(newDNSEntry.getKey());
5083742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
5093742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            List<DNSEntry> aNewValue = null;
5103742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            if (oldEntry != null) {
5113742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman                aNewValue = new ArrayList<DNSEntry>(oldEntry.getValue());
5123742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            } else {
5133742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman                aNewValue = new ArrayList<DNSEntry>();
5143742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            }
5153742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            aNewValue.remove(existingDNSEntry);
5163742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            aNewValue.add(newDNSEntry);
5173742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
5183742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            if (oldEntry != null) {
5193742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman                oldEntry.setValue(aNewValue);
5203742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            } else {
5213742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman                this.entrySet().add(new _CacheEntry(newDNSEntry.getKey(), aNewValue));
5223742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            }
5233742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            // This is probably not very informative
5243742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            result = true;
5253742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        }
5263742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        return result;
5273742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    }
5283742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
5293742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    /**
5303742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * {@inheritDoc}
5313742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     */
5323742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    @Override
5333742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    public synchronized String toString() {
5343742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        StringBuffer aLog = new StringBuffer(2000);
5353742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        aLog.append("\t---- cache ----");
5363742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        for (Map.Entry<String, List<? extends DNSEntry>> entry : this.entrySet()) {
5373742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            aLog.append("\n\t\t");
5383742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            aLog.append(entry.toString());
5393742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        }
5403742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        return aLog.toString();
5413742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    }
5423742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
5433742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman}
544