/*
 * Created on Oct 8, 2008 (C) Copyright TANDBERG Television Ltd.
 */

package com.tandbergtv.workflow.util;

import java.io.IOException;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.MalformedURLException;
import java.net.NetworkInterface;
import java.net.URL;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;

/**
 * Resolves the host name to IP address in any URL
 * 
 * @author Kinjal Mehta
 */
public class HostnameResolver {

    public static void main(String[] args) throws Exception, UnknownHostException {
        System.out.println(HostnameResolver.replaceURLWithIP("http://127.0.0.1:8888/jinfonet/tryView.jsp?reportName=/WPCatalog/AvgQTimeByRG.cls&catalogName=/WPCatalog/WPCatalog.cat&jrs.auth_uid=cms&&jrs.auth_pwd=cms&reportVersion=1&cms_session_id=1&cms_session_rec_id=1"));
    }
	/**
	 * Resolves the hostname in the specified string representation of a URL and generates a new URL
	 * containing the IP address in place of the hostname. If the hostname in the specified URL is
	 * an IP address, the return value is equal to the input
	 *
	 * @param urlValue the URL string in which to replace all hostnames with IP addresses
	 * @return the updated URL
	 * @throws MalformedURLException the input URL is not a valid URL
	 * @throws UnknownHostException the input URL has a host which cannot be resolved
	 */
	public static String replaceURLWithIP(String urlValue) throws MalformedURLException, UnknownHostException {
		URL url = new URL(urlValue);
		String ip = getIPByHostname(url.getHost());
		URL updatedUrl = new URL(url.getProtocol(), ip, url.getPort(), url.getFile());
		
		return updatedUrl.toExternalForm();
	}

	private static String getIPByHostname(String hostname) throws UnknownHostException {
		return InetAddress.getByName(hostname).getHostAddress();
	}
	
	/**
	 * Resolves the specified hostname to an IP address on the local host. Even if there is no
	 * explicit mapping of the hostname, one of the IP addresses on this host will be returned.
	 *  
	 * Ensure that the specified hostname is not mapped to a remote machine, or else the result 
	 * will be unexpected.
	 * 
	 * @param hostname
	 * @return
	 * @throws IOException 
	 */
	public static String resolveLocalName(String hostname) throws IOException {
		String addr = null;
		
		try {
			addr = getIPByHostname(hostname);
		} catch (UnknownHostException e) {
			/* We're just going to use the local IP address, no worries */
			List<String> addresses = getHostAddresses();
			
			if (addresses.isEmpty())
				throw new IOException("No IP addresses configured");
			
			addr = addresses.get(0);
		}
		
		return addr;
	}
	
	private static List<String> getHostAddresses() {
		List<String> addresses = new ArrayList<String>();
		
		try {
			InetAddress localhost = InetAddress.getByName("localhost");
			Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();

			while (interfaces.hasMoreElements()) {
				NetworkInterface ni = interfaces.nextElement();

				Enumeration<InetAddress> ips = ni.getInetAddresses();

				while (ips.hasMoreElements()) {
					InetAddress ip = ips.nextElement();

					if (ip instanceof Inet6Address)
						continue;

					if (!ip.getHostAddress().equals(localhost.getHostAddress()))
						addresses.add(ip.getHostAddress());
				}
			}
		} catch (IOException e) {
		}

		return addresses;
	}
}
