From 305eb576d58f1adf8c8f80fee8bdca49da196816 Mon Sep 17 00:00:00 2001 From: Jan Sievers Date: Wed, 8 Aug 2012 15:30:50 +0200 Subject: 386490 detect reactor with mixed tycho versions and fail-fast The maven build extension tycho-maven-plugin is merged into the maven core classloader at runtime. AFAIK the maven core classloader supports only one version per artifact. Dependencies from tycho plugins to artifacts in tycho-maven-plugin such as tycho-core are all remapped to the one single version provided by the maven core classloader. This can lead to various binary mismatch errors at runtime if several tycho versions are used. This means we cannot support several versions of tycho plugins in the same reactor. Detect this situation as early as possible and fail with a clear error message. Change-Id: Id6f9f38dd5d5a7871443c0008c82fd31d996ce77 --- .../core/maven/TychoMavenLifecycleParticipant.java | 57 +++++++++++++++++++++- .../multipleVersions/p1/META-INF/MANIFEST.MF | 4 ++ .../projects/multipleVersions/p1/build.properties | 4 ++ tycho-its/projects/multipleVersions/p1/pom.xml | 31 ++++++++++++ tycho-its/projects/multipleVersions/pom.xml | 25 ++++++++++ .../buildextension/MixedTychoVersionsTest.java | 37 ++++++++++++++ 6 files changed, 157 insertions(+), 1 deletion(-) create mode 100644 tycho-its/projects/multipleVersions/p1/META-INF/MANIFEST.MF create mode 100644 tycho-its/projects/multipleVersions/p1/build.properties create mode 100644 tycho-its/projects/multipleVersions/p1/pom.xml create mode 100644 tycho-its/projects/multipleVersions/pom.xml create mode 100644 tycho-its/src/test/java/org/eclipse/tycho/test/buildextension/MixedTychoVersionsTest.java diff --git a/tycho-core/src/main/java/org/eclipse/tycho/core/maven/TychoMavenLifecycleParticipant.java b/tycho-core/src/main/java/org/eclipse/tycho/core/maven/TychoMavenLifecycleParticipant.java index 0dd2fd414..3efb89674 100644 --- a/tycho-core/src/main/java/org/eclipse/tycho/core/maven/TychoMavenLifecycleParticipant.java +++ b/tycho-core/src/main/java/org/eclipse/tycho/core/maven/TychoMavenLifecycleParticipant.java @@ -11,8 +11,14 @@ package org.eclipse.tycho.core.maven; import java.io.File; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; import java.util.HashSet; +import java.util.LinkedHashSet; import java.util.List; +import java.util.Map; import java.util.Set; import org.apache.maven.AbstractMavenLifecycleParticipant; @@ -21,12 +27,14 @@ import org.apache.maven.execution.AbstractExecutionListener; import org.apache.maven.execution.ExecutionEvent; import org.apache.maven.execution.MavenExecutionRequest; import org.apache.maven.execution.MavenSession; +import org.apache.maven.model.Plugin; import org.apache.maven.project.MavenProject; import org.codehaus.plexus.PlexusContainer; import org.codehaus.plexus.component.annotations.Component; import org.codehaus.plexus.component.annotations.Requirement; import org.codehaus.plexus.component.repository.exception.ComponentLifecycleException; import org.codehaus.plexus.component.repository.exception.ComponentLookupException; +import org.codehaus.plexus.logging.Logger; import org.eclipse.sisu.equinox.EquinoxServiceFactory; import org.eclipse.tycho.ReactorProject; import org.eclipse.tycho.core.osgitools.BundleReader; @@ -36,6 +44,13 @@ import org.eclipse.tycho.resolver.TychoDependencyResolver; @Component(role = AbstractMavenLifecycleParticipant.class, hint = "TychoMavenLifecycleListener") public class TychoMavenLifecycleParticipant extends AbstractMavenLifecycleParticipant { + + private static final String TYCHO_GROUPID = "org.eclipse.tycho"; + private static final Set TYCHO_PLUGIN_IDS = new HashSet(Arrays.asList("tycho-maven-plugin", + "tycho-p2-director-plugin", "tycho-p2-plugin", "tycho-p2-publisher-plugin", "tycho-p2-repository-plugin", + "tycho-packaging-plugin", "tycho-pomgenerator-plugin", "tycho-source-plugin", "tycho-surefire-plugin", + "tycho-versions-plugin")); + @Requirement private BundleReader bundleReader; @@ -45,13 +60,16 @@ public class TychoMavenLifecycleParticipant extends AbstractMavenLifecyclePartic @Requirement private PlexusContainer plexus; + @Requirement + private Logger log; + @Override public void afterProjectsRead(MavenSession session) throws MavenExecutionException { if (disableLifecycleParticipation(session)) { return; } List projects = session.getProjects(); - validateUniqueBaseDirs(projects); + validate(projects); registerExecutionListener(session); configureComponents(session); @@ -65,6 +83,43 @@ public class TychoMavenLifecycleParticipant extends AbstractMavenLifecyclePartic } } + private void validate(List projects) throws MavenExecutionException { + validateConsistentTychoVersion(projects); + validateUniqueBaseDirs(projects); + } + + private void validateConsistentTychoVersion(List projects) throws MavenExecutionException { + Map> versionToProjectsMap = new HashMap>(); + for (MavenProject project : projects) { + for (Plugin plugin : project.getBuild().getPlugins()) { + if (TYCHO_GROUPID.equals(plugin.getGroupId()) && TYCHO_PLUGIN_IDS.contains(plugin.getArtifactId())) { + String version = plugin.getVersion(); + log.debug(TYCHO_GROUPID + ":" + plugin.getArtifactId() + ":" + version + " configured in " + + project); + Set projectSet = versionToProjectsMap.get(version); + if (projectSet == null) { + projectSet = new LinkedHashSet(); + versionToProjectsMap.put(version, projectSet); + } + projectSet.add(project); + } + } + } + if (versionToProjectsMap.size() > 1) { + List versions = new ArrayList(versionToProjectsMap.keySet()); + Collections.sort(versions); + log.error("Several versions of tycho plugins are configured " + versions + ":"); + for (String version : versions) { + log.error(version + ":"); + for (MavenProject project : versionToProjectsMap.get(version)) { + log.error("\t" + project.toString()); + } + } + throw new MavenExecutionException("All tycho plugins configured in one reactor must use the same version", + projects.get(0).getFile()); + } + } + private void validateUniqueBaseDirs(List projects) throws MavenExecutionException { // we store intermediate build results in the target/ folder and use the baseDir as unique key // so multiple modules in the same baseDir would lead to irreproducible/unexpected results diff --git a/tycho-its/projects/multipleVersions/p1/META-INF/MANIFEST.MF b/tycho-its/projects/multipleVersions/p1/META-INF/MANIFEST.MF new file mode 100644 index 000000000..383b50eb7 --- /dev/null +++ b/tycho-its/projects/multipleVersions/p1/META-INF/MANIFEST.MF @@ -0,0 +1,4 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-SymbolicName: tychoits.multipleversions.p1 +Bundle-Version: 1.0.0.qualifier diff --git a/tycho-its/projects/multipleVersions/p1/build.properties b/tycho-its/projects/multipleVersions/p1/build.properties new file mode 100644 index 000000000..34d2e4d2d --- /dev/null +++ b/tycho-its/projects/multipleVersions/p1/build.properties @@ -0,0 +1,4 @@ +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + . diff --git a/tycho-its/projects/multipleVersions/p1/pom.xml b/tycho-its/projects/multipleVersions/p1/pom.xml new file mode 100644 index 000000000..dc5087175 --- /dev/null +++ b/tycho-its/projects/multipleVersions/p1/pom.xml @@ -0,0 +1,31 @@ + + + 4.0.0 + + + tychoits.multipleversions + parent + 1.0.0-SNAPSHOT + + + tychoits.multipleversions.p1 + eclipse-plugin + + + + + + org.eclipse.tycho + tycho-maven-plugin + 0.13.0 + true + + + org.eclipse.tycho + tycho-source-plugin + 0.14.0 + + + + + diff --git a/tycho-its/projects/multipleVersions/pom.xml b/tycho-its/projects/multipleVersions/pom.xml new file mode 100644 index 000000000..084ee3386 --- /dev/null +++ b/tycho-its/projects/multipleVersions/pom.xml @@ -0,0 +1,25 @@ + + + 4.0.0 + tychoits.multipleversions + parent + 1.0.0-SNAPSHOT + pom + + + p1 + + + + + + org.eclipse.tycho + tycho-maven-plugin + ${tycho-version} + true + + + + + + diff --git a/tycho-its/src/test/java/org/eclipse/tycho/test/buildextension/MixedTychoVersionsTest.java b/tycho-its/src/test/java/org/eclipse/tycho/test/buildextension/MixedTychoVersionsTest.java new file mode 100644 index 000000000..02efa6f76 --- /dev/null +++ b/tycho-its/src/test/java/org/eclipse/tycho/test/buildextension/MixedTychoVersionsTest.java @@ -0,0 +1,37 @@ +/******************************************************************************* + * Copyright (c) 2012 SAP AG 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: + * SAP AG - initial API and implementation + *******************************************************************************/ + +package org.eclipse.tycho.test.buildextension; + +import static org.junit.Assert.fail; + +import org.apache.maven.it.VerificationException; +import org.apache.maven.it.Verifier; +import org.eclipse.tycho.core.utils.TychoVersion; +import org.eclipse.tycho.test.AbstractTychoIntegrationTest; +import org.junit.Test; + +public class MixedTychoVersionsTest extends AbstractTychoIntegrationTest { + + @Test + public void testSeveralTychoVersionsConfigured() throws Exception { + Verifier verifier = getVerifier("multipleVersions", false); + try { + verifier.executeGoal("compile"); + fail(); + } catch (VerificationException e) { + // expected + verifier.verifyTextInLog("[ERROR] Several versions of tycho plugins are configured [0.13.0, 0.14.0, " + + TychoVersion.getTychoVersion() + "]:"); + } + } + +} -- cgit v1.2.3