From 7396a3d446b4277ab1181ec82758e3fc5d9c7a73 Mon Sep 17 00:00:00 2001 From: Maksim Chizhov Date: Mon, 30 May 2016 16:06:54 +0200 Subject: [PATCH] Make it possible to configure port names using external resources Url could be - regular file on file system - any file within classpath Resource file should be in plain text format with `new line` character as separator. Lines starting with `#` considered commented and therefore are ignored. Signed-off-by: Maksim Chizhov --- .../invoker.properties | 2 + src/it/reserve-ports-with-urls/names1.txt | 4 + src/it/reserve-ports-with-urls/names2.txt | 4 + src/it/reserve-ports-with-urls/pom.xml | 79 ++++++++++ src/it/reserve-ports-with-urls/verify.groovy | 10 ++ .../buildhelper/ReserveListenerPortMojo.java | 144 +++++++++++++++++- src/site/apt/usage.apt.vm | 50 ++++++ 7 files changed, 288 insertions(+), 5 deletions(-) create mode 100644 src/it/reserve-ports-with-urls/invoker.properties create mode 100644 src/it/reserve-ports-with-urls/names1.txt create mode 100644 src/it/reserve-ports-with-urls/names2.txt create mode 100644 src/it/reserve-ports-with-urls/pom.xml create mode 100644 src/it/reserve-ports-with-urls/verify.groovy diff --git a/src/it/reserve-ports-with-urls/invoker.properties b/src/it/reserve-ports-with-urls/invoker.properties new file mode 100644 index 00000000..2cf67a98 --- /dev/null +++ b/src/it/reserve-ports-with-urls/invoker.properties @@ -0,0 +1,2 @@ +invoker.goals = test +invoker.buildResult = success \ No newline at end of file diff --git a/src/it/reserve-ports-with-urls/names1.txt b/src/it/reserve-ports-with-urls/names1.txt new file mode 100644 index 00000000..66e755c9 --- /dev/null +++ b/src/it/reserve-ports-with-urls/names1.txt @@ -0,0 +1,4 @@ + # Port names +port1 +port2 +port3 \ No newline at end of file diff --git a/src/it/reserve-ports-with-urls/names2.txt b/src/it/reserve-ports-with-urls/names2.txt new file mode 100644 index 00000000..ac79a30e --- /dev/null +++ b/src/it/reserve-ports-with-urls/names2.txt @@ -0,0 +1,4 @@ + # Port names +port4 +port5 +port6 \ No newline at end of file diff --git a/src/it/reserve-ports-with-urls/pom.xml b/src/it/reserve-ports-with-urls/pom.xml new file mode 100644 index 00000000..e65f5911 --- /dev/null +++ b/src/it/reserve-ports-with-urls/pom.xml @@ -0,0 +1,79 @@ + + 4.0.0 + + org.codehaus.mojo + build-helper-maven-plugin-reverse-port-it + 1.0-SNAPSHOT + build-helper-maven-plugin-reverse-port-it + + + package + + + @project.groupId@ + @project.artifactId@ + @project.version@ + + + reserve-ports + process-test-resources + + reserve-network-port + + + + file://${project.basedir}/names2.txt + + + + + reserve-ports-to-files + process-test-resources + + reserve-network-port + + + ${project.build.directory}/ports.properties + + file://${project.basedir}/names1.txt + file://${project.basedir}/names2.txt + + + + + + + maven-antrun-plugin + + + mk-target-dir + compile + + run + + + + + + + + + + echo-reserve-ports + test + + run + + + + port1=${port1} + port2=${port2} + port3=${port3} + + + + + + + + diff --git a/src/it/reserve-ports-with-urls/verify.groovy b/src/it/reserve-ports-with-urls/verify.groovy new file mode 100644 index 00000000..d24d75bd --- /dev/null +++ b/src/it/reserve-ports-with-urls/verify.groovy @@ -0,0 +1,10 @@ +File file = new File( basedir, "build.log" ); +assert file.exists(); + +String text = file.getText("utf-8"); + +assert text.contains("port1=") +assert text.contains("port2=") +assert text.contains("port3=") + +return true; diff --git a/src/main/java/org/codehaus/mojo/buildhelper/ReserveListenerPortMojo.java b/src/main/java/org/codehaus/mojo/buildhelper/ReserveListenerPortMojo.java index 66297986..889869df 100644 --- a/src/main/java/org/codehaus/mojo/buildhelper/ReserveListenerPortMojo.java +++ b/src/main/java/org/codehaus/mojo/buildhelper/ReserveListenerPortMojo.java @@ -24,11 +24,17 @@ * SOFTWARE. */ +import java.io.BufferedInputStream; +import java.io.BufferedReader; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; import java.io.OutputStream; +import java.net.MalformedURLException; import java.net.ServerSocket; +import java.net.URL; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; @@ -63,12 +69,21 @@ public class ReserveListenerPortMojo private static final Object lock = new Object(); /** - * A List to property names to be placed in Maven project + * A List to property names to be placed in Maven project. At least one of {@code #urls} or {@code #portNames} has to be specified. * * @since 1.2 */ - @Parameter( required = true ) - private final String[] portNames = new String[0]; + @Parameter + private String[] portNames = new String[0]; + + /** + * A List of urls to resource where list of name could be found. Can be in + * form of classpath:com/myproject/names.txt . At least one of {@code #urls} or {@code #portNames} has to be specified. + * + * @since 1.11 + */ + @Parameter + private String[] urls = new String[0]; /** * Output file to write the generated properties to. if not given, they are written to Maven project @@ -124,6 +139,8 @@ public void execute() properties = new Properties(); } + loadUrls(); + // Reserve the entire block of ports to guarantee we don't get the same port twice final List sockets = new ArrayList(); try @@ -231,8 +248,9 @@ private ServerSocket getServerSocket() { ServerSocket serverSocket = reservePort( port ); - if ( serverSocket != null ) + if ( serverSocket != null ) { return serverSocket; + } } } } @@ -241,7 +259,7 @@ private ServerSocket getServerSocket() private List randomPortList() { - int difference = ( maxPortNumber - minPortNumber ) + 1; + int difference = maxPortNumber - minPortNumber + 1; List portList = new ArrayList( difference ); List reservedPorts = getReservedPorts(); for ( int i = 0; i < difference; i++ ) @@ -328,4 +346,120 @@ private int findAvailablePortNumber( Integer portNumberStartingPoint, List names = new ArrayList(); + String line; + while ((line = reader.readLine()) != null) { + line = line.trim(); + if (!line.isEmpty() && !line.replace(" ", "").startsWith("#")) { + names.add(line); + } + } + if (getLog().isDebugEnabled()) { + getLog().debug("Loaded port names " + names); + } + String[] tPortNames = names.toArray(new String[portNames.length + names.size()]); + if (portNames.length > 0) { + System.arraycopy(portNames, 0, tPortNames, names.size(), portNames.length); + } + portNames = tPortNames; + } finally { + stream.close(); + } + } catch (IOException e) { + throw new MojoExecutionException("Error reading port names from \"" + resource + "\"", e); + } + } + + private class UrlResource { + private static final String CLASSPATH_PREFIX = "classpath:"; + + private static final String SLASH_PREFIX = "/"; + + private final URL url; + + private boolean isMissingClasspathResouce = false; + + private String classpathUrl; + + private InputStream stream; + + public UrlResource(String url) + throws MojoExecutionException { + if (url.startsWith(CLASSPATH_PREFIX)) { + String resource = url.substring(CLASSPATH_PREFIX.length(), url.length()); + if (resource.startsWith(SLASH_PREFIX)) { + resource = resource.substring(1, resource.length()); + } + this.url = getClass().getClassLoader().getResource(resource); + if (this.url == null) { + if (getLog().isDebugEnabled()) { + getLog().debug("Can not load classpath resouce \"" + url + "\""); + } + isMissingClasspathResouce = true; + classpathUrl = url; + } + } else { + try { + this.url = new URL(url); + } catch (MalformedURLException e) { + throw new MojoExecutionException("Badly formed URL " + url + " - " + e.getMessage()); + } + } + } + + public InputStream getInputStream() throws IOException { + if (stream == null) { + stream = openStream(); + } + return stream; + } + + public boolean canBeOpened() { + if (isMissingClasspathResouce) { + return false; + } + try { + openStream().close(); + } catch (IOException e) { + return false; + } + return true; + } + + private InputStream openStream() throws IOException { + return new BufferedInputStream(url.openStream()); + } + + @Override + public String toString() { + if (!isMissingClasspathResouce) { + return "URL " + url.toString(); + } + return classpathUrl; + } + } } diff --git a/src/site/apt/usage.apt.vm b/src/site/apt/usage.apt.vm index 914a469c..17b25e93 100644 --- a/src/site/apt/usage.apt.vm +++ b/src/site/apt/usage.apt.vm @@ -438,6 +438,56 @@ releasedVersion.incrementalVersion +------------------- + It is also possible to define port names via resource file(s). Resources in classpath are also supported (artifact + with resource has to be defined in plugin dependencies section). + + <<>> and <<>> parameters can be combined. + +------------------- + + ... + + + + org.codehaus.mojo + build-helper-maven-plugin + ${project.version} + + + jar-with-port-names.txt + [...] + + + + reserve-network-port + + reserve-network-port + + process-resources + + + file://${project.basedir}/names1.txt + classpath:port-names.txt + + + + + + + [...] + + + + +------------------- + port-names.txt: + +------------------- +# Selenium port name +selenium.server.port +# Tomcat port name +tomcat.http.port ------------------- * Set a property by applying a regex replacement to a value