org.jboss.tools.tycho.sitegenerator.CompareWithBaselineMojo.java Source code

Java tutorial

Introduction

Here is the source code for org.jboss.tools.tycho.sitegenerator.CompareWithBaselineMojo.java

Source

/*******************************************************************************
 * Copyright (c) 2015 Red Hat Inc., and others
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     Mickael Istria (Red Hat Inc.) - initial API and implementation
 *     Nick Boldt (Red Hat Inc.) - fixes
 ******************************************************************************/
package org.jboss.tools.tycho.sitegenerator;

import java.io.File;
import java.lang.reflect.Method;
import java.net.URI;
import java.util.Collections;
import java.util.List;
import java.util.Set;

import org.apache.commons.io.FileUtils;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.Component;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.project.MavenProject;
import org.codehaus.plexus.component.annotations.Requirement;
import org.codehaus.plexus.logging.Logger;
import org.eclipse.sisu.equinox.EquinoxServiceFactory;
import org.eclipse.tycho.ReactorProject;
import org.eclipse.tycho.artifacts.TargetPlatform;
import org.eclipse.tycho.core.osgitools.DefaultReactorProject;
import org.eclipse.tycho.core.shared.TargetEnvironment;
import org.eclipse.tycho.core.utils.TychoProjectUtils;
import org.eclipse.tycho.osgi.adapters.MavenLoggerAdapter;
import org.eclipse.tycho.p2.resolver.facade.P2ResolutionResult;
import org.eclipse.tycho.p2.resolver.facade.P2ResolutionResult.Entry;
import org.eclipse.tycho.p2.resolver.facade.P2Resolver;
import org.eclipse.tycho.p2.resolver.facade.P2ResolverFactory;
import org.eclipse.tycho.p2.target.facade.TargetPlatformConfigurationStub;
import org.osgi.framework.Version;

@Mojo(defaultPhase = LifecyclePhase.VERIFY, requiresProject = false, name = "compare-version-with-baselines")
public class CompareWithBaselineMojo extends AbstractMojo {

    public static enum ReportBehavior {
        fail, warn
    }

    @Parameter(property = "project", readonly = true)
    private MavenProject project;

    @Parameter(property = "baselines", name = "baselines")
    private List<String> baselines;

    @Parameter(property = "skip")
    private boolean skip;

    @Parameter(property = "onIllegalVersion", defaultValue = "fail")
    private ReportBehavior onIllegalVersion;

    @Requirement
    @Component
    private EquinoxServiceFactory equinox;

    @Component
    private Logger plexusLogger;

    public void execute() throws MojoExecutionException, MojoFailureException {
        if (skip) {
            getLog().info("Skipped");
            return;
        }
        ReactorProject reactorProject = DefaultReactorProject.adapt(project);
        Set<?> dependencyMetadata = reactorProject.getDependencyMetadata(true);
        if (dependencyMetadata == null || dependencyMetadata.isEmpty()) {
            getLog().debug("Skipping baseline version comparison, no p2 artifacts created in build.");
            return;
        }

        P2ResolverFactory resolverFactory = this.equinox.getService(P2ResolverFactory.class);
        P2Resolver resolver = resolverFactory.createResolver(new MavenLoggerAdapter(this.plexusLogger, true));

        TargetPlatformConfigurationStub baselineTPStub = new TargetPlatformConfigurationStub();
        baselineTPStub.setForceIgnoreLocalArtifacts(true);
        baselineTPStub.setEnvironments(Collections.singletonList(TargetEnvironment.getRunningEnvironment()));
        for (String baselineRepo : this.baselines) {
            baselineTPStub.addP2Repository(toRepoURI(baselineRepo));
        }
        TargetPlatform baselineTP = resolverFactory.getTargetPlatformFactory().createTargetPlatform(baselineTPStub,
                TychoProjectUtils.getExecutionEnvironmentConfiguration(this.project), null, null);

        for (Object item : dependencyMetadata) {
            try {
                Method getIdMethod = item.getClass().getMethod("getId");
                Method getVersionMethod = item.getClass().getMethod("getVersion");
                String id = (String) getIdMethod.invoke(item);
                Version version = new Version(getVersionMethod.invoke(item).toString());
                P2ResolutionResult res = resolver.resolveInstallableUnit(baselineTP, id, "0.0.0");

                for (Entry foundInBaseline : res.getArtifacts()) {
                    Version baselineVersion = new Version(foundInBaseline.getVersion());
                    String delta = "" + (version.getMajor() - baselineVersion.getMajor()) + "."
                            + (version.getMinor() - baselineVersion.getMinor()) + "."
                            + (version.getMicro() - baselineVersion.getMicro());

                    getLog().debug("Found " + foundInBaseline.getId() + "/" + foundInBaseline.getVersion()
                            + " with delta: " + delta);
                    if (version.compareTo(baselineVersion) <= 0) {
                        String message = "Version have moved backwards for (" + id + "/" + version
                                + "). Baseline has " + baselineVersion + ") with delta: " + delta;
                        if (this.onIllegalVersion == ReportBehavior.warn) {
                            getLog().warn(message);
                            return;
                        } else {
                            throw new MojoFailureException(message);
                        }
                    } else if (version.equals(baselineVersion)) {
                        File baselineFile = foundInBaseline.getLocation();
                        File currentFile = null;
                        // TODO: currently, there are only 2 kinds of (known) artifacts, but we could have more
                        // and unknown ones. Need to find something smarter to map artifact with actual file.
                        if (id.endsWith("source")) {
                            currentFile = reactorProject.getArtifact("sources");
                        } else {
                            currentFile = reactorProject.getArtifact();
                        }
                        if (!FileUtils.contentEquals(currentFile, baselineFile)) {
                            String message = "Duplicate version but different content found for (" + id + "/"
                                    + version + "). Also exists in baseline, but its content is different.";
                            if (this.onIllegalVersion == ReportBehavior.warn) {
                                getLog().warn(message);
                                return;
                            } else {
                                throw new MojoFailureException(message);
                            }
                        }
                    } else if (version.getMajor() == baselineVersion.getMajor()
                            && version.getMinor() == baselineVersion.getMinor()
                            && version.getMicro() == baselineVersion.getMicro()) {
                        String message = "Only qualifier changed for (" + id + "/" + version
                                + "). Expected to have bigger x.y.z than what is available in baseline ("
                                + baselineVersion + ")";
                        if (this.onIllegalVersion == ReportBehavior.warn) {
                            getLog().warn(message);
                            return;
                        } else {
                            throw new MojoFailureException(message);
                        }
                    }
                }

            } catch (Exception ex) {
                throw new MojoFailureException(ex.getMessage(), ex);
            }
        }
    }

    private URI toRepoURI(String s) throws MojoExecutionException {
        if (new File(s).exists()) {
            return new File(s).toURI();
        }
        if (new File(project.getBasedir(), s).exists()) {
            return new File(project.getBasedir(), s).toURI();
        }
        try {
            return new URI(s);
        } catch (Exception ex) {
            throw new MojoExecutionException("Wrong baseline: '" + s + "'", ex);
        }
    }

}