InternetAddress.java

  1. /**
  2.  *
  3.  * Copyright 2019-2023 Florian Schmaus
  4.  *
  5.  * Licensed under the Apache License, Version 2.0 (the "License");
  6.  * you may not use this file except in compliance with the License.
  7.  * You may obtain a copy of the License at
  8.  *
  9.  *     http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */
  17. package org.jivesoftware.smack.util;

  18. import java.net.Inet4Address;
  19. import java.net.Inet6Address;
  20. import java.net.InetAddress;
  21. import java.net.UnknownHostException;

  22. import org.minidns.dnslabel.DnsLabel;
  23. import org.minidns.dnsname.DnsName;
  24. import org.minidns.dnsname.InvalidDnsNameException;
  25. import org.minidns.util.InetAddressUtil;

  26. /**
  27.  * An internet address, can be given as IP or as DNS name.
  28.  * <p>
  29.  * This type is meant for strings that hold an internet address. The original string used to construct this type is
  30.  * stored and returning in the {@link #toString()} method.
  31.  * </p>
  32.  *
  33.  * @since 4.4.0
  34.  */
  35. public abstract class InternetAddress implements CharSequence {

  36.     protected final String originalString;

  37.     protected InternetAddress(String originalString) {
  38.         this.originalString = Objects.requireNonNull(originalString, "The 'originalString' argument must not be null");
  39.     }

  40.     public abstract InetAddress asInetAddress() throws UnknownHostException;

  41.     @Override
  42.     public String toString() {
  43.         return originalString;
  44.     }

  45.     @Override
  46.     public int length() {
  47.         return originalString.length();
  48.     }

  49.     @Override
  50.     public char charAt(int index) {
  51.         return originalString.charAt(index);
  52.     }

  53.     @Override
  54.     public CharSequence subSequence(int start, int end) {
  55.         return originalString.subSequence(start, end);
  56.     }

  57.     public String getRaw() {
  58.         return originalString;
  59.     }

  60.     public static InternetAddress fromIgnoringZoneId(String address) {
  61.         return from(address, true);
  62.     }

  63.     public static InternetAddress from(String address) {
  64.         return from(address, false);
  65.     }

  66.     private static InternetAddress from(String address, boolean ignoreZoneId) {
  67.         String raw = address;
  68.         if (ignoreZoneId) {
  69.             int percentPosition = address.indexOf('%');
  70.             if (percentPosition > 1) {
  71.                 address = address.substring(0, percentPosition);
  72.             }
  73.         }

  74.         final InternetAddress internetAddress;
  75.         if (InetAddressUtil.isIpV4Address(address)) {
  76.             internetAddress = new InternetAddress.Ipv4(address, raw);
  77.         } else if (InetAddressUtil.isIpV6Address(address)) {
  78.             internetAddress = new InternetAddress.Ipv6(address, raw);
  79.         } else if (address.contains(".")) {
  80.             InternetAddress domainNameInternetAddress;
  81.             try {
  82.                 DnsName dnsName = DnsName.from(address);
  83.                 domainNameInternetAddress = new InternetAddress.DomainName(address, dnsName);
  84.             } catch (InvalidDnsNameException e) {
  85.                 domainNameInternetAddress = new InternetAddress.InvalidDomainName(address, e);
  86.             }
  87.             internetAddress = domainNameInternetAddress;
  88.         } else {
  89.             DnsLabel dnsLabel = DnsLabel.from(address);
  90.             internetAddress = new InternetAddress.DomainNameLabel(address, dnsLabel);
  91.         }
  92.         return internetAddress;
  93.     }

  94.     public static InternetAddress from(InetAddress inetAddress) {
  95.         if (inetAddress instanceof Inet4Address) {
  96.             return new InternetAddress.Ipv4(inetAddress.getHostAddress(), (Inet4Address) inetAddress);
  97.         } else if (inetAddress instanceof Inet6Address) {
  98.             return new InternetAddress.Ipv6(inetAddress.getHostAddress(), (Inet6Address) inetAddress);
  99.         } else {
  100.             throw new IllegalArgumentException("Unknown type " + inetAddress.getClass() + " of " + inetAddress);
  101.         }
  102.     }

  103.     private static class InetAddressInternetAddress extends InternetAddress {
  104.         private final InetAddress inetAddress;
  105.         private final String raw;

  106.         protected InetAddressInternetAddress(String originalString, String raw, InetAddress inetAddress) {
  107.             super(originalString);
  108.             this.raw = raw;
  109.             this.inetAddress = inetAddress;
  110.         }

  111.         @Override
  112.         public InetAddress asInetAddress() {
  113.             return inetAddress;
  114.         }

  115.         @Override
  116.         public final String getRaw() {
  117.             return raw;
  118.         }
  119.     }

  120.     public static final class Ipv4 extends InetAddressInternetAddress {

  121.         private final Inet4Address inet4Address;

  122.         private Ipv4(String originalString, String raw) {
  123.             this(originalString, raw, InetAddressUtil.ipv4From(originalString));
  124.         }

  125.         private Ipv4(String originalString, Inet4Address inet4Address) {
  126.             this(originalString, originalString, inet4Address);
  127.         }

  128.         private Ipv4(String originalString, String raw, Inet4Address inet4Address) {
  129.             super(originalString, raw, inet4Address);
  130.             this.inet4Address = inet4Address;
  131.         }

  132.         public Inet4Address getInet4Address() {
  133.             return inet4Address;
  134.         }
  135.     }

  136.     public static final class Ipv6 extends InetAddressInternetAddress {

  137.         private Inet6Address inet6Address;

  138.         private Ipv6(String originalString, String raw) {
  139.             this(originalString, raw, InetAddressUtil.ipv6From(originalString));
  140.         }

  141.         private Ipv6(String originalString, Inet6Address inet6Address) {
  142.             this(originalString, originalString, inet6Address);
  143.         }

  144.         private Ipv6(String originalString, String raw, Inet6Address inet6Address) {
  145.             super(originalString, raw, inet6Address);
  146.             this.inet6Address = inet6Address;
  147.         }

  148.         public Inet6Address getInet6Address() {
  149.             return inet6Address;
  150.         }
  151.     }

  152.     private static class NonNumericInternetAddress extends InternetAddress {
  153.         private boolean attemptedToResolveInetAddress;
  154.         private InetAddress inetAddress;

  155.         protected NonNumericInternetAddress(String originalString) {
  156.             super(originalString);
  157.         }

  158.         @Override
  159.         public InetAddress asInetAddress() throws UnknownHostException {
  160.             if (inetAddress != null || attemptedToResolveInetAddress) {
  161.                 return inetAddress;
  162.             }

  163.             attemptedToResolveInetAddress = true;
  164.             inetAddress = InetAddress.getByName(originalString);

  165.             return inetAddress;
  166.         }
  167.     }

  168.     public static final class DomainName extends NonNumericInternetAddress {

  169.         private final DnsName dnsName;

  170.         private DomainName(String originalString, DnsName dnsName) {
  171.             super(originalString);
  172.             this.dnsName = dnsName;
  173.         }

  174.         public DnsName getDnsName() {
  175.             return dnsName;
  176.         }

  177.     }

  178.     public static final class DomainNameLabel extends NonNumericInternetAddress {

  179.         private final DnsLabel dnsLabel;

  180.         private DomainNameLabel(String originalString, DnsLabel dnsLabel) {
  181.             super(originalString);
  182.             this.dnsLabel = dnsLabel;
  183.         }

  184.         public DnsLabel getDnsLabel() {
  185.             return dnsLabel;
  186.         }
  187.     }

  188.     public static final class InvalidDomainName extends NonNumericInternetAddress {

  189.         private final InvalidDnsNameException invalidDnsNameException;

  190.         private InvalidDomainName(String originalString, InvalidDnsNameException invalidDnsNameException) {
  191.             super(originalString);
  192.             this.invalidDnsNameException = invalidDnsNameException;
  193.         }

  194.         public InvalidDnsNameException getInvalidDnsNameException() {
  195.             return invalidDnsNameException;
  196.         }
  197.     }
  198. }