Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve accessibility of Mojo configuration parameters and (partially) use it in M2E #996

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,12 @@

import org.apache.maven.artifact.Artifact;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.model.PluginExecution;
import org.apache.maven.plugin.MojoExecution;
import org.apache.maven.project.MavenProject;

import org.eclipse.m2e.apt.internal.utils.ProjectUtils;
import org.eclipse.m2e.core.MavenPlugin;
import org.eclipse.m2e.core.embedder.IMaven.IConfigurationParameter;
import org.eclipse.m2e.core.project.IMavenProjectFacade;
import org.eclipse.m2e.core.project.configurator.AbstractBuildParticipant;
import org.eclipse.m2e.core.project.configurator.AbstractProjectConfigurator;
Expand Down Expand Up @@ -357,13 +357,12 @@ private IClasspathEntryDescriptor getEntryDescriptor(IClasspathDescriptor classp

protected <T> T getParameterValue(String parameter, Class<T> asType, MojoExecution mojoExecution)
throws CoreException {
PluginExecution execution = new PluginExecution();
execution.setConfiguration(mojoExecution.getConfiguration());
MavenProject mavenProject = mavenFacade.getMavenProject();
return mavenFacade.createExecutionContext().execute(mavenProject, (context, monitor) -> {
//TODO provide as part of the execution context? We then probably won't need the project parameter at all?
return MavenPlugin.getMaven().getMojoParameterValue(mavenProject, parameter, asType, mojoExecution.getPlugin(),
execution, mojoExecution.getGoal(), null);
IConfigurationParameter configParameter = MavenPlugin.getMaven()
.getMojoConfiguration(mavenProject, mojoExecution, null).get(parameter);
return configParameter.exists() ? configParameter.as(asType) : null;
}, null);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@

import org.eclipse.m2e.core.MavenPlugin;
import org.eclipse.m2e.core.embedder.IMaven;
import org.eclipse.m2e.core.embedder.IMaven.IConfigurationElement;
import org.eclipse.m2e.core.embedder.IMaven.IConfigurationParameter;
import org.eclipse.m2e.core.project.IMavenProjectFacade;
import org.eclipse.m2e.core.project.configurator.MojoExecutionBuildParticipant;

Expand Down Expand Up @@ -64,12 +66,13 @@ public Set<IProject> build(int kind, IProgressMonitor monitor) throws Exception
//TODO check delta / scan source for *.java
IMavenProjectFacade mavenProjectFacade = getMavenProjectFacade();
MavenProject project = mavenProjectFacade.getMavenProject();
String compilerArgument = maven.getMojoParameterValue(project, mojoExecution, "compilerArgument", String.class,
null);
boolean isAnnotationProcessingEnabled = (compilerArgument == null) || !compilerArgument.contains("-proc:none");
IConfigurationElement config = maven.getMojoConfiguration(project, mojoExecution, null);
IConfigurationParameter compilerArgumentConfig = config.get("compilerArgument");
boolean isAnnotationProcessingEnabled = !compilerArgumentConfig.exists()
|| !compilerArgumentConfig.as(String.class).contains("-proc:none");
if(isAnnotationProcessingEnabled) {
String proc = maven.getMojoParameterValue(project, mojoExecution, PROC, String.class, null);
isAnnotationProcessingEnabled = !"none".equals(proc);
IConfigurationParameter procConfig = config.get(PROC);
isAnnotationProcessingEnabled = !procConfig.exists() || !"none".equals(procConfig.as(String.class));
}
if(!isAnnotationProcessingEnabled) {
return Collections.emptySet();
Expand Down Expand Up @@ -112,8 +115,7 @@ public Set<IProject> build(int kind, IProgressMonitor monitor) throws Exception
}

// tell m2e builder to refresh generated files
File generated = maven.getMojoParameterValue(project, getMojoExecution(),
MavenCompilerJdtAptDelegate.OUTPUT_DIRECTORY_PARAMETER, File.class, null);
File generated = maven.getMojoConfiguration(project, getMojoExecution(), null).get(MavenCompilerJdtAptDelegate.OUTPUT_DIRECTORY_PARAMETER).as(File.class);
if(generated != null) {
buildContext.refresh(generated);
}
Expand Down
52 changes: 44 additions & 8 deletions org.eclipse.m2e.core/src/org/eclipse/m2e/core/embedder/IMaven.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.stream.Stream;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
Expand Down Expand Up @@ -88,8 +90,8 @@ Artifact resolve(String groupId, String artifactId, String version, String type,
* Returns path of the specified artifact relative to repository baseDir. Can use used to access local repository
* files bypassing maven resolution logic.
*/
String getArtifactPath(ArtifactRepository repository, String groupId, String artifactId, String version,
String type, String classifier) throws CoreException;
String getArtifactPath(ArtifactRepository repository, String groupId, String artifactId, String version, String type,
String classifier) throws CoreException;

/**
* Returns true if the artifact does NOT exist in the local repository and known to be UNavailable from all specified
Expand All @@ -112,8 +114,7 @@ boolean isUnavailable(String groupId, String artifactId, String version, String
/**
* @since 1.10
*/
Map<File, MavenExecutionResult> readMavenProjects(Collection<File> pomFiles,
ProjectBuildingRequest configuration)
Map<File, MavenExecutionResult> readMavenProjects(Collection<File> pomFiles, ProjectBuildingRequest configuration)
throws CoreException;

/**
Expand Down Expand Up @@ -148,15 +149,51 @@ MavenExecutionPlan calculateExecutionPlan(MavenProject project, List<String> goa
MojoExecution setupMojoExecution(MavenProject project, MojoExecution execution, IProgressMonitor monitor)
throws CoreException;

/**
* Instances should not be cached
*
* @since 2.1
*/
public interface IConfigurationElement {
// TODO or firstChild() ? That's what it is actually but it does not look so nice when chained
IConfigurationParameter get(String name) throws NoSuchElementException;

// TODO: or all(String) or similar.
Stream<IConfigurationParameter> children(String name) throws NoSuchElementException;

// TODO: or all() or similar.
Stream<IConfigurationParameter> children() throws NoSuchElementException;
}

public interface IConfigurationParameter extends IConfigurationElement {

boolean exists();

<T> T as(Class<T> clazz) throws NoSuchElementException, IllegalStateException;
}

/**
* @since 2.1
*/
IConfigurationElement getMojoConfiguration(MavenProject project, MojoExecution mojoExecution,
IProgressMonitor monitor) throws CoreException;

/**
* @since 1.4
* @deprecated use {@link #getMojoConfiguration(MavenProject, MojoExecution, IProgressMonitor)} instead and query the
* returned {@link IConfigurationElement}.
*/
HannesWell marked this conversation as resolved.
Show resolved Hide resolved
<T> T getMojoParameterValue(MavenProject project, MojoExecution mojoExecution, String parameter,
Class<T> asType, IProgressMonitor monitor) throws CoreException;
@Deprecated(forRemoval = true, since = "2.1")
default <T> T getMojoParameterValue(MavenProject project, MojoExecution mojoExecution, String parameter,
Class<T> asType, IProgressMonitor monitor) throws CoreException {
IConfigurationParameter configParameter = getMojoConfiguration(project, mojoExecution, monitor).get(parameter);
return configParameter.exists() ? configParameter.as(asType) : null;
}

/**
* @since 1.4
*/
//TODO: deprecate that as well? Without 1:1 replacement? M2E code base does not use it anymore
<T> T getMojoParameterValue(MavenProject project, String parameter, Class<T> type, Plugin plugin,
ConfigurationContainer configuration, String goal, IProgressMonitor monitor) throws CoreException;

Expand Down Expand Up @@ -223,8 +260,7 @@ <T> T getMojoParameterValue(MavenProject project, String parameter, Class<T> typ
* {@link #releaseMojo(Object, MojoExecution)}. This method is intended to allow introspection of mojo configuration
* parameters, use {@link #execute(MavenSession, MojoExecution, IProgressMonitor)} to execute mojo.
*/
<T> T getConfiguredMojo(MavenSession session, MojoExecution mojoExecution, Class<T> clazz)
throws CoreException;
<T> T getConfiguredMojo(MavenSession session, MojoExecution mojoExecution, Class<T> clazz) throws CoreException;

/**
* Releases resources used by Mojo acquired with {@link #getConfiguredMojo(MavenSession, MojoExecution, Class)}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
/*******************************************************************************
* Copyright (c) 2022-2022 Hannes Wellmann and others
* All rights reserved. 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:
* Hannes Wellmann - initial API and implementation
*******************************************************************************/

package org.eclipse.m2e.core.internal.embedder;

import java.util.Arrays;
import java.util.NoSuchElementException;
import java.util.stream.Stream;

import org.eclipse.osgi.util.NLS;

import org.codehaus.plexus.component.configurator.ComponentConfigurationException;
import org.codehaus.plexus.component.configurator.converters.ConfigurationConverter;
import org.codehaus.plexus.component.configurator.converters.lookup.ConverterLookup;
import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluator;
import org.codehaus.plexus.configuration.PlexusConfiguration;

import org.apache.maven.plugin.descriptor.MojoDescriptor;

import org.eclipse.m2e.core.embedder.IMaven.IConfigurationElement;
import org.eclipse.m2e.core.embedder.IMaven.IConfigurationParameter;


class ConfigurationElementImpl implements IConfigurationElement {
final PlexusConfiguration configuration;

final String path;

final ValueFactory valueFactory;

ConfigurationElementImpl(PlexusConfiguration configuration, String path, ValueFactory valueComputer) {
this.path = path;
this.configuration = configuration;
this.valueFactory = valueComputer;
}

@Override
public IConfigurationParameter get(String name) {
requireExists();
PlexusConfiguration child = configuration.getChild(name);
return new ConfigurationParameterImpl(child, this.path + "/" + name, valueFactory);
}

@Override
public Stream<IConfigurationParameter> children(String name) {
requireExists();
return Arrays.stream(configuration.getChildren(name))
.map(c -> new ConfigurationParameterImpl(c, this.path + "/" + name, valueFactory));
}

@Override
public Stream<IConfigurationParameter> children() throws NoSuchElementException {
requireExists();
return Arrays.stream(configuration.getChildren())
.map(c -> new ConfigurationParameterImpl(c, this.path + "/" + c.getName(), valueFactory));
}

void requireExists() {
if(configuration == null) {
throw new NoSuchElementException(
"Plugin execution " + valueFactory.mojo.getId() + "does not have a configuration parameter " + path);
}
}

record ValueFactory(ConverterLookup lookup, MojoDescriptor mojo, ClassLoader pluginRealm,
ExpressionEvaluator evaluator) {

private <T> T create(PlexusConfiguration configuration, Class<T> clazz) throws ComponentConfigurationException {
ConfigurationConverter typeConverter = lookup.lookupConverterForType(clazz);
Object value = typeConverter.fromConfiguration(lookup, configuration, clazz, mojo.getImplementationClass(),
pluginRealm, evaluator, null);
return clazz.cast(value);
}
}

static class ConfigurationParameterImpl extends ConfigurationElementImpl implements IConfigurationParameter {

private ConfigurationParameterImpl(PlexusConfiguration configuration, String name, ValueFactory valueComputer) {
super(configuration, name, valueComputer);
}

@Override
public boolean exists() {
return configuration != null;
}

@Override
public <T> T as(Class<T> clazz) throws NoSuchElementException {
requireExists();
try {
return valueFactory.create(configuration, clazz);
} catch(ComponentConfigurationException e) {
//TODO: or throw a IllegalArgument exception
// Probably the catched exception is thrown on the wrong type. TODO: test that.
throw new IllegalStateException(
NLS.bind("Failed to compute configuration for for plugin execution {0}", valueFactory.mojo.getId(), e));
}
}

}

}
Loading