001/** 002 * 003 * Copyright 2019 Florian Schmaus 004 * 005 * Licensed under the Apache License, Version 2.0 (the "License"); 006 * you may not use this file except in compliance with the License. 007 * You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.jivesoftware.smack.util; 018 019import java.net.Inet4Address; 020import java.net.Inet6Address; 021import java.net.InetAddress; 022import java.net.UnknownHostException; 023 024import org.minidns.dnslabel.DnsLabel; 025import org.minidns.dnsname.DnsName; 026import org.minidns.dnsname.InvalidDnsNameException; 027import org.minidns.util.InetAddressUtil; 028 029/** 030 * An internet address, can be given as IP or as DNS name. 031 * <p> 032 * This type is meant for strings that hold an internet address. The original string used to construct this type is 033 * stored and returning in the {@link #toString()} method. 034 * </p> 035 * 036 * @since 4.4.0 037 */ 038public abstract class InternetAddress implements CharSequence { 039 040 protected final String originalString; 041 042 protected InternetAddress(String originalString) { 043 this.originalString = Objects.requireNonNull(originalString, "The 'originalString' argument must not be null"); 044 } 045 046 public abstract InetAddress asInetAddress() throws UnknownHostException; 047 048 @Override 049 public String toString() { 050 return originalString; 051 } 052 053 @Override 054 public int length() { 055 return originalString.length(); 056 } 057 058 @Override 059 public char charAt(int index) { 060 return originalString.charAt(index); 061 } 062 063 @Override 064 public CharSequence subSequence(int start, int end) { 065 return originalString.subSequence(start, end); 066 } 067 068 public static InternetAddress from(String address) { 069 final InternetAddress internetAddress; 070 if (InetAddressUtil.isIpV4Address(address)) { 071 internetAddress = new InternetAddress.Ipv4(address); 072 } else if (InetAddressUtil.isIpV6Address(address)) { 073 internetAddress = new InternetAddress.Ipv6(address); 074 } else if (address.contains(".")) { 075 InternetAddress domainNameInternetAddress; 076 try { 077 DnsName dnsName = DnsName.from(address); 078 domainNameInternetAddress = new InternetAddress.DomainName(address, dnsName); 079 } catch (InvalidDnsNameException e) { 080 domainNameInternetAddress = new InternetAddress.InvalidDomainName(address, e); 081 } 082 internetAddress = domainNameInternetAddress; 083 } else { 084 DnsLabel dnsLabel = DnsLabel.from(address); 085 internetAddress = new InternetAddress.DomainNameLabel(address, dnsLabel); 086 } 087 return internetAddress; 088 } 089 090 public static InternetAddress from(InetAddress inetAddress) { 091 if (inetAddress instanceof Inet4Address) { 092 return new InternetAddress.Ipv4(inetAddress.getHostAddress(), (Inet4Address) inetAddress); 093 } else if (inetAddress instanceof Inet6Address) { 094 return new InternetAddress.Ipv6(inetAddress.getHostAddress(), (Inet6Address) inetAddress); 095 } else { 096 throw new IllegalArgumentException("Unknown type " + inetAddress.getClass() + " of " + inetAddress); 097 } 098 } 099 100 private static class InetAddressInternetAddress extends InternetAddress { 101 private final InetAddress inetAddress; 102 103 protected InetAddressInternetAddress(String originalString, InetAddress inetAddress) { 104 super(originalString); 105 this.inetAddress = inetAddress; 106 } 107 108 @Override 109 public InetAddress asInetAddress() { 110 return inetAddress; 111 } 112 } 113 114 public static final class Ipv4 extends InetAddressInternetAddress { 115 116 private final Inet4Address inet4Address; 117 118 private Ipv4(String originalString) { 119 this(originalString, InetAddressUtil.ipv4From(originalString)); 120 } 121 122 private Ipv4(String originalString, Inet4Address inet4Address) { 123 super(originalString, inet4Address); 124 this.inet4Address = inet4Address; 125 } 126 127 public Inet4Address getInet4Address() { 128 return inet4Address; 129 } 130 } 131 132 public static final class Ipv6 extends InetAddressInternetAddress { 133 134 private Inet6Address inet6Address; 135 136 private Ipv6(String originalString) { 137 this(originalString, InetAddressUtil.ipv6From(originalString)); 138 } 139 140 private Ipv6(String originalString, Inet6Address inet6Address) { 141 super(originalString, inet6Address); 142 this.inet6Address = inet6Address; 143 } 144 145 public Inet6Address getInet6Address() { 146 return inet6Address; 147 } 148 } 149 150 private static class NonNumericInternetAddress extends InternetAddress { 151 private boolean attemptedToResolveInetAddress; 152 private InetAddress inetAddress; 153 154 protected NonNumericInternetAddress(String originalString) { 155 super(originalString); 156 } 157 158 @Override 159 public InetAddress asInetAddress() throws UnknownHostException { 160 if (inetAddress != null || attemptedToResolveInetAddress) { 161 return inetAddress; 162 } 163 164 attemptedToResolveInetAddress = true; 165 inetAddress = InetAddress.getByName(originalString); 166 167 return inetAddress; 168 } 169 } 170 171 public static final class DomainName extends NonNumericInternetAddress { 172 173 private final DnsName dnsName; 174 175 private DomainName(String originalString, DnsName dnsName) { 176 super(originalString); 177 this.dnsName = dnsName; 178 } 179 180 public DnsName getDnsName() { 181 return dnsName; 182 } 183 184 } 185 186 public static final class DomainNameLabel extends NonNumericInternetAddress { 187 188 private final DnsLabel dnsLabel; 189 190 private DomainNameLabel(String originalString, DnsLabel dnsLabel) { 191 super(originalString); 192 this.dnsLabel = dnsLabel; 193 } 194 195 public DnsLabel getDnsLabel() { 196 return dnsLabel; 197 } 198 } 199 200 public static final class InvalidDomainName extends NonNumericInternetAddress { 201 202 private final InvalidDnsNameException invalidDnsNameException; 203 204 private InvalidDomainName(String originalString, InvalidDnsNameException invalidDnsNameException) { 205 super(originalString); 206 this.invalidDnsNameException = invalidDnsNameException; 207 } 208 209 public InvalidDnsNameException getInvalidDnsNameException() { 210 return invalidDnsNameException; 211 } 212 } 213}