/* * Copyright 2005-2010 Ignis Software Tools Ltd. All rights reserved. */ package jsystem.runner.remote; import java.net.BindException; import java.net.ServerSocket; import java.util.logging.Level; import java.util.logging.Logger; import java.util.regex.Matcher; import java.util.regex.Pattern; import jsystem.utils.StringUtils; /** * Utility class which replaces port number template with real port number. * The class was implemented to solve the following problem: * When adding debug parameters (or jmx parameters) to the test vm parameters: * For example: -classic -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y * and running in run.mode=2, the first test runs okay, the second test fails * to bind to the port 8787 since it is occupied by the previous jvm. * (it takes the jvm ~10 seconds to close) * To solve this problem, the user can enter the following: * ... ,address=${8787},server=y,suspend=y * The replaceSocketNumber will replace the pattern ${XXX} with the first free * port starting at XXX. * In our example, if port 8787 is free the method will return * ...,address=8787,server=y,suspend=y * if port 8787 is not free the method will return * ...,address=8788,server=y,suspend=y etc' * * If for some reason, fetching available port fails the method returns * start port number. * * @author goland */ public class TestVMParamsUtil { private static Logger log = Logger.getLogger(TestVMParamsUtil.class.getName()); private static Pattern p = Pattern.compile("\\$\\{(\\d*)\\}"); /** * Replaces port pattern with actual free port number. * See class documentation. */ public String relpaceSocketNumber(String vmParams) throws Exception { Matcher m = p.matcher(vmParams); while (m.find()){ int startPort = Integer.parseInt(m.group(1)); int finalPort = findFreeServerSocket(startPort); vmParams = StringUtils.replace(vmParams, m.group(0), ""+finalPort); } return vmParams; } /** * Finds a free port starting at <code>startNumber</code> */ private int findFreeServerSocket(int startNumber) { boolean found = false; int portNumber = startNumber; ServerSocket socket = null; ; while (!found) { try { socket = new ServerSocket(portNumber); found = true; } catch (BindException e) { log.log(Level.FINEST, "port " + portNumber + " not available"); portNumber += 1; } catch (Exception e) { log.log(Level.WARNING, "failed checking port " + portNumber, e); return startNumber; } finally { try { socket.close(); } catch (Throwable t) { }; } } return portNumber; } }