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.io.ByteArrayOutputStream;
83742d9db8b6edb10627b0f89336cca5249f1d15aManuel Romanimport java.io.DataOutputStream;
93742d9db8b6edb10627b0f89336cca5249f1d15aManuel Romanimport java.io.IOException;
103742d9db8b6edb10627b0f89336cca5249f1d15aManuel Romanimport java.util.Collections;
113742d9db8b6edb10627b0f89336cca5249f1d15aManuel Romanimport java.util.Map;
123742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
133742d9db8b6edb10627b0f89336cca5249f1d15aManuel Romanimport javax.jmdns.ServiceInfo.Fields;
143742d9db8b6edb10627b0f89336cca5249f1d15aManuel Romanimport javax.jmdns.impl.constants.DNSRecordClass;
153742d9db8b6edb10627b0f89336cca5249f1d15aManuel Romanimport javax.jmdns.impl.constants.DNSRecordType;
163742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
173742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman/**
183742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman * DNS entry with a name, type, and class. This is the base class for questions and records.
193742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman *
203742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman * @author Arthur van Hoff, Pierre Frisch, Rick Blair
213742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman */
223742d9db8b6edb10627b0f89336cca5249f1d15aManuel Romanpublic abstract class DNSEntry {
233742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    // private static Logger logger = Logger.getLogger(DNSEntry.class.getName());
243742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    private final String         _key;
253742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
263742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    private final String         _name;
273742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
283742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    private final String         _type;
293742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
303742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    private final DNSRecordType  _recordType;
313742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
323742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    private final DNSRecordClass _dnsClass;
333742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
343742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    private final boolean        _unique;
353742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
363742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    final Map<Fields, String>    _qualifiedNameMap;
373742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
383742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    /**
393742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * Create an entry.
403742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     */
413742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    DNSEntry(String name, DNSRecordType type, DNSRecordClass recordClass, boolean unique) {
423742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        _name = name;
433742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        // _key = (name != null ? name.trim().toLowerCase() : null);
443742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        _recordType = type;
453742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        _dnsClass = recordClass;
463742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        _unique = unique;
473742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        _qualifiedNameMap = ServiceInfoImpl.decodeQualifiedNameMapForType(this.getName());
483742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        String domain = _qualifiedNameMap.get(Fields.Domain);
493742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        String protocol = _qualifiedNameMap.get(Fields.Protocol);
503742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        String application = _qualifiedNameMap.get(Fields.Application);
513742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        String instance = _qualifiedNameMap.get(Fields.Instance).toLowerCase();
523742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        _type = (application.length() > 0 ? "_" + application + "." : "") + (protocol.length() > 0 ? "_" + protocol + "." : "") + domain + ".";
533742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        _key = ((instance.length() > 0 ? instance + "." : "") + _type).toLowerCase();
543742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    }
553742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
563742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    /*
573742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * (non-Javadoc)
583742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * @see java.lang.Object#equals(java.lang.Object)
593742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     */
603742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    @Override
613742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    public boolean equals(Object obj) {
623742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        boolean result = false;
633742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        if (obj instanceof DNSEntry) {
643742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            DNSEntry other = (DNSEntry) obj;
653742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            result = this.getKey().equals(other.getKey()) && this.getRecordType().equals(other.getRecordType()) && this.getRecordClass() == other.getRecordClass();
663742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        }
673742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        return result;
683742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    }
693742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
703742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    /**
713742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * Check if two entries have exactly the same name, type, and class.
723742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     *
733742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * @param entry
743742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * @return <code>true</code> if the two entries have are for the same record, <code>false</code> otherwise
753742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     */
763742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    public boolean isSameEntry(DNSEntry entry) {
773742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        return this.getKey().equals(entry.getKey()) && this.getRecordType().equals(entry.getRecordType()) && ((DNSRecordClass.CLASS_ANY == entry.getRecordClass()) || this.getRecordClass().equals(entry.getRecordClass()));
783742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    }
793742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
803742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    /**
813742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * Check if two entries have the same subtype.
823742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     *
833742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * @param other
843742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * @return <code>true</code> if the two entries have are for the same subtype, <code>false</code> otherwise
853742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     */
863742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    public boolean sameSubtype(DNSEntry other) {
873742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        return this.getSubtype().equals(other.getSubtype());
883742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    }
893742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
903742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    /**
913742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * Returns the subtype of this entry
923742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     *
933742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * @return subtype of this entry
943742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     */
953742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    public String getSubtype() {
963742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        String subtype = this.getQualifiedNameMap().get(Fields.Subtype);
973742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        return (subtype != null ? subtype : "");
983742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    }
993742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
1003742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    /**
1013742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * Returns the name of this entry
1023742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     *
1033742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * @return name of this entry
1043742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     */
1053742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    public String getName() {
1063742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        return (_name != null ? _name : "");
1073742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    }
1083742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
1093742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    /**
1103742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * @return the type
1113742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     */
1123742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    public String getType() {
1133742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        return (_type != null ? _type : "");
1143742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    }
1153742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
1163742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    /**
1173742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * Returns the key for this entry. The key is the lower case name.
1183742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     *
1193742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * @return key for this entry
1203742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     */
1213742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    public String getKey() {
1223742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        return (_key != null ? _key : "");
1233742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    }
1243742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
1253742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    /**
1263742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * @return record type
1273742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     */
1283742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    public DNSRecordType getRecordType() {
1293742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        return (_recordType != null ? _recordType : DNSRecordType.TYPE_IGNORE);
1303742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    }
1313742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
1323742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    /**
1333742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * @return record class
1343742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     */
1353742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    public DNSRecordClass getRecordClass() {
1363742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        return (_dnsClass != null ? _dnsClass : DNSRecordClass.CLASS_UNKNOWN);
1373742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    }
1383742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
1393742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    /**
1403742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * @return true if unique
1413742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     */
1423742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    public boolean isUnique() {
1433742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        return _unique;
1443742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    }
1453742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
1463742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    public Map<Fields, String> getQualifiedNameMap() {
1473742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        return Collections.unmodifiableMap(_qualifiedNameMap);
1483742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    }
1493742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
1503742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    public boolean isServicesDiscoveryMetaQuery() {
1513742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        return _qualifiedNameMap.get(Fields.Application).equals("dns-sd") && _qualifiedNameMap.get(Fields.Instance).equals("_services");
1523742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    }
1533742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
1543742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    public boolean isDomainDiscoveryQuery() {
1553742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        // b._dns-sd._udp.<domain>.
1563742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        // db._dns-sd._udp.<domain>.
1573742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        // r._dns-sd._udp.<domain>.
1583742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        // dr._dns-sd._udp.<domain>.
1593742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        // lb._dns-sd._udp.<domain>.
1603742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
1613742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        if (_qualifiedNameMap.get(Fields.Application).equals("dns-sd")) {
1623742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            String name = _qualifiedNameMap.get(Fields.Instance);
1633742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            return "b".equals(name) || "db".equals(name) || "r".equals(name) || "dr".equals(name) || "lb".equals(name);
1643742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        }
1653742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        return false;
1663742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    }
1673742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
1683742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    public boolean isReverseLookup() {
1693742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        return this.isV4ReverseLookup() || this.isV6ReverseLookup();
1703742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    }
1713742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
1723742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    public boolean isV4ReverseLookup() {
1733742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        return _qualifiedNameMap.get(Fields.Domain).endsWith("in-addr.arpa");
1743742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    }
1753742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
1763742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    public boolean isV6ReverseLookup() {
1773742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        return _qualifiedNameMap.get(Fields.Domain).endsWith("ip6.arpa");
1783742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    }
1793742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
1803742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    /**
1813742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * Check if the record is stale, i.e. it has outlived more than half of its TTL.
1823742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     *
1833742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * @param now
1843742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     *            update date
1853742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * @return <code>true</code> is the record is stale, <code>false</code> otherwise.
1863742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     */
1873742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    public abstract boolean isStale(long now);
1883742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
1893742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    /**
1903742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * Check if the record is expired.
1913742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     *
1923742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * @param now
1933742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     *            update date
1943742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * @return <code>true</code> is the record is expired, <code>false</code> otherwise.
1953742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     */
1963742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    public abstract boolean isExpired(long now);
1973742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
1983742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    /**
1993742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * Check that 2 entries are of the same class.
2003742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     *
2013742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * @param entry
2023742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * @return <code>true</code> is the two class are the same, <code>false</code> otherwise.
2033742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     */
2043742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    public boolean isSameRecordClass(DNSEntry entry) {
2053742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        return (entry != null) && (entry.getRecordClass() == this.getRecordClass());
2063742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    }
2073742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
2083742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    /**
2093742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * Check that 2 entries are of the same type.
2103742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     *
2113742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * @param entry
2123742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * @return <code>true</code> is the two type are the same, <code>false</code> otherwise.
2133742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     */
2143742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    public boolean isSameType(DNSEntry entry) {
2153742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        return (entry != null) && (entry.getRecordType() == this.getRecordType());
2163742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    }
2173742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
2183742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    /**
2193742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * @param dout
2203742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * @exception IOException
2213742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     */
2223742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    protected void toByteArray(DataOutputStream dout) throws IOException {
2233742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        dout.write(this.getName().getBytes("UTF8"));
2243742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        dout.writeShort(this.getRecordType().indexValue());
2253742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        dout.writeShort(this.getRecordClass().indexValue());
2263742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    }
2273742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
2283742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    /**
2293742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * Creates a byte array representation of this record. This is needed for tie-break tests according to draft-cheshire-dnsext-multicastdns-04.txt chapter 9.2.
2303742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     *
2313742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * @return byte array representation
2323742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     */
2333742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    protected byte[] toByteArray() {
2343742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        try {
2353742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            ByteArrayOutputStream bout = new ByteArrayOutputStream();
2363742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            DataOutputStream dout = new DataOutputStream(bout);
2373742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            this.toByteArray(dout);
2383742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            dout.close();
2393742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            return bout.toByteArray();
2403742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        } catch (IOException e) {
2413742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            throw new InternalError();
2423742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        }
2433742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    }
2443742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
2453742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    /**
2463742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * Does a lexicographic comparison of the byte array representation of this record and that record. This is needed for tie-break tests according to draft-cheshire-dnsext-multicastdns-04.txt chapter 9.2.
2473742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     *
2483742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * @param that
2493742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * @return a negative integer, zero, or a positive integer as this object is less than, equal to, or greater than the specified object.
2503742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     */
2513742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    public int compareTo(DNSEntry that) {
2523742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        byte[] thisBytes = this.toByteArray();
2533742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        byte[] thatBytes = that.toByteArray();
2543742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        for (int i = 0, n = Math.min(thisBytes.length, thatBytes.length); i < n; i++) {
2553742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            if (thisBytes[i] > thatBytes[i]) {
2563742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman                return 1;
2573742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            } else if (thisBytes[i] < thatBytes[i]) {
2583742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman                return -1;
2593742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman            }
2603742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        }
2613742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        return thisBytes.length - thatBytes.length;
2623742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    }
2633742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
2643742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    /**
2653742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * Overriden, to return a value which is consistent with the value returned by equals(Object).
2663742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     */
2673742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    @Override
2683742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    public int hashCode() {
2693742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        return this.getKey().hashCode() + this.getRecordType().indexValue() + this.getRecordClass().indexValue();
2703742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    }
2713742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
2723742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    /*
2733742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * (non-Javadoc)
2743742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * @see java.lang.Object#toString()
2753742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     */
2763742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    @Override
2773742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    public String toString() {
2783742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        StringBuilder aLog = new StringBuilder(200);
2793742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        aLog.append("[" + this.getClass().getSimpleName() + "@" + System.identityHashCode(this));
2803742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        aLog.append(" type: " + this.getRecordType());
2813742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        aLog.append(", class: " + this.getRecordClass());
2823742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        aLog.append((_unique ? "-unique," : ","));
2833742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        aLog.append(" name: " + _name);
2843742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        this.toString(aLog);
2853742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        aLog.append("]");
2863742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        return aLog.toString();
2873742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    }
2883742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
2893742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    /**
2903742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     * @param aLog
2913742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman     */
2923742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    protected void toString(StringBuilder aLog) {
2933742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman        // Stub
2943742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman    }
2953742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman
2963742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman}
297