/amps-maven-plugin/src/main/java/com/atlassian/maven/plugins/amps/product/CtkServerProductHandler.java
Java | 249 lines | 196 code | 32 blank | 21 comment | 17 complexity | 17aefa4d070bc5b0c948aa59df3c7ea1 MD5 | raw file
Possible License(s): Apache-2.0, BSD-3-Clause
- package com.atlassian.maven.plugins.amps.product;
- import com.atlassian.maven.plugins.amps.MavenContext;
- import com.atlassian.maven.plugins.amps.MavenGoals;
- import com.atlassian.maven.plugins.amps.Node;
- import com.atlassian.maven.plugins.amps.Product;
- import com.atlassian.maven.plugins.amps.ProductArtifact;
- import com.atlassian.maven.plugins.amps.util.ProjectUtils;
- import com.atlassian.maven.plugins.amps.util.ant.AntJavaExecutorThread;
- import com.atlassian.maven.plugins.amps.util.ant.JavaTaskFactory;
- import org.apache.maven.plugin.MojoExecutionException;
- import org.apache.maven.plugin.logging.Log;
- import org.apache.tools.ant.taskdefs.Java;
- import javax.annotation.Nonnull;
- import javax.annotation.ParametersAreNonnullByDefault;
- import java.io.File;
- import java.io.IOException;
- import java.net.HttpURLConnection;
- import java.net.URL;
- import java.util.Arrays;
- import java.util.HashMap;
- import java.util.List;
- import java.util.Map;
- import java.util.Optional;
- import static com.atlassian.maven.plugins.amps.util.ZipUtils.unzip;
- import static com.atlassian.maven.plugins.amps.util.ant.JavaTaskFactory.output;
- import static java.lang.String.format;
- import static java.net.HttpURLConnection.HTTP_OK;
- import static java.util.Collections.emptyList;
- import static java.util.Collections.singletonList;
- import static java.util.Optional.empty;
- /**
- * The Atlassian Federated API CTK Server.
- */
- @ParametersAreNonnullByDefault
- public class CtkServerProductHandler implements ProductHandler {
- private static final String CTK_SERVER_ARTIFACT_MATCHER = "federated-api-ctk-server-.*\\.jar";
- private final MavenContext context;
- private final MavenGoals goals;
- private final JavaTaskFactory javaTaskFactory;
- private final Log log;
- public CtkServerProductHandler(final MavenContext context, final MavenGoals goals) {
- this.context = context;
- this.goals = goals;
- this.javaTaskFactory = new JavaTaskFactory(context.getLog());
- this.log = context.getLog();
- }
- @Nonnull
- @Override
- public String getId() {
- return ProductHandlerFactory.CTK_SERVER;
- }
- @Override
- public int getDefaultHttpPort() {
- return 8990;
- }
- @Override
- public int getDefaultHttpsPort() {
- return 8448;
- }
- @Nonnull
- @Override
- public ProductArtifact getArtifact() {
- throw new UnsupportedOperationException("Not implemented");
- }
- @Nonnull
- @Override
- public Optional<ProductArtifact> getTestResourcesArtifact() {
- return empty();
- }
- @Override
- @Nonnull
- public String getDefaultContextPath() {
- return "/";
- }
- @Override
- @Nonnull
- public List<Node> start(final Product product) throws MojoExecutionException {
- unpackContainer(product);
- return startContainer(product);
- }
- @Override
- public void stop(final Product product) throws MojoExecutionException {
- try {
- stopContainer(product);
- } catch (IOException e) {
- throw new MojoExecutionException("Failed to send stop command to CTK server", e);
- }
- }
- @Override
- @Nonnull
- public String getDefaultContainerId() {
- return "ctk-server";
- }
- @Override
- @Nonnull
- public String getDefaultContainerId(Product product) {
- return getDefaultContainerId();
- }
- @Override
- @Nonnull
- public List<File> getSnapshotDirectories(@Nonnull final Product product) {
- return singletonList(getBaseDirectory(product));
- }
- /**
- * @param product the current product configuration
- * @return the server is stateless, so no separate home directory
- */
- @Override
- @Nonnull
- public List<File> getHomeDirectories(@Nonnull final Product product) {
- return singletonList(getBaseDirectory(product));
- }
- /**
- * The server itself is stateless, so multiple running instances of the same version share the same base directory.
- *
- * @param product the current product configuration
- * @return the directory containing the CTK server jar files and its dependencies (for the configured product
- * version).
- */
- @Override
- @Nonnull
- public File getBaseDirectory(@Nonnull final Product product) {
- return ProjectUtils.createDirectory(new File(context.getProject().getBuild().getDirectory(), "ctk-server-" + product.getVersion()));
- }
- @Override
- public void createHomeZip(@Nonnull final File homeDirectory, @Nonnull final File targetZip, @Nonnull final Product product) {
- throw new UnsupportedOperationException();
- }
- private void unpackContainer(final Product product) throws MojoExecutionException {
- final File baseDirectory = getBaseDirectory(product);
- final String[] directoryContents = baseDirectory.list();
- if (directoryContents == null || directoryContents.length == 0) {
- final File serverDistributionArtifactFile = copyServerArtifactToOutputDirectory(product);
- unpackServerArtifact(serverDistributionArtifactFile, baseDirectory);
- deleteServerArtifact(serverDistributionArtifactFile);
- } else {
- log.debug("CTK Server " + product.getVersion() + " already unpacked.");
- }
- }
- private File copyServerArtifactToOutputDirectory(final Product product) throws MojoExecutionException {
- final File buildDirectory = new File(context.getProject().getBuild().getDirectory());
- final ProductArtifact artifact = getServerDistributionArtifact(product);
- final String filename = format("%s-%s.%s", artifact.getArtifactId(), artifact.getVersion(), artifact.getType());
- return goals.copyZip(buildDirectory, artifact, filename);
- }
- private void unpackServerArtifact(final File serverDistributionArtifactFile, final File serverDirectory)
- throws MojoExecutionException {
- try {
- unzip(serverDistributionArtifactFile, serverDirectory.getPath(), 0);
- } catch (final IOException ex) {
- throw new MojoExecutionException("Unable to extract CTK server distribution: " + serverDistributionArtifactFile, ex);
- }
- }
- private void deleteServerArtifact(final File artifactFile) {
- log.debug("Deleting CTK server distribution artifact: " + artifactFile.getPath());
- if (!artifactFile.delete()) {
- log.warn("Failed to delete CTK server distribution artifact: " + artifactFile.getPath());
- }
- }
- private List<Node> startContainer(final Product product) {
- final Map<String, String> systemProperties = getSystemProperties(product);
- final Java java = javaTaskFactory.newJavaTask(output(product.getOutput()).systemProperties(systemProperties).
- jvmArgs(product.getJvmArgs() + product.getSingleNodeDebugArgs()));
- java.setDir(getBaseDirectory(product));
- java.setJar(findServerJar(product));
- java.createArg().setValue("--host");
- java.createArg().setValue(product.getServer());
- java.createArg().setValue("--port");
- java.createArg().setValue(Integer.toString(product.getSingleNodeWebPort()));
- final AntJavaExecutorThread javaThread = new AntJavaExecutorThread(java);
- javaThread.start();
- return product.getNodes();
- }
- private ProductArtifact getServerDistributionArtifact(final Product product) {
- return new ProductArtifact("com.atlassian.federation", "federated-api-ctk-server-distribution",
- product.getVersion(), "zip");
- }
- private Map<String, String> getSystemProperties(final Product product) {
- final Map<String, String> map = new HashMap<>();
- for (Map.Entry<String, Object> entry : product.getSystemPropertyVariables().entrySet()) {
- map.put(entry.getKey(), (String) entry.getValue());
- }
- return map;
- }
- private File findServerJar(final Product product) {
- final File baseDirectory = getBaseDirectory(product);
- final File[] files = baseDirectory.listFiles((dir, name) -> name.matches(CTK_SERVER_ARTIFACT_MATCHER));
- if (files == null || files.length == 0) {
- throw new IllegalStateException("CTK Server JAR file not found in: " + baseDirectory +
- " (expected a file matching " + CTK_SERVER_ARTIFACT_MATCHER + ")");
- } else if (files.length == 1) {
- return files[0];
- } else {
- throw new IllegalStateException(
- "Found too many CTK Server JAR files, expected only one: " + Arrays.toString(files));
- }
- }
- /**
- * Send a <code>DELETE</code> request to the server to indicate it should stop serving content and shut down.
- *
- * @param product the current product
- * @throws IOException if there's an I/O error
- * @throws MojoExecutionException if there's an error stopping the container
- */
- private void stopContainer(final Product product) throws IOException, MojoExecutionException {
- final URL url = new URL(
- product.getProtocol(), product.getServer(), product.getSingleNodeWebPort(), product.getContextPath());
- final HttpURLConnection httpConnection = (HttpURLConnection) url.openConnection();
- httpConnection.setConnectTimeout(product.getShutdownTimeout());
- httpConnection.setRequestMethod("DELETE");
- final int responseCode = httpConnection.getResponseCode();
- if (responseCode != HTTP_OK) {
- throw new MojoExecutionException(
- "CTK server didn't understand stop command; received HTTP response code: " + responseCode);
- }
- }
- }