All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.oracle.tools.io.NetworkHelper Maven / Gradle / Ivy

/*
 * File: NetworkHelper.java
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * The contents of this file are subject to the terms and conditions of 
 * the Common Development and Distribution License 1.0 (the "License").
 *
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the License by consulting the LICENSE.txt file
 * distributed with this file, or by consulting https://oss.oracle.com/licenses/CDDL
 *
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing the software, include this License Header Notice in each
 * file and include the License file LICENSE.txt.
 *
 * MODIFICATIONS:
 * If applicable, add the following below the License Header, with the fields
 * enclosed by brackets [] replaced by your own identifying information:
 * "Portions Copyright [year] [name of copyright owner]"
 */

package com.oracle.tools.io;

import com.oracle.tools.predicate.Predicate;
import com.oracle.tools.predicate.Predicates;

import static com.oracle.tools.predicate.Predicates.always;

import java.io.IOException;

import java.net.DatagramSocket;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.NetworkInterface;
import java.net.ServerSocket;
import java.net.SocketException;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Enumeration;
import java.util.LinkedList;
import java.util.List;

/**
 * Common Network utilities.
 * 

* Copyright (c) 2014. All Rights Reserved. Oracle Corporation.
* Oracle is a registered trademark of Oracle Corporation and/or its affiliates. * * @author Brian Oliver */ public class NetworkHelper { /** * The {@link Predicate} for the LOOPBACK {@link InetAddress}. */ public static final Predicate LOOPBACK_ADDRESS = new Predicate() { @Override public boolean evaluate(InetAddress address) { return address != null && address.isLoopbackAddress(); } @Override public String toString() { return "LOOPBACK"; } }; /** * The {@link Predicate} for the NON_LOOPBACK {@link InetAddress}. */ public static final Predicate NON_LOOPBACK_ADDRESS = new Predicate() { @Override public boolean evaluate(InetAddress address) { return address != null &&!address.isLoopbackAddress(); } @Override public String toString() { return "NON-LOOPBACK"; } }; /** * The {@link Predicate} for the IPv4 {@link InetAddress}. */ public static final Predicate IPv4_ADDRESS = new Predicate() { @Override public boolean evaluate(InetAddress address) { return address instanceof Inet4Address; } @Override public String toString() { return "IPv4-ADDRESS"; } }; /** * The {@link Predicate} for the IPv6 {@link InetAddress}. */ public static final Predicate IPv6_ADDRESS = new Predicate() { @Override public boolean evaluate(InetAddress address) { return address instanceof Inet6Address; } @Override public String toString() { return "IPv6-ADDRESS"; } }; /** * The {@link Predicate} for the Link Local {@link InetAddress}. */ public static final Predicate LINK_LOCAL_ADDRESS = new Predicate() { @Override public boolean evaluate(InetAddress address) { return address != null && address.isLinkLocalAddress(); } @Override public String toString() { return "LINK-LOCAL-ADDRESS"; } }; /** * The {@link Predicate} for any local {@link InetAddress}. */ public static final Predicate ANY_LOCAL_ADDRESS = new Predicate() { @Override public boolean evaluate(InetAddress address) { return address != null && address.isAnyLocalAddress(); } @Override public String toString() { return "ANY-LOCAL-ADDRESS"; } }; /** * The {@link Predicate} for the DEFAULT {@link InetAddress}, based on the * defined system properties java.net.preferIPv4Stack and java.net.preferIPv6Addresses. */ public static final Predicate DEFAULT_ADDRESS = new Predicate() { @Override public boolean evaluate(InetAddress address) { Predicate predicate; if (Boolean.getBoolean("java.net.preferIPv4Stack")) { predicate = NetworkHelper.IPv4_ADDRESS; } else if (Boolean.getBoolean("java.net.preferIPv6Addresses")) { predicate = NetworkHelper.IPv6_ADDRESS; } else { predicate = always(); } return predicate.evaluate(address); } }; /** * The {@link Predicate} to test if it is possible to bind to an {@link InetAddress}. */ public static final Predicate BINDABLE_ADDRESS = new Predicate() { @Override public boolean evaluate(InetAddress address) { try (ServerSocket serverSocket = new ServerSocket(0, 1, address); DatagramSocket datagramSocket = new DatagramSocket(0, address)) { return true; } catch (IOException e) { return false; } } @Override public String toString() { return "BINDABLE_ADDRESS"; } }; /** * Acquires the first {@link InetAddress} (of the machine on which this code is executing) * that matches the specified {@link Predicate}. * * @return an {@link InetAddress} or null if no matching {@link InetAddress} * * @throws SocketException */ public static InetAddress getInetAddress(Predicate predicate) throws SocketException { for (NetworkInterface networkInterface : getNetworkInterfaces(Predicates.always())) { for (Enumeration addresses = networkInterface.getInetAddresses(); addresses.hasMoreElements(); ) { InetAddress address = (InetAddress) addresses.nextElement(); if (predicate.evaluate(address)) { return address; } } } return null; } /** * Obtains the list of {@link InetAddress}es (of the machine on which this code is executing) * that matches the specified {@link Predicate}. * * @return a {@link List} of {@link InetAddress} matching the {@link Predicate} or an empty * list if no matching {@link InetAddress} can be found */ public static List getInetAddresses(Predicate predicate) { LinkedList addressList = new LinkedList<>(); for (NetworkInterface networkInterface : getNetworkInterfaces(Predicates.always())) { for (Enumeration addresses = networkInterface.getInetAddresses(); addresses.hasMoreElements(); ) { InetAddress address = (InetAddress) addresses.nextElement(); try { if (predicate.evaluate(address)) { addressList.add(address); } } catch (Exception e) { // ignore the address if an exception occurred } } } return addressList; } /** * Obtains the list of {@link NetworkInterface}s (of the machine on which this code is executing), * ordered by {@link NetworkInterface#getIndex()}, that satisfy the specified {@link Predicate}. * * @return a list of {@link NetworkInterface}s */ public static List getNetworkInterfaces(Predicate predicate) { ArrayList networkInterfaces = new ArrayList<>(); try { // create the list of filtered network interfaces Enumeration enumeration = NetworkInterface.getNetworkInterfaces(); while (enumeration.hasMoreElements()) { NetworkInterface networkInterface = enumeration.nextElement(); if (predicate.evaluate(networkInterface)) { networkInterfaces.add(networkInterface); } } // sort the network interfaces by index Collections.sort(networkInterfaces, new Comparator() { @Override public int compare(NetworkInterface networkInterface1, NetworkInterface networkInterface2) { return networkInterface1.getIndex() - networkInterface2.getIndex(); } }); } catch (SocketException e) { // nothing to do when we've had an exception } return networkInterfaces; } /** * Obtains an {@link InetAddress} that is feasibly a reachable, bindable, non-loopback, site-local network address of the * localhost, especially in cases where a localhost is multi-homed with numerous virtual network adapters, including * loop-back. *

* This method will consult all of the network interfaces defined by the localhost to determine the * {@link InetAddress} that is feasibly a locally reachable network address. When a localhost has numerous network * interfaces, this method will return the first available and active site-local {@link InetAddress}, like 192.168.x.x * or 10.10.x.x. Should one not be available, this method will attempt to return the first non-loop-back address. * Should both of these approaches fail, the {@link InetAddress#getLocalHost()} will returned and failing that * not being available {@link InetAddress#getLoopbackAddress()} will be returned. */ public static InetAddress getFeasibleLocalHost() { try { InetAddress potentialInetAddress = null; // consider each of the NetworkInterfaces for (NetworkInterface networkInterface : getNetworkInterfaces(Predicates.always())) { // consider each of the InetAddresses defined by the NetworkInterface for (Enumeration inetAddresses = networkInterface.getInetAddresses(); inetAddresses.hasMoreElements(); ) { InetAddress inetAddress = inetAddresses.nextElement(); // ensure that we can bind to the address if (BINDABLE_ADDRESS.evaluate(inetAddress)) { // prefer non-loopback addresses if (!inetAddress.isLoopbackAddress()) { // prefer site-local addresses if (inetAddress.isSiteLocalAddress()) { // found a non-loopback site-local address! return inetAddress; } else if (potentialInetAddress == null) { // discovered a non-loopback but it's not site-local address (remember it just in case!) potentialInetAddress = inetAddress; } } } } } if (potentialInetAddress == null) { // we didn't discover a site-local or other non-loopback address, so we'll ask Java for the localhost potentialInetAddress = InetAddress.getLocalHost(); } if (potentialInetAddress == null) { // the localhost is undefined as well, so let's fall-back to loop-back potentialInetAddress = InetAddress.getLoopbackAddress(); } return potentialInetAddress; } catch (Exception e) { // TODO: log once that the address can't be discovered (we're probably without a network) return InetAddress.getLoopbackAddress(); } } /** * Obtains the wildcard address of the host. * * @return the {@link InetAddress} representing the wildcard address */ public static InetAddress getWildcardAddress() { return new InetSocketAddress(0).getAddress(); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy