Skip to content

Commit

Permalink
Make it possible to configure port names using external resources
Browse files Browse the repository at this point in the history
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 <maksim.chizhov@gmail.com>
  • Loading branch information
marc- committed Jul 1, 2016
1 parent f11e787 commit 7396a3d
Show file tree
Hide file tree
Showing 7 changed files with 288 additions and 5 deletions.
2 changes: 2 additions & 0 deletions src/it/reserve-ports-with-urls/invoker.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
invoker.goals = test
invoker.buildResult = success
4 changes: 4 additions & 0 deletions src/it/reserve-ports-with-urls/names1.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Port names
port1
port2
port3
4 changes: 4 additions & 0 deletions src/it/reserve-ports-with-urls/names2.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Port names
port4
port5
port6
79 changes: 79 additions & 0 deletions src/it/reserve-ports-with-urls/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin-reverse-port-it</artifactId>
<version>1.0-SNAPSHOT</version>
<name>build-helper-maven-plugin-reverse-port-it</name>

<build>
<defaultGoal>package</defaultGoal>
<plugins>
<plugin>
<groupId>@project.groupId@</groupId>
<artifactId>@project.artifactId@</artifactId>
<version>@project.version@</version>
<executions>
<execution>
<id>reserve-ports</id>
<phase>process-test-resources</phase>
<goals>
<goal>reserve-network-port</goal>
</goals>
<configuration>
<urls>
<url>file://${project.basedir}/names2.txt</url>
</urls>
</configuration>
</execution>
<execution>
<id>reserve-ports-to-files</id>
<phase>process-test-resources</phase>
<goals>
<goal>reserve-network-port</goal>
</goals>
<configuration>
<outputFile>${project.build.directory}/ports.properties</outputFile>
<urls>
<url>file://${project.basedir}/names1.txt</url>
<url>file://${project.basedir}/names2.txt</url>
</urls>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<id>mk-target-dir</id>
<phase>compile</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<tasks>
<mkdir dir="${project.build.directory}" />
</tasks>
</configuration>
</execution>

<execution>
<id>echo-reserve-ports</id>
<phase>test</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<tasks>
<echo>port1=${port1}</echo>
<echo>port2=${port2}</echo>
<echo>port3=${port3}</echo>
</tasks>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
10 changes: 10 additions & 0 deletions src/it/reserve-ports-with-urls/verify.groovy
Original file line number Diff line number Diff line change
@@ -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;
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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<ServerSocket> sockets = new ArrayList<ServerSocket>();
try
Expand Down Expand Up @@ -231,8 +248,9 @@ private ServerSocket getServerSocket()
{

ServerSocket serverSocket = reservePort( port );
if ( serverSocket != null )
if ( serverSocket != null ) {
return serverSocket;
}
}
}
}
Expand All @@ -241,7 +259,7 @@ private ServerSocket getServerSocket()
private List<Integer> randomPortList()
{

int difference = ( maxPortNumber - minPortNumber ) + 1;
int difference = maxPortNumber - minPortNumber + 1;
List<Integer> portList = new ArrayList<Integer>( difference );
List<Integer> reservedPorts = getReservedPorts();
for ( int i = 0; i < difference; i++ )
Expand Down Expand Up @@ -328,4 +346,120 @@ private int findAvailablePortNumber( Integer portNumberStartingPoint, List<Integ
}
return candidate;
}

private void loadUrls() throws MojoExecutionException {
for (String url : urls) {
load(new UrlResource(url));
}
}

private void load(UrlResource resource) throws MojoExecutionException {
if (resource.canBeOpened()) {
loadPortNamesFromResource(resource);
} else {
throw new MojoExecutionException("Port names could not be loaded from \"" + resource + "\"");
}
}

private void loadPortNamesFromResource(UrlResource resource) throws MojoExecutionException {
try {
if (getLog().isDebugEnabled()) {
getLog().debug("Loading port names from " + resource);
}
final InputStream stream = resource.getInputStream();

try {
BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
List<String> names = new ArrayList<String>();
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;
}
}
}
50 changes: 50 additions & 0 deletions src/site/apt/usage.apt.vm
Original file line number Diff line number Diff line change
Expand Up @@ -438,6 +438,56 @@ releasedVersion.incrementalVersion
</plugins>
</build>
</project>
-------------------
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).

<<<portNames>>> and <<<urls>>> parameters can be combined.

-------------------
<project>
...
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>${project.version}</version>
<dependencies>
<dependency>
<artifactId>jar-with-port-names.txt</artifactId>
[...]
</dependencies>
<executions>
<execution>
<id>reserve-network-port</id>
<goals>
<goal>reserve-network-port</goal>
</goals>
<phase>process-resources</phase>
<configuration>
<urls>
<url>file://${project.basedir}/names1.txt</url>
<url>classpath:port-names.txt</url>
</urls>
</configuration>
</execution>
</executions>
</plugin>

[...]

</plugins>
</build>
</project>
-------------------
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
Expand Down

0 comments on commit 7396a3d

Please sign in to comment.