/** * * Copyright 2019 Florian Schmaus * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jivesoftware.smack.util; import java.net.Inet4Address; import java.net.Inet6Address; import java.net.InetAddress; import java.net.UnknownHostException; import org.minidns.dnslabel.DnsLabel; import org.minidns.dnsname.DnsName; import org.minidns.dnsname.InvalidDnsNameException; import org.minidns.util.InetAddressUtil; /** * An internet address, can be given as IP or as DNS name. *

* This type is meant for strings that hold an internet address. The original string used to construct this type is * stored and returning in the {@link #toString()} method. *

* * @since 4.4.0 */ public abstract class InternetAddress implements CharSequence { protected final String originalString; protected InternetAddress(String originalString) { this.originalString = Objects.requireNonNull(originalString, "The 'originalString' argument must not be null"); } public abstract InetAddress asInetAddress() throws UnknownHostException; @Override public String toString() { return originalString; } @Override public int length() { return originalString.length(); } @Override public char charAt(int index) { return originalString.charAt(index); } @Override public CharSequence subSequence(int start, int end) { return originalString.subSequence(start, end); } public static InternetAddress from(String address) { final InternetAddress internetAddress; if (InetAddressUtil.isIpV4Address(address)) { internetAddress = new InternetAddress.Ipv4(address); } else if (InetAddressUtil.isIpV6Address(address)) { internetAddress = new InternetAddress.Ipv6(address); } else if (address.contains(".")) { InternetAddress domainNameInternetAddress; try { DnsName dnsName = DnsName.from(address); domainNameInternetAddress = new InternetAddress.DomainName(address, dnsName); } catch (InvalidDnsNameException e) { domainNameInternetAddress = new InternetAddress.InvalidDomainName(address, e); } internetAddress = domainNameInternetAddress; } else { DnsLabel dnsLabel = DnsLabel.from(address); internetAddress = new InternetAddress.DomainNameLabel(address, dnsLabel); } return internetAddress; } public static InternetAddress from(InetAddress inetAddress) { if (inetAddress instanceof Inet4Address) { return new InternetAddress.Ipv4(inetAddress.getHostAddress(), (Inet4Address) inetAddress); } else if (inetAddress instanceof Inet6Address) { return new InternetAddress.Ipv6(inetAddress.getHostAddress(), (Inet6Address) inetAddress); } else { throw new IllegalArgumentException("Unknown type " + inetAddress.getClass() + " of " + inetAddress); } } private static class InetAddressInternetAddress extends InternetAddress { private final InetAddress inetAddress; protected InetAddressInternetAddress(String originalString, InetAddress inetAddress) { super(originalString); this.inetAddress = inetAddress; } @Override public InetAddress asInetAddress() { return inetAddress; } } public static final class Ipv4 extends InetAddressInternetAddress { private final Inet4Address inet4Address; private Ipv4(String originalString) { this(originalString, InetAddressUtil.ipv4From(originalString)); } private Ipv4(String originalString, Inet4Address inet4Address) { super(originalString, inet4Address); this.inet4Address = inet4Address; } public Inet4Address getInet4Address() { return inet4Address; } } public static final class Ipv6 extends InetAddressInternetAddress { private Inet6Address inet6Address; private Ipv6(String originalString) { this(originalString, InetAddressUtil.ipv6From(originalString)); } private Ipv6(String originalString, Inet6Address inet6Address) { super(originalString, inet6Address); this.inet6Address = inet6Address; } public Inet6Address getInet6Address() { return inet6Address; } } private static class NonNumericInternetAddress extends InternetAddress { private boolean attemptedToResolveInetAddress; private InetAddress inetAddress; protected NonNumericInternetAddress(String originalString) { super(originalString); } @Override public InetAddress asInetAddress() throws UnknownHostException { if (inetAddress != null || attemptedToResolveInetAddress) { return inetAddress; } attemptedToResolveInetAddress = true; inetAddress = InetAddress.getByName(originalString); return inetAddress; } } public static final class DomainName extends NonNumericInternetAddress { private final DnsName dnsName; private DomainName(String originalString, DnsName dnsName) { super(originalString); this.dnsName = dnsName; } public DnsName getDnsName() { return dnsName; } } public static final class DomainNameLabel extends NonNumericInternetAddress { private final DnsLabel dnsLabel; private DomainNameLabel(String originalString, DnsLabel dnsLabel) { super(originalString); this.dnsLabel = dnsLabel; } public DnsLabel getDnsLabel() { return dnsLabel; } } public static final class InvalidDomainName extends NonNumericInternetAddress { private final InvalidDnsNameException invalidDnsNameException; private InvalidDomainName(String originalString, InvalidDnsNameException invalidDnsNameException) { super(originalString); this.invalidDnsNameException = invalidDnsNameException; } public InvalidDnsNameException getInvalidDnsNameException() { return invalidDnsNameException; } } }