blob: 79d1f3ecc0c1855d9a07ca163a7a2d1e72af08eb [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more contributor license
* agreements. See the NOTICE file distributed with this work for additional information regarding
* copyright ownership. The ASF licenses this file to You 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.apache.geode.internal.net;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.Enumeration;
import org.apache.geode.GemFireIOException;
import org.apache.geode.annotations.Immutable;
/**
* Provides static utilities for manipulating, validating, and converting InetAddresses and host
* strings.
*/
@SuppressWarnings("unused")
public class InetAddressUtils {
@Immutable
private static final InetAddress LOCALHOST = getLocalHost();
private static final String LOOPBACK_ADDRESS =
SocketCreator.preferIPv6Addresses() ? "::1" : "127.0.0.1";
@Immutable
private static final InetAddress LOOPBACK = toInetAddress(LOOPBACK_ADDRESS);
private InetAddressUtils() {
// prevent construction
}
public static InetAddress getLoopback() {
return LOOPBACK;
}
public static String getLoopbackAddress() {
return LOOPBACK_ADDRESS;
}
/**
* Returns a string version of {@code InetAddress} which can be converted back later. Essentially
* any leading slash is trimmed.
*
* @param val The InetAddress or String to return a formatted string of
*
* @return The string version of the InetAddress minus any leading slash
*/
public static String toHostString(Object val) {
if (val instanceof String) {
return trimLeadingSlash((String) val);
}
if (val instanceof InetAddress) {
return ((InetAddress) val).getHostAddress();
}
return trimLeadingSlash(val.toString());
}
/**
* Converts the string host to an instance of {@code InetAddress}. Returns null if the string is
* empty. Any leading slashes on host will be ignored. The checked exception
* {@code UnknownHostException} is captured and an AssertionError is generated instead.
*
* @param host The string version the InetAddress
*
* @return The host converted to InetAddress instance
*
* @throws AssertionError If conversion of host results in {@code UnknownHostException}
*/
public static InetAddress toInetAddress(String host) {
try {
return toInetAddressOrThrow(host);
} catch (UnknownHostException e) {
throw new AssertionError("Failed to get InetAddress: " + host, e);
}
}
/**
* Validates the host by making sure it can successfully be used to get an instance of
* InetAddress. Any leading slashes on host will be ignored. If the host string is null, empty or
* would result in {@code java.lang.UnknownHostException} then null is returned.
*
* @param host The string version the InetAddress
*
* @return The host converted to InetAddress instance
*/
public static String validateHost(String host) {
try {
return validateHostOrThrow(host);
} catch (UnknownHostException e) {
return null;
}
}
/**
* Returns true if host matches the LOCALHOST.
*/
public static boolean isLocalHost(InetAddress host) {
if (LOCALHOST.equals(host)) {
return true;
}
try {
Enumeration en = NetworkInterface.getNetworkInterfaces();
while (en.hasMoreElements()) {
NetworkInterface i = (NetworkInterface) en.nextElement();
for (Enumeration en2 = i.getInetAddresses(); en2.hasMoreElements();) {
InetAddress addr = (InetAddress) en2.nextElement();
if (host.equals(addr)) {
return true;
}
}
}
return false;
} catch (SocketException e) {
throw new GemFireIOException("Unable to query network interface", e);
}
}
/**
* Returns true if host matches the LOCALHOST.
*/
public static boolean isLocalHost(String host) {
return isLocalHost(toInetAddress(host));
}
/**
* Returns true if host matches the LOOPBACK (127.0.0.1).
*/
public static boolean isLoopback(InetAddress host) {
return LOOPBACK.equals(host);
}
/**
* Returns true if host matches the LOOPBACK (127.0.0.1).
*/
public static boolean isLoopback(String host) {
return isLoopback(toInetAddress(host));
}
/**
* Returns a version of the value after removing any leading slashes
*/
protected static String trimLeadingSlash(String value) {
if (value == null) {
return "";
}
while (value.indexOf('/') > -1) {
value = value.substring(value.indexOf('/') + 1);
}
return value;
}
/**
* Converts the string host to an instance of {@code InetAddress}. Returns null if the string is
* empty. Any leading slashes on host will be ignored.
*
* @param host The string version the InetAddress
*
* @return The host converted to InetAddress instance
*
* @throws UnknownHostException if no IP address for the {@code host} could be found
*/
protected static InetAddress toInetAddressOrThrow(String host) throws UnknownHostException {
if (host == null || host.isEmpty()) {
return null;
}
if (host.contains("/")) {
return InetAddress.getByName(host.substring(host.indexOf('/') + 1));
}
return InetAddress.getByName(host);
}
/**
* Validates the host by making sure it can successfully be used to get an instance of
* InetAddress. Any leading slashes on host will be ignored. If the host string is null or empty
* then null is returned.
*
* @param host The string version the InetAddress
*
* @return The host converted to InetAddress instance
*
* @throws UnknownHostException if no IP address for the {@code host} could be found
*/
protected static String validateHostOrThrow(String host) throws UnknownHostException {
if (host == null || host.isEmpty()) {
return null;
}
InetAddress.getByName(trimLeadingSlash(host));
return host;
}
/**
* Returns an {@code InetAddress} representing the local host. The checked exception
* {@code UnknownHostException} is captured and an AssertionError is generated instead.
*
* @return The InetAddress instance representing the local host
*
* @throws AssertionError If conversion of host results in {@code UnknownHostException}
*/
private static InetAddress getLocalHost() {
try {
return SocketCreator.getLocalHost();
} catch (UnknownHostException e) {
throw new AssertionError("Failed to get local host", e);
}
}
}