blob: 1c09a4c4c5d1282435f2c7735a5fcf28e5113206 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2003, 2005 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - Initial API and implementation
*******************************************************************************/
package org.eclipse.wst.server.core.util;
import java.io.IOException;
import java.lang.reflect.Method;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.SocketException;
import java.util.Random;
import org.eclipse.wst.server.core.internal.Trace;
/**
* A utility class for socket-related function. It's main purposes are to find
* unused ports, check whether a port is in use, and check whether a given
* address is a local(host) address.
*
* @since 1.0
*/
public class SocketUtil {
private static final Random rand = new Random(System.currentTimeMillis());
private static String dnsHostname;
private static final String DNSNAMESERVICE_CLASS = "sun.net.spi.nameservice.dns.DNSNameService";
/**
* Static utility class - cannot create an instance.
*/
private SocketUtil() {
// cannot create
}
/**
* Finds an unused port between the given from and to values.
*
* @param low lowest possible port number
* @param high highest possible port number
* @return an usused port number, or <code>-1</code> if no used ports could be found
*/
public static int findUnusedPort(int low, int high) {
if (high < low)
return -1;
for (int i = 0; i < 10; i++) {
int port = getRandomPort(low, high);
if (!isPortInUse(port))
return port;
}
return -1;
}
/**
* Return a random port number in the given range.
*
* @param low lowest possible port number
* @param high highest possible port number
* @return a random port number in the given range
*/
private static int getRandomPort(int low, int high) {
return rand.nextInt(high - low) + low;
}
/**
* Checks to see if the given port number is being used.
* Returns <code>true</code> if the given port is in use, and <code>false</code>
* otherwise. Retries every 500ms for "count" tries.
*
* @param port the port number to check
* @param count the number of times to retry
* @return boolean <code>true</code> if the port is in use, and
* <code>false</code> otherwise
*/
public static boolean isPortInUse(int port, int count) {
boolean inUse = isPortInUse(port);
while (inUse && count > 0) {
try {
Thread.sleep(500);
} catch (Exception e) {
// ignore
}
inUse = isPortInUse(port);
count --;
}
return inUse;
}
/**
* Checks to see if the given port number is being used.
* Returns <code>true</code> if the given port is in use, and <code>false</code>
* otherwise.
*
* @param port the port number to check
* @return boolean <code>true</code> if the port is in use, and
* <code>false</code> otherwise
*/
public static boolean isPortInUse(int port) {
ServerSocket s = null;
try {
s = new ServerSocket(port);
} catch (SocketException e) {
return true;
} catch (IOException e) {
return true;
} catch (Exception e) {
return true;
} finally {
if (s != null) {
try {
s.close();
} catch (Exception e) {
// ignore
}
}
}
return false;
}
/**
* Checks if the given host (name or IP address) is pointing to the local
* machine.
* Although this method is not foolproof (especially if the network
* configuration of the current machine is incorrect or failing), it will
* correctly identify just about all loopback adapters and the local hostname
* or IP address.
* <p>
* This method will not attempt to make an external network connection, so
* it returns quickly and is safe to use in UI interfaces.
* </p>
*
* @param host a hostname or IP address
* @return <code>true</code> if the given host is localhost, and
* <code>false</code> otherwise
*/
public static boolean isLocalhost(String host) {
if (host == null)
return false;
try {
if ("localhost".equals(host) || "127.0.0.1".equals(host))
return true;
InetAddress localHostaddr = InetAddress.getLocalHost();
if (localHostaddr.getHostName().equals(host) || host.equals(localHostaddr.getCanonicalHostName()))
return true;
if (localHostaddr.getHostAddress().equals(host))
return true;
if (dnsHostname == null)
try {
// workaround to break dependency with Sun's classes
Class cl = Class.forName(DNSNAMESERVICE_CLASS);
Method getHostByAddrMeth = cl.getMethod("getHostByAddr", new Class[] {byte[].class});
Object dns = cl.newInstance();
dnsHostname = (String)getHostByAddrMeth.invoke(dns,
new Object[] { localHostaddr.getAddress() });
} catch (Throwable t) {
dnsHostname = "*****************";
}
if (dnsHostname != null && dnsHostname.equals(host))
return true;
} catch (Exception e) {
Trace.trace(Trace.WARNING, "Error checking for localhost", e);
}
return false;
}
}