com.technophobia.substeps.runner.SubstepsRunnerMojo.java Source code

Java tutorial

Introduction

Here is the source code for com.technophobia.substeps.runner.SubstepsRunnerMojo.java

Source

/*
 *  Copyright Technophobia Ltd 2012
 *
 *   This file is part of Substeps Maven Runner.
 *
 *    Substeps Maven Runner is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU Lesser General Public License as published by
 *    the Free Software Foundation, either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    Substeps Maven Runner 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 Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public License
 *    along with Substeps.  If not, see <http://www.gnu.org/licenses/>.
 */
package com.technophobia.substeps.runner;

import com.google.common.io.Files;
import com.technophobia.substeps.execution.node.RootNode;
import com.technophobia.substeps.model.exception.SubstepsRuntimeException;
import com.typesafe.config.*;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.DependencyResolutionRequiredException;
import org.apache.maven.artifact.factory.ArtifactFactory;
import org.apache.maven.artifact.metadata.ArtifactMetadataSource;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.artifact.resolver.ArtifactResolver;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.*;
import org.apache.maven.project.MavenProject;
import org.apache.maven.project.ProjectBuilder;
import org.substeps.config.SubstepsConfigLoader;
import org.substeps.runner.NewSubstepsExecutionConfig;

import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.List;

/**
 * Mojo to run a number SubStep features, each contained within any number of
 * executionConfigs, encapsulating the required config and setup and tear down
 * details
 */
@Mojo(name = "run-features", defaultPhase = LifecyclePhase.INTEGRATION_TEST, requiresDependencyResolution = ResolutionScope.TEST, requiresProject = true, configurator = "include-project-dependencies")
public class SubstepsRunnerMojo extends BaseSubstepsMojo {

    private final BuildFailureManager buildFailureManager = new BuildFailureManager();

    /**
     * at component
     */
    @Component
    private ArtifactResolver artifactResolver;

    /**
     * at component
     */
    @Component

    private ArtifactFactory artifactFactory;

    /**
     * at component
     */
    @Component

    private ProjectBuilder projectBuilder;

    /**
     */
    @Parameter(defaultValue = "${localRepository}")

    private org.apache.maven.artifact.repository.ArtifactRepository localRepository;

    /**
     */
    @Parameter(defaultValue = "${project.remoteArtifactRepositories}")

    private List remoteRepositories;

    /**
     */
    @Parameter(defaultValue = "${plugin.artifacts}")

    private List<Artifact> pluginDependencies;

    /**
     * //     * at component
     */
    @Component
    private ArtifactMetadataSource artifactMetadataSource;

    @Override
    public void executeAfterAllConfigs(Config masterConfig) throws MojoFailureException {
        processBuildData();
    }

    @Override
    public void executeBeforeAllConfigs(Config masterConfig) throws MojoExecutionException {

        // write out the master config to the root data dir
        File rootDataDir = NewSubstepsExecutionConfig.getRootDataDir(masterConfig);

        File outFile = new File(rootDataDir, "masterConfig.conf");

        mkdirOrException(rootDataDir);

        try {
            String renderedConfig = SubstepsConfigLoader.render(masterConfig);
            this.getLog().info("\n\n *** USING COMBINED CONFIG:\n\n" + renderedConfig + "\n\n");

            Files.asCharSink(outFile, Charset.forName("UTF-8")).write(renderedConfig);
        } catch (IOException e) {
            throw new MojoExecutionException(e.getMessage(), e);
        }
    }

    private static void mkdirOrException(File dir) {
        if (!dir.exists() && !dir.mkdirs()) {
            throw new SubstepsRuntimeException("Failed to create dir: " + dir.getAbsolutePath());
        }
    }

    private ForkedRunner createForkedRunner() throws MojoExecutionException {

        try {

            if (this.project == null) {
                this.getLog().error("this.project is null");
            }

            return new ForkedRunner(getLog(), NewSubstepsExecutionConfig.getJmxPort(),
                    NewSubstepsExecutionConfig.getVMArgs(), this.project.getTestClasspathElements(),
                    this.stepImplementationArtifacts, this.artifactResolver, this.artifactFactory,
                    this.projectBuilder, this.localRepository, this.remoteRepositories,
                    this.artifactMetadataSource);
        } catch (final DependencyResolutionRequiredException e) {

            throw new MojoExecutionException("Unable to resolve dependencies", e);
        }
    }

    private InProcessRunner createInProcessRunner() {

        return new InProcessRunner(getLog());
    }

    @Override
    public void executeConfig(final Config executionConfig) throws MojoExecutionException {
        // executionConfig will be whole, self contained and already split and resolved from a masterConfig

        MojoRunner runner = null;

        try {
            runner = NewSubstepsExecutionConfig.isRunInForkedVM(executionConfig) ? createForkedRunner()
                    : createInProcessRunner();

            final RootNode iniitalRootNode = runner.prepareExecutionConfig(executionConfig);

            this.executionResultsCollector = NewSubstepsExecutionConfig
                    .getExecutionResultsCollector(executionConfig);

            this.executionResultsCollector
                    .setDataDir(NewSubstepsExecutionConfig.getDataOutputDirectory(executionConfig));

            this.executionResultsCollector.initOutputDirectories(iniitalRootNode);

            runner.addNotifier(this.executionResultsCollector);

            final RootNode rootNode = runner.run();

            String description = NewSubstepsExecutionConfig.getDescription(executionConfig);

            if (description != null) {

                rootNode.setLine(description);
            }

            addToLegacyReport(rootNode);

            this.buildFailureManager.addExecutionResult(rootNode);
        } finally {
            if (runner != null) {
                runner.shutdown();
            }
        }
    }

    private void addToLegacyReport(final RootNode rootNode) {

        if (reportBuilder == null && this.executionReportBuilder != null) {

            getLog().warn(
                    "\nExecutionReportBuilder is deprecated, replace with:\n\t<reportBuilder implementation=\"org.substeps.report.ReportBuilder\">\n"
                            + "\t\t<reportDir>${project.build.directory}/substeps_report</reportDir>\n"
                            + "\t</reportBuilder>\n");

            this.executionReportBuilder.addRootExecutionNode(rootNode);
        }
    }

    /**
     * @throws MojoFailureException
     */
    private void processBuildData() throws MojoFailureException {

        if (reportBuilder == null && this.executionReportBuilder != null) {

            this.executionReportBuilder.buildReport();
        }

        StringBuilder buf = new StringBuilder();
        for (String s : this.session.getGoals()) {
            buf.append(s);
            buf.append(" ");
        }

        this.getLog().info("this.session.getGoals(): " + buf.toString());

        List<String> goals = this.session.getGoals();

        if (this.buildFailureManager.testSuiteFailed()) {

            this.getLog().info("buildFailureManager.testSuiteFailed");

            MojoFailureException e = new MojoFailureException(
                    "Substep Execution failed:\n" + this.buildFailureManager.getBuildFailureInfo());

            // actually throwing an exception results in the build terminating immediately
            // - not really desireable as it stops the report from being built in the verify phase

            if (goals.contains("verify") || goals.contains("install") || goals.contains("deploy")) {

                // we don't want to throw the exception - it will be thrown in the reportbuildermojo
                getLog().info("Not immediately failing the build, deferring..");
                this.session.getResult().addException(e);
            } else {
                this.getLog().info("throwing ex..");
                throw e;
            }

        } else if (!this.buildFailureManager.testSuiteCompletelyPassed()) {
            this.getLog().info("buildFailureManager.testSuiteCompletelyPassed");

            // print out the failure string (but won't include any failures)
            getLog().info(this.buildFailureManager.getBuildFailureInfo());
        } else {
            this.getLog().info("other...");
        }
    }

    public MavenProject getProject() {
        return project;
    }

    public void setProject(MavenProject project) {
        this.project = project;
    }

    public BuildFailureManager getBuildFailureManager() {
        return buildFailureManager;
    }

    public ArtifactResolver getArtifactResolver() {
        return artifactResolver;
    }

    public void setArtifactResolver(ArtifactResolver artifactResolver) {
        this.artifactResolver = artifactResolver;
    }

    public ArtifactFactory getArtifactFactory() {
        return artifactFactory;
    }

    public void setArtifactFactory(ArtifactFactory artifactFactory) {
        this.artifactFactory = artifactFactory;
    }

    public ProjectBuilder getProjectBuilder() {
        return projectBuilder;
    }

    public void setProjectBuilder(ProjectBuilder projectBuilder) {
        this.projectBuilder = projectBuilder;
    }

    public ArtifactRepository getLocalRepository() {
        return localRepository;
    }

    public void setLocalRepository(ArtifactRepository localRepository) {
        this.localRepository = localRepository;
    }

    public List getRemoteRepositories() {
        return remoteRepositories;
    }

    public void setRemoteRepositories(List remoteRepositories) {
        this.remoteRepositories = remoteRepositories;
    }

    public List<Artifact> getPluginDependencies() {
        return pluginDependencies;
    }

    public void setPluginDependencies(List<Artifact> pluginDependencies) {
        this.pluginDependencies = pluginDependencies;
    }

    public ArtifactMetadataSource getArtifactMetadataSource() {
        return artifactMetadataSource;
    }

    public void setArtifactMetadataSource(ArtifactMetadataSource artifactMetadataSource) {
        this.artifactMetadataSource = artifactMetadataSource;
    }

}