All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.timofeevda.jstressy.plugin.BuilderMojo Maven / Gradle / Ivy

The newest version!
/*
 * The MIT License (MIT)
 *
 * Copyright (c) 2018 Denis Timofeev 
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 * the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 *
 */

package com.github.timofeevda.jstressy.plugin;

import com.github.timofeevda.jstressy.plugin.api.Exclusion;
import com.github.timofeevda.jstressy.plugin.api.ScenarioBundle;
import com.github.timofeevda.jstressy.plugin.api.SystemBundle;
import com.github.timofeevda.jstressy.plugin.core.ArtifactFileNameUtils;
import com.github.timofeevda.jstressy.plugin.core.ArtifactResolver;
import com.github.timofeevda.jstressy.plugin.core.Constants;
import com.github.timofeevda.jstressy.plugin.core.DependencyDescriptor;
import com.github.timofeevda.jstressy.plugin.core.FelixConfigWriter;
import com.github.timofeevda.jstressy.plugin.core.FileUtils;
import com.github.timofeevda.jstressy.plugin.core.JarUtils;
import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
import org.apache.maven.model.Dependency;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.Component;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.project.MavenProject;
import org.eclipse.aether.RepositorySystem;
import org.eclipse.aether.RepositorySystemSession;
import org.eclipse.aether.artifact.Artifact;
import org.eclipse.aether.artifact.DefaultArtifact;
import org.eclipse.aether.repository.RemoteRepository;
import org.eclipse.aether.resolution.ArtifactRequest;
import org.eclipse.aether.resolution.ArtifactResult;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Mojo(name = "build", aggregator = true)
public class BuilderMojo extends AbstractMojo {

    @Parameter(defaultValue = "zip")
    private String archive;

    @Parameter(defaultValue = "5.6.10")
    private String felixVersion;

    @Parameter(defaultValue = "")
    private String felixConfigFile;

    @Parameter(defaultValue = "")
    private String logbackFile;

    @Parameter(defaultValue = "")
    private String runBatFile;

    @Parameter(defaultValue = "")
    private String runShFile;

    @Parameter(defaultValue = "")
    private String stressyConfigFile;

    @Parameter
    private List exclusions = Collections.emptyList();

    @Parameter
    private List systemBundles = Collections.emptyList();

    @Parameter
    private List scenarioBundles = Collections.emptyList();

    @Parameter(defaultValue = "target")
    private String target;

    @Parameter(defaultValue = "${project}")
    private MavenProject mavenProject;

    @Component
    private RepositorySystem repositorySystem;

    @Parameter(defaultValue = "${repositorySystemSession}")
    private RepositorySystemSession repositorySystemSession;

    @Parameter(defaultValue = "${project.remoteProjectRepositories}", readonly = true)
    private List remoteRepositories;

    private ArtifactResolver artifactResolver;

    @Override
    public void execute() throws MojoFailureException {
        artifactResolver = new ArtifactResolver(remoteRepositories,
                repositorySystem, repositorySystemSession, exclusions, getLog());

        deleteOutputFolder();

        createOutputFolders();

        copyConfigurationFiles();

        // get list of system bundles - bundles needed to be run before all other bundles, right after felix start
        Collection systemBundles = getSystemBundles()
                .stream()
                .map(DependencyDescriptor::deriveAetherArtifact)
                .collect(Collectors.toSet());

        // get list of scenario bundles
        Collection scenarioBundles = getScenarioBundles()
                .stream().map(DependencyDescriptor::deriveAetherArtifact)
                .collect(Collectors.toSet());

        // prepare list of bundles to exclude from application folder
        Set exclusionsSet =
                Stream.concat(systemBundles.stream(), scenarioBundles.stream())
                        .map(descriptor -> artifactResolver.resolveArtifact(
                                descriptor.getGroupId(), descriptor.getArtifactId(), descriptor.getClassifier(),
                                descriptor.getType(), descriptor.getVersion()
                        ))
                        .map(DependencyDescriptor::deriveAetherArtifact)
                        .collect(Collectors.toSet());

        Collection applicationBundles = getApplicationBundles(exclusionsSet)
                .stream()
                .map(DependencyDescriptor::deriveAetherArtifact)
                .collect(Collectors.toSet());

        copySystemBundlesArtifacts(getBundlesWithMaxVersions(systemBundles));
        copyApplicationBundlesArtifact(getBundlesWithMaxVersions(applicationBundles));
        copyScenarioBundles(getBundlesWithMaxVersions(scenarioBundles));

        writeFelixConfig();

        writeFelixRunnable();

        archiveBundle();
    }

    private void deleteOutputFolder() {
        FileUtils.deleteFolder(new File(target));
    }

    private Collection getBundlesWithMaxVersions(Collection dependencyDescriptors) {
        return dependencyDescriptors.stream()
                .collect(Collectors.toMap(
                        dd -> dd.getGroupId() + dd.getArtifactId(),
                        Function.identity(),
                        this::selectMaxVersionDependency))
                .values();
    }

    private void writeFelixRunnable() throws MojoFailureException {
        copyArtifactFile(DependencyDescriptor.deriveAetherArtifact(downloadFelixBundle()), "bin/", "felix.jar");
    }

    private void writeFelixConfig() {
        try {
            FelixConfigWriter.writeConfig(target, target);
        } catch (IOException e) {
            getLog().error(e);
        }
    }

    private void createOutputFolders() {
        try {
            FileUtils.createFolders(new File(target + File.separator + Constants.FELIX_BIN),
                    new File(target + File.separator + Constants.BUNDLES_APPLICATION),
                    new File(target + File.separator + Constants.BUNDLES_SYSTEM),
                    new File(target + File.separator + Constants.BUNDLES_PLUGIN),
                    new File(target + Constants.CONFIGURATION_FOLDER));
        } catch (IOException e) {
            getLog().error(e);
        }
    }

    private Artifact downloadFelixBundle() throws MojoFailureException {
        Artifact artifact = new DefaultArtifact(Constants.FELIX_GROUP_ID, Constants.FELIX_ARTIFACT_ID,
                "jar", felixVersion);

        ArtifactRequest artifactRequest = new ArtifactRequest();
        artifactRequest.setRepositories(remoteRepositories);
        artifactRequest.setArtifact(artifact);

        ArtifactResult artifactResult;
        try {
            artifactResult = repositorySystem.resolveArtifact(repositorySystemSession, artifactRequest);
        } catch (org.eclipse.aether.resolution.ArtifactResolutionException ex) {
            getLog().error(ex);
            throw new MojoFailureException("Couldn't get Apache Felix runnable");
        }

        File artifactFile = new File(
                repositorySystemSession.getLocalRepository().getBasedir()
                        + File.separator
                        + repositorySystemSession.getLocalRepositoryManager().getPathForLocalArtifact(artifactRequest.getArtifact()));
        return artifactResult.getArtifact().setFile(artifactFile);
    }

    private void copyApplicationBundlesArtifact(Collection dependencyList) {
        dependencyList.forEach(descriptor -> copyArtifactFile(descriptor, Constants.BUNDLES_APPLICATION));
    }

    private void copySystemBundlesArtifacts(Collection dependencyList) {
        dependencyList.forEach(descriptor -> copyArtifactFile(descriptor, Constants.BUNDLES_SYSTEM));
    }

    private void copyScenarioBundles(Collection scenarioBundles) {
        scenarioBundles.forEach(bundle -> copyArtifactFile(bundle, Constants.BUNDLES_PLUGIN));
    }

    private void copyArtifactFile(DependencyDescriptor dependencyDescriptor, String folder) {
        copyArtifactFile(dependencyDescriptor, folder, null);
    }

    private void copyArtifactFile(DependencyDescriptor dependencyDescriptor, String folder, String fileNameOverride) {
        String artifactFileName =
                fileNameOverride != null ? fileNameOverride :
                        ArtifactFileNameUtils.getArtifactFileName(dependencyDescriptor);
        try {
            if (!JarUtils.isBundle(new File(dependencyDescriptor.getPath()))) {
                getLog().warn("Skipping non-bundle artifact: " + artifactFileName);
                return;
            }
        } catch (Exception ex) {
            getLog().warn(ex);
        }

        try {
            File fileToCopy = new File(target + File.separator + folder + artifactFileName);
            if (!fileToCopy.exists()) {
                FileUtils.copyFile(new File(dependencyDescriptor.getPath()), fileToCopy);
            }
        } catch (IOException e) {
            getLog().error(e);
        }
    }

    private void copyConfigurationFiles() {
        try {
            copyFelixConfig();
            writeLogbackConfig();
            writeWindowsRunner();
            writeUnixRunner();
            writeStressyConfig();
        } catch (Exception ex) {
            getLog().error(ex);
        }
    }

    private void writeStressyConfig() throws Exception {
        InputStream templateConfig = stressyConfigFile == null ?
                BuilderMojo.class.getResourceAsStream("/stressy/stressy.yml") :
                new FileInputStream(stressyConfigFile);
        FileUtils.copyFile(templateConfig, new File(target + "/stressy.yml"));
    }

    private void writeUnixRunner() throws Exception {
        InputStream unixRunner = runShFile == null ?
                BuilderMojo.class.getResourceAsStream("/run/run.sh") :
                new FileInputStream(runShFile);
        FileUtils.copyFile(unixRunner, new File(target + "/run.sh"));
    }

    private void writeWindowsRunner() throws Exception {
        InputStream windowsRunner = runBatFile == null ?
                BuilderMojo.class.getResourceAsStream("/run/run.bat") :
                new FileInputStream(runBatFile);
        FileUtils.copyFile(windowsRunner, new File(target + "/run.bat"));
    }

    private void writeLogbackConfig() throws Exception {
        // copy logback config
        InputStream logback = logbackFile == null ?
                BuilderMojo.class.getResourceAsStream("/logback/logback.xml") :
                new FileInputStream(logbackFile);
        FileUtils.copyFile(logback, new File(target + Constants.CONFIGURATION_FOLDER + "/logback.xml"));
    }

    private void copyFelixConfig() throws Exception {
        InputStream felixConfig = felixConfigFile == null ?
                BuilderMojo.class.getResourceAsStream("/felix/" + Constants.FELIX_CONFIG) :
                new FileInputStream(felixConfigFile);
        FileUtils.copyFile(felixConfig, new File(target + Constants.CONFIGURATION_FOLDER + "/" + Constants.FELIX_CONFIG));
    }

    private Set getApplicationBundles(Set exclusionsSet) {
        return mavenProject.getDependencies()
                .stream()
                .flatMap(dep -> getBundleDependencies(dep).stream())
                .distinct()
                .filter(artifact -> !exclusionsSet.contains(DependencyDescriptor.deriveAetherArtifact(artifact)))
                .collect(Collectors.toSet());
    }

    private Collection getSystemBundles() {
        return systemBundles == null ? Collections.emptySet() :
                systemBundles.stream()
                        .flatMap(systemBundle ->
                                mavenProject.getDependencies().stream()
                                        .filter(dependency -> systemBundle.getArtifactId().equals(dependency.getArtifactId())
                                                && systemBundle.getGroupId().equals(dependency.getGroupId())))
                        .flatMap(dep -> getBundleDependencies(dep).stream())
                        .collect(Collectors.toSet());
    }

    private Set getScenarioBundles() {
        return scenarioBundles == null ? Collections.emptySet()
                : scenarioBundles.stream()
                .flatMap(scenarioBundle -> mavenProject.getDependencies().stream()
                        .filter(dependency -> scenarioBundle.getArtifactId().equals(dependency.getArtifactId())
                                && scenarioBundle.getGroupId().equals(dependency.getGroupId())))
                .map(DependencyDescriptor::deriveMavenDependency)
                .map(dd -> artifactResolver.resolveArtifact(dd.getGroupId(),
                        dd.getArtifactId(), dd.getClassifier(), dd.getType(), dd.getVersion()))
                .collect(Collectors.toSet());
    }

    private List getBundleDependencies(Dependency dependency) {
        String scope = dependency.getScope() == null ? "compile" : dependency.getScope();

        if (scope.equals("compile")
                || scope.equals("runtime")) {
            return artifactResolver.resolveDependencies(DependencyDescriptor.deriveMavenDependency(dependency))
                    .stream()
                    .filter(artifact ->
                            exclusions.stream()
                                    .noneMatch(exclusion ->
                                            exclusion.getGroupId().equals(artifact.getGroupId())
                                                    && exclusion.getArtifactId().equals(artifact.getArtifactId())))
                    .collect(Collectors.toList());
        } else {
            return Collections.emptyList();
        }
    }

    private DependencyDescriptor selectMaxVersionDependency(DependencyDescriptor dd1,
                                                            DependencyDescriptor dd2) {
        DefaultArtifactVersion v1 = new DefaultArtifactVersion(dd1.getVersion());
        DefaultArtifactVersion v2 = new DefaultArtifactVersion(dd2.getVersion());
        return v1.compareTo(v2) > 0 ? dd1 : dd2;
    }

    private void archiveBundle() {
        try {
            if (this.archive.equals(Constants.ARCHIVE_TYPE_TAR)) {
                FileUtils.tarGzFolder(target,
                        target + File.separator + "jstressy.tar.gz", "jstressy.tar.gz", target + "/");
            } else if (this.archive.equals(Constants.ARCHIVE_TYPE_ZIP)) {
                FileUtils.zipFolder(target,
                        target + File.separator + "jstressy.zip", "jstressy.zip", target + "/");
            }
        } catch (IOException e) {
            getLog().error(e);
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy