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); + } }