From 28c0022c12302f573756f888d8d74b0d8f5a6d8f Mon Sep 17 00:00:00 2001 From: Hannes Wellmann Date: Sat, 15 Oct 2022 16:23:08 +0200 Subject: [PATCH] Improve accessibility of Mojo configuration parameters Advantages: - Enables access to nested elements - Enables accessing multiple elements of same name - In general enables to selectively walk the configuration element tree --- .../org/eclipse/m2e/core/embedder/IMaven.java | 41 ++++++- .../embedder/ConfigurationElementImpl.java | 112 ++++++++++++++++++ .../m2e/core/internal/embedder/MavenImpl.java | 51 ++++---- 3 files changed, 171 insertions(+), 33 deletions(-) create mode 100644 org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/embedder/ConfigurationElementImpl.java diff --git a/org.eclipse.m2e.core/src/org/eclipse/m2e/core/embedder/IMaven.java b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/embedder/IMaven.java index fd23b7516a..35d83aea78 100644 --- a/org.eclipse.m2e.core/src/org/eclipse/m2e/core/embedder/IMaven.java +++ b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/embedder/IMaven.java @@ -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; @@ -148,11 +150,46 @@ MojoExecution setupMojoExecution(MavenProject project, MojoExecution execution, throws CoreException; /** - * @since 1.4 + * Instances should not be cached + * + * @since 2.1 */ - T getMojoParameterValue(MavenProject project, MojoExecution mojoExecution, String parameter, Class asType, + 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 children(String name) throws NoSuchElementException; + + // TODO: or all() or similar. + Stream children() throws NoSuchElementException; + } + + public interface IConfigurationParameter extends IConfigurationElement { + + boolean exists(); + + T as(Class 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}. + */ + @Deprecated(forRemoval = true, since = "2.1") + default T getMojoParameterValue(MavenProject project, MojoExecution mojoExecution, String parameter, + Class asType, IProgressMonitor monitor) throws CoreException { + IConfigurationParameter configParameter = getMojoConfiguration(project, mojoExecution, monitor).get(parameter); + return configParameter.exists() ? configParameter.as(asType) : null; + } + /** * @since 1.4 */ diff --git a/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/embedder/ConfigurationElementImpl.java b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/embedder/ConfigurationElementImpl.java new file mode 100644 index 0000000000..011e7d7294 --- /dev/null +++ b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/embedder/ConfigurationElementImpl.java @@ -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 children(String name) { + requireExists(); + return Arrays.stream(configuration.getChildren(name)) + .map(c -> new ConfigurationParameterImpl(c, this.path + "/" + name, valueFactory)); + } + + @Override + public Stream 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 create(PlexusConfiguration configuration, Class 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 as(Class 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)); + } + } + + } + +} diff --git a/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/embedder/MavenImpl.java b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/embedder/MavenImpl.java index 1d29128541..865c0c1fd2 100644 --- a/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/embedder/MavenImpl.java +++ b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/embedder/MavenImpl.java @@ -151,6 +151,7 @@ import org.eclipse.m2e.core.embedder.MavenConfigurationChangeEvent; import org.eclipse.m2e.core.internal.IMavenConstants; import org.eclipse.m2e.core.internal.Messages; +import org.eclipse.m2e.core.internal.embedder.ConfigurationElementImpl.ValueFactory; import org.eclipse.m2e.core.internal.preferences.MavenPreferenceConstants; import org.eclipse.m2e.core.project.IMavenProjectFacade; @@ -716,38 +717,26 @@ private File getLastUpdatedFile(ArtifactRepository localRepository, Artifact art "m2e-lastUpdated.properties").toFile(); } - private T getMojoParameterValue(MavenSession session, MojoExecution mojoExecution, String parameter, - Class asType) throws CoreException { - try { - MojoDescriptor mojoDescriptor = mojoExecution.getMojoDescriptor(); - - ClassRealm pluginRealm = lookup(BuildPluginManager.class).getPluginRealm(session, - mojoDescriptor.getPluginDescriptor()); - - ExpressionEvaluator expressionEvaluator = new PluginParameterExpressionEvaluator(session, mojoExecution); - ConfigurationConverter typeConverter = converterLookup.lookupConverterForType(asType); - Xpp3Dom dom = mojoExecution.getConfiguration(); - if(dom == null) { - return null; - } - PlexusConfiguration configuration = new XmlPlexusConfiguration(dom).getChild(parameter); - if(configuration == null) { - return null; - } - Object value = typeConverter.fromConfiguration(converterLookup, configuration, asType, - mojoDescriptor.getImplementationClass(), pluginRealm, expressionEvaluator, null); - return asType.cast(value); - } catch(Exception e) { - throw new CoreException(Status - .error(NLS.bind(Messages.MavenImpl_error_param_for_execution, parameter, mojoExecution.getExecutionId()), e)); - } - } - @Override - public T getMojoParameterValue(MavenProject project, MojoExecution mojoExecution, String parameter, - Class asType, IProgressMonitor monitor) throws CoreException { - return getExecutionContext().execute(project, - (context, pm) -> getMojoParameterValue(context.getSession(), mojoExecution, parameter, asType), monitor); + public IConfigurationElement getMojoConfiguration(MavenProject project, MojoExecution execution, + IProgressMonitor monitor) throws CoreException { + return getExecutionContext().execute(project, (context, pm) -> { + try { + MavenSession session = context.getSession(); + MojoDescriptor mojo = execution.getMojoDescriptor(); + ClassRealm pluginRealm = lookup(BuildPluginManager.class).getPluginRealm(session, mojo.getPluginDescriptor()); + PluginParameterExpressionEvaluator evaluator = new PluginParameterExpressionEvaluator(session, execution); + ValueFactory valueComputer = new ValueFactory(converterLookup, mojo, pluginRealm, evaluator); + + Xpp3Dom dom = execution.getConfiguration(); + PlexusConfiguration configuration = dom != null ? new XmlPlexusConfiguration(dom) + : new XmlPlexusConfiguration(""); + return new ConfigurationElementImpl(configuration, "", valueComputer); + } catch(Exception e) { + throw new CoreException(Status.error( + NLS.bind("Could not get the configuration for for plugin execution {0}", execution.getExecutionId()), e)); + } + }, monitor); } private T getMojoParameterValue(String parameter, Class type, MavenSession session, Plugin plugin,