/* * JBoss, Home of Professional Open Source * Copyright 2005-2008, Red Hat Middleware LLC, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.jboss.test.messaging.tools.container; import java.io.IOException; import java.net.InetAddress; import java.net.ServerSocket; import java.security.SecureRandom; import org.jboss.messaging.core.logging.Logger; /** * PortUtil is a set of utilities for dealing with TCP/IP ports * * @author <a href="mailto:jhaynie@vocalocity.net">Jeff Haynie</a> * @author <a href="mailto:tom@jboss.org">Tom Elrod</a> * @version $Revision$ */ public class PortUtil { private static final Logger log = Logger.getLogger(PortUtil.class); private static final int MIN_UNPRIVILEGED_PORT = 1024; private static final int MAX_LEGAL_PORT = 65535; private static int portCounter = 0; private static int retryMax = 50; static { portCounter = getRandomStartingPort(); } /** * Checks to see if the specified port is free. * * @param p * @return true if available, false if already in use */ public static boolean checkPort(int p, String host) { boolean available = true; ServerSocket socket = null; try { InetAddress inetAddress = InetAddress.getByName(host); socket = new ServerSocket(p, 0, inetAddress); } catch(IOException e) { log.debug("port " + p + " already in use. Will try another."); available = false; } finally { if(socket != null) { try { socket.close(); } catch(IOException e) { } } } return available; } /** * Will try to find a port that is not in use up to 50 tries, at which point, * will throw an exception. * @return */ public static int findFreePort(String host) throws IOException { Integer port = null; int tryCount = 0; while(port == null && tryCount < retryMax) { port = getFreePort(host); if(port != null) { // validate port again, just in case two instances start on the port at same time. if(!checkPort(port.intValue(), host)) { port = null; } } tryCount++; } if(tryCount >= retryMax) { throw new IOException("Can not find a free port for use."); } return port.intValue(); } private static Integer getFreePort(String host) { int p = getNextPort(); if(checkPort(p, host)) { return new Integer(p); } else { return null; } } private static synchronized int getNextPort() { if (portCounter < MAX_LEGAL_PORT) return portCounter++; portCounter = MIN_UNPRIVILEGED_PORT; return MAX_LEGAL_PORT; } public static int getRandomStartingPort() { Object o = new Object(); String os = o.toString(); os = os.substring(17); int n = Integer.parseInt(os, 16); int p = Math.abs(new SecureRandom(String.valueOf(System.currentTimeMillis() + n).getBytes()).nextInt(2000)) + 2000; return p; } }