diff --git a/org.eclipse.m2e.pde.connector/META-INF/MANIFEST.MF b/org.eclipse.m2e.pde.connector/META-INF/MANIFEST.MF index b391b693ce..6fed4b6ade 100644 --- a/org.eclipse.m2e.pde.connector/META-INF/MANIFEST.MF +++ b/org.eclipse.m2e.pde.connector/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: M2E PDE Connector Bundle-SymbolicName: org.eclipse.m2e.pde.connector;singleton:=true -Bundle-Version: 2.0.1.qualifier +Bundle-Version: 2.1.0.qualifier Automatic-Module-Name: org.eclipse.m2e.pde.connector Bundle-RequiredExecutionEnvironment: JavaSE-17 Bundle-Vendor: Eclipse.org - m2e @@ -13,5 +13,7 @@ Require-Bundle: org.eclipse.m2e.core;bundle-version="[2.0.0,3.0.0)", org.eclipse.core.resources;bundle-version="3.16.0", org.eclipse.m2e.maven.runtime;bundle-version="[3.8.6,4.0.0)", org.eclipse.pde.core, - org.eclipse.jdt.core + org.eclipse.jdt.core, + org.eclipse.pde.ds.annotations, + org.eclipse.equinox.preferences Bundle-Activator: org.eclipse.m2e.pde.connector.Activator diff --git a/org.eclipse.m2e.pde.connector/lifecycle-mapping-metadata.xml b/org.eclipse.m2e.pde.connector/lifecycle-mapping-metadata.xml index dff31e9b33..a4a4f51ccc 100644 --- a/org.eclipse.m2e.pde.connector/lifecycle-mapping-metadata.xml +++ b/org.eclipse.m2e.pde.connector/lifecycle-mapping-metadata.xml @@ -51,6 +51,37 @@ + + + org.eclipse.tycho + tycho-packaging-plugin + [1.0.0,) + + package-plugin + package-feature + + + + + org.apache.m2e.pde.connector.configurator.tycho + + + + + + org.eclipse.tycho + tycho-surefire-plugin + [1.0.0,) + + test + + + + + org.apache.m2e.pde.connector.configurator.tycho + + + diff --git a/org.eclipse.m2e.pde.connector/plugin.xml b/org.eclipse.m2e.pde.connector/plugin.xml index 98133496a7..f8c318529a 100644 --- a/org.eclipse.m2e.pde.connector/plugin.xml +++ b/org.eclipse.m2e.pde.connector/plugin.xml @@ -6,9 +6,15 @@ + name="PDE integration for Maven bundle plugin projects"> + + + 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 111505b23a..fa0a3c1d85 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 @@ -23,11 +23,13 @@ import org.eclipse.m2e.core.MavenPlugin; import org.eclipse.m2e.core.embedder.IMaven; import org.eclipse.m2e.core.internal.IMavenConstants; +import org.eclipse.m2e.core.internal.markers.IMavenMarkerManager; 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.IMavenProjectRegistry; import org.eclipse.m2e.core.project.configurator.AbstractBuildParticipant; import org.eclipse.m2e.core.project.configurator.AbstractProjectConfigurator; import org.eclipse.m2e.core.project.configurator.ILifecycleMappingConfiguration; @@ -92,6 +94,11 @@ public void configure(ProjectConfigurationRequest request, IProgressMonitor moni private void createWarningMarker(ProjectConfigurationRequest request, MojoExecution execution, String attribute, String message) { + createWarningMarker(projectManager, markerManager, request, execution, attribute, message); + } + + static void createWarningMarker(IMavenProjectRegistry projectManager, IMavenMarkerManager markerManager, + ProjectConfigurationRequest request, MojoExecution execution, String attribute, String message) { SourceLocation location = SourceLocationHelper.findLocation(execution.getPlugin(), attribute); String[] gav = location.getResourceId().split(":"); diff --git a/org.eclipse.m2e.pde.connector/src/org/eclipse/m2e/pde/connector/PDEProjectHelper.java b/org.eclipse.m2e.pde.connector/src/org/eclipse/m2e/pde/connector/PDEProjectHelper.java index 4a6e650532..0ac78d8b64 100644 --- a/org.eclipse.m2e.pde.connector/src/org/eclipse/m2e/pde/connector/PDEProjectHelper.java +++ b/org.eclipse.m2e.pde.connector/src/org/eclipse/m2e/pde/connector/PDEProjectHelper.java @@ -86,7 +86,7 @@ public IStatus runInWorkspace(IProgressMonitor monitor) throws CoreException { } @SuppressWarnings("restriction") - public void configurePDEBundleProject(IProject project, MavenProject mavenProject, IProgressMonitor monitor) + public static void configurePDEBundleProject(IProject project, MavenProject mavenProject, IProgressMonitor monitor) throws CoreException { // see org.eclipse.pde.internal.ui.wizards.plugin.NewProjectCreationOperation @@ -118,7 +118,7 @@ public void configurePDEBundleProject(IProject project, MavenProject mavenProjec } @SuppressWarnings("restriction") - private void addProjectForUpdateClasspath(IProject project) { + private static void addProjectForUpdateClasspath(IProject project) { synchronized (PROJECTS_FOR_UPDATE_CLASSPATH) { PROJECTS_FOR_UPDATE_CLASSPATH.add(project); if (!isListeningForPluginModelChanges) { @@ -129,7 +129,7 @@ private void addProjectForUpdateClasspath(IProject project) { } } - private IPath getOutputLocation(IProject project, MavenProject mavenProject, IProgressMonitor monitor) + private static IPath getOutputLocation(IProject project, MavenProject mavenProject, IProgressMonitor monitor) throws CoreException { File outputDirectory = new File(mavenProject.getBuild().getOutputDirectory()); outputDirectory.mkdirs(); diff --git a/org.eclipse.m2e.pde.connector/src/org/eclipse/m2e/pde/connector/TychoPackagingsConfigurator.java b/org.eclipse.m2e.pde.connector/src/org/eclipse/m2e/pde/connector/TychoPackagingsConfigurator.java new file mode 100644 index 0000000000..ef941525d5 --- /dev/null +++ b/org.eclipse.m2e.pde.connector/src/org/eclipse/m2e/pde/connector/TychoPackagingsConfigurator.java @@ -0,0 +1,133 @@ +/******************************************************************************* + * Copyright (c) 2022 Konrad Windszus + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Konrad Windszus + *******************************************************************************/ +package org.eclipse.m2e.pde.connector; + +import java.util.List; + +import org.apache.maven.plugin.MojoExecution; +import org.apache.maven.project.MavenProject; +import org.codehaus.plexus.util.xml.Xpp3Dom; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.ProjectScope; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.preferences.IEclipsePreferences; +import org.eclipse.m2e.core.internal.markers.SourceLocationHelper; +import org.eclipse.m2e.core.project.configurator.AbstractProjectConfigurator; +import org.eclipse.m2e.core.project.configurator.ProjectConfigurationRequest; +import org.eclipse.pde.ds.internal.annotations.DSAnnotationVersion; +import org.eclipse.pde.internal.core.natures.PDE; +import org.osgi.framework.Version; + +@SuppressWarnings("restriction") +public class TychoPackagingsConfigurator extends AbstractProjectConfigurator { + + private static final String TYCHO_GROUP_ID = "org.eclipse.tycho"; + private static final String TYCHO_DS_PLUGIN_ARTIFACT_ID = "tycho-ds-plugin"; + private static final String GOAL_DECLARATIVE_SERVICES = "declarative-services"; + + @Override + public void configure(ProjectConfigurationRequest request, IProgressMonitor monitor) throws CoreException { + MavenProject mavenProject = request.mavenProject(); + IProject project = request.mavenProjectFacade().getProject(); + String packaging = mavenProject.getPackaging(); + if ("eclipse-plugin".equals(packaging) || "eclipse-test-plugin".equals(packaging)) { + PDEProjectHelper.configurePDEBundleProject(project, mavenProject, monitor); + applyDsConfiguration(request, monitor); + } else if ("eclipse-feature".equals(packaging)) { + // see + // org.eclipse.pde.internal.ui.wizards.feature.AbstractCreateFeatureOperation + if (!project.hasNature(PDE.FEATURE_NATURE)) { + addNature(project, PDE.FEATURE_NATURE, monitor); + } + } + } + + private void applyDsConfiguration(ProjectConfigurationRequest request, IProgressMonitor monitor) + throws CoreException { + List mojoExecutions = getTychoDsPluginMojoExecutions(request, monitor); + if (mojoExecutions.isEmpty()) { + return; + } + if (mojoExecutions.size() > 1) { + String message = String.format( + "Found more than one execution for plugin %s:%s and goal %s, only consider configuration of this one", + TYCHO_GROUP_ID, TYCHO_DS_PLUGIN_ARTIFACT_ID, GOAL_DECLARATIVE_SERVICES); + createWarningMarker(request, mojoExecutions.get(0), "executions", message); + } + // first mojo execution is relevant + Xpp3Dom dom = mojoExecutions.get(0).getConfiguration(); + // apply PDE configuration for DS + IEclipsePreferences prefs = new ProjectScope(request.mavenProjectFacade().getProject()) + .getNode(org.eclipse.pde.ds.internal.annotations.Activator.PLUGIN_ID); + Xpp3Dom dsEnabled = dom.getChild("enabled"); + boolean isDsEnabled = false; + if (dsEnabled != null && !dsEnabled.getValue().isEmpty()) { + isDsEnabled = Boolean.valueOf(dsEnabled.getValue()); + prefs.putBoolean(org.eclipse.pde.ds.internal.annotations.Activator.PREF_ENABLED, isDsEnabled); + } + if (isDsEnabled) { + Xpp3Dom dsVersion = dom.getChild("dsVersion"); + if (containsExplicitConfigurationValue(dsVersion)) { + String versionValue = dsVersion.getValue(); + DSAnnotationVersion version = parseVersion(versionValue); + if (version != null) { + prefs.put(org.eclipse.pde.ds.internal.annotations.Activator.PREF_SPEC_VERSION, version.name()); + } else { + String message = "Unsupported DS spec version " + versionValue + " found, using default instead"; + createWarningMarker(request, mojoExecutions.get(0), SourceLocationHelper.CONFIGURATION, message); + } + } + Xpp3Dom path = dom.getChild("path"); + if (containsExplicitConfigurationValue(path)) { + prefs.put(org.eclipse.pde.ds.internal.annotations.Activator.PREF_PATH, path.getValue()); + } + } + } + + private boolean containsExplicitConfigurationValue(Xpp3Dom config) { + // check if value is a property name + return config != null && !config.getValue().startsWith("${"); + } + + private DSAnnotationVersion parseVersion(String version) { + if (version.startsWith("V")) { + version = version.substring(1).replace('_', '.'); + } + try { + Version osgiVersion = Version.parseVersion(version); + if (osgiVersion.getMajor() == 1 && osgiVersion.getMinor() == 1) { + return DSAnnotationVersion.V1_1; + } else if (osgiVersion.getMajor() == 1 && osgiVersion.getMinor() == 2) { + return DSAnnotationVersion.V1_2; + } else if (osgiVersion.getMajor() == 1 && osgiVersion.getMinor() == 3) { + return DSAnnotationVersion.V1_3; + } + } catch (IllegalArgumentException e) { // assume no match + } + return null; + } + + private List getTychoDsPluginMojoExecutions(ProjectConfigurationRequest request, + IProgressMonitor monitor) throws CoreException { + return request.mavenProjectFacade().getMojoExecutions(TYCHO_GROUP_ID, TYCHO_DS_PLUGIN_ARTIFACT_ID, monitor, + GOAL_DECLARATIVE_SERVICES); + } + + private void createWarningMarker(ProjectConfigurationRequest request, MojoExecution execution, String attribute, + String message) { + PDEMavenBundlePluginConfigurator.createWarningMarker(projectManager, markerManager, request, execution, + attribute, message); + } +}