com.ardikars.common.net.Inet6Address Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of common-net Show documentation
Show all versions of common-net Show documentation
Java Common is an project focused on all aspects of reusable Java components.
The newest version!
/**
* Copyright 2017-2019 the original author or authors.
*
* 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 com.ardikars.common.net;
import com.ardikars.common.annotation.Immutable;
import com.ardikars.common.util.Validate;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* This class represents an Internet Protocol version 6 (IPv6) address.
* Defined by IPv6 Address
*
* @author Ardika Rommy Sanjaya
* @since 1.0.0
*/
@Immutable
public final class Inet6Address extends InetAddress {
/**
* Zero IPv6 Address.
*/
public static final Inet6Address ZERO = valueOf(new byte[] {
(byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0,
(byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0,
(byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0,
(byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0,
});
/**
* IPv6 Loopback Address (::1).
*/
public static final Inet6Address LOCALHOST = valueOf("::1");
/**
* IPv6 Address Length.
*/
public static final short IPV6_ADDRESS_LENGTH = 16;
private byte[] address;
{
address = new byte[Inet6Address.IPV6_ADDRESS_LENGTH];
}
private Inet6Address() {
}
private Inet6Address(byte[] address) {
Validate.nullPointer(address);
Validate.notIllegalArgument(address.length == IPV6_ADDRESS_LENGTH);
this.address = address;
}
/**
* Determines the IPv6 address.
* @param bytesAddress ipv6 bytesAddress address.
* @return an IPv6 address.
*/
public static Inet6Address valueOf(final byte[] bytesAddress) {
return new Inet6Address(bytesAddress);
}
/**
* Determines the IPv6 address.
* @param stringAddress ipv6 stringAddress address.
* @return an IPv6 address.
*/
public static Inet6Address valueOf(String stringAddress) {
stringAddress = Validate.nullPointer(stringAddress, "::");
final int ipv6MaxHexGroups = 8;
final int ipv6MaxHexDigitsPerGroup = 4;
boolean containsCompressedZeroes = stringAddress.contains("::");
Validate.notIllegalArgument(!(containsCompressedZeroes && (stringAddress.indexOf("::") != stringAddress.lastIndexOf("::"))));
Validate.notIllegalArgument(!((stringAddress.startsWith(":") && !stringAddress.startsWith("::"))
|| (stringAddress.endsWith(":") && !stringAddress.endsWith("::"))));
String[] parts = stringAddress.split(":");
if (containsCompressedZeroes) {
List partsAsList = new ArrayList(Arrays.asList(parts));
if (stringAddress.endsWith("::")) {
partsAsList.add("");
} else if (stringAddress.startsWith("::") && !partsAsList.isEmpty()) {
partsAsList.remove(0);
}
parts = partsAsList.toArray(new String[partsAsList.size()]);
}
Validate.notIllegalArgument(!(parts.length > ipv6MaxHexGroups));
int validOctets = 0;
int emptyOctets = 0;
for (int index = 0; index < parts.length; index++) {
String octet = parts[index];
if (octet.length() == 0) {
emptyOctets++;
Validate.notIllegalArgument(!(emptyOctets > 1));
} else {
emptyOctets = 0;
if (index == parts.length - 1 && octet.contains(".")) {
byte[] quad;
quad = Inet4Address.valueOf(octet).toBytes();
String initialPart = stringAddress.substring(0, stringAddress.lastIndexOf(":") + 1);
String penultimate = Integer.toHexString(((quad[0] & 0xff) << 8) | (quad[1] & 0xff));
String ultimate = Integer.toHexString(((quad[2] & 0xff) << 8) | (quad[3] & 0xff));
stringAddress = initialPart + penultimate + ultimate;
validOctets += 2;
continue;
}
Validate.notIllegalArgument(!(octet.length() > ipv6MaxHexDigitsPerGroup));
}
validOctets++;
}
Validate.notIllegalArgument(!(validOctets > ipv6MaxHexGroups || (validOctets < ipv6MaxHexGroups && !containsCompressedZeroes)));
parts = stringAddress.split(":", 8 + 2);
Validate.notIllegalArgument(!(parts.length < 3 || parts.length > 8 + 1));
int skipIndex = -1;
for (int i = 1; i < parts.length - 1; i++) {
if (parts[i].length() == 0) {
Validate.notIllegalArgument(!(skipIndex >= 0));
skipIndex = i;
}
}
int partsHi;
int partsLo;
if (skipIndex >= 0) {
partsHi = skipIndex;
partsLo = parts.length - skipIndex - 1;
Validate.notIllegalArgument(!(parts[0].length() == 0 && --partsHi != 0));
Validate.notIllegalArgument(!(parts[parts.length - 1].length() == 0 && --partsLo != 0));
} else {
partsHi = parts.length;
partsLo = 0;
}
int partsSkipped = 8 - (partsHi + partsLo);
Validate.notIllegalArgument((skipIndex >= 0 ? partsSkipped >= 1 : partsSkipped == 0));
ByteBuffer rawBytes = ByteBuffer.allocate(2 * 8);
try {
for (int i = 0; i < partsHi; i++) {
rawBytes.putShort(parseHextet(parts[i]));
}
for (int i = 0; i < partsSkipped; i++) {
rawBytes.putShort((short) 0);
}
for (int i = partsLo; i > 0; i--) {
rawBytes.putShort(parseHextet(parts[parts.length - i]));
}
} catch (NumberFormatException ex) {
return null;
}
return new Inet6Address(rawBytes.array());
}
@Override
public boolean isMulticastAddress() {
return ((address[0] & 0xff) == 0xff);
}
@Override
public boolean isAnyLocalAddress() {
byte test = 0x00;
for (int i = 0; i < Inet6Address.IPV6_ADDRESS_LENGTH; i++) {
test |= address[i];
}
return (test == 0x00);
}
@Override
public boolean isLoopbackAddress() {
byte test = 0x00;
for (int i = 0; i < 15; i++) {
test |= address[i];
}
return (test == 0x00) && (address[15] == 0x01);
}
@Override
public boolean isLinkLocalAddress() {
return ((address[0] & 0xff) == 0xfe
&& (address[1] & 0xc0) == 0x80);
}
@Override
public boolean isSiteLocalAddress() {
return ((address[0] & 0xff) == 0xfe
&& (address[1] & 0xc0) == 0xc0);
}
@Override
public boolean isMcGlobal() {
return ((address[0] & 0xff) == 0xff
&& (address[1] & 0x0f) == 0x0e);
}
@Override
public boolean isMcNodeLocal() {
return ((address[0] & 0xff) == 0xff
&& (address[1] & 0x0f) == 0x01);
}
@Override
public boolean isMcLinkLocal() {
return ((address[0] & 0xff) == 0xff
&& (address[1] & 0x0f) == 0x02);
}
@Override
public boolean isMcSiteLocal() {
return ((address[0] & 0xff) == 0xff
&& (address[1] & 0x0f) == 0x05);
}
@Override
public boolean isMcOrgLocal() {
return ((address[0] & 0xff) == 0xff
&& (address[1] & 0x0f) == 0x08);
}
/**
* Returns the raw IPv6 address of this {@code Inet6Address}
* object.
* @return the raw IPv6 address of this object.
*/
public byte[] toBytes() {
return Arrays.copyOf(this.address, this.address.length);
}
/**
* Returns {@code long} address.
* @return returns {@code long} address.
*/
public long toLong() {
ByteBuffer bb = ByteBuffer.allocate(this.address.length);
bb.put(this.address);
return bb.getLong();
}
private static short parseHextet(final String ipPart) {
int hextet = Integer.parseInt(ipPart, 16);
if (hextet > 0xffff) {
throw new NumberFormatException();
}
return (short) hextet;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Inet6Address that = (Inet6Address) o;
return Arrays.equals(address, that.address);
}
@Override
public int hashCode() {
return Arrays.hashCode(address);
}
/**
* returns ipv6 string.
* @return ipv6 string.
*/
public String toString() {
int cmprHextet = -1;
int cmprSize = 0;
for (int hextet = 0; hextet < 7; ) {
int curByte = hextet * 2;
int size = 0;
while (curByte < this.address.length && this.address[curByte] == 0
&& this.address[curByte + 1] == 0) {
curByte += 2;
size++;
}
if (size > cmprSize) {
cmprHextet = hextet;
cmprSize = size;
}
hextet = (curByte / 2) + 1;
}
StringBuilder sb = new StringBuilder(39);
if (cmprHextet == -1 || cmprSize < 2) {
ipv6toStr(sb, this.address, 0, 8);
return sb.toString();
}
ipv6toStr(sb, this.address, 0, cmprHextet);
sb.append(new char[]{':', ':'});
ipv6toStr(sb, this.address, cmprHextet + cmprSize, 8);
return sb.toString();
}
private static void ipv6toStr(StringBuilder sb, byte[] src,
int fromHextet, int toHextet) {
for (int i = fromHextet; i < toHextet; i++) {
sb.append(Integer.toHexString(((src[i << 1] << 8) & 0xff00)
| (src[(i << 1) + 1] & 0xff)));
if (i < toHextet - 1) {
sb.append(':');
}
}
}
/**
* Returns the raw IPv6 address of this {@code Inet6Address}
* object.
* @return the raw IPv6 address of this object.
*/
@Override
public byte[] getAddress() {
return Arrays.copyOf(this.address, this.address.length);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy