All Implemented Interfaces:
Serializable, CharSequence, Comparable<DnsName>

public final class DnsNameextends SafeCharSequence implements Serializable, Comparable<DnsName>
A DNS name, also called "domain name". A DNS name consists of multiple 'labels' (see DnsLabel) and is subject to certain restrictions (see for example RFC 3696 § 2.).

Instances of this class can be created by using from(String).

This class holds three representations of a DNS name: ACE, raw ACE and IDN. ACE (ASCII Compatible Encoding), which can be accessed via ace, represents mostly the data that got send over the wire. But since DNS names are case insensitive, the ACE value is normalized to lower case. You can use getRawAce() to get the raw ACE data that was received, which possibly includes upper case characters. The IDN (Internationalized Domain Name), that is the DNS name as it should be shown to the user, can be retrieved using asIdn().

More information about Internationalized Domain Names can be found at:
See Also:
  • Field Details

    • serialVersionUID

      private static final long serialVersionUID
      Serial version of the serialized form.
      See Also:
    • LABEL_SEP_REGEX

      private static final String LABEL_SEP_REGEX
      Regex matching label separator dots.
      See Also:
    • MAX_DNSNAME_LENGTH_IN_OCTETS

      static final int MAX_DNSNAME_LENGTH_IN_OCTETS
      See Also:
    • MAX_LABELS

      public static final int MAX_LABELS
      Largest number of labels a DNS name may carry.
      See Also:
    • ROOT

      public static final DnsName ROOT
      The root name, written as a lone dot.
    • IN_ADDR_ARPA

      public static final DnsName IN_ADDR_ARPA
      The reverse lookup zone for IPv4 addresses.
    • IP6_ARPA

      public static final DnsName IP6_ARPA
      IP6_ARPA.
    • VALIDATE

      public static boolean VALIDATE
      Whether or not the DNS name is validated on construction.
    • ace

      public final String ace
      The DNS name in ASCII Compatible Encoding (ACE).
    • rawAce

      private final String rawAce
      The DNS name in raw format, i.e. as it was received from the remote server. This means that compared to ace, this String may not be lower-cased.
    • bytes

      private transient byte[] bytes
      Cached wire format of the name.
    • rawBytes

      private transient byte[] rawBytes
      Cached wire format including the root label.
    • idn

      private transient String idn
      Cached internationalized form of the name.
    • domainpart

      private transient String domainpart
      Cached domain part of the name.
    • hostpart

      private transient String hostpart
      Cached host part of the name.
    • labels

      private transient DnsLabel[] labels
      The labels in reverse order.
    • rawLabels

      private transient DnsLabel[] rawLabels
      Cached labels of the name.
    • hashCode

      private transient int hashCode
      Cached hash code, 0 until computed.
    • size

      private int size
      Size
    • safeToStringRepresentation

      private transient String safeToStringRepresentation
      Cached printable form of the name.
  • Constructor Details

    • DnsName

      private DnsName(String name)
      Builds a name from a unicode string.
      Parameters:
      name - the name to parse
    • DnsName

      private DnsName(String name, boolean inAce)
      Builds a name from a string in either form.
      Parameters:
      name - the name to parse
      inAce - true if the name is already ACE encoded
    • DnsName

      private DnsName(DnsLabel[] rawLabels, boolean validateMaxDnsnameLength)
      Builds a name from its labels.
      Parameters:
      rawLabels - the labels of the name
      validateMaxDnsnameLength - true to check the total length
  • Method Details

    • labelsToString

      private static String labelsToString(DnsLabel[] labels, int stringLength)
      Joins the labels into one name.
      Parameters:
      labels - the labels to join
      stringLength - the expected length of the result
      Returns:
      the name as a string
    • validateMaxDnsnameLengthInOctets

      private void validateMaxDnsnameLengthInOctets()
      Checks the name against the DNS length limit.
      Throws:
      IllegalArgumentException - if the name is too long
    • writeToStream

      public void writeToStream(OutputStream os) throws IOException
      Write the binary domain name to the stream, length-prefixing each label and terminating with the root byte.
      Parameters:
      os - the stream to write the binary domain name to
      Throws:
      IOException - if the stream rejects or fails the write
    • getBytes

      public byte[] getBytes()
      Serialize a domain name under IDN rules.
      Returns:
      The binary domain name representation.
    • getRawBytes

      public byte[] getRawBytes()
      Binary form built from the raw labels rather than the IDN-normalised ones, so uppercase letters received over the wire are preserved.
      Returns:
      a copy of the binary domain name built from the raw labels
    • setBytesIfRequired

      private void setBytesIfRequired()
      Computes the cached wire form of the name.
    • toBytes

      private static byte[] toBytes(DnsLabel[] labels)
      Encodes the labels in the wire format.
      Parameters:
      labels - the labels to encode
      Returns:
      the encoded name
    • setLabelsIfRequired

      private void setLabelsIfRequired()
      Computes the cached labels of the name.
    • getLabels

      private static DnsLabel[] getLabels(String ace)
      Splits an ACE name into its labels.
      Parameters:
      ace - the name in ACE form
      Returns:
      the labels found
    • getAce

      public String getAce()
      Return the ACE (ASCII Compatible Encoding) version of this DNS name. Note that this method may return a String containing null bytes. Those Strings are notoriously difficult to handle from a security perspective. Therefore it is recommended to use toString() instead, which will return a sanitized String.
      Returns:
      the ACE version of this DNS name.
    • getRawAce

      public String getRawAce()
      Returns the raw ACE version of this DNS name. That is, the version as it was received over the wire. Most notably, this version may include uppercase letters. Please refer to getAce() for a discussion of the security implications when working with the ACE representation of a DNS name.
      Returns:
      the raw ACE version of this DNS name.
      See Also:
    • asIdn

      public String asIdn()
      Decodes the ACE form into Unicode, caching the result.
      Returns:
      the Unicode form of this name, decoded from its ACE representation
    • getDomainpart

      public String getDomainpart()
      The domain part of the name, in ACE form.
      Returns:
      the domain part, ACE encoded
    • getHostpart

      public String getHostpart()
      The host part of the name, in ACE form.
      Returns:
      the host part, ACE encoded
    • getHostpartLabel

      public DnsLabel getHostpartLabel()
      Fetches the label at the far left of this name.
      Returns:
      the leftmost label of this name, which is its host part
    • setHostnameAndDomainpartIfRequired

      private void setHostnameAndDomainpartIfRequired()
      Computes the cached host and domain parts.
    • size

      public int size()
      Computes the encoded length of this name, caching the result.
      Returns:
      the length in octets this name occupies in wire format, counting each label's length prefix and the terminating root byte
    • toString

      public String toString()
      Renders this name in dotted presentation format.
      Specified by:
      toString in interface CharSequence
      Overrides:
      toString in class Object
    • from

      public static DnsName from(CharSequence name)
      Wraps a name given in presentation format.
      Parameters:
      name - the domain name in presentation format, which is converted to ACE
      Returns:
      the DNS name wrapping that presentation form
    • from

      public static DnsName from(String name)
      Wraps a name given in presentation format.
      Parameters:
      name - the domain name in presentation format, which is converted to ACE
      Returns:
      the DNS name wrapping that presentation form
    • from

      public static DnsName from(DnsName child, DnsName parent)
      Create a DNS name by "concatenating" the child under the parent name. The child can also be seen as the "left" part of the resulting DNS name and the parent is the "right" part.

      For example using "i.am.the.child" as child and "of.this.parent.example" as parent, will result in a DNS name: "i.am.the.child.of.this.parent.example".

      Parameters:
      child - the child DNS name.
      parent - the parent DNS name.
      Returns:
      the resulting of DNS name.
    • from

      public static DnsName from(CharSequence child, DnsName parent)
      Places one text label directly under the given parent name.
      Parameters:
      child - the text of the single label to place directly under parent
      parent - the DNS name supplying the labels to the right of the child
      Returns:
      the DNS name formed by placing child under parent
    • from

      public static DnsName from(DnsLabel child, DnsName parent)
      Places one label directly under the given parent name.
      Parameters:
      child - the label to place directly under parent
      parent - the DNS name supplying the labels to the right of the child
      Returns:
      the DNS name formed by placing child under parent
    • from

      public static DnsName from(DnsLabel grandchild, DnsLabel child, DnsName parent)
      Places a two-label run under the given parent name.
      Parameters:
      grandchild - the label to place directly under child
      child - the label to place between grandchild and parent
      parent - the DNS name supplying the labels to the right of the child
      Returns:
      the DNS name formed by placing grandchild under child under parent
    • from

      public static DnsName from(DnsName... nameComponents)
      Joins any number of names into a single one with a dot between them.
      Parameters:
      nameComponents - the DNS names to concatenate, ordered leftmost (child) to rightmost (parent)
      Returns:
      the single DNS name formed by joining the components with a dot
    • from

      public static DnsName from(String[] parts)
      Builds a name from labels supplied top-level first.
      Parameters:
      parts - the labels in reverse order, so parts[0] is the top-level domain label
      Returns:
      the DNS name made of those labels, caching a lowercase variant of each
    • parse

      public static DnsName parse(DataInputStream dis, byte[] data) throws IOException
      Parse a domain name starting at the current offset and moving the input stream pointer past this domain name (even if cross references occur).
      Parameters:
      dis - The input stream.
      data - The raw data (for cross references).
      Returns:
      The domain name string.
      Throws:
      IOException - Should never happen.
    • parse

      private static DnsName parse(byte[] data, int offset, HashSet<Integer> jumps) throws IllegalStateException
      Parse a domain name starting at the given offset.
      Parameters:
      data - The raw data.
      offset - the index into data at which this domain name starts
      jumps - The list of jumps (by now).
      Returns:
      The parsed domain name.
      Throws:
      IllegalStateException - if the compression pointers form a cycle.
    • compareTo

      public int compareTo(DnsName other)
      Orders names by their ACE form.
      Specified by:
      compareTo in interface Comparable<DnsName>
    • equals

      public boolean equals(Object other)
      Compares two names by their encoded bytes.
      Overrides:
      equals in class Object
    • hashCode

      public int hashCode()
      Hashes the encoded bytes, caching the result.
      Overrides:
      hashCode in class Object
    • isDirectChildOf

      public boolean isDirectChildOf(DnsName parent)
      Tests whether exactly one label of this name sits above the given parent.
      Parameters:
      parent - the candidate ancestor name to compare this name against
      Returns:
      true if this name carries exactly one label more than parent and shares its remaining labels
    • isChildOf

      public boolean isChildOf(DnsName parent)
      Tests whether this name sits below the given parent at any depth.
      Parameters:
      parent - the candidate ancestor name to test this name against
      Returns:
      true if this name ends with parent's labels at any depth, so it may be a grandchild or further down
    • getLabelCount

      public int getLabelCount()
      Counts the labels of this name, forcing them to be parsed first.
      Returns:
      the number of labels in this name, where the root label on its own counts as zero
    • getLabels

      public DnsLabel[] getLabels()
      Get a copy of the labels of this DNS name. The resulting array will contain the labels in reverse order, that is, the top-level domain will be at res[0].
      Returns:
      an array of the labels in reverse order.
    • getLabel

      public DnsLabel getLabel(int labelNum)
      Fetches one label by its index in the reversed array.
      Parameters:
      labelNum - the index into the reversed label array, so 0 is the top-level domain label
      Returns:
      the label at that index of the reversed array
    • getRawLabels

      public DnsLabel[] getRawLabels()
      Get a copy of the raw labels of this DNS name. The resulting array will contain the labels in reverse order, that is, the top-level domain will be at res[0].
      Returns:
      an array of the raw labels in reverse order.
    • stripToLabels

      public DnsName stripToLabels(int labelCount)
      Discards labels to the left, keeping only the rightmost few.
      Parameters:
      labelCount - how many of the rightmost labels to keep, from 0 for the root up to getLabelCount()
      Returns:
      a name built from that many labels, this name itself when it is already that short, and the root at 0
      Throws:
      IllegalArgumentException - if labelCount exceeds this name's label count
    • getParent

      public DnsName getParent()
      Return the parent of this DNS label. Will return the root label if this label itself is the root label (because there is no parent of root).

      For example:

      • "foo.bar.org".getParent() == "bar.org"
      • ".".getParent() == "."
      Returns:
      the parent of this DNS label.
    • isRootLabel

      public boolean isRootLabel()
      Tests whether this name is the root, empty or a lone dot.
      Returns:
      true if this name is the root, written either as an empty string or as a lone dot