org.codehaus.cargo.maven3.AbstractCargoMojo Maven / Gradle / Ivy
/*
* ========================================================================
*
* Codehaus Cargo, copyright 2004-2011 Vincent Massol, 2012-2022 Ali Tokmen.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ========================================================================
*/
package org.codehaus.cargo.maven3;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLClassLoader;
import java.security.Security;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugins.annotations.Component;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.project.ProjectBuildingRequest;
import org.apache.maven.settings.Settings;
import org.apache.maven.shared.artifact.filter.resolve.ScopeFilter;
import org.apache.maven.shared.transfer.artifact.DefaultArtifactCoordinate;
import org.apache.maven.shared.transfer.artifact.resolve.ArtifactResolver;
import org.apache.maven.shared.transfer.artifact.resolve.ArtifactResult;
import org.apache.maven.shared.transfer.dependencies.DefaultDependableCoordinate;
import org.apache.maven.shared.transfer.dependencies.resolve.DependencyResolver;
import org.codehaus.cargo.container.ContainerType;
import org.codehaus.cargo.container.LocalContainer;
import org.codehaus.cargo.container.RemoteContainer;
import org.codehaus.cargo.container.configuration.ConfigurationType;
import org.codehaus.cargo.container.configuration.LocalConfiguration;
import org.codehaus.cargo.container.configuration.RuntimeConfiguration;
import org.codehaus.cargo.container.deployer.DeployableMonitor;
import org.codehaus.cargo.container.installer.Proxy;
import org.codehaus.cargo.container.internal.util.ResourceUtils;
import org.codehaus.cargo.container.spi.deployer.DeployerWatchdog;
import org.codehaus.cargo.maven3.configuration.ArtifactInstaller;
import org.codehaus.cargo.maven3.configuration.Configuration;
import org.codehaus.cargo.maven3.configuration.Container;
import org.codehaus.cargo.maven3.configuration.Daemon;
import org.codehaus.cargo.maven3.configuration.Deployable;
import org.codehaus.cargo.maven3.configuration.Deployer;
import org.codehaus.cargo.maven3.configuration.ZipUrlInstaller;
import org.codehaus.cargo.maven3.deployer.DefaultDeployableMonitorFactory;
import org.codehaus.cargo.maven3.deployer.DeployableMonitorFactory;
import org.codehaus.cargo.maven3.log.MavenLogger;
import org.codehaus.cargo.maven3.util.CargoProject;
import org.codehaus.cargo.maven3.util.EmbeddedContainerArtifactResolver;
import org.codehaus.cargo.util.DefaultFileHandler;
import org.codehaus.cargo.util.FileHandler;
import org.codehaus.cargo.util.log.FileLogger;
import org.codehaus.cargo.util.log.LogLevel;
import org.codehaus.cargo.util.log.Logger;
/**
* Common code used by Cargo MOJOs requiring <container>
and
* <configuration>
elements and supporting the notion of
* Auto-deployable.
*/
public abstract class AbstractCargoMojo extends AbstractCommonMojo
{
/**
* The key under which the container instance is stored in the plugin context.
* We store it so that it's possible to get back the same container instance
* even if this mojo is called in a different Maven execution context. This is
* required for stopping embedded containers for example as we need to use the
* same instance that was started in order to stop them.
*/
public static final String CONTEXT_KEY_CONTAINER =
AbstractCargoMojo.class.getName() + "-Container";
/**
* The key suffix under which the classloader of the container instance is
* stored in the plugin context. We store it so that it's possible to get back
* the same classloader even if this mojo is called in a different Maven
* execution context. This is required for starting and stopping multiple
* containers as each container initialization requires different classloader.
*/
public static final String CONTEXT_KEY_CLASSLOADER = "-classloader";
/**
* File utility class.
*/
private FileHandler fileHandler = new DefaultFileHandler();
/**
* Configures a Cargo
* {@link org.codehaus.cargo.container.configuration.Configuration}. See the
* Cargo
* Maven 3 plugin reference guide for more details.
*
* @see #getConfigurationElement()
*/
@Parameter
private Configuration configuration;
/**
* Configures a Cargo {@link org.codehaus.cargo.container.Container}. See the
* Cargo
* Maven 3 plugin reference guide for more details.
*/
@Parameter
private Container container;
/**
* Daemon configuration.
*/
@Parameter
private Daemon daemon;
/**
* Configures a Cargo {@link org.codehaus.cargo.container.deployer.Deployer}.
* See the Cargo
* Maven 3 plugin reference guide for more details.
*
* @see #getDeployerElement()
*/
@Parameter
private Deployer deployer;
/**
* List of {@link org.codehaus.cargo.maven3.configuration.Deployable}. See the
* Cargo
* Maven 3 plugin reference guide for more details.
*
* @see #getDeployablesElement()
*/
@Parameter
private Deployable[] deployables;
/**
* Maven artifact resolver, used to dynamically resolve JARs for the containers
* and also to resolve the JARs for the embedded container's classpaths.
*/
@Component
private ArtifactResolver artifactResolver;
/**
* Maven dependency resolver, used to dynamically resolve dependencies of
* artifacts.
*/
@Component
private DependencyResolver dependencyResolver;
/**
* Maven project building request.
*/
@Parameter(
defaultValue = "${session.projectBuildingRequest}", readonly = true, required = true)
private ProjectBuildingRequest projectBuildingRequest;
/**
* Set this to true
to bypass cargo execution.
*/
@Parameter(property = "cargo.maven.skip", defaultValue = "false")
private boolean skip;
/**
* @see org.codehaus.cargo.maven3.util.CargoProject
*/
private CargoProject cargoProject;
/**
* Maven settings, injected automatically.
*/
@Parameter(property = "settings", readonly = true, required = true)
private Settings settings;
/**
* Cargo plugin version.
*/
@Parameter(property = "plugin.version", readonly = true, required = true)
private String pluginVersion;
/**
* Should the mojo ignore failures if something fails
*/
@Parameter(property = "cargo.ignore.failures", defaultValue = "false")
private boolean ignoreFailures = false;
/**
* Calculates the container artifact ID for a given container ID. Note that all
* containers identifier are in the form
* containerArtifactId + the version number + x
; for example
* jboss42x
is from container artifact ID
* cargo-core-container-jboss
.
*
* @param containerId Container ID, for example jboss42x
.
* @return Container artifact ID, for example
* cargo-core-container-jboss
.
*/
public static String calculateContainerArtifactId(String containerId)
{
return "cargo-core-container-" + containerId.replaceAll("\\d+x", "");
}
/**
* @return the Cargo file utility class
*/
protected FileHandler getFileHandler()
{
return this.fileHandler;
}
/**
* @param fileHandler the Cargo file utility class to use. This method is useful
* for unit testing with Mock objects as it can be passed a
* test file handler that doesn't perform any real file
* action.
*/
protected void setFileHandler(FileHandler fileHandler)
{
this.fileHandler = fileHandler;
}
/**
* See the
* Cargo Maven 3 plugin reference guide for more details.
*
* @return the user configuration of a Cargo
* {@link org.codehaus.cargo.container.deployer.Deployer}.
* @see #setDeployerElement(Deployer)
*/
protected Deployer getDeployerElement()
{
return this.deployer;
}
/**
* See the
* Cargo Maven 3 plugin reference guide for more details.
*
* @param deployerElement the
* {@link org.codehaus.cargo.container.deployer.Deployer}
* configuration defined by the user
* @see #getDeployerElement()
*/
protected void setDeployerElement(Deployer deployerElement)
{
this.deployer = deployerElement;
}
/**
* @return The daemon configuration
*/
protected Daemon getDaemon()
{
if (this.daemon == null)
{
this.daemon = new Daemon();
}
return this.daemon;
}
/**
* See the
* Cargo Maven 3 plugin reference guide for more details.
*
* @return the user configuration of the list of
* {@link org.codehaus.cargo.maven3.configuration.Deployable}.
* @see #setDeployablesElement(Deployable[])
*/
protected Deployable[] getDeployablesElement()
{
return this.deployables;
}
/**
* See the
* Cargo Maven 3 plugin reference guide for more details.
*
* @param deployablesElement the list of
* {@link org.codehaus.cargo.maven3.configuration.Deployable}.
* @see #getDeployablesElement()
*/
protected void setDeployablesElement(Deployable[] deployablesElement)
{
this.deployables = deployablesElement;
}
/**
* See the
* Cargo Maven 3 plugin reference guide for more details.
*
* @return the user configuration of a Cargo
* {@link org.codehaus.cargo.container.configuration.Configuration}.
* @see #setConfigurationElement(Configuration)
*/
protected Configuration getConfigurationElement()
{
return this.configuration;
}
/**
* See the
* Cargo Maven 3 plugin reference guide for more details.
*
* @param configurationElement the
* {@link org.codehaus.cargo.container.configuration.Configuration}
* configuration defined by the user
* @see #getConfigurationElement()
*/
protected void setConfigurationElement(Configuration configurationElement)
{
this.configuration = configurationElement;
}
/**
* See the
* Cargo Maven 3 plugin reference guide for more details.
*
* @return the user configuration of a Cargo
* {@link org.codehaus.cargo.container.Container}.
* @see #setConfigurationElement(Configuration)
*/
protected Container getContainerElement()
{
return this.container;
}
/**
* See the
* Cargo Maven 3 plugin reference guide for more details.
*
* @param containerElement the {@link org.codehaus.cargo.container.Container}
* configuration defined by the user
* @see #getContainerElement()
*/
protected void setContainerElement(Container containerElement)
{
this.container = containerElement;
}
/**
* @param cargoProject Cargo project
*/
protected void setCargoProject(CargoProject cargoProject)
{
this.cargoProject = cargoProject;
}
/**
* @return Cargo project
*/
protected CargoProject getCargoProject()
{
return this.cargoProject;
}
/**
* @return the ignoreFailures
*/
public boolean isIgnoreFailures()
{
return ignoreFailures;
}
/**
* @param ignoreFailures the ignoreFailures to set
*/
public void setIgnoreFailures(boolean ignoreFailures)
{
this.ignoreFailures = ignoreFailures;
}
/**
* {@inheritDoc}
*
*
* Note: This method is final so that extending classes cannot extend it.
* Instead they should implement the {@link #doExecute()} method.
*
*/
@Override
public final void execute() throws MojoExecutionException
{
if (this.skip)
{
getLog().info("Skipping cargo execution");
return;
}
if (this.cargoProject == null)
{
this.cargoProject = new CargoProject(getProject(), getLog());
}
Proxy proxy = null;
if (settings != null)
{
org.apache.maven.settings.Proxy activeProxy = settings.getActiveProxy();
if (activeProxy != null)
{
// CARGO-1042, CARGO-1119, CARGO-1121 and CARGO-1533:
// Use proxy definitions from the Maven settings - Even if the JVM is executing
// with http.proxyHost / https.proxyHost properties
getLog().debug("Using proxy definitions from the Maven settings");
proxy = new Proxy();
proxy.setHost(activeProxy.getHost());
proxy.setPort(activeProxy.getPort());
proxy.setExcludeHosts(activeProxy.getNonProxyHosts());
proxy.setUser(activeProxy.getUsername());
proxy.setPassword(activeProxy.getPassword());
}
}
Map previousProperties = null;
try
{
if (proxy != null)
{
previousProperties = proxy.configure();
}
doExecute();
}
catch (MojoExecutionException e)
{
if (ignoreFailures)
{
getLog().error("Ignoring failures during execution", e);
}
else
{
throw e;
}
}
finally
{
if (proxy != null)
{
proxy.clear(previousProperties);
}
}
}
/**
* Executes the plugin.
*
*
* This method must be implemented by all Mojos extending this class. The reason
* for this pattern is because we want the {@link #execute()} method to always
* be called so that necessary plugin initialization can be performed. Without
* this pattern Mojos extending this class could "forget" to call
* super.execute()
thus leading to unpredictible results.
*
*
* @throws MojoExecutionException in case of error
*/
protected abstract void doExecute() throws MojoExecutionException;
/**
* Creates a {@link org.codehaus.cargo.container.configuration.Configuration}
* instance. If the user has not specified a configuration element in the POM
* file then automatically create a standalone configuration if the container's
* type is local or otherwise create a runtime configuration.
*
* @return a valid
* {@link org.codehaus.cargo.container.configuration.Configuration}
* instance
* @throws MojoExecutionException in case of error
*/
protected org.codehaus.cargo.container.configuration.Configuration createConfiguration()
throws MojoExecutionException
{
org.codehaus.cargo.container.configuration.Configuration configuration;
// If no configuration element has been specified create one with default values.
if (getConfigurationElement() == null)
{
Configuration configurationElement = new Configuration();
if (getContainerElement().getType().isLocal())
{
File home = new File(getCargoProject().getBuildDirectory(),
"cargo/configurations/" + getContainerElement().getContainerId());
configurationElement.setType(ConfigurationType.STANDALONE);
configurationElement.setHome(home.getAbsolutePath());
}
else
{
configurationElement.setType(ConfigurationType.RUNTIME);
}
setConfigurationElement(configurationElement);
}
else
{
if (getConfigurationElement().getHome() != null && !getCargoProject().isDaemonRun())
{
getConfigurationElement().setHome(calculateAbsoluteDirectory(
"configuration home", getConfigurationElement().getHome()));
}
}
String contextKey = null;
if (getContainerElement() != null && getContainerElement().getContextKey() != null
&& !getContainerElement().getContextKey().trim().isEmpty())
{
contextKey = getContainerElement().getContextKey().trim();
}
configuration = getConfigurationElement().createConfiguration(
getContainerElement().getContainerId(), getContainerElement().getType(),
getDeployablesElement(), getCargoProject(), getProject(), contextKey, settings,
getLog());
return configuration;
}
/**
* @return a {@link org.codehaus.cargo.container.Container} instance if no
* container object was stored in the Maven Plugin Context or returns
* the saved instance otherwise. If a new container instance is created
* it's also saved in the Maven Plugin Context for later retrieval.
* @throws MojoExecutionException in case of error
*/
protected org.codehaus.cargo.container.Container createContainer()
throws MojoExecutionException
{
org.codehaus.cargo.container.Container container = null;
// Try to find the container in the Maven Plugin Context first.
Map