[MNG-5668] Dynamic component resolution to allow older Maven versions to fail gracefully
Example on a project that has the experimental features enabled:
$ mvn -version
Apache Maven 3.5.4 (1edded0938998edf8bf061f1ceb3cfdeccf443fe; 2018-06-17T19:33:14+01:00)
Maven home: /usr/local/Cellar/maven/3.5.4/libexec
Java version: 1.8.0_152, vendor: Oracle Corporation, runtime: /Library/Java/JavaVirtualMachines/jdk1.8.0_152.jdk/Contents/Home/jre
Default locale: en_IE, platform encoding: UTF-8
OS name: "mac os x", version: "10.14.6", arch: "x86_64", family: "mac"
$ mvn validate
[ERROR] The project uses experimental features that require exactly Maven 3.7.0-SNAPSHOT -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MavenExecutionException
diff --git a/maven-experiments/src/main/java/org/apache/maven/feature/check/Helper.java b/maven-experiments/src/main/java/org/apache/maven/feature/check/Helper.java
new file mode 100644
index 0000000..eda0433
--- /dev/null
+++ b/maven-experiments/src/main/java/org/apache/maven/feature/check/Helper.java
@@ -0,0 +1,50 @@
+package org.apache.maven.feature.check;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import java.io.File;
+
+import org.apache.maven.MavenExecutionException;
+import org.apache.maven.execution.MavenSession;
+import org.apache.maven.feature.api.MavenFeatures;
+import org.apache.maven.feature.spi.DefaultMavenFeatures;
+import org.codehaus.plexus.PlexusContainer;
+import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
+
+/**
+ * Helper class to work around class scanning/loading issues.
+ */
+class Helper
+{
+ static void enableFeatures( MavenSession session, String targetVersion, PlexusContainer container,
+ File topLevelProjectFile )
+ throws MavenExecutionException, ClassNotFoundException, ComponentLookupException
+ {
+ MavenFeatures features = container.lookup( MavenFeatures.class, "default" );
+ if ( !( features instanceof DefaultMavenFeatures ) )
+ {
+ throw new MavenExecutionException(
+ "This project uses experimental features that require exactly Maven " + targetVersion
+ + ", cannot enable experimental features because feature flag component is not as expected (was: "
+ + features + ")", topLevelProjectFile );
+ }
+ ( (DefaultMavenFeatures) features ).enable( session );
+ }
+}
diff --git a/maven-experiments/src/main/java/org/apache/maven/feature/check/MavenExperimentEnabler.java b/maven-experiments/src/main/java/org/apache/maven/feature/check/MavenExperimentEnabler.java
index 26e2ee4..4ef526c 100644
--- a/maven-experiments/src/main/java/org/apache/maven/feature/check/MavenExperimentEnabler.java
+++ b/maven-experiments/src/main/java/org/apache/maven/feature/check/MavenExperimentEnabler.java
@@ -32,10 +32,10 @@
import org.apache.maven.Maven;
import org.apache.maven.MavenExecutionException;
import org.apache.maven.execution.MavenSession;
-import org.apache.maven.feature.api.MavenFeatures;
-import org.apache.maven.feature.spi.DefaultMavenFeatures;
+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.ComponentLookupException;
import org.codehaus.plexus.logging.Logger;
/**
@@ -49,8 +49,8 @@
@Requirement
private Logger log;
- @Requirement( role = MavenFeatures.class, hint = "default", optional = true )
- private MavenFeatures features;
+ @Requirement
+ private PlexusContainer container;
private final Map<MavenSession, Void> startedSessions = new WeakHashMap<>();
@@ -112,9 +112,9 @@
}
try
{
- enableFeatures( session, targetVersion );
+ Helper.enableFeatures( session, targetVersion, this.container, this.topLevelProjectFile( session ) );
}
- catch ( LinkageError e )
+ catch ( LinkageError | ClassNotFoundException | ComponentLookupException e )
{
throw new MavenExecutionException(
"The project uses experimental features that require exactly Maven " + targetVersion,
@@ -122,19 +122,6 @@
}
}
- private void enableFeatures( MavenSession session, String targetVersion )
- throws MavenExecutionException
- {
- if ( !( features instanceof DefaultMavenFeatures ) )
- {
- throw new MavenExecutionException(
- "This project uses experimental features that require exactly Maven " + targetVersion
- + ", cannot enable experimental features because feature flag component is not as expected (was: "
- + features + ")", topLevelProjectFile( session ) );
- }
- ( (DefaultMavenFeatures) features ).enable( session );
- }
-
private File topLevelProjectFile( MavenSession session )
{
return session.getTopLevelProject() != null ? session.getTopLevelProject().getFile() : null;