diff --git a/org.eclipse.m2e.pde.connector/lifecycle-mapping-metadata.xml b/org.eclipse.m2e.pde.connector/lifecycle-mapping-metadata.xml
index 85428db36c..2362411676 100644
--- a/org.eclipse.m2e.pde.connector/lifecycle-mapping-metadata.xml
+++ b/org.eclipse.m2e.pde.connector/lifecycle-mapping-metadata.xml
@@ -33,6 +33,22 @@
+
+
+ biz.aQute.bnd
+ bnd-maven-plugin
+ [5.0.0,)
+
+ jar
+ bnd-process
+
+
+
+
+ org.eclipse.m2e.pde.connector.configurator.bundle
+
+
+
\ No newline at end of file
diff --git a/org.eclipse.m2e.pde.connector/src/org/eclipse/m2e/pde/connector/PDEMavenBundlePluginConfigurator.java b/org.eclipse.m2e.pde.connector/src/org/eclipse/m2e/pde/connector/PDEMavenBundlePluginConfigurator.java
index 63b0ae3afc..c42a4101a2 100644
--- a/org.eclipse.m2e.pde.connector/src/org/eclipse/m2e/pde/connector/PDEMavenBundlePluginConfigurator.java
+++ b/org.eclipse.m2e.pde.connector/src/org/eclipse/m2e/pde/connector/PDEMavenBundlePluginConfigurator.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2008 Sonatype, Inc.
+ * Copyright (c) 2008, 2021 Sonatype, Inc.
* 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
@@ -7,11 +7,12 @@
*******************************************************************************/
package org.eclipse.m2e.pde.connector;
-
import java.io.File;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
+import org.apache.maven.model.Plugin;
import org.apache.maven.plugin.MojoExecution;
import org.apache.maven.project.MavenProject;
import org.eclipse.core.resources.IMarker;
@@ -25,9 +26,12 @@
import org.eclipse.m2e.core.internal.markers.MavenProblemInfo;
import org.eclipse.m2e.core.internal.markers.SourceLocation;
import org.eclipse.m2e.core.internal.markers.SourceLocationHelper;
+import org.eclipse.m2e.core.lifecyclemapping.model.IPluginExecutionMetadata;
import org.eclipse.m2e.core.project.IMavenProjectFacade;
+import org.eclipse.m2e.core.project.configurator.AbstractBuildParticipant;
import org.eclipse.m2e.core.project.configurator.AbstractProjectConfigurator;
import org.eclipse.m2e.core.project.configurator.ILifecycleMappingConfiguration;
+import org.eclipse.m2e.core.project.configurator.MojoExecutionBuildParticipant;
import org.eclipse.m2e.core.project.configurator.MojoExecutionKey;
import org.eclipse.m2e.core.project.configurator.ProjectConfigurationRequest;
import org.eclipse.m2e.jdt.IClasspathDescriptor;
@@ -42,84 +46,129 @@
* manifest
*
*/
-@SuppressWarnings( "restriction" )
-public class PDEMavenBundlePluginConfigurator
- extends AbstractProjectConfigurator
- implements IJavaProjectConfigurator
-{
-
- public static final String FELIX_PARAM_MANIFESTLOCATION = "manifestLocation";
-
- @Override
- public void configure( ProjectConfigurationRequest request, IProgressMonitor monitor )
- throws CoreException
- {
- List executions = getMojoExecutions( request, monitor );
-
- if ( executions.size() > 1 )
- {
- List errors = new ArrayList();
-
- for ( MojoExecution mojoExecution : executions )
- {
- SourceLocation location = SourceLocationHelper.findLocation( mojoExecution.getPlugin(), "executions" );
- MavenProblemInfo problem =
- new MavenProblemInfo( "Duplicate " + mojoExecution.getGoal()
- + " executions found. Please remove any explicitly defined " + mojoExecution.getGoal()
- + " executions in your pom.xml.", IMarker.SEVERITY_ERROR, location );
- errors.add( problem );
- }
-
- this.markerManager.addErrorMarkers( request.getPom(), IMavenConstants.MARKER_LIFECYCLEMAPPING_ID, errors );
- }
-
- // bundle manifest is generated in #configureRawClasspath, which is invoked earlier during project configuration
-
- IProject project = request.getProject();
- IMavenProjectFacade facade = request.getMavenProjectFacade();
-
- IPath metainfPath = getMetainfPath( facade, executions, monitor );
-
- PDEProjectHelper.addPDENature( project, metainfPath, monitor );
- }
-
- @Override
- public void configureClasspath( IMavenProjectFacade facade, IClasspathDescriptor classpath, IProgressMonitor monitor )
- throws CoreException
- {
- }
-
- @Override
- public void configureRawClasspath( ProjectConfigurationRequest request, IClasspathDescriptor classpath,
- IProgressMonitor monitor )
- throws CoreException
- {
- }
-
- private IPath getMetainfPath( IMavenProjectFacade facade, List executions, IProgressMonitor monitor )
- throws CoreException
- {
- IMaven maven = MavenPlugin.getMaven();
- for ( MojoExecution execution : executions )
- {
- MavenProject mavenProject = facade.getMavenProject( monitor );
- File location =
- maven.getMojoParameterValue(mavenProject, execution, FELIX_PARAM_MANIFESTLOCATION, File.class,
- monitor);
- if ( location != null )
- {
- return facade.getProjectRelativePath( location.getAbsolutePath() );
- }
- }
-
- return null;
- }
-
- @Override
- public boolean hasConfigurationChanged( IMavenProjectFacade newFacade,
- ILifecycleMappingConfiguration oldProjectConfiguration,
- MojoExecutionKey key, IProgressMonitor monitor )
- {
- return false;
- }
+@SuppressWarnings("restriction")
+public class PDEMavenBundlePluginConfigurator extends AbstractProjectConfigurator implements IJavaProjectConfigurator {
+
+ private static final String FELIX_PARAM_MANIFESTLOCATION = "manifestLocation";
+ private static final String FELIX_PARAM_SUPPORTINCREMENTALBUILD = "supportIncrementalBuild";
+ private static final String FELIX_MANIFEST_GOAL = "manifest";
+ private static final String BND_PARAM_MANIFESTLOCATION = "manifestPath";
+ private static final String[] BND_MANIFEST_GOALS = { "bnd-process", "bnd-process-tests", "jar", "test-jar" };
+
+ @Override
+ public void configure(ProjectConfigurationRequest request, IProgressMonitor monitor) throws CoreException {
+ List executions = getMojoExecutions(request, monitor);
+ List problems = new ArrayList();
+ boolean hasManifestExecution = false;
+ for (MojoExecution execution : executions) {
+ Plugin plugin = execution.getPlugin();
+ if (isFelix(plugin)) {
+ MavenProject mavenProject = request.getMavenProject();
+ IMaven maven = MavenPlugin.getMaven();
+ if (isFelixBundleGoal(execution)) {
+ Boolean supportIncremental = maven.getMojoParameterValue(mavenProject, execution,
+ FELIX_PARAM_SUPPORTINCREMENTALBUILD, Boolean.class, monitor);
+ if (supportIncremental == null || !supportIncremental.booleanValue()) {
+ SourceLocation location = SourceLocationHelper.findLocation(execution.getPlugin(),
+ "configuration");
+ MavenProblemInfo problem = new MavenProblemInfo(
+ "Incremental updates are currently disabled, set supportIncrementalBuild=true to support automatic manifest updates for this project.",
+ IMarker.SEVERITY_WARNING, location);
+ problems.add(problem);
+ }
+ hasManifestExecution = true;
+ }
+ } else if (isBND(plugin)) {
+ if (isBNDBundleGoal(execution)) {
+ hasManifestExecution = true;
+ }
+ }
+ }
+ if (!hasManifestExecution) {
+ for (MojoExecution execution : executions) {
+ SourceLocation location = SourceLocationHelper.findLocation(execution.getPlugin(), "executions");
+ MavenProblemInfo problem = new MavenProblemInfo(
+ "There is currently no execution that generates a manifest, consider adding an execution for one of the following goal: "
+ + (isFelix(execution.getPlugin()) ? FELIX_MANIFEST_GOAL
+ : Arrays.toString(BND_MANIFEST_GOALS))
+ + ".",
+ IMarker.SEVERITY_WARNING, location);
+ problems.add(problem);
+ break;
+ }
+ }
+ if (problems.size() > 0) {
+ this.markerManager.addErrorMarkers(request.getPom(), IMavenConstants.MARKER_LIFECYCLEMAPPING_ID, problems);
+ }
+ IProject project = request.getProject();
+ IMavenProjectFacade facade = request.getMavenProjectFacade();
+
+ IPath metainfPath = getMetainfPath(facade, executions, monitor);
+
+ PDEProjectHelper.addPDENature(project, metainfPath, monitor);
+ }
+
+ private boolean isFelixBundleGoal(MojoExecution execution) {
+ return FELIX_MANIFEST_GOAL.equals(execution.getGoal());
+ }
+
+ private boolean isBNDBundleGoal(MojoExecution execution) {
+ String executionGoal = execution.getGoal();
+ for (String goal : BND_MANIFEST_GOALS) {
+ if (goal.equals(executionGoal)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public void configureClasspath(IMavenProjectFacade facade, IClasspathDescriptor classpath, IProgressMonitor monitor)
+ throws CoreException {
+ }
+
+ @Override
+ public void configureRawClasspath(ProjectConfigurationRequest request, IClasspathDescriptor classpath,
+ IProgressMonitor monitor) throws CoreException {
+ }
+
+ private IPath getMetainfPath(IMavenProjectFacade facade, List executions, IProgressMonitor monitor)
+ throws CoreException {
+ IMaven maven = MavenPlugin.getMaven();
+ for (MojoExecution execution : executions) {
+ Plugin plugin = execution.getPlugin();
+ MavenProject mavenProject = facade.getMavenProject(monitor);
+ File location = maven.getMojoParameterValue(mavenProject, execution,
+ isBND(plugin) ? BND_PARAM_MANIFESTLOCATION : FELIX_PARAM_MANIFESTLOCATION, File.class, monitor);
+ if (location != null) {
+ return facade.getProjectRelativePath(location.getAbsolutePath());
+ }
+ }
+ return null;
+ }
+
+ private boolean isBND(Plugin plugin) {
+ return plugin != null && "bnd-maven-plugin".equals(plugin.getArtifactId());
+ }
+
+ private boolean isFelix(Plugin plugin) {
+ return plugin != null && "org.apache.felix".equals(plugin.getGroupId())
+ && "maven-bundle-plugin".equals(plugin.getArtifactId());
+ }
+
+ @Override
+ public boolean hasConfigurationChanged(IMavenProjectFacade newFacade,
+ ILifecycleMappingConfiguration oldProjectConfiguration, MojoExecutionKey key, IProgressMonitor monitor) {
+ return false;
+ }
+
+ @Override
+ public AbstractBuildParticipant getBuildParticipant(IMavenProjectFacade projectFacade, MojoExecution execution,
+ IPluginExecutionMetadata executionMetadata) {
+ if ((isFelix(execution.getPlugin()) && isFelixBundleGoal(execution))
+ || (isBND(execution.getPlugin()) && isBNDBundleGoal(execution))) {
+ return new MojoExecutionBuildParticipant(execution, true, true);
+ }
+ return super.getBuildParticipant(projectFacade, execution, executionMetadata);
+ }
}