com.github.alexcojocaru.mojo.elasticsearch.v2.step.resolveartifact.ElasticsearchArtifactResolverMaster Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of elasticsearch-maven-plugin Show documentation
Show all versions of elasticsearch-maven-plugin Show documentation
A Maven plugin to run a single node Elasticsearch cluster during the integration test phase of a build
package com.github.alexcojocaru.mojo.elasticsearch.v2.step.resolveartifact;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.URL;
import java.net.URLConnection;
import java.nio.channels.AsynchronousServerSocketChannel;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.Optional;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import com.github.alexcojocaru.mojo.elasticsearch.v2.ClusterConfiguration;
import com.github.alexcojocaru.mojo.elasticsearch.v2.ElasticsearchArtifact;
import com.github.alexcojocaru.mojo.elasticsearch.v2.configuration.ArtifactException;
import com.github.alexcojocaru.mojo.elasticsearch.v2.util.FilesystemUtil;
/**
* Resolver for the Elasticsearch artifact, playing the master role
* (ie. running the download and installation of the artifact).
*
* @author Alex Cojocaru
*
*/
public class ElasticsearchArtifactResolverMaster
{
private final String ELASTICSEARCH_FILE_PARAM ="/%s";
private final String ELASTICSEARCH_DOWNLOAD_URL =
"https://artifacts.elastic.co/downloads/elasticsearch/%s";
private final ClusterConfiguration config;
private final ElasticsearchArtifact artifactReference;
public ElasticsearchArtifactResolverMaster(
ClusterConfiguration config,
ElasticsearchArtifact artifactReference)
{
this.config = config;
this.artifactReference = artifactReference;
}
/**
* Run the "master" side of the artifact resolution:
* start a server and write its port to the lock file,
* then download and install the artifact.
* The server is always closed at the end, even on exception.
* @param lockFile The lock file to maintain
* @throws ArtifactException when an artifact exception occurs
* @throws IOException when an IO exception occurs
*/
public void resolve(File lockFile) throws ArtifactException, IOException
{
// open a non-blocking server which will stay alive
// until the artifact download is complete
try (AsynchronousServerSocketChannel listener = AsynchronousServerSocketChannel
.open()
// bind to localhost and let it find a random open port
.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0)))
{
InetSocketAddress address = (InetSocketAddress)listener.getLocalAddress();
config.getLog().debug("Using port " + address.getPort() + " for the local server");
// write the port to the lock file
FileUtils.writeStringToFile(
lockFile,
String.valueOf(address.getPort()),
Charset.defaultCharset());
config.getLog().debug("Wrote port " + address.getPort() + " to the lock file");
listener.accept(null, createServerHandler(listener));
config.getLog().debug("Started the server on port " + address.getPort());
File tempFile = downloadArtifact();
config.getArtifactInstaller().installArtifact(artifactReference, tempFile);
}
}
private CompletionHandler createServerHandler(
AsynchronousServerSocketChannel listener)
{
return new CompletionHandler()
{
@Override
public void completed(AsynchronousSocketChannel client, Void attachment)
{
config.getLog().debug("New connection created");
// keep listening
if (listener.isOpen())
{
listener.accept(null, this);
}
if ((client != null) && (client.isOpen()))
{
try
{
client.close();
}
catch (IOException e)
{
config.getLog().warn("Failed to close the socket channel", e);
}
config.getLog().debug("New connection closed");
}
else
{
config.getLog().debug("New connection is null or already closed");
}
}
@Override
public void failed(Throwable exc, Void attachment)
{
// not much to do; ignore it
}
};
}
/**
* Download the artifact from the download repository.
* @return the downloaded file
* @throws IOException when an IO exception occurs
*/
private File downloadArtifact() throws IOException
{
config.getLog().debug("Downloading the ES artifact");
String filename = artifactReference.buildBundleFilename();
File tempFile = new File(FilesystemUtil.getTempDirectory(), filename);
tempFile.deleteOnExit();
FileUtils.deleteQuietly(tempFile);
URL downloadUrl = new URL(
StringUtils.isBlank(config.getDownloadUrl())
? String.format(ELASTICSEARCH_DOWNLOAD_URL, filename)
: config.getDownloadUrl().endsWith(ELASTICSEARCH_FILE_PARAM)
? String.format(config.getDownloadUrl(), filename)
: config.getDownloadUrl());
config.getLog().info("Downloading " + downloadUrl + " to " + tempFile);
URLConnection connection = downloadUrl.openConnection();
Optional.ofNullable(config.getDownloadUrlUsername()).ifPresent(username -> {
String basicAuthenticationEncoded = Base64.getEncoder().encodeToString((config.getDownloadUrlUsername() + ":" + config.getDownloadUrlPassword()).getBytes(StandardCharsets.UTF_8));
connection.setRequestProperty("Authorization", "Basic " + basicAuthenticationEncoded);
});
try (OutputStream out = FileUtils.openOutputStream(tempFile)) {
IOUtils.copyLarge(connection.getInputStream(), out);
}
return tempFile;
}
}