/*
* Copyright 2008-2013 Don Brown
*
* 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.twdata.maven.mojoexecutor;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.model.Dependency;
import org.apache.maven.model.Plugin;
import org.apache.maven.plugin.BuildPluginManager;
import org.apache.maven.plugin.MojoExecution;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.descriptor.MojoDescriptor;
import org.apache.maven.plugin.descriptor.PluginDescriptor;
import org.apache.maven.project.MavenProject;
import org.codehaus.plexus.util.xml.Xpp3Dom;
import org.codehaus.plexus.util.xml.Xpp3DomUtils;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import static org.twdata.maven.mojoexecutor.PlexusConfigurationUtils.toXpp3Dom;
/**
* Executes an arbitrary mojo using a fluent interface. This is meant to be executed within the context of a Maven 2
* mojo.
* <p/>
* Here is an execution that invokes the dependency plugin:
* <pre>
* executeMojo(
* plugin(
* groupId("org.apache.maven.plugins"),
* artifactId("maven-dependency-plugin"),
* version("2.0")
* ),
* goal("copy-dependencies"),
* configuration(
* element(name("outputDirectory"), "${project.build.directory}/foo")
* ),
* executionEnvironment(
* project,
* session,
* pluginManager
* )
* );
* </pre>
*/
public class MojoExecutor {
/**
* Entry point for executing a mojo
*
* @param plugin The plugin to execute
* @param goal The goal to execute
* @param configuration The execution configuration
* @param env The execution environment
* @throws MojoExecutionException If there are any exceptions locating or executing the mojo
*/
public static void executeMojo(Plugin plugin, String goal, Xpp3Dom configuration, ExecutionEnvironment env)
throws MojoExecutionException {
if (configuration == null) {
throw new NullPointerException("configuration may not be null");
}
try {
String executionId = null;
if (goal != null && goal.length() > 0 && goal.indexOf('#') > -1) {
int pos = goal.indexOf('#');
executionId = goal.substring(pos + 1);
goal = goal.substring(0, pos);
}
MavenSession session = env.getMavenSession();
PluginDescriptor pluginDescriptor = MavenCompatibilityHelper.loadPluginDescriptor(plugin, env, session);
MojoDescriptor mojoDescriptor = pluginDescriptor.getMojo(goal);
if (mojoDescriptor == null) {
throw new MojoExecutionException("Could not find goal '" + goal + "' in plugin "
+ plugin.getGroupId() + ":"
+ plugin.getArtifactId() + ":"
+ plugin.getVersion());
}
MojoExecution exec = mojoExecution(mojoDescriptor, executionId, configuration);
env.getPluginManager().executeMojo(session, exec);
} catch (Exception e) {
throw new MojoExecutionException("Unable to execute mojo", e);
}
}
private static MojoExecution mojoExecution(MojoDescriptor mojoDescriptor, String executionId,
Xpp3Dom configuration) {
if (executionId != null) {
return new MojoExecution(mojoDescriptor, executionId);
} else {
configuration = Xpp3DomUtils.mergeXpp3Dom(configuration, toXpp3Dom(mojoDescriptor.getMojoConfiguration()));
return new MojoExecution(mojoDescriptor, configuration);
}
}
/**
* Constructs the {@link ExecutionEnvironment} instance fluently
*
* @param mavenProject The current Maven project
* @param mavenSession The current Maven session
* @param pluginManager The Build plugin manager
* @return The execution environment
* @throws NullPointerException if mavenProject, mavenSession or pluginManager
* are null
*/
public static ExecutionEnvironment executionEnvironment(MavenProject mavenProject,
MavenSession mavenSession,
BuildPluginManager pluginManager) {
return new ExecutionEnvironment(mavenProject, mavenSession, pluginManager);
}
/**
* Builds the configuration for the goal using Elements
*
* @param elements A list of elements for the configuration section
* @return The elements transformed into the Maven-native XML format
*/
public static Xpp3Dom configuration(Element... elements) {
Xpp3Dom dom = new Xpp3Dom("configuration");
for (Element e : elements) {
dom.addChild(e.toDom());
}
return dom;
}
/**
* Defines the plugin without its version or dependencies.
*
* @param groupId The group id
* @param artifactId The artifact id
* @return The plugin instance
*/
public static Plugin plugin(String groupId, String artifactId) {
return plugin(groupId, artifactId, null);
}
/**
* Defines a plugin without dependencies.
*
* @param groupId The group id
* @param artifactId The artifact id
* @param version The plugin version
* @return The plugin instance
*/
public static Plugin plugin(String groupId, String artifactId, String version) {
return plugin(groupId, artifactId, version, Collections.<Dependency>emptyList());
}
/**
* Defines a plugin.
*
* @param groupId The group id
* @param artifactId The artifact id
* @param version The plugin version
* @param dependencies The plugin dependencies
* @return The plugin instance
*/
public static Plugin plugin(String groupId, String artifactId, String version, List<Dependency> dependencies) {
Plugin plugin = new Plugin();
plugin.setArtifactId(artifactId);
plugin.setGroupId(groupId);
plugin.setVersion(version);
plugin.setDependencies(dependencies);
return plugin;
}
/**
* Wraps the group id string in a more readable format
*
* @param groupId The value
* @return The value
*/
public static String groupId(String groupId) {
return groupId;
}
/**
* Wraps the artifact id string in a more readable format
*
* @param artifactId The value
* @return The value
*/
public static String artifactId(String artifactId) {
return artifactId;
}
/**
* Wraps the version string in a more readable format
*
* @param version The value
* @return The value
*/
public static String version(String version) {
return version;
}
/**
* Creates a list of dependencies.
*
* @param dependencies the dependencies
* @return A list of dependencies
*/
public static List<Dependency> dependencies(Dependency... dependencies) {
return Arrays.asList(dependencies);
}
/**
* Defines a dependency
*
* @param groupId The group id
* @param artifactId The artifact id
* @param version The plugin version
* @return the dependency instance
*/
public static Dependency dependency(String groupId, String artifactId, String version) {
Dependency dependency = new Dependency();
dependency.setGroupId(groupId);
dependency.setArtifactId(artifactId);
dependency.setVersion(version);
return dependency;
}
/**
* Wraps the goal string in a more readable format
*
* @param goal The value
* @return The value
*/
public static String goal(String goal) {
return goal;
}
/**
* Wraps the element name string in a more readable format
*
* @param name The value
* @return The value
*/
public static String name(String name) {
return name;
}
/**
* Constructs the element with a textual body
*
* @param name The element name
* @param value The element text value
* @return The element object
*/
public static Element element(String name, String value) {
return new Element(name, value);
}
/**
* Constructs the element with a textual body and attributes
*
* @param name The element name
* @param value The element text value
* @param attributes The element attributes
* @return The element object
*/
public static Element element(String name, String value, Attributes attributes) {
return new Element(name, value, attributes);
}
/**
* Constructs the element with a textual body and only attribute
*
* @param name The element name
* @param value The element text value
* @param attribute The element attribute
* @return The element object
*/
public static Element element(String name, String value, Attribute attribute) {
return new Element(name, value, new Attributes(attribute));
}
/**
* Constructs the element containing child elements
*
* @param name The element name
* @param elements The child elements
* @return The Element object
*/
public static Element element(String name, Element... elements) {
return new Element(name, elements);
}
/**
* Constructs the element containing child elements and attributes
*
* @param name The element name
* @param attributes The element attributes
* @param elements The child elements
* @return The Element object
*/
public static Element element(String name, Attributes attributes, Element... elements) {
return new Element(name, attributes, elements);
}
/**
* Constructs the element containing child elements and only attribute
*
* @param name The element name
* @param attribute The element attribute
* @param elements The child elements
* @return The Element object
*/
public static Element element(String name, Attribute attribute, Element... elements) {
return new Element(name, new Attributes(attribute), elements);
}
/**
* Constructs the attributes wrapper
*
* @param attributes The attributes
* @return The Attributes object
*/
public static Attributes attributes(Attribute ... attributes) {
return new Attributes(attributes);
}
/**
* Constructs the attribute
*
* @param name The attribute name
* @param value The attribute value
* @return The Attribute object
*/
public static Attribute attribute(String name, String value) {
return new Attribute(name, value);
}
/**
* Element wrapper class for configuration elements
*/
public static class Element {
private final Element[] children;
private final String name;
private final String text;
private final Attributes attributes;
public Element(String name, Element... children) {
this(name, null, new Attributes(), children);
}
public Element(String name, Attributes attributes, Element... children) {
this(name, null, attributes, children);
}
public Element(String name, String text, Element... children) {
this.name = name;
this.text = text;
this.children = children;
this.attributes = new Attributes();
}
public Element(String name, String text, Attributes attributes, Element... children) {
this.name = name;
this.text = text;
this.children = children;
this.attributes = attributes;
}
public Xpp3Dom toDom() {
Xpp3Dom dom = new Xpp3Dom(name);
if (text != null) {
dom.setValue(text);
}
for (Element e : children) {
dom.addChild(e.toDom());
}
for(Attribute attribute : attributes.attributes) {
dom.setAttribute(attribute.name, attribute.value);
}
return dom;
}
}
/**
* Collection of attributes wrapper class
*/
public static class Attributes {
private List<Attribute> attributes;
public Attributes(Attribute ... attributes) {
this.attributes = Arrays.asList(attributes);
}
}
/**
* Attribute wrapper class
*/
public static class Attribute {
private final String name;
private final String value;
public Attribute(String name, String value) {
this.name = name;
this.value = value;
}
}
/**
* Collects Maven execution information
*/
public static class ExecutionEnvironment {
private final MavenProject mavenProject;
private final MavenSession mavenSession;
private final BuildPluginManager pluginManager;
public ExecutionEnvironment(MavenProject mavenProject,
MavenSession mavenSession,
BuildPluginManager pluginManager) {
if (mavenProject == null) {
throw new NullPointerException("mavenProject may not be null");
}
if (mavenSession == null) {
throw new NullPointerException("mavenSession may not be null");
}
if (pluginManager == null) {
throw new NullPointerException("pluginManager may not be null");
}
this.mavenProject = mavenProject;
this.mavenSession = mavenSession;
this.pluginManager = pluginManager;
}
public MavenProject getMavenProject() {
return mavenProject;
}
public MavenSession getMavenSession() {
return mavenSession;
}
public BuildPluginManager getPluginManager() {
return pluginManager;
}
}
}