org.ngrinder.recorder.util.NetworkUtil.java Source code

Java tutorial

Introduction

Here is the source code for org.ngrinder.recorder.util.NetworkUtil.java

Source

/* 
 * 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 org.ngrinder.recorder.util;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
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.Socket;
import java.net.SocketAddress;
import java.net.SocketException;
import java.net.URL;
import java.net.URLConnection;
import java.net.UnknownHostException;
import java.util.Enumeration;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.ngrinder.recorder.infra.NGrinderRuntimeException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Common network utility. This contains very careful implementation to detect current machine's ip.
 * There are the following cases which block to get the appropriate ip.
 * 
 * <ul>
 * <li>If there are VM in the same machine</li>
 * <li>If /etc/hosts are not very well specified</li>
 * </ul>
 * 
 * @author JunHo Yoon
 * @author Mavlarn
 * 
 * @since 1.0
 * 
 */
public abstract class NetworkUtil {
    private static final Logger LOGGER = LoggerFactory.getLogger(NetworkUtil.class);

    /**
     * Get the available port using the given default port. If it's not available, it chooses the
     * random port.
     * 
     * @param localHostAddress
     *            address in which the port will be assigned.
     * @param defaultPort
     *            default port.
     * @return usable port.
     */
    public static int getAvailablePort(InetAddress localHostAddress, int defaultPort) {
        ServerSocket socket = null;
        try {
            socket = new ServerSocket(defaultPort, 50, localHostAddress);

            return socket.getLocalPort();
        } catch (IOException e) {
            LOGGER.error("Error during openning port. {}", e.getMessage());
            LOGGER.debug("Details:{}", e.getMessage(), e);
            return getAvailablePort(localHostAddress);
        } finally {
            if (socket != null) {
                try {
                    socket.close();
                } catch (IOException e) {
                    LOGGER.error("Error during port close");
                }
            }
        }
    }

    /**
     * Get a available port.
     * 
     * @param localHostAddress
     *            localHostAddress
     * 
     * @return min port available from scanStartPort
     */
    public static int getAvailablePort(InetAddress localHostAddress) {
        ServerSocket socket = null;
        try {
            socket = new ServerSocket(0, 50, localHostAddress);
            return socket.getLocalPort();
        } catch (IOException e) {
            LOGGER.error("Error during openning port. {}", e.getMessage());
            LOGGER.debug("Details:{}", e.getMessage(), e);
            return 16000;
        } finally {
            if (socket != null) {
                try {
                    socket.close();
                } catch (IOException e) {
                    LOGGER.error("Error during closing port");
                }
            }
        }
    }

    /**
     * Get the local host address, try to get actual IP.
     * 
     * @return ip form of host address
     */
    public static InetAddress getLocalHostAddress() {
        InetAddress localHost = null;
        try {
            localHost = getFirstNonLoopbackAddress(true, false);
        } catch (Exception e) {
            LOGGER.error("Error while get localhost address", e);
        }
        if (localHost != null && !localHost.isLoopbackAddress()) {
            return localHost;
        }
        try {
            localHost = InetAddress.getLocalHost();
        } catch (Exception e) {
            LOGGER.error("Error while get localhost address", e);
        }
        if (!localHost.isLoopbackAddress()) {
            return localHost;
        }
        return getLocalHostAddress("www.google.com", 80);
    }

    /**
     * Get local address by connecting to a server.
     * 
     * @param byConnecting
     *            the server address to connect.
     * @param port
     *            the port to connect
     * @return IP address local IP address
     */
    public static InetAddress getLocalHostAddress(String byConnecting, int port) {
        InetAddress addr = getLocalInetAddress(byConnecting, port);
        if (addr != null) {
            return addr;
        } else {
            // It's final...
            try {
                return InetAddress.getByName("127.0.0.1");
            } catch (UnknownHostException e) {
                return null;
            }
        }
    }

    /**
     * Get local host name by connecting to a server.
     * 
     * @param byConnecting
     *            the server address to connect.
     * @param port
     *            the port to connect
     * @return localhost name. if fails, return "localhost"
     */
    public static String getLocalHostName(String byConnecting, int port) {
        InetAddress addr = getLocalInetAddress(byConnecting, port);
        if (addr != null) {
            return addr.getHostName();
        } else {
            return "localhost";
        }
    }

    private static InetAddress getLocalInetAddress(String byConnecting, int port) {
        InetAddress addr = getAddressWithSocket(byConnecting, port);
        if (addr == null) {
            addr = getAddressWithSocket("www.baidu.com", 80);
        }
        return addr;
    }

    private static InetAddress getAddressWithSocket(String byConnecting, int port) {
        Socket s = null;
        try {
            s = new Socket();
            SocketAddress addr = new InetSocketAddress(byConnecting, port);
            s.connect(addr, 2000); // 2 seconds timeout
            return s.getLocalAddress();
        } catch (Exception e) {
            return null;
        } finally {
            IOUtils.closeQuietly(s);
        }
    }

    private static InetAddress getFirstNonLoopbackAddress(boolean preferIpv4, boolean preferIPv6)
            throws SocketException {
        Enumeration<?> en = NetworkInterface.getNetworkInterfaces();
        while (en.hasMoreElements()) {
            NetworkInterface i = (NetworkInterface) en.nextElement();
            if (!i.isUp()) {
                continue;
            }
            if (StringUtils.containsIgnoreCase(i.getDisplayName(), "Host-Only")) {
                continue;
            }
            for (Enumeration<?> en2 = i.getInetAddresses(); en2.hasMoreElements();) {
                InetAddress addr = (InetAddress) en2.nextElement();
                if (!addr.isLoopbackAddress()) {
                    if (addr instanceof Inet4Address) {
                        if (preferIPv6) {
                            continue;
                        }
                        return addr;
                    }
                    if (addr instanceof Inet6Address) {
                        if (preferIpv4) {
                            continue;
                        }
                        return addr;
                    }
                }
            }
        }
        return null;
    }

    /**
     * Get local host name. On some platform, InetAddress.getLocalHost().getHostName() will return
     * "localhost". If the /etc/hosts file is not set properly, it will return "localhost" or throw
     * exception. So, at this circumstance, we will get the address by connecting a network address.
     * 
     * @return local host name
     */
    public static String getLocalHostName() {
        String hostName = null;
        try {
            hostName = InetAddress.getLocalHost().getHostName();
        } catch (Exception e) {
            LOGGER.error("Error while get localhost name", e);
        }
        if (hostName != null && !"localhost".equals(hostName)) {
            return hostName;
        }
        return getLocalHostName("www.google.com", 80);

    }

    /**
     * Get the IP addresses from host name.
     * 
     * @param host
     *            host
     * @return {@link InetAddress} array
     */
    public static InetAddress[] getIpsFromHost(String host) {
        try {
            return InetAddress.getAllByName(host);
        } catch (UnknownHostException e) {
            LOGGER.error("Error while get localhost name for {}", host, e);
            return new InetAddress[] {};
        }
    }

    /**
     * Download a file from the given URL string.
     * 
     * @param urlString
     *            URL string
     * @param toFile
     *            file to be saved.
     */
    public static void downloadFile(String urlString, File toFile) {
        FileOutputStream os = null;
        InputStream in = null;
        URLConnection connection = null;
        try {
            URL url = new URL(urlString);
            connection = url.openConnection();
            connection.connect();
            byte[] buffer = new byte[4 * 1024];
            int read;
            os = new FileOutputStream(toFile);
            in = connection.getInputStream();
            while ((read = in.read(buffer)) > 0) {
                os.write(buffer, 0, read);
            }
        } catch (Exception e) {
            LOGGER.error("download file from {} was failed", urlString, e);
            throw new NGrinderRuntimeException("Error while download " + urlString, e);
        } finally {
            ((HttpURLConnection) connection).disconnect();
            IOUtils.closeQuietly(os);
            IOUtils.closeQuietly(in);
        }
        return;
    }

    private static final String PATTERN = "^([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\."
            + "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." + "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\."
            + "([01]?\\d\\d?|2[0-4]\\d|25[0-5])$";

    private static final Pattern IP_PATTERN = Pattern.compile(PATTERN);

    /**
     * Check if the given IP is well formed.
     * 
     * @param ip
     *            ip
     * @return true if valid
     */
    public static boolean isValidIP(final String ip) {
        Matcher matcher = IP_PATTERN.matcher(ip);
        return matcher.matches();
    }
}