com.greenpepper.maven.runner.CommandLineRunner Maven / Gradle / Ivy
/**
* Copyright (c) 2008 Pyxis Technologies inc.
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA,
* or see the FSF site: http://www.fsf.org.
*
* @author oaouattara
* @version $Id: $Id
*/
package com.greenpepper.maven.runner;
import static com.greenpepper.util.CollectionUtil.toArray;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintStream;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.ParseException;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.manager.WagonManager;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.cli.ConsoleDownloadMonitor;
import org.apache.maven.embedder.MavenEmbedder;
import org.apache.maven.embedder.MavenEmbedderException;
import org.apache.maven.embedder.MavenEmbedderLogger;
import org.apache.maven.embedder.PlexusLoggerAdapter;
import org.apache.maven.model.Plugin;
import org.apache.maven.profiles.ProfileManager;
import org.apache.maven.project.DefaultProjectBuilderConfiguration;
import org.apache.maven.project.MavenProject;
import org.apache.maven.project.ProjectBuilderConfiguration;
import org.apache.maven.project.interpolation.ModelInterpolationException;
import org.apache.maven.project.interpolation.StringSearchModelInterpolator;
import org.apache.maven.project.path.DefaultPathTranslator;
import org.apache.maven.settings.MavenSettingsBuilder;
import org.apache.maven.settings.Mirror;
import org.apache.maven.settings.Server;
import org.apache.maven.settings.Settings;
import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException;
import org.codehaus.plexus.util.xml.Xpp3Dom;
import com.greenpepper.maven.runner.resolver.ProjectFileResolver;
import com.greenpepper.maven.runner.util.ReflectionUtils;
import com.greenpepper.util.cli.ArgumentMissingException;
public class CommandLineRunner {
private static final String PLUGIN_KEY = "com.github.strator-dev.greenpepper:greenpepper-maven-plugin";
private boolean isDebug = false;
private String projectDependencyDescriptor;
/** Constant CWD="System.getProperty(user.dir)"
*/
public static final String CWD = System.getProperty("user.dir");
@SuppressWarnings("serial")
private ArrayList scopes = new ArrayList() {
{
add("runtime");
add("compile");
}
};
private Logger logger;
private MavenEmbedder embedder;
private MavenProject project;
private List artifacts = new ArrayList();
private ArgumentsParser argumentsParser;
private ProjectFileResolver resolvers;
/**
* Constructor for CommandLineRunner.
*/
public CommandLineRunner() {
this(System.out);
}
/**
* Constructor for CommandLineRunner.
*
* @param out a {@link java.io.PrintStream} object.
*/
public CommandLineRunner(PrintStream out) {
this.logger = new Logger(out);
this.argumentsParser = new ArgumentsParser(out);
}
/**
* run.
*
* @param args a {@link java.lang.String} object.
* @throws java.lang.Exception if any.
*/
public void run(String... args) throws Exception {
List parameters = parseCommandLine(args);
if (!parameters.isEmpty()) {
runClassicRunner(parameters);
}
}
@SuppressWarnings("unchecked")
private List parseCommandLine(String[] args) throws ArgumentMissingException, IOException, ParseException {
List parameters = new ArrayList();
CommandLine commandLine = argumentsParser.parse(args);
if (commandLine != null) {
Option[] options = commandLine.getOptions();
for (Option option : options) {
if ("v".equals(option.getOpt())) {
isDebug = true;
parameters.add("--debug");
} else if ("p".equals(option.getOpt())) {
projectDependencyDescriptor = option.getValue();
} else if ("m".equals(option.getOpt())) {
usingScopes(option.getValue());
} else if ("o".equals(option.getOpt())) {
parameters.add("-" + option.getOpt());
parameters.add(option.getValue());
} else if ("r".equals(option.getOpt())) {
parameters.add("-" + option.getOpt());
parameters.add(option.getValue());
} else {
parameters.add("--" + option.getLongOpt());
if (option.hasArg()) {
parameters.add(option.getValue());
}
}
}
parameters.addAll(commandLine.getArgList());
}
return parameters;
}
private void usingScopes(String values) {
StringTokenizer st = new StringTokenizer(values, ";", false);
while (st.hasMoreTokens()) {
String scope = st.nextToken();
if (!scopes.contains(scope)) {
scopes.add(scope);
}
}
}
private void runClassicRunner(List args) throws Exception {
ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader();
initMavenEmbedder(originalClassLoader);
resolveProject();
ProjectFileResolver.MavenGAV mavenGAV = resolvers.getMavenGAV();
if (StringUtils.isNotEmpty(mavenGAV.getClassifier())) {
Artifact artifactWithClassifier = embedder.createArtifactWithClassifier(project.getGroupId(), project.getArtifactId(), project.getVersion(), mavenGAV.getPackaging(),
mavenGAV.getClassifier());
resolve(artifactWithClassifier,artifacts);
} else {
resolveScopedArtifacts();
resolveMavenPluginArtifact();
resolveProjectArtifact();
}
URL[] classpaths = buildRuntimeClasspaths();
URLClassLoader urlClassLoader = new URLClassLoader(classpaths, originalClassLoader);
Thread.currentThread().setContextClassLoader(urlClassLoader);
ReflectionUtils.setDebugEnabled(urlClassLoader, isDebug);
ReflectionUtils.setSystemOutputs(urlClassLoader, logger.getOut(), System.err);
Class> mainClass = urlClassLoader.loadClass("com.greenpepper.runner.Main");
logger.debug("Invoking: com.greenpepper.runner.Main " + StringUtils.join(args, ' '));
ReflectionUtils.invokeMain(mainClass, args);
Thread.currentThread().setContextClassLoader(originalClassLoader);
}
private void resolveProject() throws Exception {
File projectFile = resolveProjectFile();
if (!projectFile.exists()) {
throw new FileNotFoundException(String.format("Project dependency descriptor file not found: %s", projectFile.getAbsolutePath()));
}
project = readProjectWithDependencies(projectFile);
interpolateProject();
}
private void interpolateProject() throws InitializationException, Exception, ModelInterpolationException {
StringSearchModelInterpolator interpolator = new StringSearchModelInterpolator(new DefaultPathTranslator());
interpolator.enableLogging(new PlexusLoggerAdapter(embedder.getLogger()));
interpolator.initialize();
ProjectBuilderConfiguration config = new DefaultProjectBuilderConfiguration();
config.setLocalRepository(getLocalRepository());
config.setGlobalProfileManager(getProfileManager());
interpolator.interpolate(project.getModel(), project.getBasedir(), config, logger.isDebugEnabled());
}
private MavenProject readProjectWithDependencies(File projectFile) throws Exception {
return embedder.readProjectWithDependencies(projectFile, new ConsoleDownloadMonitor());
}
private File resolveProjectFile() throws Exception {
resolvers = new ProjectFileResolver(embedder, logger);
return resolvers.resolve(projectDependencyDescriptor);
}
@SuppressWarnings("unchecked")
private void resolveScopedArtifacts() {
artifacts = new ArrayList(project.getArtifacts().size());
for (Iterator i = project.getArtifacts().iterator(); i.hasNext();) {
Artifact a = i.next();
if (scopes.contains(a.getScope())) {
artifacts.add(a);
}
}
}
private void resolveProjectArtifact() {
try {
Artifact selfArtifact = project.getArtifact();
if (selfArtifact.getFile() == null) {
resolve(selfArtifact, artifacts);
}
} catch (Exception ex) {
logger.error("Resolving project artifact", ex);
}
}
private void resolveMavenPluginArtifact() {
try {
@SuppressWarnings("unchecked")
Map plugins = project.getPluginArtifactMap();
if (plugins.get(PLUGIN_KEY) != null) {
Artifact fixtureArtifact = embedder.createArtifactWithClassifier(project.getGroupId(), project.getArtifactId(), project.getVersion(), project.getPackaging(),
"fixtures");
resolve(fixtureArtifact, artifacts);
}
} catch (Exception ex) {
logger.error("Resolving maven-plugin artifact", ex);
}
}
private void resolve(Artifact artifact, List runtimeArtifacts) throws Exception {
embedder.resolve(artifact, project.getRemoteArtifactRepositories(), embedder.getLocalRepository());
if (artifact.getFile() != null) {
runtimeArtifacts.add(artifact);
}
}
private void initMavenEmbedder(ClassLoader classLoader) throws MavenEmbedderException {
embedder = new MavenEmbedder();
embedder.setClassLoader(classLoader);
if (isDebug) {
logger.setThreshold(MavenEmbedderLogger.LEVEL_DEBUG);
}
embedder.setLogger(logger);
embedder.setAlignWithUserInstallation(true);
embedder.start();
initAuthenticationSettings();
}
private void initAuthenticationSettings() throws MavenEmbedderException {
/**
* GP-775 : MavenEmbedder does not read servers/mirrors configuration properly. Mimic the
* resolveParameter
* found in the DefaultMaven class to allow credentials to be taken into account.
*/
try {
WagonManager wagonManager = getWagonManager();
Settings settings = getSettings();
for (Object item : settings.getServers()) {
Server server = (Server) item;
wagonManager.addAuthenticationInfo(server.getId(), server.getUsername(), server.getPassword(), server.getPrivateKey(), server.getPassphrase());
wagonManager.addPermissionInfo(server.getId(), server.getFilePermissions(), server.getDirectoryPermissions());
if (server.getConfiguration() != null) {
wagonManager.addConfiguration(server.getId(), (Xpp3Dom) server.getConfiguration());
}
}
for (Object item : settings.getMirrors()) {
Mirror mirror = (Mirror) item;
wagonManager.addMirror(mirror.getId(), mirror.getMirrorOf(), mirror.getUrl());
}
} catch (Exception ex) {
throw new MavenEmbedderException("Failed to handle authentication settings", ex);
}
}
private URL[] buildRuntimeClasspaths() throws IOException {
final Map actualClasspaths = getActualClasspaths();
List classpaths = new ArrayList();
for (Artifact artifact : artifacts) {
File artifactFile = actualClasspaths.get(artifact.getFile().getName());
if (artifactFile == null || !artifactFile.equals(artifact.getFile())) {
logger.debug(String.format("Artifact: %s (%s)", artifact, artifact.getFile()));
classpaths.add(artifact.getFile().toURI().toURL());
}
}
// Add project folders, if any.
String buildOutputDirectory = project.getBuild().getOutputDirectory();
classpaths.add(new File(buildOutputDirectory).toURI().toURL());
@SuppressWarnings("unchecked")
List buildPlugins = project.getBuildPlugins();
for (Plugin plugin : buildPlugins) {
if (StringUtils.equals(PLUGIN_KEY,plugin.getKey())) {
Xpp3Dom configuration = (Xpp3Dom)plugin.getConfiguration();
if (configuration != null) {
Xpp3Dom fixtureOutputDirectory = configuration.getChild("fixtureOutputDirectory");
String relativeDirectory = fixtureOutputDirectory.getValue();
if (!StringUtils.isEmpty(relativeDirectory)){
File directory = FileUtils.getFile(project.getBasedir(), relativeDirectory);
classpaths.add(directory.toURI().toURL());
}
}
break;
}
}
logger.debug("Classpath used: " + classpaths.toString(), null);
return toArray(classpaths, URL.class);
}
private Map getActualClasspaths() {
Map classpaths = new HashMap();
String[] javaClassPath = System.getProperty("java.class.path").split(System.getProperty("path.separator"));
for (String classPath : javaClassPath) {
File file = new File(classPath);
classpaths.put(file.getName(), file);
}
return classpaths;
}
private WagonManager getWagonManager() throws Exception {
return (WagonManager) ReflectionUtils.getDeclaredFieldValue(embedder, "wagonManager");
}
private Settings getSettings() throws Exception {
MavenSettingsBuilder mavenSettingsBuilder = getMavenSettingsBuilder();
return mavenSettingsBuilder.buildSettings();
}
private MavenSettingsBuilder getMavenSettingsBuilder() throws Exception {
return (MavenSettingsBuilder) ReflectionUtils.getDeclaredFieldValue(embedder, "settingsBuilder");
}
private ArtifactRepository getLocalRepository() throws Exception {
return (ArtifactRepository) ReflectionUtils.getDeclaredFieldValue(embedder, "localRepository");
}
private ProfileManager getProfileManager() throws Exception {
return (ProfileManager) ReflectionUtils.getDeclaredFieldValue(embedder, "profileManager");
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy