001/**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  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.apache.camel.util;
018
019import java.net.InetAddress;
020import java.net.NetworkInterface;
021import java.net.SocketException;
022import java.net.UnknownHostException;
023import java.util.Enumeration;
024import java.util.LinkedHashSet;
025import java.util.Map;
026import java.util.Set;
027import java.util.TreeMap;
028
029public final class HostUtils {
030
031    private HostUtils() {
032        //Utility Class
033    }
034
035    /**
036     * Returns a {@link Map} of {@link InetAddress} per {@link NetworkInterface}.
037     */
038    public static Map<String, Set<InetAddress>> getNetworkInterfaceAddresses() {
039        //JVM returns interfaces in a non-predictable order, so to make this more predictable
040        //let's have them sort by interface name (by using a TreeMap).
041        Map<String, Set<InetAddress>> interfaceAddressMap = new TreeMap<>();
042        try {
043            Enumeration<NetworkInterface> ifaces = NetworkInterface.getNetworkInterfaces();
044            while (ifaces.hasMoreElements()) {
045                NetworkInterface iface = ifaces.nextElement();
046                //We only care about usable non-loopback interfaces.
047                if (iface.isUp() && !iface.isLoopback() && !iface.isPointToPoint()) {
048                    String name = iface.getName();
049                    Enumeration<InetAddress> ifaceAdresses = iface.getInetAddresses();
050                    while (ifaceAdresses.hasMoreElements()) {
051                        InetAddress ia = ifaceAdresses.nextElement();
052                        //We want to filter out mac addresses
053                        if (!ia.isLoopbackAddress() && !ia.getHostAddress().contains(":")) {
054                            Set<InetAddress> addresses = interfaceAddressMap.get(name);
055                            if (addresses == null) {
056                                addresses = new LinkedHashSet<>();
057                            }
058                            addresses.add(ia);
059                            interfaceAddressMap.put(name, addresses);
060                        }
061                    }
062                }
063            }
064        } catch (SocketException ex) {
065            //noop
066        }
067        return interfaceAddressMap;
068    }
069
070    /**
071     * Returns a {@link Set} of {@link InetAddress} that are non-loopback or mac.
072     */
073    public static Set<InetAddress> getAddresses() {
074        Set<InetAddress> allAddresses = new LinkedHashSet<>();
075        Map<String, Set<InetAddress>> interfaceAddressMap = getNetworkInterfaceAddresses();
076        for (Map.Entry<String, Set<InetAddress>> entry : interfaceAddressMap.entrySet()) {
077            Set<InetAddress> addresses = entry.getValue();
078            if (!addresses.isEmpty()) {
079                for (InetAddress address : addresses) {
080                    allAddresses.add(address);
081                }
082            }
083        }
084        return allAddresses;
085    }
086
087
088    /**
089     * Chooses one of the available {@link InetAddress} based on the specified preference.
090     */
091    private static InetAddress chooseAddress() throws UnknownHostException {
092        Set<InetAddress> addresses = getAddresses();
093        if (addresses.contains(InetAddress.getLocalHost())) {
094            //Then if local host address is not bound to a loop-back interface, use it.
095            return InetAddress.getLocalHost();
096        } else if (addresses != null && !addresses.isEmpty()) {
097            //else return the first available addrress
098            return addresses.toArray(new InetAddress[addresses.size()])[0];
099        } else {
100            //else we are forcedt to use the localhost address.
101            return InetAddress.getLocalHost();
102        }
103    }
104
105    /**
106     * Returns the local hostname. It loops through the network interfaces and returns the first non loopback hostname
107     */
108    public static String getLocalHostName() throws UnknownHostException {
109        return chooseAddress().getHostName();
110    }
111
112    /**
113     * Returns the local IP. It loops through the network interfaces and returns the first non loopback address
114     */
115    public static String getLocalIp() throws UnknownHostException {
116        return chooseAddress().getHostAddress();
117    }
118
119}