[MNG-7947] Plugin API (#1309)

* Add an InternalSession interface to avoid casting to the implementation in various places
* Upgrade to Guice 6.0.0 and add support for jakarta.inject annotations
* Maven 4 Plugin API
This commit is contained in:
Guillaume Nodet 2023-12-05 09:11:33 +01:00 committed by GitHub
parent 63927175d9
commit 23bca281fc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
73 changed files with 1489 additions and 703 deletions

View File

@ -51,6 +51,15 @@
<artifactId>maven-api-toolchain</artifactId> <artifactId>maven-api-toolchain</artifactId>
<version>4.0.0-alpha-9-SNAPSHOT</version> <version>4.0.0-alpha-9-SNAPSHOT</version>
</dependency> </dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-api-plugin</artifactId>
<version>4.0.0-alpha-9-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>jakarta.inject</groupId>
<artifactId>jakarta.inject-api</artifactId>
</dependency>
</dependencies> </dependencies>
</project> </project>

View File

@ -22,23 +22,37 @@ import java.util.Optional;
import org.apache.maven.api.annotations.Experimental; import org.apache.maven.api.annotations.Experimental;
import org.apache.maven.api.annotations.Nonnull; import org.apache.maven.api.annotations.Nonnull;
import org.apache.maven.api.model.Plugin; import org.apache.maven.api.model.PluginExecution;
import org.apache.maven.api.plugin.descriptor.MojoDescriptor;
import org.apache.maven.api.xml.XmlNode; import org.apache.maven.api.xml.XmlNode;
/** /**
* A {@code MojoExecution} * A {@code MojoExecution} represents a single execution of a Maven Plugin during a given build.
* An instance of this object is bound to the {@link org.apache.maven.api.di.MojoExecutionScoped}
* and available as {@code mojoExecution} within {@link org.apache.maven.api.plugin.annotations.Parameter}
* expressions.
*/ */
@Experimental @Experimental
public interface MojoExecution { public interface MojoExecution {
@Nonnull @Nonnull
Plugin getPlugin(); Plugin getPlugin();
@Nonnull
PluginExecution getModel();
@Nonnull
MojoDescriptor getDescriptor();
@Nonnull @Nonnull
String getExecutionId(); String getExecutionId();
@Nonnull @Nonnull
String getGoal(); String getGoal();
@Nonnull
String getLifecyclePhase();
@Nonnull @Nonnull
Optional<XmlNode> getConfiguration(); Optional<XmlNode> getConfiguration();
} }

View File

@ -0,0 +1,58 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.maven.api;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import org.apache.maven.api.annotations.Experimental;
import org.apache.maven.api.annotations.Nonnull;
import org.apache.maven.api.plugin.descriptor.PluginDescriptor;
import org.apache.maven.api.plugin.descriptor.lifecycle.Lifecycle;
/**
* Represents a maven plugin runtime
*/
@Experimental
public interface Plugin {
@Nonnull
org.apache.maven.api.model.Plugin getModel();
@Nonnull
PluginDescriptor getDescriptor();
@Nonnull
List<Lifecycle> getLifecycles();
@Nonnull
ClassLoader getClassLoader();
@Nonnull
Artifact getArtifact();
@Nonnull
default Collection<Dependency> getDependencies() {
return getDependenciesMap().values();
}
@Nonnull
Map<String, Dependency> getDependenciesMap();
}

View File

@ -214,6 +214,13 @@ public interface Session {
@Nonnull @Nonnull
DependencyCoordinate createDependencyCoordinate(@Nonnull ArtifactCoordinate coordinate); DependencyCoordinate createDependencyCoordinate(@Nonnull ArtifactCoordinate coordinate);
/**
* Shortcut for <code>getService(DependencyFactory.class).create(...)</code>
* @see DependencyCoordinateFactory#create(Session, Dependency)
*/
@Nonnull
DependencyCoordinate createDependencyCoordinate(@Nonnull Dependency dependency);
/** /**
* Shortcut for <code>getService(ArtifactFactory.class).create(...)</code> * Shortcut for <code>getService(ArtifactFactory.class).create(...)</code>
* @see org.apache.maven.api.services.ArtifactFactory#create(Session, String, String, String, String) * @see org.apache.maven.api.services.ArtifactFactory#create(Session, String, String, String, String)

View File

@ -29,7 +29,7 @@ import org.apache.maven.api.annotations.Nonnull;
@Experimental @Experimental
public interface VersionRange { public interface VersionRange {
// TODO: add access to the version information // TODO: v4: add access to the version information
/** /**
* Determines whether the specified version is contained within this range. * Determines whether the specified version is contained within this range.

View File

@ -16,42 +16,26 @@
* specific language governing permissions and limitations * specific language governing permissions and limitations
* under the License. * under the License.
*/ */
package org.apache.maven.api.plugin.annotations; package org.apache.maven.api.di;
import java.lang.annotation.Documented; import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import java.lang.annotation.Target;
import org.apache.maven.api.annotations.Experimental; import jakarta.inject.Scope;
import org.apache.maven.api.annotations.Nonnull;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/** /**
* Used to configure injection of Plexus components by * Indicates that the annotated bean has a lifespan limited to a given mojo execution,
* <a href="/ref/current/maven-core/apidocs/org/apache/maven/plugin/MavenPluginManager.html"> * which means each mojo execution will result in a different instance being injected.
* <code>MavenPluginManager.getConfiguredMojo(...)</code></a>.
* *
* @since 4.0.0 * @since 4.0.0
*/ */
@Experimental @Scope
@Documented @Documented
@Retention(RetentionPolicy.CLASS) @Retention(RUNTIME)
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER}) @Target({TYPE, METHOD})
@Inherited public @interface MojoExecutionScoped {}
public @interface Component {
/**
* role of the component to inject.
* @return the role
*/
@Nonnull
Class<?> role() default Object.class;
/**
* hint of the component to inject.
* @return the hint
*/
@Nonnull
String hint() default "";
}

View File

@ -16,29 +16,26 @@
* specific language governing permissions and limitations * specific language governing permissions and limitations
* under the License. * under the License.
*/ */
package org.apache.maven.api.plugin.annotations; package org.apache.maven.api.di;
import org.apache.maven.api.annotations.Experimental; import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import jakarta.inject.Scope;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/** /**
* Component instantiation strategy. * Indicates that annotated component should be instantiated before session execution starts
* and discarded after session execution completes.
* *
* @since 4.0.0 * @since 4.0.0
*/ */
@Experimental @Scope
public enum InstantiationStrategy { @Documented
PER_LOOKUP("per-lookup"), @Retention(RUNTIME)
SINGLETON("singleton"), @Target({TYPE, METHOD})
KEEP_ALIVE("keep-alive"), public @interface SessionScoped {}
POOLABLE("poolable");
private final String id;
InstantiationStrategy(String id) {
this.id = id;
}
public String id() {
return this.id;
}
}

View File

@ -34,6 +34,8 @@ public final class Features {
/** /**
* Name of the Maven user property to enable or disable the build/consumer POM feature. * Name of the Maven user property to enable or disable the build/consumer POM feature.
*
* TODO: v4: remove experimental bit
*/ */
public static final String BUILDCONSUMER = "maven.experimental.buildconsumer"; public static final String BUILDCONSUMER = "maven.experimental.buildconsumer";

View File

@ -0,0 +1,39 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.maven.api.plugin;
import java.util.List;
import org.apache.maven.api.annotations.Consumer;
import org.apache.maven.api.annotations.Experimental;
import org.apache.maven.api.plugin.descriptor.lifecycle.Lifecycle;
/**
* Interface that can be provided by the plugin to wire in custom lifecycles
* leveraged using the {@link org.apache.maven.api.plugin.annotations.Execute}
* annotation. If a {@code META-INF/maven/lifecycle.xml} file is packaged
* in the plugin, Maven will provide a default implementation that will parse
* the file and return the contained lifecycle definitions.
*/
@Experimental
@Consumer
public interface LifecycleProvider {
List<Lifecycle> getLifecycles();
}

View File

@ -31,6 +31,9 @@ import org.apache.maven.api.annotations.Nonnull;
/** /**
* This annotation will mark your class as a Mojo (ie. goal in a Maven plugin). * This annotation will mark your class as a Mojo (ie. goal in a Maven plugin).
* The mojo can be annotated with {@code jakarta.inject.*} annotations.
* The {@link Parameter} annotation can be added on fields to inject data
* from the plugin configuration or from other components.
* *
* @since 4.0.0 * @since 4.0.0
*/ */
@ -59,27 +62,20 @@ public @interface Mojo {
* @return the required dependency resolution scope * @return the required dependency resolution scope
*/ */
@Nonnull @Nonnull
ResolutionScope requiresDependencyResolution() default ResolutionScope.NONE; ResolutionScope dependencyResolutionRequired() default ResolutionScope.NONE;
/** /**
* the required dependency collection scope. * the required dependency collection scope.
* @return the required dependency collection scope * @return the required dependency collection scope
*/ */
@Nonnull @Nonnull
ResolutionScope requiresDependencyCollection() default ResolutionScope.NONE; ResolutionScope dependencyCollectionRequired() default ResolutionScope.NONE;
/**
* your Mojo instantiation strategy. (Only <code>per-lookup</code> and <code>singleton</code> are supported)
* @return the instantiation strategy
*/
@Nonnull
InstantiationStrategy instantiationStrategy() default InstantiationStrategy.PER_LOOKUP;
/** /**
* does your mojo requires a project to be executed? * does your mojo requires a project to be executed?
* @return requires a project * @return requires a project
*/ */
boolean requiresProject() default true; boolean projectRequired() default true;
/** /**
* if the Mojo uses the Maven project and its child modules. * if the Mojo uses the Maven project and its child modules.
@ -91,9 +87,10 @@ public @interface Mojo {
* does this Mojo need to be online to be executed? * does this Mojo need to be online to be executed?
* @return need to be online * @return need to be online
*/ */
boolean requiresOnline() default false; boolean onlineRequired() default false;
/** /**
* TODO: v4: add a SPI for the configurator
* configurator bean name. * configurator bean name.
* @return the configurator bean name * @return the configurator bean name
*/ */

View File

@ -0,0 +1,105 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.apache.maven</groupId>
<artifactId>maven-api</artifactId>
<version>4.0.0-alpha-9-SNAPSHOT</version>
</parent>
<artifactId>maven-api-plugin</artifactId>
<name>Maven 4 API :: Plugin</name>
<description>Maven 4 API - Immutable Plugin model.</description>
<dependencies>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-api-xml</artifactId>
<version>4.0.0-alpha-9-SNAPSHOT</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.modello</groupId>
<artifactId>modello-maven-plugin</artifactId>
<executions>
<execution>
<id>plugin</id>
<goals>
<goal>velocity</goal>
<goal>xdoc</goal>
<goal>xsd</goal>
</goals>
<phase>generate-resources</phase>
<configuration>
<velocityBasedir>${project.basedir}/../../src/mdo</velocityBasedir>
<version>2.0.0</version>
<models>
<model>src/main/mdo/plugin.mdo</model>
</models>
<templates>
<template>model.vm</template>
</templates>
<params>
<param>packageModelV4=org.apache.maven.api.plugin.descriptor</param>
</params>
</configuration>
</execution>
<execution>
<id>lifecycle</id>
<goals>
<goal>velocity</goal>
<goal>xdoc</goal>
<goal>xsd</goal>
</goals>
<phase>generate-resources</phase>
<configuration>
<velocityBasedir>${project.basedir}/../../src/mdo</velocityBasedir>
<version>1.0.0</version>
<models>
<model>src/main/mdo/lifecycle.mdo</model>
</models>
<templates>
<template>model.vm</template>
</templates>
<params>
<param>packageModelV4=org.apache.maven.api.plugin.descriptor.lifecycle</param>
</params>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<excludes>
<exclude>**/package-info.java</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,5 @@
// CHECKSTYLE_OFF: RegexpHeader
/**
* Maven Plugin forked lifecycle model.
*/
package org.apache.maven.api.plugin.descriptor.lifecycle;

View File

@ -0,0 +1,5 @@
// CHECKSTYLE_OFF: RegexpHeader
/**
* Maven Plugin descriptor model.
*/
package org.apache.maven.api.plugin.descriptor;

View File

@ -17,22 +17,16 @@ specific language governing permissions and limitations
under the License. under the License.
--> -->
<model xmlns="http://codehaus-plexus.github.io/MODELLO/1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" <model xmlns="http://codehaus-plexus.github.io/MODELLO/2.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://codehaus-plexus.github.io/MODELLO/1.0.0 http://codehaus-plexus.github.io/modello/xsd/modello-1.0.0.xsd" xsi:schemaLocation="http://codehaus-plexus.github.io/MODELLO/2.0.0 http://codehaus-plexus.github.io/modello/xsd/modello-2.0.0.xsd"
xml.namespace="http://maven.apache.org/LIFECYCLE/${version}" xml.namespace="http://maven.apache.org/LIFECYCLE/${version}"
xml.schemaLocation="http://maven.apache.org/xsd/lifecycle-${version}.xsd"> xml.schemaLocation="http://maven.apache.org/xsd/lifecycle-${version}.xsd">
<id>lifecycle-mappings</id> <id>lifecycle</id>
<name>LifecycleMappings</name> <name>Lifecycle</name>
<description><![CDATA[ <description><![CDATA[
Configuration of custom lifecycle mappings for the plugin, as generally stored in Configuration of custom lifecycle mappings for the plugin, as generally stored in
<code>META-INF/maven/lifecycle.xml</code> in a plugin's jar artifact. <code>META-INF/maven/lifecycle.xml</code> in a plugin's jar artifact.
]]></description> ]]></description>
<defaults>
<default>
<key>package</key>
<value>org.apache.maven.plugin.lifecycle</value>
</default>
</defaults>
<classes> <classes>
<class rootElement="true" xml.tagName="lifecycles" xsd.compositor="sequence"> <class rootElement="true" xml.tagName="lifecycles" xsd.compositor="sequence">
<name>LifecycleConfiguration</name> <name>LifecycleConfiguration</name>

View File

@ -24,26 +24,15 @@ under the License.
<id>plugin</id> <id>plugin</id>
<name>PluginDescriptor</name> <name>PluginDescriptor</name>
<description><![CDATA[ <description><![CDATA[
Plugin descriptor, stored in <code>META-INF/maven/plugin.xml</code> in a plugin's jar artifact. Maven 4 Plugin descriptor, stored in <code>META-INF/maven/plugin.xml</code> in a plugin's jar artifact.
This descriptor is generally generated from plugin sources, using This descriptor is generally using the information contained in the annotations of the plugin api.
<a href="/plugins/maven-plugin-plugin/">maven-plugin-plugin</a>. <p>An XSD is available at <a href="https://maven.apache.org/xsd/plugin-2.0.0.xsd">https://maven.apache.org/xsd/plugin-2.0.0.xsd</a></p>
<p><i>Notice:</i> this documentation is generated from a Modello model but the
<a href="apidocs/org/apache/maven/plugin/descriptor/PluginDescriptor.html"><code>PluginDescriptor</code></a>/<a href="apidocs/org/apache/maven/plugin/descriptor/MojoDescriptor.html"><code>MojoDescriptor</code></a>
code executed is not generated from this model. Please report if you find anything wrong this documentation.</p>
<p>An XSD is available at <a href="https://maven.apache.org/xsd/plugin-1.1.0.xsd">https://maven.apache.org/xsd/plugin-1.1.0.xsd</a></p>
]]></description> ]]></description>
<defaults>
<default>
<key>package</key>
<value>plugin descriptor XML documentation (no java generation)</value><!-- intentionally non-buildable value -->
</default>
</defaults>
<classes> <classes>
<class rootElement="true" xml.tagName="plugin" xdoc.anchorName="plugin"> <class rootElement="true" xml.tagName="plugin" xdoc.anchorName="plugin">
<name>PluginDescriptor</name> <name>PluginDescriptor</name>
<version>1.0.0+</version> <version>1.0.0+</version>
<description><![CDATA[Root element of the <code>plugin.xml</code> file.]]></description> <description><![CDATA[Root element of the <code>plugin.xml</code> file.]]></description>
<!-- see o.a.m.plugin.descriptor.PluginDescriptor -->
<fields> <fields>
<field> <field>
<name>name</name> <name>name</name>
@ -120,7 +109,7 @@ under the License.
</field> </field>
<field xdoc.separator="blank"> <field xdoc.separator="blank">
<name>dependencies</name> <name>dependencies</name>
<version>1.0.0+</version> <version>1.0.0/1.1.0</version>
<association> <association>
<type>Dependency</type> <type>Dependency</type>
<multiplicity>*</multiplicity> <multiplicity>*</multiplicity>
@ -131,6 +120,21 @@ under the License.
</description> </description>
</field> </field>
</fields> </fields>
<codeSegments>
<codeSegment>
<version>2.0.0+</version>
<code><![CDATA[
public String getPluginLookupKey() {
return groupId + ":" + artifactId;
}
public String getId() {
return groupId + ":" + artifactId + ":" + version;
}
]]></code>
</codeSegment>
</codeSegments>
</class> </class>
<class xdoc.anchorName="mojo"> <class xdoc.anchorName="mojo">
@ -139,7 +143,6 @@ under the License.
<description><![CDATA[ <description><![CDATA[
A Mojo description. A Mojo description.
]]></description> ]]></description>
<!-- see o.a.m.plugin.descriptor.MojoDescriptor -->
<fields> <fields>
<field> <field>
<name>goal</name> <name>goal</name>
@ -203,7 +206,18 @@ under the License.
</field> </field>
<field> <field>
<name>requiresDependencyResolution</name> <name>requiresDependencyResolution</name>
<version>1.0.0+</version> <version>1.0.0/1.1.0</version>
<type>String</type>
<defaultValue>runtime</defaultValue>
<description><![CDATA[
Flags this Mojo as requiring the dependencies in the specified class path to be resolved before it can
execute: <code>compile</code>, <code>runtime</code>, <code>test</code>,
<code>compile+runtime</code> (since Maven 3.0) or <code>runtime+system</code> (since Maven 3.0)
]]></description>
</field>
<field>
<name>dependencyResolution</name>
<version>2.0.0+</version>
<type>String</type> <type>String</type>
<defaultValue>runtime</defaultValue> <defaultValue>runtime</defaultValue>
<description><![CDATA[ <description><![CDATA[
@ -214,7 +228,20 @@ under the License.
</field> </field>
<field> <field>
<name>requiresDependencyCollection</name> <name>requiresDependencyCollection</name>
<version>1.0.0+</version> <version>1.0.0/1.1.0</version>
<type>String</type>
<description><![CDATA[
Flags this Mojo as requiring information about the dependencies that would make up the specified class
path. As the name suggests, this is similar to requiresDependencyResolution and supports the same values.
The important difference is this will not resolve the files for the dependencies, i.e. the artifacts
associated with a Maven project can lack a file. As such, this annotation is meant for Mojos that only
want to analyze the set of transitive dependencies, in particular during early lifecycle phases where
full dependency resolution might fail due to projects which haven't been built yet.
]]></description>
</field>
<field>
<name>dependencyCollection</name>
<version>2.0.0+</version>
<type>String</type> <type>String</type>
<description><![CDATA[ <description><![CDATA[
Flags this Mojo as requiring information about the dependencies that would make up the specified class Flags this Mojo as requiring information about the dependencies that would make up the specified class
@ -227,14 +254,28 @@ under the License.
</field> </field>
<field> <field>
<name>requiresDirectInvocation</name> <name>requiresDirectInvocation</name>
<version>1.0.0+</version> <version>1.0.0/1.1.0</version>
<type>boolean</type>
<description>Flags this Mojo to be invoked directly only.</description>
<defaultValue>false</defaultValue>
</field>
<field>
<name>directInvocationOnly</name>
<version>2.0.0+</version>
<type>boolean</type> <type>boolean</type>
<description>Flags this Mojo to be invoked directly only.</description> <description>Flags this Mojo to be invoked directly only.</description>
<defaultValue>false</defaultValue> <defaultValue>false</defaultValue>
</field> </field>
<field> <field>
<name>requiresProject</name> <name>requiresProject</name>
<version>1.0.0+</version> <version>1.0.0/1.1.0</version>
<type>boolean</type>
<description>Flags this Mojo to require running inside of a project.</description>
<defaultValue>true</defaultValue>
</field>
<field>
<name>projectRequired</name>
<version>2.0.0+</version>
<type>boolean</type> <type>boolean</type>
<description>Flags this Mojo to require running inside of a project.</description> <description>Flags this Mojo to require running inside of a project.</description>
<defaultValue>true</defaultValue> <defaultValue>true</defaultValue>
@ -248,7 +289,14 @@ under the License.
</field> </field>
<field> <field>
<name>requiresOnline</name> <name>requiresOnline</name>
<version>1.0.0+</version> <version>1.0.0/1.1.0</version>
<type>boolean</type>
<description>Flags this Mojo to require online mode for its operation.</description>
<defaultValue>false</defaultValue>
</field>
<field>
<name>onlineRequired</name>
<version>2.0.0+</version>
<type>boolean</type> <type>boolean</type>
<description>Flags this Mojo to require online mode for its operation.</description> <description>Flags this Mojo to require online mode for its operation.</description>
<defaultValue>false</defaultValue> <defaultValue>false</defaultValue>
@ -272,7 +320,7 @@ under the License.
</field> </field>
<field> <field>
<name>threadSafe</name> <name>threadSafe</name>
<version>1.0.0+</version> <version>1.0.0/1.1.0</version>
<type>boolean</type> <type>boolean</type>
<description> <description>
Marks this Mojo as being thread-safe, i.e. the Mojo safely supports concurrent execution during parallel Marks this Mojo as being thread-safe, i.e. the Mojo safely supports concurrent execution during parallel
@ -283,21 +331,21 @@ under the License.
</field> </field>
<field> <field>
<name>v4Api</name> <name>v4Api</name>
<version>1.1.0+</version> <version>1.1.0</version>
<type>boolean</type> <type>boolean</type>
<description>Marks this Mojo as using Maven 4 API. This makes the plugin implicitly incompatible with earlier Maven versions. Only evaluated since Maven 4.</description> <description>Marks this Mojo as using Maven 4 API. This makes the plugin implicitly incompatible with earlier Maven versions. Only evaluated since Maven 4.</description>
<defaultValue>false</defaultValue> <defaultValue>false</defaultValue>
</field> </field>
<field> <field>
<name>instantiationStrategy</name> <name>instantiationStrategy</name>
<version>1.0.0+</version> <version>1.0.0/1.1.0</version>
<type>String</type> <type>String</type>
<defaultValue>per-lookup</defaultValue> <defaultValue>per-lookup</defaultValue>
<description>Specify the instantiation strategy.</description> <description>Specify the instantiation strategy.</description>
</field> </field>
<field> <field>
<name>executionStrategy</name> <name>executionStrategy</name>
<version>1.0.0+</version> <version>1.0.0/1.1.0</version>
<type>String</type> <type>String</type>
<description><![CDATA[ <description><![CDATA[
Specify the execution strategy: <code>once-per-session</code>, <code>always</code>. Specify the execution strategy: <code>once-per-session</code>, <code>always</code>.
@ -331,7 +379,7 @@ under the License.
</field> </field>
<field> <field>
<name>composer</name> <name>composer</name>
<version>1.0.0+</version> <version>1.0.0/1.1.0</version>
<type>String</type> <type>String</type>
<description></description> <description></description>
</field> </field>
@ -344,27 +392,27 @@ under the License.
<multiplicity>*</multiplicity> <multiplicity>*</multiplicity>
</association> </association>
</field> </field>
<field>
<name>configuration</name>
<version>1.0.0+</version>
<description>Specifies default values of parameters (with attribute "default-value") as well as how they can be overwritten by Maven properties (in the element content).</description>
<!-- https://github.com/codehaus-plexus/modello/issues/264 -->
<type>DOM</type>
<!--
<association xml.tagName="paramName">
<type>Configuration</type>
<multiplicity>*</multiplicity>
</association> -->
</field>
<field xdoc.separator="blank"> <field xdoc.separator="blank">
<name>requirements</name> <name>requirements</name>
<version>1.0.0+</version> <version>1.0.0/1.1.0</version>
<description></description> <description></description>
<association> <association>
<type>Requirement</type> <type>Requirement</type>
<multiplicity>*</multiplicity> <multiplicity>*</multiplicity>
</association> </association>
</field> </field>
<field xml.format="((PluginDescriptor.Builder) context.peekLast()).build().getId() + &quot;:&quot; + mojoDescriptor.build().getGoal()">
<name>id</name>
<version>2.0.0+</version>
<type>String</type>
<description>the id of the mojo, based on the goal name</description>
</field>
<field xml.format="((PluginDescriptor.Builder) context.peekLast()).build().getGoalPrefix() + &quot;:&quot; + mojoDescriptor.build().getGoal()">
<name>fullGoalName</name>
<version>2.0.0+</version>
<type>String</type>
<description>the full goal name</description>
</field>
</fields> </fields>
</class> </class>
@ -428,12 +476,6 @@ under the License.
full of Strings. full of Strings.
]]></description> ]]></description>
</field> </field>
<field>
<name>implementation</name>
<version>1.0.0+</version>
<type>String</type>
<description></description>
</field>
<field> <field>
<name>description</name> <name>description</name>
<version>1.0.0+</version> <version>1.0.0+</version>
@ -455,31 +497,15 @@ under the License.
This will trigger a warning when a user tries to configure a parameter marked as deprecated. This will trigger a warning when a user tries to configure a parameter marked as deprecated.
]]></description> ]]></description>
</field> </field>
</fields> <field>
</class>
<class>
<name>Configuration</name>
<version>1.0.0+</version>
<description>A parameter configuration.</description>
<!-- see o.a.m.plugin.descriptor.Parameter -->
<fields>
<field xml.content="true">
<name>expression</name> <name>expression</name>
<required>true</required> <version>2.0.0+</version>
<version>1.0.0+</version>
<type>String</type> <type>String</type>
<description>Parameter expression, to let user override default value with a user property, system property or project property.</description> <description>Parameter expression, to let user override default value with a user property, system property or project property.</description>
</field> </field>
<field xml.attribute="true" xml.tagName="implementation"> <field>
<name>implementation</name>
<version>1.0.0+</version>
<type>String</type>
<description></description>
</field>
<field xml.attribute="true" xml.tagName="default-value">
<name>defaultValue</name> <name>defaultValue</name>
<version>1.0.0+</version> <version>2.0.0+</version>
<type>String</type> <type>String</type>
<description>The default value, as an expression that will be evaluated at injection or run-time.</description> <description>The default value, as an expression that will be evaluated at injection or run-time.</description>
</field> </field>
@ -488,7 +514,7 @@ under the License.
<class xdoc.anchorName="requirement"> <class xdoc.anchorName="requirement">
<name>Requirement</name> <name>Requirement</name>
<version>1.0.0+</version> <version>1.0.0/1.1.0</version>
<description>Describes a component requirement.</description> <description>Describes a component requirement.</description>
<!-- see o.a.m.plugin.descriptor.Requirement --> <!-- see o.a.m.plugin.descriptor.Requirement -->
<fields> <fields>
@ -517,7 +543,7 @@ under the License.
<class xdoc.anchorName="dependency"> <class xdoc.anchorName="dependency">
<name>Dependency</name> <name>Dependency</name>
<version>1.0.0+</version> <version>1.0.0/1.1.0</version>
<description>Definition of a dependency, needed by the plugin at runtime.</description> <description>Definition of a dependency, needed by the plugin at runtime.</description>
<fields> <fields>
<field> <field>

View File

@ -0,0 +1,33 @@
~~ Licensed to the Apache Software Foundation (ASF) under one
~~ or more contributor license agreements. See the NOTICE file
~~ distributed with this work for additional information
~~ regarding copyright ownership. The ASF licenses this file
~~ to you under the Apache License, Version 2.0 (the
~~ "License"); you may not use this file except in compliance
~~ with the License. You may obtain a copy of the License at
~~
~~ http://www.apache.org/licenses/LICENSE-2.0
~~
~~ Unless required by applicable law or agreed to in writing,
~~ software distributed under the License is distributed on an
~~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
~~ KIND, either express or implied. See the License for the
~~ specific language governing permissions and limitations
~~ under the License.
-----
Introduction
-----
Guillaume Nodet
-----
2023-11-15
-----
Maven 4 API - Plugin Descriptor Model
This is the immutable model for Maven Plugin Descriptor in <<<org.apache.maven.api.plugin.descriptor>>> package.
The following are generated from this model:
* {{{./apidocs/index.html}Java sources}} with <<<Builder>>> inner classes for immutable instances creation.

View File

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<project xmlns="http://maven.apache.org/DECORATION/1.8.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/DECORATION/1.8.0 http://maven.apache.org/xsd/decoration-1.8.0.xsd">
<edit>${project.scm.url}</edit>
<body>
<menu name="Overview">
<item name="Introduction" href="index.html"/>
<item name="Javadocs" href="apidocs/index.html"/>
<item name="Source Xref" href="xref/index.html"/>
<!--item name="FAQ" href="faq.html"/-->
</menu>
<menu ref="parent"/>
<menu ref="reports"/>
</body>
</project>

View File

@ -35,6 +35,7 @@
<module>maven-api-meta</module> <module>maven-api-meta</module>
<module>maven-api-xml</module> <module>maven-api-xml</module>
<module>maven-api-model</module> <module>maven-api-model</module>
<module>maven-api-plugin</module>
<module>maven-api-settings</module> <module>maven-api-settings</module>
<module>maven-api-toolchain</module> <module>maven-api-toolchain</module>
<module>maven-api-core</module> <module>maven-api-core</module>

View File

@ -122,6 +122,11 @@ under the License.
<artifactId>maven-api-toolchain</artifactId> <artifactId>maven-api-toolchain</artifactId>
<version>${project.version}</version> <version>${project.version}</version>
</dependency> </dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-api-plugin</artifactId>
<version>${project.version}</version>
</dependency>
<dependency> <dependency>
<groupId>org.apache.maven</groupId> <groupId>org.apache.maven</groupId>
<artifactId>maven-api-xml</artifactId> <artifactId>maven-api-xml</artifactId>

View File

@ -36,7 +36,6 @@ import java.util.LinkedHashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Function; import java.util.function.Function;
import java.util.stream.Stream; import java.util.stream.Stream;
@ -60,8 +59,8 @@ import org.apache.maven.graph.GraphBuilder;
import org.apache.maven.graph.ProjectSelector; import org.apache.maven.graph.ProjectSelector;
import org.apache.maven.internal.aether.DefaultRepositorySystemSessionFactory; import org.apache.maven.internal.aether.DefaultRepositorySystemSessionFactory;
import org.apache.maven.internal.aether.MavenChainedWorkspaceReader; import org.apache.maven.internal.aether.MavenChainedWorkspaceReader;
import org.apache.maven.internal.impl.DefaultSession;
import org.apache.maven.internal.impl.DefaultSessionFactory; import org.apache.maven.internal.impl.DefaultSessionFactory;
import org.apache.maven.internal.impl.InternalSession;
import org.apache.maven.lifecycle.LifecycleExecutionException; import org.apache.maven.lifecycle.LifecycleExecutionException;
import org.apache.maven.lifecycle.internal.ExecutionEventCatapult; import org.apache.maven.lifecycle.internal.ExecutionEventCatapult;
import org.apache.maven.lifecycle.internal.LifecycleStarter; import org.apache.maven.lifecycle.internal.LifecycleStarter;
@ -215,18 +214,18 @@ public class DefaultMaven implements Maven {
// so that @SessionScoped components can be @Injected into AbstractLifecycleParticipants. // so that @SessionScoped components can be @Injected into AbstractLifecycleParticipants.
// //
sessionScope.enter(); sessionScope.enter();
try (CloseableSession closeableSession = newCloseableSession(request)) { MavenChainedWorkspaceReader chainedWorkspaceReader = new MavenChainedWorkspaceReader();
AtomicReference<CloseableSession> closeableSessionRef = new AtomicReference<>(closeableSession); try (CloseableSession closeableSession = newCloseableSession(request, chainedWorkspaceReader)) {
MavenSession session = new MavenSession(closeableSessionRef::get, request, result); MavenSession session = new MavenSession(closeableSession, request, result);
session.setSession(defaultSessionFactory.getSession(session)); session.setSession(defaultSessionFactory.getSession(session));
sessionScope.seed(MavenSession.class, session); sessionScope.seed(MavenSession.class, session);
sessionScope.seed(Session.class, session.getSession()); sessionScope.seed(Session.class, session.getSession());
sessionScope.seed(DefaultSession.class, (DefaultSession) session.getSession()); sessionScope.seed(InternalSession.class, InternalSession.from(session.getSession()));
legacySupport.setSession(session); legacySupport.setSession(session);
return doExecute(request, session, result, closeableSessionRef); return doExecute(request, session, result, chainedWorkspaceReader);
} finally { } finally {
sessionScope.exit(); sessionScope.exit();
} }
@ -236,7 +235,7 @@ public class DefaultMaven implements Maven {
MavenExecutionRequest request, MavenExecutionRequest request,
MavenSession session, MavenSession session,
MavenExecutionResult result, MavenExecutionResult result,
AtomicReference<CloseableSession> closeableSessionRef) { MavenChainedWorkspaceReader chainedWorkspaceReader) {
try { try {
afterSessionStart(session); afterSessionStart(session);
} catch (MavenExecutionException e) { } catch (MavenExecutionException e) {
@ -245,11 +244,7 @@ public class DefaultMaven implements Maven {
try { try {
WorkspaceReader reactorReader = container.lookup(WorkspaceReader.class, ReactorReader.HINT); WorkspaceReader reactorReader = container.lookup(WorkspaceReader.class, ReactorReader.HINT);
closeableSessionRef.set(closeableSessionRef chainedWorkspaceReader.setReaders(Collections.singletonList(reactorReader));
.get()
.copy()
.setWorkspaceReader(reactorReader)
.build());
} catch (ComponentLookupException e) { } catch (ComponentLookupException e) {
return addExceptionToResult(result, e); return addExceptionToResult(result, e);
} }
@ -270,7 +265,7 @@ public class DefaultMaven implements Maven {
} }
try { try {
closeableSessionRef.set(setupWorkspaceReader(session, closeableSessionRef.get())); setupWorkspaceReader(session, chainedWorkspaceReader);
} catch (ComponentLookupException e) { } catch (ComponentLookupException e) {
return addExceptionToResult(result, e); return addExceptionToResult(result, e);
} }
@ -340,7 +335,7 @@ public class DefaultMaven implements Maven {
return result; return result;
} }
private CloseableSession setupWorkspaceReader(MavenSession session, CloseableSession repoSession) private void setupWorkspaceReader(MavenSession session, MavenChainedWorkspaceReader chainedWorkspaceReader)
throws ComponentLookupException { throws ComponentLookupException {
// Desired order of precedence for workspace readers before querying the local artifact repositories // Desired order of precedence for workspace readers before querying the local artifact repositories
Set<WorkspaceReader> workspaceReaders = new LinkedHashSet<>(); Set<WorkspaceReader> workspaceReaders = new LinkedHashSet<>();
@ -348,16 +343,14 @@ public class DefaultMaven implements Maven {
WorkspaceReader reactorReader = container.lookup(WorkspaceReader.class, ReactorReader.HINT); WorkspaceReader reactorReader = container.lookup(WorkspaceReader.class, ReactorReader.HINT);
workspaceReaders.add(reactorReader); workspaceReaders.add(reactorReader);
// 2) Repository system session-scoped workspace reader // 2) Repository system session-scoped workspace reader
WorkspaceReader repoWorkspaceReader = repoSession.getWorkspaceReader(); for (WorkspaceReader repoWorkspaceReader : chainedWorkspaceReader.getReaders()) {
if (repoWorkspaceReader != null && repoWorkspaceReader != reactorReader) { if (repoWorkspaceReader != null && repoWorkspaceReader != reactorReader) {
workspaceReaders.add(repoWorkspaceReader); workspaceReaders.add(repoWorkspaceReader);
} }
}
// 3) .. n) Project-scoped workspace readers // 3) .. n) Project-scoped workspace readers
workspaceReaders.addAll(getProjectScopedExtensionComponents(session.getProjects(), WorkspaceReader.class)); workspaceReaders.addAll(getProjectScopedExtensionComponents(session.getProjects(), WorkspaceReader.class));
return repoSession chainedWorkspaceReader.setReaders(workspaceReaders);
.copy()
.setWorkspaceReader(MavenChainedWorkspaceReader.of(workspaceReaders))
.build();
} }
private void afterSessionStart(MavenSession session) throws MavenExecutionException { private void afterSessionStart(MavenSession session) throws MavenExecutionException {
@ -418,11 +411,14 @@ public class DefaultMaven implements Maven {
*/ */
@Deprecated @Deprecated
public RepositorySystemSession newRepositorySession(MavenExecutionRequest request) { public RepositorySystemSession newRepositorySession(MavenExecutionRequest request) {
return newCloseableSession(request); return newCloseableSession(request, new MavenChainedWorkspaceReader());
} }
private CloseableSession newCloseableSession(MavenExecutionRequest request) { private CloseableSession newCloseableSession(MavenExecutionRequest request, WorkspaceReader workspaceReader) {
return repositorySessionFactory.newRepositorySessionBuilder(request).build(); return repositorySessionFactory
.newRepositorySessionBuilder(request)
.setWorkspaceReader(workspaceReader)
.build();
} }
private void validateLocalRepository(MavenExecutionRequest request) throws IOException { private void validateLocalRepository(MavenExecutionRequest request) throws IOException {

View File

@ -27,7 +27,6 @@ import java.util.Map;
import java.util.Properties; import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ConcurrentMap;
import java.util.function.Supplier;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import org.apache.maven.api.Session; import org.apache.maven.api.Session;
@ -58,7 +57,7 @@ public class MavenSession implements Cloneable {
private final MavenExecutionResult result; private final MavenExecutionResult result;
private final Supplier<RepositorySystemSession> repositorySystemSessionSupplier; private final RepositorySystemSession repositorySystemSession;
private final Properties executionProperties; private final Properties executionProperties;
@ -260,7 +259,7 @@ public class MavenSession implements Cloneable {
} }
public RepositorySystemSession getRepositorySession() { public RepositorySystemSession getRepositorySession() {
return repositorySystemSessionSupplier.get(); return repositorySystemSession;
} }
private Map<String, MavenProject> projectMap; private Map<String, MavenProject> projectMap;
@ -298,14 +297,14 @@ public class MavenSession implements Cloneable {
} }
public MavenSession( public MavenSession(
Supplier<RepositorySystemSession> repositorySystemSessionSupplier, RepositorySystemSession repositorySystemSession,
MavenExecutionRequest request, MavenExecutionRequest request,
MavenExecutionResult result) { MavenExecutionResult result) {
this.container = null; this.container = null;
this.request = requireNonNull(request); this.request = requireNonNull(request);
this.result = requireNonNull(result); this.result = requireNonNull(result);
this.settings = adaptSettings(request); this.settings = adaptSettings(request);
this.repositorySystemSessionSupplier = requireNonNull(repositorySystemSessionSupplier); this.repositorySystemSession = requireNonNull(repositorySystemSession);
Properties executionProperties = new Properties(); Properties executionProperties = new Properties();
executionProperties.putAll(request.getSystemProperties()); executionProperties.putAll(request.getSystemProperties());
executionProperties.putAll(request.getUserProperties()); executionProperties.putAll(request.getUserProperties());
@ -322,7 +321,7 @@ public class MavenSession implements Cloneable {
this.request = request; this.request = request;
this.result = result; this.result = result;
this.settings = adaptSettings(request); this.settings = adaptSettings(request);
this.repositorySystemSessionSupplier = () -> repositorySession; this.repositorySystemSession = repositorySession;
Properties executionProperties = new Properties(); Properties executionProperties = new Properties();
executionProperties.putAll(request.getSystemProperties()); executionProperties.putAll(request.getSystemProperties());
executionProperties.putAll(request.getUserProperties()); executionProperties.putAll(request.getUserProperties());
@ -386,7 +385,7 @@ public class MavenSession implements Cloneable {
this.request.setBaseDirectory((executionRootDir != null) ? new File(executionRootDir) : null); this.request.setBaseDirectory((executionRootDir != null) ? new File(executionRootDir) : null);
this.request.setStartTime(startTime); this.request.setStartTime(startTime);
this.result = null; this.result = null;
this.repositorySystemSessionSupplier = () -> null; this.repositorySystemSession = null;
} }
@Deprecated @Deprecated
@ -404,7 +403,7 @@ public class MavenSession implements Cloneable {
executionProperties.putAll(request.getUserProperties()); executionProperties.putAll(request.getUserProperties());
this.executionProperties = executionProperties; this.executionProperties = executionProperties;
setProjects(projects); setProjects(projects);
this.repositorySystemSessionSupplier = () -> null; this.repositorySystemSession = null;
} }
/** /**

View File

@ -43,6 +43,7 @@ public class MojoExecutionScopeModule extends AbstractModule {
@Override @Override
protected void configure() { protected void configure() {
bindScope(MojoExecutionScoped.class, scope); bindScope(MojoExecutionScoped.class, scope);
bindScope(org.apache.maven.api.di.MojoExecutionScoped.class, scope);
bind(MojoExecutionScope.class).toInstance(scope); bind(MojoExecutionScope.class).toInstance(scope);
bind(MavenProject.class) bind(MavenProject.class)
.toProvider(MojoExecutionScope.seededKeyProvider()) .toProvider(MojoExecutionScope.seededKeyProvider())

View File

@ -19,61 +19,122 @@
package org.apache.maven.internal.aether; package org.apache.maven.internal.aether;
import java.io.File; import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List; import java.util.List;
import java.util.stream.Collectors;
import org.apache.maven.model.Model; import org.apache.maven.model.Model;
import org.apache.maven.repository.internal.MavenWorkspaceReader; import org.apache.maven.repository.internal.MavenWorkspaceReader;
import org.eclipse.aether.artifact.Artifact; import org.eclipse.aether.artifact.Artifact;
import org.eclipse.aether.repository.WorkspaceReader; import org.eclipse.aether.repository.WorkspaceReader;
import org.eclipse.aether.repository.WorkspaceRepository; import org.eclipse.aether.repository.WorkspaceRepository;
import org.eclipse.aether.util.repository.ChainedWorkspaceReader;
import static java.util.Objects.requireNonNull;
/** /**
* A maven workspace reader that delegates to a chain of other readers, effectively aggregating their contents. * A maven workspace reader that delegates to a chain of other readers, effectively aggregating their contents.
*/ */
public final class MavenChainedWorkspaceReader implements MavenWorkspaceReader { public class MavenChainedWorkspaceReader implements MavenWorkspaceReader {
private ChainedWorkspaceReader delegate; protected List<WorkspaceReader> readers;
protected WorkspaceRepository repository;
private WorkspaceReader[] readers;
/** /**
* Creates a new workspace reader by chaining the specified readers. * Creates a new workspace reader by chaining the specified readers.
* *
* @param readers The readers to chain must not be {@code null}. * @param readers The readers to chain must not be {@code null}.
*/ */
private MavenChainedWorkspaceReader(WorkspaceReader... readers) { public MavenChainedWorkspaceReader(WorkspaceReader... readers) {
this.delegate = new ChainedWorkspaceReader(readers); setReaders(Arrays.asList(readers));
this.readers = readers;
}
@Override
public Model findModel(Artifact artifact) {
for (WorkspaceReader workspaceReader : readers) {
if (workspaceReader instanceof MavenWorkspaceReader) {
Model model = ((MavenWorkspaceReader) workspaceReader).findModel(artifact);
if (model != null) {
return model;
}
}
}
return null;
} }
@Override @Override
public WorkspaceRepository getRepository() { public WorkspaceRepository getRepository() {
return delegate.getRepository(); return this.repository;
}
@Override
public Model findModel(Artifact artifact) {
requireNonNull(artifact, "artifact cannot be null");
Model model = null;
for (WorkspaceReader workspaceReader : readers) {
if (workspaceReader instanceof MavenWorkspaceReader) {
model = ((MavenWorkspaceReader) workspaceReader).findModel(artifact);
if (model != null) {
break;
}
}
}
return model;
} }
@Override @Override
public File findArtifact(Artifact artifact) { public File findArtifact(Artifact artifact) {
return delegate.findArtifact(artifact); requireNonNull(artifact, "artifact cannot be null");
File file = null;
for (WorkspaceReader reader : readers) {
file = reader.findArtifact(artifact);
if (file != null) {
break;
}
}
return file;
} }
@Override @Override
public List<String> findVersions(Artifact artifact) { public List<String> findVersions(Artifact artifact) {
return delegate.findVersions(artifact); requireNonNull(artifact, "artifact cannot be null");
Collection<String> versions = new LinkedHashSet<>();
for (WorkspaceReader reader : readers) {
versions.addAll(reader.findVersions(artifact));
}
return Collections.unmodifiableList(new ArrayList<>(versions));
}
public void setReaders(Collection<WorkspaceReader> readers) {
this.readers = Collections.unmodifiableList(new ArrayList<>(readers));
Key key = new Key(this.readers);
this.repository = new WorkspaceRepository(key.getContentType(), key);
}
public List<WorkspaceReader> getReaders() {
return readers;
}
private static class Key {
private final List<Object> keys;
private final String type;
Key(Collection<WorkspaceReader> readers) {
keys = readers.stream().map(r -> r.getRepository().getKey()).collect(Collectors.toList());
type = readers.stream().map(r -> r.getRepository().getContentType()).collect(Collectors.joining("+"));
}
public String getContentType() {
return type;
}
public boolean equals(Object obj) {
if (this == obj) {
return true;
} else {
return obj != null && this.getClass().equals(obj.getClass()) && this.keys.equals(((Key) obj).keys);
}
}
public int hashCode() {
return this.keys.hashCode();
}
} }
/** /**

View File

@ -66,7 +66,7 @@ import org.apache.maven.project.MavenProject;
import static org.apache.maven.internal.impl.Utils.nonNull; import static org.apache.maven.internal.impl.Utils.nonNull;
public abstract class AbstractSession implements Session { public abstract class AbstractSession implements InternalSession {
private final List<Listener> listeners = new CopyOnWriteArrayList<>(); private final List<Listener> listeners = new CopyOnWriteArrayList<>();
private final Map<org.eclipse.aether.graph.DependencyNode, Node> allNodes = private final Map<org.eclipse.aether.graph.DependencyNode, Node> allNodes =

View File

@ -31,11 +31,11 @@ import static org.apache.maven.internal.impl.Utils.nonNull;
* A wrapper class around a maven resolver artifact. * A wrapper class around a maven resolver artifact.
*/ */
public class DefaultArtifact implements Artifact { public class DefaultArtifact implements Artifact {
private final @Nonnull AbstractSession session; private final @Nonnull InternalSession session;
private final @Nonnull org.eclipse.aether.artifact.Artifact artifact; private final @Nonnull org.eclipse.aether.artifact.Artifact artifact;
private final String id; private final String id;
public DefaultArtifact(@Nonnull AbstractSession session, @Nonnull org.eclipse.aether.artifact.Artifact artifact) { public DefaultArtifact(@Nonnull InternalSession session, @Nonnull org.eclipse.aether.artifact.Artifact artifact) {
this.session = nonNull(session, "session can not be null"); this.session = nonNull(session, "session can not be null");
this.artifact = nonNull(artifact, "artifact can not be null"); this.artifact = nonNull(artifact, "artifact can not be null");
this.id = getGroupId() this.id = getGroupId()

View File

@ -30,11 +30,11 @@ import static org.apache.maven.internal.impl.Utils.nonNull;
* A wrapper class around a maven resolver artifact. * A wrapper class around a maven resolver artifact.
*/ */
public class DefaultArtifactCoordinate implements ArtifactCoordinate { public class DefaultArtifactCoordinate implements ArtifactCoordinate {
private final @Nonnull AbstractSession session; private final @Nonnull InternalSession session;
private final @Nonnull org.eclipse.aether.artifact.Artifact coordinate; private final @Nonnull org.eclipse.aether.artifact.Artifact coordinate;
public DefaultArtifactCoordinate( public DefaultArtifactCoordinate(
@Nonnull AbstractSession session, @Nonnull org.eclipse.aether.artifact.Artifact coordinate) { @Nonnull InternalSession session, @Nonnull org.eclipse.aether.artifact.Artifact coordinate) {
this.session = nonNull(session, "session can not be null"); this.session = nonNull(session, "session can not be null");
this.coordinate = nonNull(coordinate, "coordinate can not be null"); this.coordinate = nonNull(coordinate, "coordinate can not be null");
} }

View File

@ -27,7 +27,6 @@ import org.apache.maven.api.services.ArtifactCoordinateFactory;
import org.apache.maven.api.services.ArtifactCoordinateFactoryRequest; import org.apache.maven.api.services.ArtifactCoordinateFactoryRequest;
import org.eclipse.aether.artifact.ArtifactType; import org.eclipse.aether.artifact.ArtifactType;
import static org.apache.maven.internal.impl.Utils.cast;
import static org.apache.maven.internal.impl.Utils.nonNull; import static org.apache.maven.internal.impl.Utils.nonNull;
@Named @Named
@ -36,8 +35,7 @@ public class DefaultArtifactCoordinateFactory implements ArtifactCoordinateFacto
@Override @Override
public ArtifactCoordinate create(@Nonnull ArtifactCoordinateFactoryRequest request) { public ArtifactCoordinate create(@Nonnull ArtifactCoordinateFactoryRequest request) {
nonNull(request, "request can not be null"); nonNull(request, "request can not be null");
DefaultSession session = InternalSession session = InternalSession.from(request.getSession());
cast(DefaultSession.class, request.getSession(), "request.session should be a " + DefaultSession.class);
ArtifactType type = null; ArtifactType type = null;
if (request.getType() != null) { if (request.getType() != null) {
type = session.getSession().getArtifactTypeRegistry().get(request.getType()); type = session.getSession().getArtifactTypeRegistry().get(request.getType());

View File

@ -35,7 +35,6 @@ import org.eclipse.aether.deployment.DeployRequest;
import org.eclipse.aether.deployment.DeployResult; import org.eclipse.aether.deployment.DeployResult;
import org.eclipse.aether.deployment.DeploymentException; import org.eclipse.aether.deployment.DeploymentException;
import static org.apache.maven.internal.impl.Utils.cast;
import static org.apache.maven.internal.impl.Utils.nonNull; import static org.apache.maven.internal.impl.Utils.nonNull;
/** /**
@ -54,8 +53,7 @@ public class DefaultArtifactDeployer implements ArtifactDeployer {
@Override @Override
public void deploy(@Nonnull ArtifactDeployerRequest request) { public void deploy(@Nonnull ArtifactDeployerRequest request) {
nonNull(request, "request can not be null"); nonNull(request, "request can not be null");
DefaultSession session = InternalSession session = InternalSession.from(request.getSession());
cast(DefaultSession.class, request.getSession(), "request.session should be a " + DefaultSession.class);
Collection<Artifact> artifacts = nonNull(request.getArtifacts(), "request.artifacts can not be null"); Collection<Artifact> artifacts = nonNull(request.getArtifacts(), "request.artifacts can not be null");
RemoteRepository repository = nonNull(request.getRepository(), "request.repository can not be null"); RemoteRepository repository = nonNull(request.getRepository(), "request.repository can not be null");
try { try {

View File

@ -27,7 +27,6 @@ import org.apache.maven.api.services.ArtifactFactory;
import org.apache.maven.api.services.ArtifactFactoryRequest; import org.apache.maven.api.services.ArtifactFactoryRequest;
import org.eclipse.aether.artifact.ArtifactType; import org.eclipse.aether.artifact.ArtifactType;
import static org.apache.maven.internal.impl.Utils.cast;
import static org.apache.maven.internal.impl.Utils.nonNull; import static org.apache.maven.internal.impl.Utils.nonNull;
@Named @Named
@ -36,8 +35,7 @@ public class DefaultArtifactFactory implements ArtifactFactory {
@Override @Override
public Artifact create(@Nonnull ArtifactFactoryRequest request) { public Artifact create(@Nonnull ArtifactFactoryRequest request) {
nonNull(request, "request can not be null"); nonNull(request, "request can not be null");
DefaultSession session = InternalSession session = InternalSession.from(request.getSession());
cast(DefaultSession.class, request.getSession(), "request.session should be a " + DefaultSession.class);
ArtifactType type = null; ArtifactType type = null;
if (request.getType() != null) { if (request.getType() != null) {
type = session.getSession().getArtifactTypeRegistry().get(request.getType()); type = session.getSession().getArtifactTypeRegistry().get(request.getType());

View File

@ -31,7 +31,6 @@ import org.eclipse.aether.installation.InstallRequest;
import org.eclipse.aether.installation.InstallResult; import org.eclipse.aether.installation.InstallResult;
import org.eclipse.aether.installation.InstallationException; import org.eclipse.aether.installation.InstallationException;
import static org.apache.maven.internal.impl.Utils.cast;
import static org.apache.maven.internal.impl.Utils.nonNull; import static org.apache.maven.internal.impl.Utils.nonNull;
@Named @Named
@ -48,8 +47,7 @@ public class DefaultArtifactInstaller implements ArtifactInstaller {
@Override @Override
public void install(ArtifactInstallerRequest request) throws ArtifactInstallerException, IllegalArgumentException { public void install(ArtifactInstallerRequest request) throws ArtifactInstallerException, IllegalArgumentException {
nonNull(request, "request can not be null"); nonNull(request, "request can not be null");
DefaultSession session = InternalSession session = InternalSession.from(request.getSession());
cast(DefaultSession.class, request.getSession(), "request.session should be a " + DefaultSession.class);
try { try {
InstallRequest installRequest = InstallRequest installRequest =
new InstallRequest().setArtifacts(session.toArtifacts(request.getArtifacts())); new InstallRequest().setArtifacts(session.toArtifacts(request.getArtifacts()));

View File

@ -24,26 +24,30 @@ import javax.inject.Named;
import java.io.File; import java.io.File;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.Map; import java.util.Map;
import java.util.Objects;
import java.util.Optional; import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Stream;
import org.apache.maven.SessionScoped;
import org.apache.maven.api.Artifact; import org.apache.maven.api.Artifact;
import org.apache.maven.api.annotations.Nonnull; import org.apache.maven.api.annotations.Nonnull;
import org.apache.maven.api.di.SessionScoped;
import org.apache.maven.api.services.ArtifactManager; import org.apache.maven.api.services.ArtifactManager;
import org.apache.maven.project.MavenProject; import org.apache.maven.project.MavenProject;
import org.eclipse.sisu.Typed;
@Named @Named
@Typed
@SessionScoped @SessionScoped
public class DefaultArtifactManager implements ArtifactManager { public class DefaultArtifactManager implements ArtifactManager {
@Nonnull @Nonnull
private final DefaultSession session; private final InternalSession session;
private final Map<String, Path> paths = new ConcurrentHashMap<>(); private final Map<String, Path> paths = new ConcurrentHashMap<>();
@Inject @Inject
public DefaultArtifactManager(@Nonnull DefaultSession session) { public DefaultArtifactManager(@Nonnull InternalSession session) {
this.session = session; this.session = session;
} }
@ -73,12 +77,10 @@ public class DefaultArtifactManager implements ArtifactManager {
public void setPath(@Nonnull Artifact artifact, Path path) { public void setPath(@Nonnull Artifact artifact, Path path) {
String id = id(artifact); String id = id(artifact);
if (session.getMavenSession().getAllProjects() != null) { if (session.getMavenSession().getAllProjects() != null) {
for (MavenProject project : session.getMavenSession().getAllProjects()) { session.getMavenSession().getAllProjects().stream()
if (id.equals(id(project.getArtifact()))) { .flatMap(this::getProjectArtifacts)
project.getArtifact().setFile(path != null ? path.toFile() : null); .filter(a -> Objects.equals(id, id(a)))
break; .forEach(a -> a.setFile(path != null ? path.toFile() : null));
}
}
} }
if (path == null) { if (path == null) {
paths.remove(id); paths.remove(id);
@ -87,10 +89,18 @@ public class DefaultArtifactManager implements ArtifactManager {
} }
} }
/**
* Retrieve a stream of the project's artifacts.
* Do not include the POM artifact as the file can't be set anyway.
*/
private Stream<org.apache.maven.artifact.Artifact> getProjectArtifacts(MavenProject project) {
return Stream.concat(Stream.of(project.getArtifact()), project.getAttachedArtifacts().stream());
}
private String id(org.apache.maven.artifact.Artifact artifact) { private String id(org.apache.maven.artifact.Artifact artifact) {
return artifact.getGroupId() return artifact.getGroupId()
+ ":" + artifact.getArtifactId() + ":" + artifact.getArtifactId()
+ ":" + artifact.getType() + ":" + artifact.getArtifactHandler().getExtension()
+ (artifact.getClassifier() == null || artifact.getClassifier().isEmpty() + (artifact.getClassifier() == null || artifact.getClassifier().isEmpty()
? "" ? ""
: ":" + artifact.getClassifier()) : ":" + artifact.getClassifier())

View File

@ -23,12 +23,13 @@ import javax.inject.Named;
import javax.inject.Singleton; import javax.inject.Singleton;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.stream.Collectors;
import org.apache.maven.api.Artifact; import org.apache.maven.api.Artifact;
import org.apache.maven.api.ArtifactCoordinate;
import org.apache.maven.api.annotations.Nonnull; import org.apache.maven.api.annotations.Nonnull;
import org.apache.maven.api.services.ArtifactManager; import org.apache.maven.api.services.ArtifactManager;
import org.apache.maven.api.services.ArtifactResolver; import org.apache.maven.api.services.ArtifactResolver;
@ -41,7 +42,6 @@ import org.eclipse.aether.resolution.ArtifactRequest;
import org.eclipse.aether.resolution.ArtifactResolutionException; import org.eclipse.aether.resolution.ArtifactResolutionException;
import org.eclipse.aether.resolution.ArtifactResult; import org.eclipse.aether.resolution.ArtifactResult;
import static org.apache.maven.internal.impl.Utils.cast;
import static org.apache.maven.internal.impl.Utils.nonNull; import static org.apache.maven.internal.impl.Utils.nonNull;
@Named @Named
@ -58,27 +58,32 @@ public class DefaultArtifactResolver implements ArtifactResolver {
public ArtifactResolverResult resolve(ArtifactResolverRequest request) public ArtifactResolverResult resolve(ArtifactResolverRequest request)
throws ArtifactResolverException, IllegalArgumentException { throws ArtifactResolverException, IllegalArgumentException {
nonNull(request, "request can not be null"); nonNull(request, "request can not be null");
DefaultSession session = InternalSession session = InternalSession.from(request.getSession());
cast(DefaultSession.class, request.getSession(), "request.session should be a " + DefaultSession.class);
try { try {
List<RemoteRepository> repositories = session.toRepositories(session.getRemoteRepositories());
List<ArtifactRequest> requests = request.getCoordinates().stream()
.map(coord -> new ArtifactRequest(session.toArtifact(coord), repositories, null))
.collect(Collectors.toList());
List<ArtifactResult> results = repositorySystem.resolveArtifacts(session.getSession(), requests);
Map<Artifact, Path> paths = new HashMap<>(); Map<Artifact, Path> paths = new HashMap<>();
ArtifactManager artifactManager = session.getService(ArtifactManager.class);
List<RemoteRepository> repositories = session.toRepositories(session.getRemoteRepositories());
List<ArtifactRequest> requests = new ArrayList<>();
for (ArtifactCoordinate coord : request.getCoordinates()) {
org.eclipse.aether.artifact.Artifact aetherArtifact = session.toArtifact(coord);
Artifact artifact = session.getArtifact(aetherArtifact);
Path path = artifactManager.getPath(artifact).orElse(null);
if (path != null) {
paths.put(artifact, path);
} else {
requests.add(new ArtifactRequest(aetherArtifact, repositories, null));
}
}
if (!requests.isEmpty()) {
List<ArtifactResult> results = repositorySystem.resolveArtifacts(session.getSession(), requests);
for (ArtifactResult result : results) { for (ArtifactResult result : results) {
Artifact artifact = session.getArtifact(result.getArtifact()); Artifact artifact = session.getArtifact(result.getArtifact());
Path path = result.getArtifact().getFile().toPath(); Path path = result.getArtifact().getFile().toPath();
session.getService(ArtifactManager.class).setPath(artifact, path); artifactManager.setPath(artifact, path);
paths.put(artifact, path); paths.put(artifact, path);
} }
return new ArtifactResolverResult() {
@Override
public Map<Artifact, Path> getArtifacts() {
return paths;
} }
}; return () -> paths;
} catch (ArtifactResolutionException e) { } catch (ArtifactResolutionException e) {
throw new ArtifactResolverException("Unable to resolve artifact", e); throw new ArtifactResolverException("Unable to resolve artifact", e);
} }

View File

@ -34,13 +34,13 @@ import org.eclipse.aether.artifact.ArtifactProperties;
import static org.apache.maven.internal.impl.Utils.nonNull; import static org.apache.maven.internal.impl.Utils.nonNull;
public class DefaultDependency implements Dependency { public class DefaultDependency implements Dependency {
private final AbstractSession session; private final InternalSession session;
private final org.eclipse.aether.graph.Dependency dependency; private final org.eclipse.aether.graph.Dependency dependency;
private final DependencyProperties dependencyProperties; private final DependencyProperties dependencyProperties;
private final String key; private final String key;
public DefaultDependency( public DefaultDependency(
@Nonnull AbstractSession session, @Nonnull org.eclipse.aether.graph.Dependency dependency) { @Nonnull InternalSession session, @Nonnull org.eclipse.aether.graph.Dependency dependency) {
this.session = nonNull(session, "session"); this.session = nonNull(session, "session");
this.dependency = nonNull(dependency, "dependency"); this.dependency = nonNull(dependency, "dependency");
this.dependencyProperties = this.dependencyProperties =
@ -50,7 +50,7 @@ public class DefaultDependency implements Dependency {
+ getArtifactId() + getArtifactId()
+ ':' + ':'
+ getExtension() + getExtension()
+ (getClassifier().length() > 0 ? ":" + getClassifier() : "") + (!getClassifier().isEmpty() ? ":" + getClassifier() : "")
+ ':' + ':'
+ getVersion(); + getVersion();
} }

View File

@ -41,7 +41,6 @@ import org.eclipse.aether.graph.Dependency;
import org.eclipse.aether.util.graph.manager.DependencyManagerUtils; import org.eclipse.aether.util.graph.manager.DependencyManagerUtils;
import org.eclipse.aether.util.graph.transformer.ConflictResolver; import org.eclipse.aether.util.graph.transformer.ConflictResolver;
import static org.apache.maven.internal.impl.Utils.cast;
import static org.apache.maven.internal.impl.Utils.nonNull; import static org.apache.maven.internal.impl.Utils.nonNull;
@Named @Named
@ -60,8 +59,7 @@ public class DefaultDependencyCollector implements DependencyCollector {
public DependencyCollectorResult collect(@Nonnull DependencyCollectorRequest request) public DependencyCollectorResult collect(@Nonnull DependencyCollectorRequest request)
throws DependencyCollectorException, IllegalArgumentException { throws DependencyCollectorException, IllegalArgumentException {
nonNull(request, "request can not be null"); nonNull(request, "request can not be null");
DefaultSession session = InternalSession session = InternalSession.from(request.getSession());
cast(DefaultSession.class, request.getSession(), "request.session should be a " + DefaultSession.class);
Artifact rootArtifact = Artifact rootArtifact =
request.getRootArtifact().map(session::toArtifact).orElse(null); request.getRootArtifact().map(session::toArtifact).orElse(null);

View File

@ -33,11 +33,11 @@ import org.eclipse.aether.artifact.ArtifactProperties;
import static org.apache.maven.internal.impl.Utils.nonNull; import static org.apache.maven.internal.impl.Utils.nonNull;
public class DefaultDependencyCoordinate implements DependencyCoordinate { public class DefaultDependencyCoordinate implements DependencyCoordinate {
private final AbstractSession session; private final InternalSession session;
private final org.eclipse.aether.graph.Dependency dependency; private final org.eclipse.aether.graph.Dependency dependency;
public DefaultDependencyCoordinate( public DefaultDependencyCoordinate(
@Nonnull AbstractSession session, @Nonnull org.eclipse.aether.graph.Dependency dependency) { @Nonnull InternalSession session, @Nonnull org.eclipse.aether.graph.Dependency dependency) {
this.session = nonNull(session, "session"); this.session = nonNull(session, "session");
this.dependency = nonNull(dependency, "dependency"); this.dependency = nonNull(dependency, "dependency");
} }

View File

@ -30,7 +30,6 @@ import org.apache.maven.api.services.DependencyCoordinateFactory;
import org.apache.maven.api.services.DependencyCoordinateFactoryRequest; import org.apache.maven.api.services.DependencyCoordinateFactoryRequest;
import org.eclipse.aether.artifact.ArtifactType; import org.eclipse.aether.artifact.ArtifactType;
import static org.apache.maven.internal.impl.Utils.cast;
import static org.apache.maven.internal.impl.Utils.nonNull; import static org.apache.maven.internal.impl.Utils.nonNull;
@Named @Named
@ -41,8 +40,7 @@ public class DefaultDependencyCoordinateFactory implements DependencyCoordinateF
@Override @Override
public DependencyCoordinate create(@Nonnull DependencyCoordinateFactoryRequest request) { public DependencyCoordinate create(@Nonnull DependencyCoordinateFactoryRequest request) {
nonNull(request, "request can not be null"); nonNull(request, "request can not be null");
DefaultSession session = InternalSession session = InternalSession.from(request.getSession());
cast(DefaultSession.class, request.getSession(), "request.session should be a " + DefaultSession.class);
ArtifactType type = null; ArtifactType type = null;
if (request.getType() != null) { if (request.getType() != null) {

View File

@ -28,10 +28,10 @@ import org.apache.maven.api.Session;
import org.apache.maven.execution.ExecutionEvent; import org.apache.maven.execution.ExecutionEvent;
public class DefaultEvent implements Event { public class DefaultEvent implements Event {
private final AbstractSession session; private final InternalSession session;
private final ExecutionEvent delegate; private final ExecutionEvent delegate;
public DefaultEvent(AbstractSession session, ExecutionEvent delegate) { public DefaultEvent(InternalSession session, ExecutionEvent delegate) {
this.session = session; this.session = session;
this.delegate = delegate; this.delegate = delegate;
} }
@ -53,11 +53,11 @@ public class DefaultEvent implements Event {
@Override @Override
public Optional<MojoExecution> getMojoExecution() { public Optional<MojoExecution> getMojoExecution() {
return Optional.ofNullable(delegate.getMojoExecution()).map(DefaultMojoExecution::new); return Optional.ofNullable(delegate.getMojoExecution()).map(me -> new DefaultMojoExecution(session, me));
} }
@Override @Override
public Optional<Exception> getException() { public Optional<Exception> getException() {
return Optional.empty(); return Optional.ofNullable(delegate.getException());
} }
} }

View File

@ -35,7 +35,7 @@ public class DefaultLocalRepositoryManager implements LocalRepositoryManager {
@Override @Override
public Path getPathForLocalArtifact(Session session, LocalRepository local, Artifact artifact) { public Path getPathForLocalArtifact(Session session, LocalRepository local, Artifact artifact) {
DefaultSession s = (DefaultSession) session; InternalSession s = InternalSession.from(session);
String path = getManager(s, local).getPathForLocalArtifact(s.toArtifact(artifact)); String path = getManager(s, local).getPathForLocalArtifact(s.toArtifact(artifact));
return local.getPath().resolve(path); return local.getPath().resolve(path);
} }
@ -43,14 +43,14 @@ public class DefaultLocalRepositoryManager implements LocalRepositoryManager {
@Override @Override
public Path getPathForRemoteArtifact( public Path getPathForRemoteArtifact(
Session session, LocalRepository local, RemoteRepository remote, Artifact artifact) { Session session, LocalRepository local, RemoteRepository remote, Artifact artifact) {
DefaultSession s = (DefaultSession) session; InternalSession s = InternalSession.from(session);
String path = String path =
getManager(s, local).getPathForRemoteArtifact(s.toArtifact(artifact), s.toRepository(remote), null); getManager(s, local).getPathForRemoteArtifact(s.toArtifact(artifact), s.toRepository(remote), null);
return local.getPath().resolve(path); return local.getPath().resolve(path);
} }
private org.eclipse.aether.repository.LocalRepositoryManager getManager( private org.eclipse.aether.repository.LocalRepositoryManager getManager(
DefaultSession session, LocalRepository local) { InternalSession session, LocalRepository local) {
org.eclipse.aether.repository.LocalRepository repository = session.toRepository(local); org.eclipse.aether.repository.LocalRepository repository = session.toRepository(local);
if ("enhanced".equals(repository.getContentType())) { if ("enhanced".equals(repository.getContentType())) {
repository = new org.eclipse.aether.repository.LocalRepository(repository.getBasedir(), ""); repository = new org.eclipse.aether.repository.LocalRepository(repository.getBasedir(), "");

View File

@ -18,17 +18,34 @@
*/ */
package org.apache.maven.internal.impl; package org.apache.maven.internal.impl;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional; import java.util.Optional;
import java.util.stream.Collectors;
import org.apache.maven.RepositoryUtils;
import org.apache.maven.api.Artifact;
import org.apache.maven.api.Dependency;
import org.apache.maven.api.MojoExecution; import org.apache.maven.api.MojoExecution;
import org.apache.maven.api.model.Plugin; import org.apache.maven.api.Node;
import org.apache.maven.api.Plugin;
import org.apache.maven.api.model.PluginExecution;
import org.apache.maven.api.plugin.descriptor.MojoDescriptor;
import org.apache.maven.api.plugin.descriptor.PluginDescriptor;
import org.apache.maven.api.plugin.descriptor.lifecycle.Lifecycle;
import org.apache.maven.api.xml.XmlNode; import org.apache.maven.api.xml.XmlNode;
import org.codehaus.plexus.util.xml.Xpp3Dom; import org.codehaus.plexus.util.xml.Xpp3Dom;
import org.eclipse.aether.graph.DependencyNode;
public class DefaultMojoExecution implements MojoExecution { public class DefaultMojoExecution implements MojoExecution {
private final InternalSession session;
private final org.apache.maven.plugin.MojoExecution delegate; private final org.apache.maven.plugin.MojoExecution delegate;
public DefaultMojoExecution(org.apache.maven.plugin.MojoExecution delegate) { public DefaultMojoExecution(InternalSession session, org.apache.maven.plugin.MojoExecution delegate) {
this.session = session;
this.delegate = delegate; this.delegate = delegate;
} }
@ -38,9 +55,73 @@ public class DefaultMojoExecution implements MojoExecution {
@Override @Override
public Plugin getPlugin() { public Plugin getPlugin() {
return new Plugin() {
@Override
public org.apache.maven.api.model.Plugin getModel() {
return delegate.getPlugin().getDelegate(); return delegate.getPlugin().getDelegate();
} }
@Override
public PluginDescriptor getDescriptor() {
return delegate.getMojoDescriptor().getPluginDescriptor().getPluginDescriptorV4();
}
@Override
public List<Lifecycle> getLifecycles() {
try {
return Collections.unmodifiableList(new ArrayList<>(delegate.getMojoDescriptor()
.getPluginDescriptor()
.getLifecycleMappings()
.values()));
} catch (Exception e) {
throw new RuntimeException("Unable to load plugin lifecycles", e);
}
}
@Override
public ClassLoader getClassLoader() {
return delegate.getMojoDescriptor().getRealm();
}
@Override
public Artifact getArtifact() {
org.apache.maven.artifact.Artifact artifact =
delegate.getMojoDescriptor().getPluginDescriptor().getPluginArtifact();
org.eclipse.aether.artifact.Artifact resolverArtifact = RepositoryUtils.toArtifact(artifact);
return resolverArtifact != null ? session.getArtifact(resolverArtifact) : null;
}
@Override
public Map<String, Dependency> getDependenciesMap() {
DependencyNode resolverNode =
delegate.getMojoDescriptor().getPluginDescriptor().getDependencyNode();
DefaultNode node = new DefaultNode(session, resolverNode, false);
return Collections.unmodifiableMap(node.stream()
.map(Node::getDependency)
.collect(Collectors.toMap(d -> d.getGroupId() + ":" + d.getArtifactId(), d -> d)));
}
};
}
@Override
public PluginExecution getModel() {
return delegate.getPlugin().getExecutions().stream()
.filter(pe -> Objects.equals(pe.getId(), getExecutionId()))
.findFirst()
.map(org.apache.maven.model.PluginExecution::getDelegate)
.orElse(null);
}
@Override
public MojoDescriptor getDescriptor() {
return delegate.getMojoDescriptor().getMojoDescriptorV4();
}
@Override
public String getLifecyclePhase() {
return delegate.getLifecyclePhase();
}
@Override @Override
public String getExecutionId() { public String getExecutionId() {
return delegate.getExecutionId(); return delegate.getExecutionId();

View File

@ -33,12 +33,12 @@ import org.eclipse.aether.util.graph.transformer.ConflictResolver;
public class DefaultNode extends AbstractNode { public class DefaultNode extends AbstractNode {
protected final @Nonnull AbstractSession session; protected final @Nonnull InternalSession session;
protected final @Nonnull org.eclipse.aether.graph.DependencyNode node; protected final @Nonnull org.eclipse.aether.graph.DependencyNode node;
protected final boolean verbose; protected final boolean verbose;
public DefaultNode( public DefaultNode(
@Nonnull AbstractSession session, @Nonnull org.eclipse.aether.graph.DependencyNode node, boolean verbose) { @Nonnull InternalSession session, @Nonnull org.eclipse.aether.graph.DependencyNode node, boolean verbose) {
this.session = session; this.session = session;
this.node = node; this.node = node;
this.verbose = verbose; this.verbose = verbose;
@ -66,7 +66,7 @@ public class DefaultNode extends AbstractNode {
@Override @Override
public Optional<RemoteRepository> getRepository() { public Optional<RemoteRepository> getRepository() {
// TODO // TODO: v4: implement
throw new UnsupportedOperationException("Not implemented yet"); throw new UnsupportedOperationException("Not implemented yet");
} }

View File

@ -44,15 +44,15 @@ import org.apache.maven.project.MavenProject;
public class DefaultProject implements Project { public class DefaultProject implements Project {
private final AbstractSession session; private final InternalSession session;
private final MavenProject project; private final MavenProject project;
public DefaultProject(AbstractSession session, MavenProject project) { public DefaultProject(InternalSession session, MavenProject project) {
this.session = session; this.session = session;
this.project = project; this.project = project;
} }
public AbstractSession getSession() { public InternalSession getSession() {
return session; return session;
} }

View File

@ -69,7 +69,7 @@ public class DefaultProjectBuilder implements ProjectBuilder {
@Override @Override
public ProjectBuilderResult build(ProjectBuilderRequest request) public ProjectBuilderResult build(ProjectBuilderRequest request)
throws ProjectBuilderException, IllegalArgumentException { throws ProjectBuilderException, IllegalArgumentException {
DefaultSession session = (DefaultSession) request.getSession(); InternalSession session = InternalSession.from(request.getSession());
try { try {
List<ArtifactRepository> repositories = session.toArtifactRepositories(session.getRemoteRepositories()); List<ArtifactRepository> repositories = session.toArtifactRepositories(session.getRemoteRepositories());
ProjectBuildingRequest req = new DefaultProjectBuildingRequest() ProjectBuildingRequest req = new DefaultProjectBuildingRequest()

View File

@ -30,7 +30,6 @@ import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import org.apache.maven.RepositoryUtils; import org.apache.maven.RepositoryUtils;
import org.apache.maven.SessionScoped;
import org.apache.maven.api.Artifact; import org.apache.maven.api.Artifact;
import org.apache.maven.api.Node; import org.apache.maven.api.Node;
import org.apache.maven.api.Project; import org.apache.maven.api.Project;
@ -39,6 +38,7 @@ import org.apache.maven.api.ResolutionScope;
import org.apache.maven.api.Scope; import org.apache.maven.api.Scope;
import org.apache.maven.api.Session; import org.apache.maven.api.Session;
import org.apache.maven.api.annotations.Nonnull; import org.apache.maven.api.annotations.Nonnull;
import org.apache.maven.api.di.SessionScoped;
import org.apache.maven.api.services.ArtifactManager; import org.apache.maven.api.services.ArtifactManager;
import org.apache.maven.api.services.MavenException; import org.apache.maven.api.services.MavenException;
import org.apache.maven.api.services.ProjectManager; import org.apache.maven.api.services.ProjectManager;
@ -47,8 +47,10 @@ import org.apache.maven.lifecycle.internal.LifecycleDependencyResolver;
import org.apache.maven.project.MavenProject; import org.apache.maven.project.MavenProject;
import org.codehaus.plexus.PlexusContainer; import org.codehaus.plexus.PlexusContainer;
import org.codehaus.plexus.component.repository.exception.ComponentLookupException; import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
import org.eclipse.sisu.Typed;
@Named @Named
@Typed
@SessionScoped @SessionScoped
public class DefaultProjectManager implements ProjectManager { public class DefaultProjectManager implements ProjectManager {
@ -73,7 +75,7 @@ public class DefaultProjectManager implements ProjectManager {
@Nonnull @Nonnull
@Override @Override
public Collection<Artifact> getAttachedArtifacts(Project project) { public Collection<Artifact> getAttachedArtifacts(Project project) {
AbstractSession session = ((DefaultProject) project).getSession(); InternalSession session = ((DefaultProject) project).getSession();
Collection<Artifact> attached = getMavenProject(project).getAttachedArtifacts().stream() Collection<Artifact> attached = getMavenProject(project).getAttachedArtifacts().stream()
.map(RepositoryUtils::toArtifact) .map(RepositoryUtils::toArtifact)
.map(session::getArtifact) .map(session::getArtifact)
@ -129,12 +131,12 @@ public class DefaultProjectManager implements ProjectManager {
getMavenProject(project), getMavenProject(project),
toResolve, toResolve,
toResolve, toResolve,
((DefaultSession) session).getMavenSession(), InternalSession.from(session).getMavenSession(),
false, false,
Collections.emptySet()); Collections.emptySet());
return artifacts.stream() return artifacts.stream()
.map(RepositoryUtils::toArtifact) .map(RepositoryUtils::toArtifact)
.map(((DefaultSession) session)::getArtifact) .map(InternalSession.from(session)::getArtifact)
.collect(Collectors.toList()); .collect(Collectors.toList());
} catch (LifecycleExecutionException | ComponentLookupException e) { } catch (LifecycleExecutionException | ComponentLookupException e) {
throw new MavenException("Unable to resolve project dependencies", e); throw new MavenException("Unable to resolve project dependencies", e);

View File

@ -21,11 +21,11 @@ package org.apache.maven.internal.impl;
import java.nio.file.Path; import java.nio.file.Path;
import java.time.Instant; import java.time.Instant;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.NoSuchElementException; import java.util.NoSuchElementException;
import java.util.Objects; import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Supplier; import java.util.function.Supplier;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -65,7 +65,7 @@ public class DefaultSession extends AbstractSession {
private final MavenRepositorySystem mavenRepositorySystem; private final MavenRepositorySystem mavenRepositorySystem;
private final PlexusContainer container; private final PlexusContainer container;
private final RuntimeInformation runtimeInformation; private final RuntimeInformation runtimeInformation;
private final Map<Class<? extends Service>, Service> services = new HashMap<>(); private final Map<Class<? extends Service>, Service> services = new ConcurrentHashMap<>();
@SuppressWarnings("checkstyle:ParameterNumber") @SuppressWarnings("checkstyle:ParameterNumber")
public DefaultSession( public DefaultSession(
@ -213,8 +213,7 @@ public class DefaultSession extends AbstractSession {
RepositorySystemSession repoSession = RepositorySystemSession repoSession =
new DefaultRepositorySystemSession(session).setLocalRepositoryManager(localRepositoryManager); new DefaultRepositorySystemSession(session).setLocalRepositoryManager(localRepositoryManager);
MavenSession newSession = MavenSession newSession = new MavenSession(repoSession, mavenSession.getRequest(), mavenSession.getResult());
new MavenSession(() -> repoSession, mavenSession.getRequest(), mavenSession.getResult());
return new DefaultSession( return new DefaultSession(
newSession, repositorySystem, repositories, mavenRepositorySystem, container, runtimeInformation); newSession, repositorySystem, repositories, mavenRepositorySystem, container, runtimeInformation);
} }

View File

@ -53,7 +53,7 @@ public class DefaultSessionFactory {
public Session getSession(MavenSession mavenSession) { public Session getSession(MavenSession mavenSession) {
SessionData data = mavenSession.getRepositorySession().getData(); SessionData data = mavenSession.getRepositorySession().getData();
return (Session) data.computeIfAbsent(DefaultSession.class, () -> newSession(mavenSession)); return (Session) data.computeIfAbsent(InternalSession.class, () -> newSession(mavenSession));
} }
private Session newSession(MavenSession mavenSession) { private Session newSession(MavenSession mavenSession) {

View File

@ -57,7 +57,7 @@ public class DefaultSettingsBuilder implements SettingsBuilder {
@Override @Override
public SettingsBuilderResult build(SettingsBuilderRequest request) public SettingsBuilderResult build(SettingsBuilderRequest request)
throws SettingsBuilderException, IllegalArgumentException { throws SettingsBuilderException, IllegalArgumentException {
DefaultSession session = (DefaultSession) request.getSession(); InternalSession session = InternalSession.from(request.getSession());
try { try {
DefaultSettingsBuildingRequest req = new DefaultSettingsBuildingRequest(); DefaultSettingsBuildingRequest req = new DefaultSettingsBuildingRequest();
req.setUserProperties(toProperties(session.getUserProperties())); req.setUserProperties(toProperties(session.getUserProperties()));

View File

@ -49,7 +49,7 @@ public class DefaultToolchainManager implements ToolchainManager {
@Override @Override
public List<Toolchain> getToolchains(Session session, String type, Map<String, String> requirements) public List<Toolchain> getToolchains(Session session, String type, Map<String, String> requirements)
throws ToolchainManagerException { throws ToolchainManagerException {
MavenSession s = ((DefaultSession) session).getMavenSession(); MavenSession s = InternalSession.from(session).getMavenSession();
List<org.apache.maven.toolchain.Toolchain> toolchains = List<org.apache.maven.toolchain.Toolchain> toolchains =
toolchainManagerPrivate.getToolchains(s, type, requirements); toolchainManagerPrivate.getToolchains(s, type, requirements);
return new MappedList<>(toolchains, this::toToolchain); return new MappedList<>(toolchains, this::toToolchain);
@ -58,7 +58,7 @@ public class DefaultToolchainManager implements ToolchainManager {
@Override @Override
public Optional<Toolchain> getToolchainFromBuildContext(Session session, String type) public Optional<Toolchain> getToolchainFromBuildContext(Session session, String type)
throws ToolchainManagerException { throws ToolchainManagerException {
MavenSession s = ((DefaultSession) session).getMavenSession(); MavenSession s = InternalSession.from(session).getMavenSession();
return Optional.ofNullable(toolchainManagerPrivate.getToolchainFromBuildContext(type, s)) return Optional.ofNullable(toolchainManagerPrivate.getToolchainFromBuildContext(type, s))
.map(this::toToolchain); .map(this::toToolchain);
} }
@ -66,7 +66,7 @@ public class DefaultToolchainManager implements ToolchainManager {
@Override @Override
public List<Toolchain> getToolchainsForType(Session session, String type) throws ToolchainManagerException { public List<Toolchain> getToolchainsForType(Session session, String type) throws ToolchainManagerException {
try { try {
MavenSession s = ((DefaultSession) session).getMavenSession(); MavenSession s = InternalSession.from(session).getMavenSession();
ToolchainPrivate[] toolchains = toolchainManagerPrivate.getToolchainsForType(type, s); ToolchainPrivate[] toolchains = toolchainManagerPrivate.getToolchainsForType(type, s);
return new MappedList<>(Arrays.asList(toolchains), this::toToolchain); return new MappedList<>(Arrays.asList(toolchains), this::toToolchain);
} catch (MisconfiguredToolchainException e) { } catch (MisconfiguredToolchainException e) {
@ -76,7 +76,7 @@ public class DefaultToolchainManager implements ToolchainManager {
@Override @Override
public void storeToolchainToBuildContext(Session session, Toolchain toolchain) throws ToolchainManagerException { public void storeToolchainToBuildContext(Session session, Toolchain toolchain) throws ToolchainManagerException {
MavenSession s = ((DefaultSession) session).getMavenSession(); MavenSession s = InternalSession.from(session).getMavenSession();
org.apache.maven.toolchain.ToolchainPrivate tc = org.apache.maven.toolchain.ToolchainPrivate tc =
(org.apache.maven.toolchain.ToolchainPrivate) ((ToolchainWrapper) toolchain).toolchain; (org.apache.maven.toolchain.ToolchainPrivate) ((ToolchainWrapper) toolchain).toolchain;
toolchainManagerPrivate.storeToolchainToBuildContext(tc, s); toolchainManagerPrivate.storeToolchainToBuildContext(tc, s);

View File

@ -52,7 +52,7 @@ public class DefaultTransportProvider implements TransportProvider {
return new DefaultTransport( return new DefaultTransport(
baseURI, baseURI,
transporterProvider.newTransporter( transporterProvider.newTransporter(
((DefaultSession) session).getSession(), InternalSession.from(session).getSession(),
((DefaultRemoteRepository) repository).getRepository())); ((DefaultRemoteRepository) repository).getRepository()));
} catch (URISyntaxException e) { } catch (URISyntaxException e) {
throw new TransportProviderException("Remote repository URL invalid", e); throw new TransportProviderException("Remote repository URL invalid", e);

View File

@ -47,7 +47,7 @@ public class EventSpyImpl implements EventSpy {
public void onEvent(Object arg) throws Exception { public void onEvent(Object arg) throws Exception {
if (arg instanceof ExecutionEvent) { if (arg instanceof ExecutionEvent) {
ExecutionEvent ee = (ExecutionEvent) arg; ExecutionEvent ee = (ExecutionEvent) arg;
AbstractSession session = (AbstractSession) sessionFactory.getSession(ee.getSession()); InternalSession session = InternalSession.from(sessionFactory.getSession(ee.getSession()));
Collection<Listener> listeners = session.getListeners(); Collection<Listener> listeners = session.getListeners();
if (!listeners.isEmpty()) { if (!listeners.isEmpty()) {
Event event = new DefaultEvent(session, ee); Event event = new DefaultEvent(session, ee);

View File

@ -0,0 +1,88 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.maven.internal.impl;
import java.util.Collection;
import java.util.List;
import org.apache.maven.api.Artifact;
import org.apache.maven.api.ArtifactCoordinate;
import org.apache.maven.api.Dependency;
import org.apache.maven.api.DependencyCoordinate;
import org.apache.maven.api.LocalRepository;
import org.apache.maven.api.Node;
import org.apache.maven.api.Project;
import org.apache.maven.api.RemoteRepository;
import org.apache.maven.api.Session;
import org.apache.maven.api.annotations.Nonnull;
import org.apache.maven.execution.MavenSession;
import org.eclipse.aether.RepositorySystem;
import org.eclipse.aether.RepositorySystemSession;
import static org.apache.maven.internal.impl.Utils.cast;
public interface InternalSession extends Session {
static InternalSession from(Session session) {
return cast(InternalSession.class, session, "session should be an " + InternalSession.class);
}
RemoteRepository getRemoteRepository(org.eclipse.aether.repository.RemoteRepository repository);
Node getNode(org.eclipse.aether.graph.DependencyNode node);
Node getNode(org.eclipse.aether.graph.DependencyNode node, boolean verbose);
@Nonnull
Artifact getArtifact(@Nonnull org.eclipse.aether.artifact.Artifact artifact);
@Nonnull
Dependency getDependency(@Nonnull org.eclipse.aether.graph.Dependency dependency);
List<Project> getProjects(List<org.apache.maven.project.MavenProject> projects);
Project getProject(org.apache.maven.project.MavenProject project);
List<org.eclipse.aether.repository.RemoteRepository> toRepositories(List<RemoteRepository> repositories);
org.eclipse.aether.repository.RemoteRepository toRepository(RemoteRepository repository);
org.eclipse.aether.repository.LocalRepository toRepository(LocalRepository repository);
List<org.apache.maven.artifact.repository.ArtifactRepository> toArtifactRepositories(
List<RemoteRepository> repositories);
org.apache.maven.artifact.repository.ArtifactRepository toArtifactRepository(RemoteRepository repository);
List<org.eclipse.aether.graph.Dependency> toDependencies(Collection<DependencyCoordinate> dependencies);
org.eclipse.aether.graph.Dependency toDependency(DependencyCoordinate dependency);
List<org.eclipse.aether.artifact.Artifact> toArtifacts(Collection<Artifact> artifacts);
org.eclipse.aether.artifact.Artifact toArtifact(Artifact artifact);
org.eclipse.aether.artifact.Artifact toArtifact(ArtifactCoordinate coord);
MavenSession getMavenSession();
RepositorySystemSession getSession();
RepositorySystem getRepositorySystem();
}

View File

@ -24,16 +24,10 @@ import javax.inject.Singleton;
import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamException;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.*;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.maven.api.plugin.descriptor.lifecycle.Execution;
import org.apache.maven.api.plugin.descriptor.lifecycle.Phase;
import org.apache.maven.api.xml.XmlNode; import org.apache.maven.api.xml.XmlNode;
import org.apache.maven.execution.MavenSession; import org.apache.maven.execution.MavenSession;
import org.apache.maven.internal.xml.XmlNodeImpl; import org.apache.maven.internal.xml.XmlNodeImpl;
@ -55,8 +49,6 @@ import org.apache.maven.plugin.PluginResolutionException;
import org.apache.maven.plugin.descriptor.MojoDescriptor; import org.apache.maven.plugin.descriptor.MojoDescriptor;
import org.apache.maven.plugin.descriptor.Parameter; import org.apache.maven.plugin.descriptor.Parameter;
import org.apache.maven.plugin.descriptor.PluginDescriptor; import org.apache.maven.plugin.descriptor.PluginDescriptor;
import org.apache.maven.plugin.lifecycle.Execution;
import org.apache.maven.plugin.lifecycle.Phase;
import org.apache.maven.plugin.prefix.NoPluginFoundForPrefixException; import org.apache.maven.plugin.prefix.NoPluginFoundForPrefixException;
import org.apache.maven.plugin.version.PluginVersionResolutionException; import org.apache.maven.plugin.version.PluginVersionResolutionException;
import org.apache.maven.project.MavenProject; import org.apache.maven.project.MavenProject;
@ -340,8 +332,12 @@ public class DefaultLifecycleExecutionPlanCalculator implements LifecycleExecuti
} }
private XmlNode getMojoConfiguration(MojoDescriptor mojoDescriptor) { private XmlNode getMojoConfiguration(MojoDescriptor mojoDescriptor) {
if (mojoDescriptor.isV4Api()) {
return MojoDescriptorCreator.convert(mojoDescriptor.getMojoDescriptorV4());
} else {
return MojoDescriptorCreator.convert(mojoDescriptor).getDom(); return MojoDescriptorCreator.convert(mojoDescriptor).getDom();
} }
}
@Override @Override
public void calculateForkedExecutions(MojoExecution mojoExecution, MavenSession session) public void calculateForkedExecutions(MojoExecution mojoExecution, MavenSession session)
@ -459,7 +455,7 @@ public class DefaultLifecycleExecutionPlanCalculator implements LifecycleExecuti
return; return;
} }
org.apache.maven.plugin.lifecycle.Lifecycle lifecycleOverlay; org.apache.maven.api.plugin.descriptor.lifecycle.Lifecycle lifecycleOverlay;
try { try {
lifecycleOverlay = pluginDescriptor.getLifecycleMapping(forkedLifecycle); lifecycleOverlay = pluginDescriptor.getLifecycleMapping(forkedLifecycle);
@ -491,7 +487,7 @@ public class DefaultLifecycleExecutionPlanCalculator implements LifecycleExecuti
MojoExecution forkedExecution = MojoExecution forkedExecution =
new MojoExecution(forkedMojoDescriptor, mojoExecution.getExecutionId()); new MojoExecution(forkedMojoDescriptor, mojoExecution.getExecutionId());
XmlNodeImpl forkedConfiguration = (XmlNodeImpl) execution.getConfiguration(); XmlNode forkedConfiguration = execution.getConfiguration();
forkedExecution.setConfiguration(forkedConfiguration); forkedExecution.setConfiguration(forkedConfiguration);
@ -501,7 +497,7 @@ public class DefaultLifecycleExecutionPlanCalculator implements LifecycleExecuti
} }
} }
XmlNodeImpl phaseConfiguration = (XmlNodeImpl) phase.getConfiguration(); XmlNode phaseConfiguration = phase.getConfiguration();
if (phaseConfiguration != null) { if (phaseConfiguration != null) {
for (MojoExecution forkedExecution : forkedExecutions) { for (MojoExecution forkedExecution : forkedExecutions) {

View File

@ -26,6 +26,7 @@ import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.stream.Collectors;
import org.apache.maven.api.xml.XmlNode; import org.apache.maven.api.xml.XmlNode;
import org.apache.maven.execution.MavenSession; import org.apache.maven.execution.MavenSession;
@ -91,6 +92,21 @@ public class MojoDescriptorCreator {
return null; return null;
} }
public static XmlNode convert(org.apache.maven.api.plugin.descriptor.MojoDescriptor mojoDescriptor) {
List<XmlNode> children = mojoDescriptor.getParameters().stream()
.filter(p -> p.getDefaultValue() != null || p.getExpression() != null)
.map(p -> new XmlNodeImpl(
p.getName(),
p.getExpression(),
p.getDefaultValue() != null
? Collections.singletonMap("default-value", p.getDefaultValue())
: null,
null,
null))
.collect(Collectors.toList());
return new XmlNodeImpl("configuration", null, null, children, null);
}
public static org.codehaus.plexus.util.xml.Xpp3Dom convert(MojoDescriptor mojoDescriptor) { public static org.codehaus.plexus.util.xml.Xpp3Dom convert(MojoDescriptor mojoDescriptor) {
PlexusConfiguration c = mojoDescriptor.getMojoConfiguration(); PlexusConfiguration c = mojoDescriptor.getMojoConfiguration();

View File

@ -34,7 +34,7 @@ import org.apache.maven.execution.MojoExecutionListener;
import org.apache.maven.execution.scope.internal.MojoExecutionScope; import org.apache.maven.execution.scope.internal.MojoExecutionScope;
import org.apache.maven.internal.impl.DefaultLog; import org.apache.maven.internal.impl.DefaultLog;
import org.apache.maven.internal.impl.DefaultMojoExecution; import org.apache.maven.internal.impl.DefaultMojoExecution;
import org.apache.maven.internal.impl.DefaultSession; import org.apache.maven.internal.impl.InternalSession;
import org.apache.maven.model.Plugin; import org.apache.maven.model.Plugin;
import org.apache.maven.plugin.descriptor.MojoDescriptor; import org.apache.maven.plugin.descriptor.MojoDescriptor;
import org.apache.maven.plugin.descriptor.PluginDescriptor; import org.apache.maven.plugin.descriptor.PluginDescriptor;
@ -121,8 +121,9 @@ public class DefaultBuildPluginManager implements BuildPluginManager {
org.apache.maven.api.plugin.Log.class, org.apache.maven.api.plugin.Log.class,
new DefaultLog(LoggerFactory.getLogger( new DefaultLog(LoggerFactory.getLogger(
mojoExecution.getMojoDescriptor().getFullGoalName()))); mojoExecution.getMojoDescriptor().getFullGoalName())));
scope.seed(Project.class, ((DefaultSession) session.getSession()).getProject(project)); InternalSession sessionV4 = InternalSession.from(session.getSession());
scope.seed(org.apache.maven.api.MojoExecution.class, new DefaultMojoExecution(mojoExecution)); scope.seed(Project.class, sessionV4.getProject(project));
scope.seed(org.apache.maven.api.MojoExecution.class, new DefaultMojoExecution(sessionV4, mojoExecution));
if (mojoDescriptor.isV4Api()) { if (mojoDescriptor.isV4Api()) {
org.apache.maven.api.plugin.Mojo mojoV4 = mavenPluginManager.getConfiguredMojo( org.apache.maven.api.plugin.Mojo mojoV4 = mavenPluginManager.getConfiguredMojo(

View File

@ -28,11 +28,8 @@ import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import org.apache.maven.RepositoryUtils; import org.apache.maven.RepositoryUtils;
import org.apache.maven.artifact.ArtifactUtils;
import org.apache.maven.model.Plugin; import org.apache.maven.model.Plugin;
import org.apache.maven.plugin.descriptor.MojoDescriptor;
import org.apache.maven.plugin.descriptor.PluginDescriptor; import org.apache.maven.plugin.descriptor.PluginDescriptor;
import org.codehaus.plexus.component.repository.ComponentDescriptor;
import org.eclipse.aether.RepositorySystemSession; import org.eclipse.aether.RepositorySystemSession;
import org.eclipse.aether.repository.LocalRepository; import org.eclipse.aether.repository.LocalRepository;
import org.eclipse.aether.repository.RemoteRepository; import org.eclipse.aether.repository.RemoteRepository;
@ -97,49 +94,7 @@ public class DefaultPluginDescriptorCache implements PluginDescriptorCache {
} }
protected static PluginDescriptor clone(PluginDescriptor original) { protected static PluginDescriptor clone(PluginDescriptor original) {
PluginDescriptor clone = null; return new PluginDescriptor(original);
if (original != null) {
clone = new PluginDescriptor();
clone.setGroupId(original.getGroupId());
clone.setArtifactId(original.getArtifactId());
clone.setVersion(original.getVersion());
clone.setGoalPrefix(original.getGoalPrefix());
clone.setInheritedByDefault(original.isInheritedByDefault());
clone.setName(original.getName());
clone.setDescription(original.getDescription());
clone.setRequiredMavenVersion(original.getRequiredMavenVersion());
clone.setRequiredJavaVersion(original.getRequiredJavaVersion());
clone.setPluginArtifact(ArtifactUtils.copyArtifactSafe(original.getPluginArtifact()));
clone.setComponents(clone(original.getMojos(), clone));
clone.setId(original.getId());
clone.setIsolatedRealm(original.isIsolatedRealm());
clone.setSource(original.getSource());
clone.setDependencies(original.getDependencies());
}
return clone;
}
private static List<ComponentDescriptor<?>> clone(List<MojoDescriptor> mojos, PluginDescriptor pluginDescriptor) {
List<ComponentDescriptor<?>> clones = null;
if (mojos != null) {
clones = new ArrayList<>(mojos.size());
for (MojoDescriptor mojo : mojos) {
MojoDescriptor clone = mojo.clone();
clone.setPluginDescriptor(pluginDescriptor);
clones.add(clone);
}
}
return clones;
} }
private static final class CacheKey implements Key { private static final class CacheKey implements Key {

View File

@ -21,16 +21,15 @@ package org.apache.maven.plugin;
import java.io.File; import java.io.File;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional; import java.util.Optional;
import java.util.Properties; import java.util.Properties;
import org.apache.maven.api.MojoExecution;
import org.apache.maven.api.Project; import org.apache.maven.api.Project;
import org.apache.maven.api.Session; import org.apache.maven.api.Session;
import org.apache.maven.internal.impl.DefaultMojoExecution;
import org.apache.maven.internal.impl.DefaultSession;
import org.apache.maven.model.interpolation.reflection.ReflectionValueExtractor; import org.apache.maven.model.interpolation.reflection.ReflectionValueExtractor;
import org.apache.maven.plugin.descriptor.MojoDescriptor;
import org.apache.maven.plugin.descriptor.PluginDescriptor;
import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluationException; import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluationException;
import org.codehaus.plexus.component.configurator.expression.TypeAwareExpressionEvaluator; import org.codehaus.plexus.component.configurator.expression.TypeAwareExpressionEvaluator;
@ -40,36 +39,18 @@ import org.codehaus.plexus.component.configurator.expression.TypeAwareExpression
* <table border="1"> * <table border="1">
* <caption>Expression matrix</caption> * <caption>Expression matrix</caption>
* <tr><th>expression</th> <th></th> <th>evaluation result</th></tr> * <tr><th>expression</th> <th></th> <th>evaluation result</th></tr>
* <tr><td><code>session</code></td> <td></td> <td>the actual {@link Session}</td></tr> * <tr><td><code>session.*</code></td> <td></td> <td></td></tr>
* <tr><td><code>session.*</code></td> <td>(since Maven 3)</td><td></td></tr>
* <tr><td><code>localRepository</code></td> <td></td>
* <td>{@link Session#getLocalRepository()}</td></tr>
* <tr><td><code>reactorProjects</code></td> <td></td> <td>{@link Session#getProjects()}</td></tr>
* <tr><td><code>project</code></td> <td></td>
* <td>{@link org.apache.maven.execution.MavenSession#getCurrentProject()}</td></tr>
* <tr><td><code>project.*</code></td> <td></td> <td></td></tr> * <tr><td><code>project.*</code></td> <td></td> <td></td></tr>
* <tr><td><code>pom.*</code></td> <td>(since Maven 3)</td><td>same as <code>project.*</code></td></tr>
* <tr><td><code>executedProject</code></td> <td></td>
* <td>{@link org.apache.maven.project.MavenProject#getExecutionProject()}</td></tr>
* <tr><td><code>settings</code></td> <td></td> <td>{@link Session#getSettings()}</td></tr>
* <tr><td><code>settings.*</code></td> <td></td> <td></td></tr> * <tr><td><code>settings.*</code></td> <td></td> <td></td></tr>
* <tr><td><code>basedir</code></td> <td></td> * <tr><td><code>mojo.*</code></td> <td></td> <td>the actual {@link MojoExecution}</td></tr>
* <td>{@link Session#getTopDirectory()} or
* <code>System.getProperty( "user.dir" )</code> if null</td></tr>
* <tr><td><code>mojoExecution</code></td> <td></td> <td>the actual {@link MojoExecution}</td></tr>
* <tr><td><code>mojo</code></td> <td>(since Maven 3)</td><td>same as <code>mojoExecution</code></td></tr>
* <tr><td><code>mojo.*</code></td> <td>(since Maven 3)</td><td></td></tr>
* <tr><td><code>plugin</code></td> <td>(since Maven 3)</td>
* <td>{@link MojoExecution#getMojoDescriptor()}.{@link MojoDescriptor#getPluginDescriptor()
* getPluginDescriptor()}</td></tr>
* <tr><td><code>plugin.*</code></td> <td></td> <td></td></tr>
* <tr><td><code>*</code></td> <td></td> <td>user properties</td></tr> * <tr><td><code>*</code></td> <td></td> <td>user properties</td></tr>
* <tr><td><code>*</code></td> <td></td> <td>system properties</td></tr> * <tr><td><code>*</code></td> <td></td> <td>system properties</td></tr>
* <tr><td><code>*</code></td> <td></td> <td>project properties</td></tr> * <tr><td><code>*</code></td> <td></td> <td>project properties</td></tr>
* </table> * </table>
* <i>Notice:</i> <code>reports</code> was supported in Maven 2.x but was removed in Maven 3
* *
* @see Session * @see Session
* @see Project
* @see org.apache.maven.api.settings.Settings
* @see MojoExecution * @see MojoExecution
*/ */
public class PluginParameterExpressionEvaluatorV4 implements TypeAwareExpressionEvaluator { public class PluginParameterExpressionEvaluatorV4 implements TypeAwareExpressionEvaluator {
@ -165,19 +146,18 @@ public class PluginParameterExpressionEvaluatorV4 implements TypeAwareExpression
return expression.replace("$$", "$"); return expression.replace("$$", "$");
} }
if ("localRepository".equals(expression)) { Map<String, Object> objects = new HashMap<>();
// TODO: v4 objects.put("session.", session);
value = session.getLocalRepository(); objects.put("project.", project);
} else if ("session".equals(expression)) { objects.put("mojo.", mojoExecution);
value = session; objects.put("settings.", session.getSettings());
} else if (expression.startsWith("session")) { for (Map.Entry<String, Object> ctx : objects.entrySet()) {
// TODO: v4 if (expression.startsWith(ctx.getKey())) {
try { try {
int pathSeparator = expression.indexOf('/'); int pathSeparator = expression.indexOf('/');
if (pathSeparator > 0) { if (pathSeparator > 0) {
String pathExpression = expression.substring(0, pathSeparator); String pathExpression = expression.substring(0, pathSeparator);
value = ReflectionValueExtractor.evaluate(pathExpression, session); value = ReflectionValueExtractor.evaluate(pathExpression, ctx.getValue());
if (pathSeparator < expression.length() - 1) { if (pathSeparator < expression.length() - 1) {
if (value instanceof Path) { if (value instanceof Path) {
value = ((Path) value).resolve(expression.substring(pathSeparator + 1)); value = ((Path) value).resolve(expression.substring(pathSeparator + 1));
@ -186,108 +166,14 @@ public class PluginParameterExpressionEvaluatorV4 implements TypeAwareExpression
} }
} }
} else { } else {
value = ReflectionValueExtractor.evaluate(expression, session); value = ReflectionValueExtractor.evaluate(expression, ctx.getValue());
} }
break;
} catch (Exception e) { } catch (Exception e) {
// TODO don't catch exception // TODO don't catch exception
throw new ExpressionEvaluationException( throw new ExpressionEvaluationException(
"Error evaluating plugin parameter expression: " + expression, e); "Error evaluating plugin parameter expression: " + expression, e);
} }
} else if ("reactorProjects".equals(expression)) {
value = session.getProjects();
} else if ("project".equals(expression)) {
value = project;
} else if ("executedProject".equals(expression)) {
value = ((DefaultSession) session)
.getProject(((DefaultSession) session)
.getMavenSession()
.getCurrentProject()
.getExecutionProject());
} else if (expression.startsWith("project") || expression.startsWith("pom")) {
// TODO: v4
try {
int pathSeparator = expression.indexOf('/');
if (pathSeparator > 0) {
String pathExpression = expression.substring(0, pathSeparator);
value = ReflectionValueExtractor.evaluate(pathExpression, project);
value = value + expression.substring(pathSeparator);
} else {
value = ReflectionValueExtractor.evaluate(expression, project);
}
} catch (Exception e) {
// TODO don't catch exception
throw new ExpressionEvaluationException(
"Error evaluating plugin parameter expression: " + expression, e);
}
} else if (expression.equals("repositorySystemSession")) {
// TODO: v4
} else if (expression.equals("mojo") || expression.equals("mojoExecution")) {
value = new DefaultMojoExecution(mojoExecution);
} else if (expression.startsWith("mojo")) {
// TODO: v4
try {
int pathSeparator = expression.indexOf('/');
if (pathSeparator > 0) {
String pathExpression = expression.substring(0, pathSeparator);
value = ReflectionValueExtractor.evaluate(pathExpression, mojoExecution);
value = value + expression.substring(pathSeparator);
} else {
value = ReflectionValueExtractor.evaluate(expression, mojoExecution);
}
} catch (Exception e) {
// TODO don't catch exception
throw new ExpressionEvaluationException(
"Error evaluating plugin parameter expression: " + expression, e);
}
} else if (expression.equals("plugin")) {
// TODO: v4
value = mojoExecution.getMojoDescriptor().getPluginDescriptor();
} else if (expression.startsWith("plugin")) {
// TODO: v4
try {
int pathSeparator = expression.indexOf('/');
PluginDescriptor pluginDescriptor =
mojoExecution.getMojoDescriptor().getPluginDescriptor();
if (pathSeparator > 0) {
String pathExpression = expression.substring(0, pathSeparator);
value = ReflectionValueExtractor.evaluate(pathExpression, pluginDescriptor);
value = value + expression.substring(pathSeparator);
} else {
value = ReflectionValueExtractor.evaluate(expression, pluginDescriptor);
}
} catch (Exception e) {
throw new ExpressionEvaluationException(
"Error evaluating plugin parameter expression: " + expression, e);
}
} else if ("settings".equals(expression)) {
value = session.getSettings();
} else if (expression.startsWith("settings")) {
try {
int pathSeparator = expression.indexOf('/');
if (pathSeparator > 0) {
String pathExpression = expression.substring(0, pathSeparator);
value = ReflectionValueExtractor.evaluate(pathExpression, session.getSettings());
value = value + expression.substring(pathSeparator);
} else {
value = ReflectionValueExtractor.evaluate(expression, session.getSettings());
}
} catch (Exception e) {
// TODO don't catch exception
throw new ExpressionEvaluationException(
"Error evaluating plugin parameter expression: " + expression, e);
}
} else if ("basedir".equals(expression)) {
value = basedir.toString();
} else if (expression.startsWith("basedir")) {
int pathSeparator = expression.indexOf('/');
if (pathSeparator > 0) {
value = basedir.toString() + expression.substring(pathSeparator);
} }
} }

View File

@ -25,7 +25,6 @@ import javax.inject.Singleton;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream; import java.io.PrintStream;
import java.nio.file.Files; import java.nio.file.Files;
import java.util.ArrayList; import java.util.ArrayList;
@ -39,13 +38,16 @@ import java.util.jar.JarFile;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.zip.ZipEntry; import java.util.zip.ZipEntry;
import com.google.inject.AbstractModule;
import com.google.inject.name.Names;
import org.apache.maven.RepositoryUtils; import org.apache.maven.RepositoryUtils;
import org.apache.maven.api.xml.XmlNode; import org.apache.maven.api.xml.XmlNode;
import org.apache.maven.artifact.Artifact; import org.apache.maven.artifact.Artifact;
import org.apache.maven.classrealm.ClassRealmManager; import org.apache.maven.classrealm.ClassRealmManager;
import org.apache.maven.execution.MavenSession; import org.apache.maven.execution.MavenSession;
import org.apache.maven.execution.scope.internal.MojoExecutionScopeModule; import org.apache.maven.execution.scope.internal.MojoExecutionScopeModule;
import org.apache.maven.internal.impl.DefaultSession; import org.apache.maven.internal.impl.DefaultMojoExecution;
import org.apache.maven.internal.impl.InternalSession;
import org.apache.maven.internal.xml.XmlPlexusConfiguration; import org.apache.maven.internal.xml.XmlPlexusConfiguration;
import org.apache.maven.model.Plugin; import org.apache.maven.model.Plugin;
import org.apache.maven.plugin.ContextEnabled; import org.apache.maven.plugin.ContextEnabled;
@ -220,18 +222,18 @@ public class DefaultMavenPluginManager implements MavenPluginManager {
ZipEntry pluginDescriptorEntry = pluginJar.getEntry(getPluginDescriptorLocation()); ZipEntry pluginDescriptorEntry = pluginJar.getEntry(getPluginDescriptorLocation());
if (pluginDescriptorEntry != null) { if (pluginDescriptorEntry != null) {
InputStream is = pluginJar.getInputStream(pluginDescriptorEntry); pluginDescriptor = parsePluginDescriptor(
() -> pluginJar.getInputStream(pluginDescriptorEntry),
pluginDescriptor = parsePluginDescriptor(is, plugin, pluginFile.getAbsolutePath()); plugin,
pluginFile.getAbsolutePath());
} }
} }
} else { } else {
File pluginXml = new File(pluginFile, getPluginDescriptorLocation()); File pluginXml = new File(pluginFile, getPluginDescriptorLocation());
if (pluginXml.isFile()) { if (pluginXml.isFile()) {
try (InputStream is = Files.newInputStream(pluginXml.toPath())) { pluginDescriptor = parsePluginDescriptor(
pluginDescriptor = parsePluginDescriptor(is, plugin, pluginXml.getAbsolutePath()); () -> Files.newInputStream(pluginXml.toPath()), plugin, pluginXml.getAbsolutePath());
}
} }
} }
@ -259,7 +261,8 @@ public class DefaultMavenPluginManager implements MavenPluginManager {
return "META-INF/maven/plugin.xml"; return "META-INF/maven/plugin.xml";
} }
private PluginDescriptor parsePluginDescriptor(InputStream is, Plugin plugin, String descriptorLocation) private PluginDescriptor parsePluginDescriptor(
PluginDescriptorBuilder.StreamSupplier is, Plugin plugin, String descriptorLocation)
throws PluginDescriptorParsingException { throws PluginDescriptorParsingException {
try { try {
return builder.build(is, descriptorLocation); return builder.build(is, descriptorLocation);
@ -410,6 +413,7 @@ public class DefaultMavenPluginManager implements MavenPluginManager {
discoverPluginComponents(pluginRealm, plugin, pluginDescriptor); discoverPluginComponents(pluginRealm, plugin, pluginDescriptor);
pluginDescriptor.setDependencyNode(root);
pluginDescriptor.setClassRealm(pluginRealm); pluginDescriptor.setClassRealm(pluginRealm);
pluginDescriptor.setArtifacts(pluginArtifacts); pluginDescriptor.setArtifacts(pluginArtifacts);
} }
@ -419,15 +423,40 @@ public class DefaultMavenPluginManager implements MavenPluginManager {
throws PluginContainerException { throws PluginContainerException {
try { try {
if (pluginDescriptor != null) { if (pluginDescriptor != null) {
for (ComponentDescriptor<?> componentDescriptor : pluginDescriptor.getComponents()) { for (MojoDescriptor mojo : pluginDescriptor.getMojos()) {
componentDescriptor.setRealm(pluginRealm); if (!mojo.isV4Api()) {
container.addComponentDescriptor(componentDescriptor); mojo.setRealm(pluginRealm);
container.addComponentDescriptor(mojo);
}
} }
} }
((DefaultPlexusContainer) container) ((DefaultPlexusContainer) container)
.discoverComponents( .discoverComponents(
pluginRealm, pluginRealm,
new AbstractModule() {
@Override
protected void configure() {
if (pluginDescriptor != null) {
for (MojoDescriptor mojo : pluginDescriptor.getMojos()) {
if (mojo.isV4Api()) {
try {
mojo.setRealm(pluginRealm);
Class<?> cl = mojo.getImplementationClass();
if (cl == null) {
cl = pluginRealm.loadClass(mojo.getImplementation());
}
bind(org.apache.maven.api.plugin.Mojo.class)
.annotatedWith(Names.named(mojo.getId()))
.to((Class) cl);
} catch (ClassNotFoundException e) {
throw new IllegalStateException("Unable to load mojo class", e);
}
}
}
}
}
},
new SessionScopeModule(container), new SessionScopeModule(container),
new MojoExecutionScopeModule(container), new MojoExecutionScopeModule(container),
new PluginConfigurationModule(plugin.getDelegate())); new PluginConfigurationModule(plugin.getDelegate()));
@ -584,11 +613,12 @@ public class DefaultMavenPluginManager implements MavenPluginManager {
} }
ExpressionEvaluator expressionEvaluator; ExpressionEvaluator expressionEvaluator;
InternalSession sessionV4 = InternalSession.from(session.getSession());
if (mojoDescriptor.isV4Api()) { if (mojoDescriptor.isV4Api()) {
expressionEvaluator = new PluginParameterExpressionEvaluatorV4( expressionEvaluator = new PluginParameterExpressionEvaluatorV4(
session.getSession(), sessionV4,
((DefaultSession) session.getSession()).getProject(session.getCurrentProject()), sessionV4.getProject(session.getCurrentProject()),
mojoExecution); new DefaultMojoExecution(sessionV4, mojoExecution));
} else { } else {
expressionEvaluator = new PluginParameterExpressionEvaluator(session, mojoExecution); expressionEvaluator = new PluginParameterExpressionEvaluator(session, mojoExecution);
} }

View File

@ -39,7 +39,7 @@ import org.apache.maven.artifact.InvalidArtifactRTException;
import org.apache.maven.artifact.InvalidRepositoryException; import org.apache.maven.artifact.InvalidRepositoryException;
import org.apache.maven.artifact.repository.ArtifactRepository; import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.bridge.MavenRepositorySystem; import org.apache.maven.bridge.MavenRepositorySystem;
import org.apache.maven.internal.impl.DefaultSession; import org.apache.maven.internal.impl.InternalSession;
import org.apache.maven.model.Build; import org.apache.maven.model.Build;
import org.apache.maven.model.Dependency; import org.apache.maven.model.Dependency;
import org.apache.maven.model.DependencyManagement; import org.apache.maven.model.DependencyManagement;
@ -860,7 +860,7 @@ public class DefaultProjectBuilder implements ProjectBuilder {
modelBuildingRequest.setModelCache(modelCacheFactory.createCache(session)); modelBuildingRequest.setModelCache(modelCacheFactory.createCache(session));
} }
modelBuildingRequest.setTransformerContextBuilder(transformerContextBuilder); modelBuildingRequest.setTransformerContextBuilder(transformerContextBuilder);
DefaultSession session = (DefaultSession) this.session.getData().get(DefaultSession.class); InternalSession session = (InternalSession) this.session.getData().get(InternalSession.class);
if (session != null) { if (session != null) {
try { try {
modelBuildingRequest.setRootDirectory(session.getRootDirectory()); modelBuildingRequest.setRootDirectory(session.getRootDirectory());

View File

@ -110,10 +110,19 @@ public class SessionScope implements Scope {
return method.invoke(getScopeState().scope(key, unscoped).get(), args); return method.invoke(getScopeState().scope(key, unscoped).get(), args);
}; };
Class<T> superType = (Class<T>) key.getTypeLiteral().getRawType(); Class<T> superType = (Class<T>) key.getTypeLiteral().getRawType();
Class<?>[] interfaces = getInterfaces(superType);
return (T) java.lang.reflect.Proxy.newProxyInstance(superType.getClassLoader(), interfaces, dispatcher);
}
private Class<?>[] getInterfaces(Class<?> superType) {
if (superType.isInterface()) {
return new Class<?>[] {superType};
} else {
for (Annotation a : superType.getAnnotations()) { for (Annotation a : superType.getAnnotations()) {
Class<? extends Annotation> annotationType = a.annotationType(); Class<? extends Annotation> annotationType = a.annotationType();
if ("org.eclipse.sisu.Typed".equals(annotationType.getName()) if ("org.eclipse.sisu.Typed".equals(annotationType.getName())
|| "javax.enterprise.inject.Typed".equals(annotationType.getName())) { || "javax.enterprise.inject.Typed".equals(annotationType.getName())
|| "jakarta.enterprise.inject.Typed".equals(annotationType.getName())) {
try { try {
Class<?>[] value = Class<?>[] value =
(Class<?>[]) annotationType.getMethod("value").invoke(a); (Class<?>[]) annotationType.getMethod("value").invoke(a);
@ -127,7 +136,7 @@ public class SessionScope implements Scope {
"The Typed annotation must contain only interfaces but the following types are not: " "The Typed annotation must contain only interfaces but the following types are not: "
+ nonInterfaces); + nonInterfaces);
} }
return (T) java.lang.reflect.Proxy.newProxyInstance(superType.getClassLoader(), value, dispatcher); return value;
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
throw new IllegalStateException(e); throw new IllegalStateException(e);
} }
@ -136,6 +145,7 @@ public class SessionScope implements Scope {
throw new IllegalArgumentException("The use of session scoped proxies require " throw new IllegalArgumentException("The use of session scoped proxies require "
+ "a org.eclipse.sisu.Typed or javax.enterprise.inject.Typed annotation"); + "a org.eclipse.sisu.Typed or javax.enterprise.inject.Typed annotation");
} }
}
/** /**
* A provider wrapping an existing provider with a cache * A provider wrapping an existing provider with a cache
@ -170,4 +180,10 @@ public class SessionScope implements Scope {
public static <T> Provider<T> seededKeyProvider() { public static <T> Provider<T> seededKeyProvider() {
return (Provider<T>) SEEDED_KEY_PROVIDER; return (Provider<T>) SEEDED_KEY_PROVIDER;
} }
public static <T> Provider<T> seededKeyProvider(Class<? extends T> clazz) {
return () -> {
throw new IllegalStateException("No instance of " + clazz.getName() + " is bound to the session scope.");
};
}
} }

View File

@ -25,7 +25,7 @@ import com.google.inject.AbstractModule;
import org.apache.maven.SessionScoped; import org.apache.maven.SessionScoped;
import org.apache.maven.api.Session; import org.apache.maven.api.Session;
import org.apache.maven.execution.MavenSession; import org.apache.maven.execution.MavenSession;
import org.apache.maven.internal.impl.DefaultSession; import org.apache.maven.internal.impl.InternalSession;
import org.codehaus.plexus.PlexusContainer; import org.codehaus.plexus.PlexusContainer;
import org.codehaus.plexus.component.repository.exception.ComponentLookupException; import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
@ -52,10 +52,17 @@ public class SessionScopeModule extends AbstractModule {
@Override @Override
protected void configure() { protected void configure() {
bindScope(SessionScoped.class, scope); bindScope(SessionScoped.class, scope);
bindScope(org.apache.maven.api.di.SessionScoped.class, scope);
bind(SessionScope.class).toInstance(scope); bind(SessionScope.class).toInstance(scope);
bind(MavenSession.class).toProvider(SessionScope.seededKeyProvider()).in(scope); bind(MavenSession.class)
bind(Session.class).toProvider(SessionScope.seededKeyProvider()).in(scope); .toProvider(SessionScope.seededKeyProvider(MavenSession.class))
bind(DefaultSession.class).toProvider(SessionScope.seededKeyProvider()).in(scope); .in(scope);
bind(Session.class)
.toProvider(SessionScope.seededKeyProvider(Session.class))
.in(scope);
bind(InternalSession.class)
.toProvider(SessionScope.seededKeyProvider(InternalSession.class))
.in(scope);
} }
} }

View File

@ -111,6 +111,9 @@ under the License.
<exportedPackage>javax.annotation.*</exportedPackage> <exportedPackage>javax.annotation.*</exportedPackage>
<exportedPackage>javax.annotation.security.*</exportedPackage> <exportedPackage>javax.annotation.security.*</exportedPackage>
<exportedPackage>jakarta.inject.*</exportedPackage>
<exportedPackage>jakarta.annotation.*</exportedPackage>
<!-- <!--
| We may potentially want to export these, but right now I'm not sure that anything Guice specific needs | We may potentially want to export these, but right now I'm not sure that anything Guice specific needs
| to be made available to plugin authors. If we find people are getting fancy and want to take advantage of | to be made available to plugin authors. If we find people are getting fancy and want to take advantage of

View File

@ -98,7 +98,7 @@ class TestApi {
RepositorySystemSession rss = MavenRepositorySystemUtils.newSession(); RepositorySystemSession rss = MavenRepositorySystemUtils.newSession();
DefaultMavenExecutionRequest mer = new DefaultMavenExecutionRequest(); DefaultMavenExecutionRequest mer = new DefaultMavenExecutionRequest();
DefaultMavenExecutionResult meres = new DefaultMavenExecutionResult(); DefaultMavenExecutionResult meres = new DefaultMavenExecutionResult();
MavenSession ms = new MavenSession(() -> rss, mer, meres); MavenSession ms = new MavenSession(rss, mer, meres);
DefaultSession session = new DefaultSession( DefaultSession session = new DefaultSession(
ms, ms,
repositorySystem, repositorySystem,
@ -114,7 +114,7 @@ class TestApi {
.withRemoteRepositories(Collections.singletonList(remoteRepository)); .withRemoteRepositories(Collections.singletonList(remoteRepository));
sessionScope.enter(); sessionScope.enter();
sessionScope.seed(DefaultSession.class, (DefaultSession) this.session); sessionScope.seed(InternalSession.class, InternalSession.from(this.session));
} }
@Test @Test

View File

@ -401,7 +401,7 @@ class PluginParameterExpressionEvaluatorTest extends AbstractCoreMavenComponentT
mavenSession.getRequest().setTopDirectory(path); mavenSession.getRequest().setTopDirectory(path);
mavenSession.getRequest().setRootDirectory(path); mavenSession.getRequest().setRootDirectory(path);
Object result = new PluginParameterExpressionEvaluatorV4(mavenSession.getSession(), null) Object result = new PluginParameterExpressionEvaluator(mavenSession, new MojoExecution(null))
.evaluate("${session.rootDirectory.uri}"); .evaluate("${session.rootDirectory.uri}");
assertEquals(path.toUri(), result); assertEquals(path.toUri(), result);
} }
@ -414,7 +414,7 @@ class PluginParameterExpressionEvaluatorTest extends AbstractCoreMavenComponentT
mavenSession.getRequest().setTopDirectory(path); mavenSession.getRequest().setTopDirectory(path);
mavenSession.getRequest().setRootDirectory(path); mavenSession.getRequest().setRootDirectory(path);
Object result = new PluginParameterExpressionEvaluatorV4(mavenSession.getSession(), null) Object result = new PluginParameterExpressionEvaluator(mavenSession, new MojoExecution(null))
.evaluate("${session.rootDirectory/target}"); .evaluate("${session.rootDirectory/target}");
assertEquals(path.resolve("target"), result); assertEquals(path.resolve("target"), result);
} }
@ -428,8 +428,8 @@ class PluginParameterExpressionEvaluatorTest extends AbstractCoreMavenComponentT
mavenSession.getRequest().setRootDirectory(path); mavenSession.getRequest().setRootDirectory(path);
DefaultModelBuildingRequest mbr = new DefaultModelBuildingRequest(); DefaultModelBuildingRequest mbr = new DefaultModelBuildingRequest();
PluginParameterExpressionEvaluatorV4 evaluator = PluginParameterExpressionEvaluator evaluator =
new PluginParameterExpressionEvaluatorV4(mavenSession.getSession(), null); new PluginParameterExpressionEvaluator(mavenSession, new MojoExecution(null));
DefaultPlexusConfiguration configuration = new DefaultPlexusConfiguration("config"); DefaultPlexusConfiguration configuration = new DefaultPlexusConfiguration("config");
configuration.addChild("uri", "${session.rootDirectory.uri}"); configuration.addChild("uri", "${session.rootDirectory.uri}");
@ -438,7 +438,7 @@ class PluginParameterExpressionEvaluatorTest extends AbstractCoreMavenComponentT
configuration.addChild("uriAsciiString", "${session.rootDirectory.uri.ASCIIString}"); configuration.addChild("uriAsciiString", "${session.rootDirectory.uri.ASCIIString}");
configuration.addChild("pathString", "${session.rootDirectory.string}"); configuration.addChild("pathString", "${session.rootDirectory.string}");
PluginParameterExpressionEvaluatorV4Test.Mojo mojo = new PluginParameterExpressionEvaluatorV4Test.Mojo(); Mojo mojo = new Mojo();
new EnhancedComponentConfigurator().configureComponent(mojo, configuration, evaluator, null); new EnhancedComponentConfigurator().configureComponent(mojo, configuration, evaluator, null);
assertEquals( assertEquals(

View File

@ -24,17 +24,19 @@ import java.io.File;
import java.net.URI; import java.net.URI;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.ArrayList; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.Properties; import java.util.Properties;
import org.apache.maven.AbstractCoreMavenComponentTestCase; import org.apache.maven.AbstractCoreMavenComponentTestCase;
import org.apache.maven.RepositoryUtils;
import org.apache.maven.api.Artifact;
import org.apache.maven.api.MojoExecution;
import org.apache.maven.api.Session; import org.apache.maven.api.Session;
import org.apache.maven.artifact.Artifact; import org.apache.maven.artifact.DefaultArtifact;
import org.apache.maven.artifact.ArtifactUtils; import org.apache.maven.artifact.handler.DefaultArtifactHandler;
import org.apache.maven.artifact.repository.ArtifactRepository; import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.bridge.MavenRepositorySystem; import org.apache.maven.bridge.MavenRepositorySystem;
import org.apache.maven.configuration.internal.EnhancedComponentConfigurator; import org.apache.maven.configuration.internal.EnhancedComponentConfigurator;
@ -42,10 +44,11 @@ import org.apache.maven.execution.DefaultMavenExecutionRequest;
import org.apache.maven.execution.DefaultMavenExecutionResult; import org.apache.maven.execution.DefaultMavenExecutionResult;
import org.apache.maven.execution.MavenExecutionRequest; import org.apache.maven.execution.MavenExecutionRequest;
import org.apache.maven.execution.MavenSession; import org.apache.maven.execution.MavenSession;
import org.apache.maven.internal.impl.AbstractSession;
import org.apache.maven.internal.impl.DefaultMojoExecution;
import org.apache.maven.internal.impl.DefaultProject; import org.apache.maven.internal.impl.DefaultProject;
import org.apache.maven.internal.impl.DefaultSession; import org.apache.maven.internal.impl.DefaultSession;
import org.apache.maven.model.Build; import org.apache.maven.model.Build;
import org.apache.maven.model.Dependency;
import org.apache.maven.model.Model; import org.apache.maven.model.Model;
import org.apache.maven.model.building.DefaultModelBuildingRequest; import org.apache.maven.model.building.DefaultModelBuildingRequest;
import org.apache.maven.model.interpolation.reflection.IntrospectionException; import org.apache.maven.model.interpolation.reflection.IntrospectionException;
@ -62,6 +65,7 @@ import org.codehaus.plexus.configuration.DefaultPlexusConfiguration;
import org.codehaus.plexus.util.Os; import org.codehaus.plexus.util.Os;
import org.eclipse.aether.DefaultRepositorySystemSession; import org.eclipse.aether.DefaultRepositorySystemSession;
import org.eclipse.aether.RepositorySystem; import org.eclipse.aether.RepositorySystem;
import org.eclipse.aether.graph.DefaultDependencyNode;
import org.eclipse.aether.internal.impl.SimpleLocalRepositoryManagerFactory; import org.eclipse.aether.internal.impl.SimpleLocalRepositoryManagerFactory;
import org.eclipse.aether.repository.LocalRepository; import org.eclipse.aether.repository.LocalRepository;
import org.eclipse.aether.repository.NoLocalRepositoryManagerException; import org.eclipse.aether.repository.NoLocalRepositoryManagerException;
@ -82,6 +86,9 @@ import static org.mockito.Mockito.mock;
public class PluginParameterExpressionEvaluatorV4Test extends AbstractCoreMavenComponentTestCase { public class PluginParameterExpressionEvaluatorV4Test extends AbstractCoreMavenComponentTestCase {
private static final String FS = File.separator; private static final String FS = File.separator;
@Inject
PlexusContainer container;
@Inject @Inject
private MavenRepositorySystem factory; private MavenRepositorySystem factory;
@ -89,83 +96,74 @@ public class PluginParameterExpressionEvaluatorV4Test extends AbstractCoreMavenC
@Test @Test
public void testPluginDescriptorExpressionReference() throws Exception { public void testPluginDescriptorExpressionReference() throws Exception {
MojoExecution exec = newMojoExecution();
Session session = newSession(); Session session = newSession();
MojoExecution exec = newMojoExecution(session);
Object result = new PluginParameterExpressionEvaluatorV4(session, null, exec).evaluate("${plugin}"); Object result =
new PluginParameterExpressionEvaluatorV4(session, null, exec).evaluate("${mojo.plugin.descriptor}");
System.out.println("Result: " + result); System.out.println("Result: " + result);
assertSame( assertSame(
exec.getMojoDescriptor().getPluginDescriptor(), exec.getPlugin().getDescriptor(),
result, result,
"${plugin} expression does not return plugin descriptor."); "${mojo.plugin.descriptor} expression does not return plugin descriptor.");
} }
@Test @Test
public void testPluginArtifactsExpressionReference() throws Exception { public void testPluginArtifactsExpressionReference() throws Exception {
MojoExecution exec = newMojoExecution();
Artifact depArtifact = createArtifact("group", "artifact", "1");
List<Artifact> deps = new ArrayList<>();
deps.add(depArtifact);
exec.getMojoDescriptor().getPluginDescriptor().setArtifacts(deps);
Session session = newSession(); Session session = newSession();
MojoExecution exec = newMojoExecution(session);
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
List<Artifact> depResults = (List<Artifact>) Collection<Artifact> depResults = (Collection<Artifact>)
new PluginParameterExpressionEvaluatorV4(session, null, exec).evaluate("${plugin.artifacts}"); new PluginParameterExpressionEvaluatorV4(session, null, exec).evaluate("${mojo.plugin.dependencies}");
System.out.println("Result: " + depResults); System.out.println("Result: " + depResults);
assertNotNull(depResults); assertNotNull(depResults);
assertEquals(1, depResults.size()); assertEquals(1, depResults.size());
assertSame(depArtifact, depResults.get(0), "dependency artifact is wrong."); assertEquals(
exec.getPlugin().getArtifact().key(),
depResults.iterator().next().key(),
"dependency artifact is wrong.");
} }
@Test @Test
public void testPluginArtifactMapExpressionReference() throws Exception { public void testPluginArtifactMapExpressionReference() throws Exception {
MojoExecution exec = newMojoExecution();
Artifact depArtifact = createArtifact("group", "artifact", "1");
List<Artifact> deps = new ArrayList<>();
deps.add(depArtifact);
exec.getMojoDescriptor().getPluginDescriptor().setArtifacts(deps);
Session session = newSession(); Session session = newSession();
MojoExecution exec = newMojoExecution(session);
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
Map<String, Artifact> depResults = (Map<String, Artifact>) Map<String, org.apache.maven.api.Dependency> depResults = (Map<String, org.apache.maven.api.Dependency>)
new PluginParameterExpressionEvaluatorV4(session, null, exec).evaluate("${plugin.artifactMap}"); new PluginParameterExpressionEvaluatorV4(session, null, exec)
.evaluate("${mojo.plugin.dependenciesMap}");
System.out.println("Result: " + depResults); System.out.println("Result: " + depResults);
assertNotNull(depResults); assertNotNull(depResults);
assertEquals(1, depResults.size()); assertEquals(1, depResults.size());
assertSame( assertTrue(depResults.containsKey("org.myco.plugins:my-plugin"));
depArtifact, assertEquals(
depResults.get(ArtifactUtils.versionlessKey(depArtifact)), exec.getPlugin().getArtifact().key(),
depResults.get("org.myco.plugins:my-plugin").key(),
"dependency artifact is wrong."); "dependency artifact is wrong.");
} }
@Test @Test
public void testPluginArtifactIdExpressionReference() throws Exception { public void testPluginArtifactIdExpressionReference() throws Exception {
MojoExecution exec = newMojoExecution();
Session session = newSession(); Session session = newSession();
Object result = new PluginParameterExpressionEvaluatorV4(session, null, exec).evaluate("${plugin.artifactId}"); MojoExecution exec = newMojoExecution(session);
Object result = new PluginParameterExpressionEvaluatorV4(session, null, exec)
.evaluate("${mojo.plugin.artifact.artifactId}");
System.out.println("Result: " + result); System.out.println("Result: " + result);
assertSame( assertSame(
exec.getMojoDescriptor().getPluginDescriptor().getArtifactId(), exec.getPlugin().getArtifact().getArtifactId(),
result, result,
"${plugin.artifactId} expression does not return plugin descriptor's artifactId."); "${plugin.artifactId} expression does not return plugin descriptor's artifactId.");
} }
@ -183,7 +181,7 @@ public class PluginParameterExpressionEvaluatorV4Test extends AbstractCoreMavenC
MavenProject project = new MavenProject(model); MavenProject project = new MavenProject(model);
project.setFile(new File("pom.xml").getCanonicalFile()); project.setFile(new File("pom.xml").getCanonicalFile());
ExpressionEvaluator expressionEvaluator = createExpressionEvaluator(project, null, new Properties()); ExpressionEvaluator expressionEvaluator = createExpressionEvaluator(project, new Properties());
Object value = expressionEvaluator.evaluate("${project.build.directory}/classes"); Object value = expressionEvaluator.evaluate("${project.build.directory}/classes");
String actual = new File(value.toString()).getCanonicalPath(); String actual = new File(value.toString()).getCanonicalPath();
@ -200,7 +198,7 @@ public class PluginParameterExpressionEvaluatorV4Test extends AbstractCoreMavenC
MavenProject project = new MavenProject(model); MavenProject project = new MavenProject(model);
ExpressionEvaluator ee = createExpressionEvaluator(project, null, new Properties()); ExpressionEvaluator ee = createExpressionEvaluator(project, new Properties());
Object value = ee.evaluate("$" + var); Object value = ee.evaluate("$" + var);
@ -217,7 +215,7 @@ public class PluginParameterExpressionEvaluatorV4Test extends AbstractCoreMavenC
MavenProject project = new MavenProject(model); MavenProject project = new MavenProject(model);
ExpressionEvaluator ee = createExpressionEvaluator(project, null, new Properties()); ExpressionEvaluator ee = createExpressionEvaluator(project, new Properties());
Object value = ee.evaluate("$" + key); Object value = ee.evaluate("$" + key);
@ -234,7 +232,7 @@ public class PluginParameterExpressionEvaluatorV4Test extends AbstractCoreMavenC
MavenProject project = new MavenProject(model); MavenProject project = new MavenProject(model);
ExpressionEvaluator ee = createExpressionEvaluator(project, null, new Properties()); ExpressionEvaluator ee = createExpressionEvaluator(project, new Properties());
Object value = ee.evaluate(key); Object value = ee.evaluate(key);
@ -247,7 +245,7 @@ public class PluginParameterExpressionEvaluatorV4Test extends AbstractCoreMavenC
MavenProject project = new MavenProject(new Model()); MavenProject project = new MavenProject(new Model());
ExpressionEvaluator ee = createExpressionEvaluator(project, null, new Properties()); ExpressionEvaluator ee = createExpressionEvaluator(project, new Properties());
Object value = ee.evaluate(expr); Object value = ee.evaluate(expr);
@ -267,22 +265,13 @@ public class PluginParameterExpressionEvaluatorV4Test extends AbstractCoreMavenC
MavenProject project = new MavenProject(model); MavenProject project = new MavenProject(model);
ExpressionEvaluator ee = createExpressionEvaluator(project, null, new Properties()); ExpressionEvaluator ee = createExpressionEvaluator(project, new Properties());
Object value = ee.evaluate("${" + key + "}"); Object value = ee.evaluate("${" + key + "}");
assertEquals(checkValue, value); assertEquals(checkValue, value);
} }
@Test
public void testBasedirExtractionWithMissingProject() throws Exception {
ExpressionEvaluator ee = createExpressionEvaluator(null, null, new Properties());
Object value = ee.evaluate("${basedir}");
assertEquals(System.getProperty("user.dir"), value);
}
@Test @Test
public void testValueExtractionFromSystemPropertiesWithMissingProject() throws Exception { public void testValueExtractionFromSystemPropertiesWithMissingProject() throws Exception {
String sysprop = "PPEET_sysprop1"; String sysprop = "PPEET_sysprop1";
@ -293,7 +282,7 @@ public class PluginParameterExpressionEvaluatorV4Test extends AbstractCoreMavenC
executionProperties.setProperty(sysprop, "value"); executionProperties.setProperty(sysprop, "value");
} }
ExpressionEvaluator ee = createExpressionEvaluator(null, null, executionProperties); ExpressionEvaluator ee = createExpressionEvaluator(null, executionProperties);
Object value = ee.evaluate("${" + sysprop + "}"); Object value = ee.evaluate("${" + sysprop + "}");
@ -310,7 +299,7 @@ public class PluginParameterExpressionEvaluatorV4Test extends AbstractCoreMavenC
executionProperties.setProperty(sysprop, "value"); executionProperties.setProperty(sysprop, "value");
} }
ExpressionEvaluator ee = createExpressionEvaluator(null, null, executionProperties); ExpressionEvaluator ee = createExpressionEvaluator(null, executionProperties);
Object value = ee.evaluate("${" + sysprop + "}"); Object value = ee.evaluate("${" + sysprop + "}");
@ -335,15 +324,6 @@ public class PluginParameterExpressionEvaluatorV4Test extends AbstractCoreMavenC
return session; return session;
} }
@Test
public void testLocalRepositoryExtraction() throws Exception {
ExpressionEvaluator expressionEvaluator =
createExpressionEvaluator(createDefaultProject(), null, new Properties());
Object value = expressionEvaluator.evaluate("${localRepository}");
assertEquals("local", ((org.apache.maven.api.LocalRepository) value).getId());
}
@Test @Test
public void testTwoExpressions() throws Exception { public void testTwoExpressions() throws Exception {
Build build = new Build(); Build build = new Build();
@ -353,8 +333,7 @@ public class PluginParameterExpressionEvaluatorV4Test extends AbstractCoreMavenC
Model model = new Model(); Model model = new Model();
model.setBuild(build); model.setBuild(build);
ExpressionEvaluator expressionEvaluator = ExpressionEvaluator expressionEvaluator = createExpressionEvaluator(new MavenProject(model), new Properties());
createExpressionEvaluator(new MavenProject(model), null, new Properties());
Object value = expressionEvaluator.evaluate("${project.build.directory}" + FS + "${project.build.finalName}"); Object value = expressionEvaluator.evaluate("${project.build.directory}" + FS + "${project.build.finalName}");
@ -363,37 +342,31 @@ public class PluginParameterExpressionEvaluatorV4Test extends AbstractCoreMavenC
@Test @Test
public void testShouldExtractPluginArtifacts() throws Exception { public void testShouldExtractPluginArtifacts() throws Exception {
PluginDescriptor pd = new PluginDescriptor(); ExpressionEvaluator ee = createExpressionEvaluator(createDefaultProject(), new Properties());
Artifact artifact = createArtifact("testGroup", "testArtifact", "1.0"); Object value = ee.evaluate("${mojo.plugin.dependencies}");
pd.setArtifacts(Collections.singletonList(artifact)); assertTrue(value instanceof Collection);
ExpressionEvaluator ee = createExpressionEvaluator(createDefaultProject(), pd, new Properties());
Object value = ee.evaluate("${plugin.artifacts}");
assertTrue(value instanceof List);
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
List<Artifact> artifacts = (List<Artifact>) value; Collection<Artifact> artifacts = (Collection<Artifact>) value;
assertEquals(1, artifacts.size()); assertEquals(1, artifacts.size());
Artifact result = artifacts.get(0); Artifact result = artifacts.iterator().next();
assertEquals("testGroup", result.getGroupId()); assertEquals("org.myco.plugins", result.getGroupId());
} }
@Test @Test
void testRootDirectoryNotPrefixed() throws Exception { void testRootDirectoryNotPrefixed() throws Exception {
ExpressionEvaluator ee = createExpressionEvaluator(createDefaultProject(), null, new Properties()); ExpressionEvaluator ee = createExpressionEvaluator(createDefaultProject(), new Properties());
assertNull(ee.evaluate("${rootDirectory}")); assertNull(ee.evaluate("${rootDirectory}"));
} }
@Test @Test
void testRootDirectoryWithNull() throws Exception { void testRootDirectoryWithNull() throws Exception {
ExpressionEvaluator ee = createExpressionEvaluator(createDefaultProject(), null, new Properties()); ExpressionEvaluator ee = createExpressionEvaluator(createDefaultProject(), new Properties());
Exception e = assertThrows(Exception.class, () -> ee.evaluate("${session.rootDirectory}")); Exception e = assertThrows(Exception.class, () -> ee.evaluate("${session.rootDirectory}"));
e = assertInstanceOf(IntrospectionException.class, e.getCause()); e = assertInstanceOf(IntrospectionException.class, e.getCause());
e = assertInstanceOf(IllegalStateException.class, e.getCause()); e = assertInstanceOf(IllegalStateException.class, e.getCause());
@ -403,7 +376,7 @@ public class PluginParameterExpressionEvaluatorV4Test extends AbstractCoreMavenC
@Test @Test
void testRootDirectory() throws Exception { void testRootDirectory() throws Exception {
this.rootDirectory = Paths.get("myRootDirectory"); this.rootDirectory = Paths.get("myRootDirectory");
ExpressionEvaluator ee = createExpressionEvaluator(createDefaultProject(), null, new Properties()); ExpressionEvaluator ee = createExpressionEvaluator(createDefaultProject(), new Properties());
assertInstanceOf(Path.class, ee.evaluate("${session.rootDirectory}")); assertInstanceOf(Path.class, ee.evaluate("${session.rootDirectory}"));
} }
@ -411,54 +384,59 @@ public class PluginParameterExpressionEvaluatorV4Test extends AbstractCoreMavenC
return new MavenProject(new Model()); return new MavenProject(new Model());
} }
private ExpressionEvaluator createExpressionEvaluator( private ExpressionEvaluator createExpressionEvaluator(MavenProject project, Properties executionProperties)
MavenProject project, PluginDescriptor pluginDescriptor, Properties executionProperties) throws Exception { throws Exception {
ArtifactRepository repo = getLocalRepository(); ArtifactRepository repo = getLocalRepository();
MutablePlexusContainer container = (MutablePlexusContainer) getContainer(); MutablePlexusContainer container = (MutablePlexusContainer) getContainer();
MavenSession mavenSession = createSession(container, repo, executionProperties); MavenSession mavenSession = createSession(container, repo, executionProperties);
mavenSession.setCurrentProject(project); mavenSession.setCurrentProject(project);
mavenSession.getRequest().setRootDirectory(rootDirectory); mavenSession.getRequest().setRootDirectory(rootDirectory);
mavenSession.getRequest().setTopDirectory(rootDirectory);
DefaultSession session = new DefaultSession(mavenSession, mock(RepositorySystem.class), null, null, null, null); DefaultSession session =
new DefaultSession(mavenSession, mock(RepositorySystem.class), null, null, container, null);
MojoDescriptor mojo = new MojoDescriptor(); MojoExecution mojoExecution = newMojoExecution(session);
mojo.setPluginDescriptor(pluginDescriptor);
mojo.setGoal("goal");
MojoExecution mojoExecution = new MojoExecution(mojo);
return new PluginParameterExpressionEvaluatorV4( return new PluginParameterExpressionEvaluatorV4(
session, project != null ? new DefaultProject(session, project) : null, mojoExecution); session, project != null ? new DefaultProject(session, project) : null, mojoExecution);
} }
protected Artifact createArtifact(String groupId, String artifactId, String version) throws Exception { private MojoExecution newMojoExecution(Session session) {
Dependency dependency = new Dependency();
dependency.setGroupId(groupId);
dependency.setArtifactId(artifactId);
dependency.setVersion(version);
dependency.setType("jar");
dependency.setScope("compile");
return factory.createDependencyArtifact(dependency);
}
private MojoExecution newMojoExecution() {
PluginDescriptor pd = new PluginDescriptor(); PluginDescriptor pd = new PluginDescriptor();
pd.setArtifactId("my-plugin"); pd.setArtifactId("my-plugin");
pd.setGroupId("org.myco.plugins"); pd.setGroupId("org.myco.plugins");
pd.setVersion("1"); pd.setVersion("1");
DefaultArtifact artifact = new DefaultArtifact(
pd.getGroupId(),
pd.getArtifactId(),
pd.getVersion(),
"compile",
"maven-plugin",
"",
new DefaultArtifactHandler("maven-plugin"));
pd.setPluginArtifact(artifact);
pd.setArtifacts(Collections.singletonList(artifact));
DefaultDependencyNode node = new DefaultDependencyNode(
new org.eclipse.aether.graph.Dependency(RepositoryUtils.toArtifact(artifact), "compile"));
pd.setDependencyNode(node);
MojoDescriptor md = new MojoDescriptor(); MojoDescriptor md = new MojoDescriptor();
md.setGoal("my-goal");
md.setPluginDescriptor(pd); md.setPluginDescriptor(pd);
pd.addComponentDescriptor(md); pd.addComponentDescriptor(md);
return new MojoExecution(md); return new DefaultMojoExecution((AbstractSession) session, new org.apache.maven.plugin.MojoExecution(md));
} }
private DefaultSession newSession() throws Exception { private DefaultSession newSession() throws Exception {
return new DefaultSession(newMavenSession(), mock(RepositorySystem.class), null, null, null, null); DefaultSession session =
new DefaultSession(newMavenSession(), mock(RepositorySystem.class), null, null, container, null);
return session;
} }
private MavenSession newMavenSession() throws Exception { private MavenSession newMavenSession() throws Exception {

View File

@ -23,8 +23,8 @@ import javax.inject.Named;
import javax.inject.Singleton; import javax.inject.Singleton;
import com.google.inject.OutOfScopeException; import com.google.inject.OutOfScopeException;
import org.apache.maven.SessionScoped;
import org.apache.maven.api.Session; import org.apache.maven.api.Session;
import org.apache.maven.api.di.SessionScoped;
import org.apache.maven.session.scope.internal.SessionScope; import org.apache.maven.session.scope.internal.SessionScope;
import org.codehaus.plexus.PlexusContainer; import org.codehaus.plexus.PlexusContainer;
import org.codehaus.plexus.component.repository.exception.ComponentLookupException; import org.codehaus.plexus.component.repository.exception.ComponentLookupException;

View File

@ -26,6 +26,7 @@ import java.lang.reflect.Method;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Optional;
import java.util.WeakHashMap; import java.util.WeakHashMap;
import org.apache.maven.api.annotations.Nonnull; import org.apache.maven.api.annotations.Nonnull;
@ -213,6 +214,9 @@ public class ReflectionValueExtractor {
} }
} }
if (value instanceof Optional) {
value = ((Optional<?>) value).orElse(null);
}
return value; return value;
} }

View File

@ -32,6 +32,10 @@ under the License.
<description>The API for plugins - Mojos - development.</description> <description>The API for plugins - Mojos - development.</description>
<dependencies> <dependencies>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-api-plugin</artifactId>
</dependency>
<dependency> <dependency>
<groupId>org.apache.maven</groupId> <groupId>org.apache.maven</groupId>
<artifactId>maven-model</artifactId> <artifactId>maven-model</artifactId>
@ -54,6 +58,10 @@ under the License.
<groupId>org.codehaus.plexus</groupId> <groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-classworlds</artifactId> <artifactId>plexus-classworlds</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.apache.maven.resolver</groupId>
<artifactId>maven-resolver-api</artifactId>
</dependency>
</dependencies> </dependencies>
<build> <build>
@ -63,44 +71,55 @@ under the License.
<artifactId>modello-maven-plugin</artifactId> <artifactId>modello-maven-plugin</artifactId>
<configuration> <configuration>
<velocityBasedir>${project.basedir}/../src/mdo</velocityBasedir> <velocityBasedir>${project.basedir}/../src/mdo</velocityBasedir>
<models>
<model>src/main/mdo/lifecycle.mdo</model>
</models>
<version>1.0.0</version>
</configuration> </configuration>
<executions> <executions>
<execution> <execution>
<id>velocity</id> <id>velocity-lifecycle</id>
<goals> <goals>
<goal>velocity</goal> <goal>velocity</goal>
</goals> </goals>
<phase>generate-sources</phase> <phase>generate-sources</phase>
<configuration> <configuration>
<templates> <templates>
<template>model.vm</template>
<template>reader-stax.vm</template> <template>reader-stax.vm</template>
<template>writer-stax.vm</template> <template>writer-stax.vm</template>
</templates> </templates>
<params> <params>
<param>packageModelV3=org.apache.maven.plugin.lifecycle</param> <param>packageModelV4=org.apache.maven.api.plugin.descriptor.lifecycle</param>
<param>packageModelV4=org.apache.maven.plugin.lifecycle</param>
<param>packageToolV4=org.apache.maven.plugin.lifecycle.io</param> <param>packageToolV4=org.apache.maven.plugin.lifecycle.io</param>
</params> </params>
<models>
<model>../api/maven-api-plugin/src/main/mdo/lifecycle.mdo</model>
</models>
<version>1.0.0</version>
</configuration> </configuration>
</execution> </execution>
<execution> <execution>
<id>modello-site-docs2</id> <id>velocity-plugin</id>
<goals> <goals>
<goal>xdoc</goal> <goal>velocity</goal>
</goals> </goals>
<phase>pre-site</phase> <phase>generate-sources</phase>
<configuration> <configuration>
<templates>
<template>reader-stax.vm</template>
<template>writer-stax.vm</template>
</templates>
<params>
<param>packageModelV3=org.apache.maven.plugin.descriptor</param>
<param>packageModelV4=org.apache.maven.api.plugin.descriptor</param>
<param>packageToolV4=org.apache.maven.plugin.descriptor.io</param>
</params>
<models> <models>
<model>src/main/mdo/plugin.mdo</model> <model>../api/maven-api-plugin/src/main/mdo/plugin.mdo</model>
</models> </models>
<version>1.1.0</version> <version>2.0.0</version>
</configuration> </configuration>
</execution> </execution>
<execution>
<id>modello-site-docs</id>
<phase>none</phase>
</execution>
</executions> </executions>
</plugin> </plugin>
<plugin> <plugin>
@ -110,32 +129,8 @@ under the License.
<parameter> <parameter>
<excludes> <excludes>
<exclude>org.apache.maven.monitor.logging.DefaultLog</exclude> <exclude>org.apache.maven.monitor.logging.DefaultLog</exclude>
<exclude>org.apache.maven.plugin.lifecycle.Execution#addGoal(java.lang.String):METHOD_REMOVED</exclude> <exclude>org.apache.maven.plugin.lifecycle</exclude>
<exclude>org.apache.maven.plugin.lifecycle.Execution#getConfiguration():METHOD_RETURN_TYPE_CHANGED</exclude> <exclude>org.apache.maven.plugin.descriptor.PluginDescriptor#getLifecycleMapping(java.lang.String)</exclude>
<exclude>org.apache.maven.plugin.lifecycle.Execution#removeGoal(java.lang.String):METHOD_REMOVED</exclude>
<exclude>org.apache.maven.plugin.lifecycle.Execution#setConfiguration(java.lang.Object):METHOD_REMOVED</exclude>
<exclude>org.apache.maven.plugin.lifecycle.Execution#setGoals(java.util.List):METHOD_REMOVED</exclude>
<exclude>org.apache.maven.plugin.lifecycle.Execution#Execution():CONSTRUCTOR_REMOVED</exclude>
<exclude>org.apache.maven.plugin.lifecycle.io.xpp3.LifecycleMappingsXpp3Reader#contentTransformer</exclude>
<exclude>org.apache.maven.plugin.lifecycle.Lifecycle#addPhase(org.apache.maven.plugin.lifecycle.Phase):METHOD_REMOVED</exclude>
<exclude>org.apache.maven.plugin.lifecycle.Lifecycle#removePhase(org.apache.maven.plugin.lifecycle.Phase):METHOD_REMOVED</exclude>
<exclude>org.apache.maven.plugin.lifecycle.Lifecycle#setId(java.lang.String):METHOD_REMOVED</exclude>
<exclude>org.apache.maven.plugin.lifecycle.Lifecycle#setPhases(java.util.List):METHOD_REMOVED</exclude>
<exclude>org.apache.maven.plugin.lifecycle.Lifecycle#Lifecycle():CONSTRUCTOR_REMOVED</exclude>
<exclude>org.apache.maven.plugin.lifecycle.LifecycleConfiguration#addLifecycle(org.apache.maven.plugin.lifecycle.Lifecycle):METHOD_REMOVED</exclude>
<exclude>org.apache.maven.plugin.lifecycle.LifecycleConfiguration#removeLifecycle(org.apache.maven.plugin.lifecycle.Lifecycle):METHOD_REMOVED</exclude>
<exclude>org.apache.maven.plugin.lifecycle.LifecycleConfiguration#setLifecycles(java.util.List):METHOD_REMOVED</exclude>
<exclude>org.apache.maven.plugin.lifecycle.LifecycleConfiguration#setModelEncoding(java.lang.String):METHOD_REMOVED</exclude>
<exclude>org.apache.maven.plugin.lifecycle.LifecycleConfiguration#LifecycleConfiguration():CONSTRUCTOR_REMOVED</exclude>
<exclude>org.apache.maven.plugin.lifecycle.Phase#addExecution(org.apache.maven.plugin.lifecycle.Execution):METHOD_REMOVED</exclude>
<exclude>org.apache.maven.plugin.lifecycle.Phase#getConfiguration():METHOD_RETURN_TYPE_CHANGED</exclude>
<exclude>org.apache.maven.plugin.lifecycle.Phase#removeExecution(org.apache.maven.plugin.lifecycle.Execution):METHOD_REMOVED</exclude>
<exclude>org.apache.maven.plugin.lifecycle.Phase#setConfiguration(java.lang.Object):METHOD_REMOVED</exclude>
<exclude>org.apache.maven.plugin.lifecycle.Phase#setExecutions(java.util.List):METHOD_REMOVED</exclude>
<exclude>org.apache.maven.plugin.lifecycle.Phase#setId(java.lang.String):METHOD_REMOVED</exclude>
<exclude>org.apache.maven.plugin.lifecycle.Phase#Phase():CONSTRUCTOR_REMOVED</exclude>
<exclude>org.apache.maven.plugin.lifecycle.io.xpp3.LifecycleMappingsXpp3Reader</exclude>
<exclude>org.apache.maven.plugin.lifecycle.io.xpp3.LifecycleMappingsXpp3Writer</exclude>
</excludes> </excludes>
</parameter> </parameter>
</configuration> </configuration>

View File

@ -23,6 +23,7 @@ import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.stream.Collectors;
import org.apache.maven.plugin.Mojo; import org.apache.maven.plugin.Mojo;
import org.codehaus.plexus.component.repository.ComponentDescriptor; import org.codehaus.plexus.component.repository.ComponentDescriptor;
@ -146,6 +147,34 @@ public class MojoDescriptor extends ComponentDescriptor<Mojo> implements Cloneab
setComponentFactory(DEFAULT_LANGUAGE); setComponentFactory(DEFAULT_LANGUAGE);
} }
public MojoDescriptor(PluginDescriptor pd, org.apache.maven.api.plugin.descriptor.MojoDescriptor md) {
this();
this.setPluginDescriptor(pd);
this.setGoal(md.getGoal());
this.setExecuteGoal(md.getExecuteGoal());
this.setExecuteLifecycle(md.getExecuteLifecycle());
this.setExecutePhase(md.getExecutePhase());
this.setDeprecated(md.getDeprecated());
this.setLanguage(md.getLanguage());
this.setAggregator(md.isAggregator());
this.setDependencyCollectionRequired(md.getDependencyCollection());
this.setDependencyResolutionRequired(md.getDependencyResolution());
this.setComponentConfigurator(md.getConfigurator());
this.setInheritedByDefault(md.isInheritedByDefault());
this.setPhase(md.getPhase());
this.setOnlineRequired(md.isOnlineRequired());
this.setProjectRequired(md.isProjectRequired());
this.setSince(md.getSince());
this.setThreadSafe(true);
this.setV4Api(true);
this.setImplementation(md.getImplementation());
try {
this.setParameters(md.getParameters().stream().map(Parameter::new).collect(Collectors.toList()));
} catch (DuplicateParameterException e) {
throw new IllegalArgumentException(e);
}
this.mojoDescriptorV4 = md;
}
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
// //
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
@ -608,4 +637,41 @@ public class MojoDescriptor extends ComponentDescriptor<Mojo> implements Cloneab
throw new UnsupportedOperationException(e); throw new UnsupportedOperationException(e);
} }
} }
private volatile org.apache.maven.api.plugin.descriptor.MojoDescriptor mojoDescriptorV4;
public org.apache.maven.api.plugin.descriptor.MojoDescriptor getMojoDescriptorV4() {
if (mojoDescriptorV4 == null) {
synchronized (this) {
if (mojoDescriptorV4 == null) {
mojoDescriptorV4 = org.apache.maven.api.plugin.descriptor.MojoDescriptor.newBuilder()
.goal(goal)
.description(getDescription())
.implementation(getImplementation())
.language(getLanguage())
.phase(phase)
.executeGoal(executeGoal)
.executeLifecycle(executeLifecycle)
.executePhase(executePhase)
.aggregator(aggregator)
.dependencyResolution(dependencyResolutionRequired)
.dependencyCollection(dependencyCollectionRequired)
.projectRequired(projectRequired)
.onlineRequired(onlineRequired)
.inheritedByDefault(inheritedByDefault)
.since(since)
.deprecated(deprecated)
.configurator(getComponentConfigurator())
.parameters(getParameters().stream()
.filter(p -> p.getRequirement() == null)
.map(Parameter::getParameterV4)
.collect(Collectors.toList()))
.id(getId())
.fullGoalName(getFullGoalName())
.build();
}
}
}
return mojoDescriptorV4;
}
} }

View File

@ -49,6 +49,25 @@ public class Parameter implements Cloneable {
// //
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
public Parameter() {}
public Parameter(org.apache.maven.api.plugin.descriptor.Parameter p) {
this.setAlias(p.getAlias());
this.setName(p.getName());
this.setRequired(p.isRequired());
this.setEditable(p.isEditable());
this.setDescription(p.getDescription());
this.setExpression(p.getExpression());
this.setDeprecated(p.getDeprecated());
this.setDefaultValue(p.getDefaultValue());
this.setType(p.getType());
this.setSince(p.getSince());
}
// ----------------------------------------------------------------------
//
// ----------------------------------------------------------------------
public String getName() { public String getName() {
return name; return name;
} }
@ -168,4 +187,19 @@ public class Parameter implements Cloneable {
throw new UnsupportedOperationException(e); throw new UnsupportedOperationException(e);
} }
} }
public org.apache.maven.api.plugin.descriptor.Parameter getParameterV4() {
return org.apache.maven.api.plugin.descriptor.Parameter.newBuilder()
.alias(alias)
.name(name)
.type(type)
.required(required)
.editable(editable)
.description(description)
.expression(expression)
.deprecated(deprecated)
.defaultValue(defaultValue)
.since(since)
.build();
}
} }

View File

@ -26,21 +26,25 @@ import java.io.InputStream;
import java.net.MalformedURLException; import java.net.MalformedURLException;
import java.net.URL; import java.net.URL;
import java.nio.file.Files; import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import java.util.stream.Collectors;
import org.apache.maven.api.plugin.descriptor.lifecycle.Lifecycle;
import org.apache.maven.api.plugin.descriptor.lifecycle.LifecycleConfiguration;
import org.apache.maven.artifact.Artifact; import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.ArtifactUtils; import org.apache.maven.artifact.ArtifactUtils;
import org.apache.maven.model.Plugin; import org.apache.maven.model.Plugin;
import org.apache.maven.plugin.lifecycle.Lifecycle; import org.apache.maven.plugin.lifecycle.io.LifecycleStaxReader;
import org.apache.maven.plugin.lifecycle.LifecycleConfiguration;
import org.apache.maven.plugin.lifecycle.io.LifecycleMappingsStaxReader;
import org.codehaus.plexus.classworlds.realm.ClassRealm; import org.codehaus.plexus.classworlds.realm.ClassRealm;
import org.codehaus.plexus.component.repository.ComponentDescriptor;
import org.codehaus.plexus.component.repository.ComponentSetDescriptor; import org.codehaus.plexus.component.repository.ComponentSetDescriptor;
import org.eclipse.aether.graph.DependencyNode;
/** /**
*/ */
@ -64,6 +68,8 @@ public class PluginDescriptor extends ComponentSetDescriptor implements Cloneabl
private List<Artifact> artifacts; private List<Artifact> artifacts;
private DependencyNode dependencyNode;
private ClassRealm classRealm; private ClassRealm classRealm;
// calculated on-demand. // calculated on-demand.
@ -89,6 +95,67 @@ public class PluginDescriptor extends ComponentSetDescriptor implements Cloneabl
// //
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
public PluginDescriptor() {}
public PluginDescriptor(PluginDescriptor original) {
this.setGroupId(original.getGroupId());
this.setArtifactId(original.getArtifactId());
this.setVersion(original.getVersion());
this.setGoalPrefix(original.getGoalPrefix());
this.setInheritedByDefault(original.isInheritedByDefault());
this.setName(original.getName());
this.setDescription(original.getDescription());
this.setRequiredMavenVersion(original.getRequiredMavenVersion());
this.setRequiredJavaVersion(original.getRequiredJavaVersion());
this.setPluginArtifact(ArtifactUtils.copyArtifactSafe(original.getPluginArtifact()));
this.setComponents(clone(original.getMojos(), this));
this.setId(original.getId());
this.setIsolatedRealm(original.isIsolatedRealm());
this.setSource(original.getSource());
this.setDependencies(original.getDependencies());
this.setDependencyNode(original.getDependencyNode());
}
private static List<ComponentDescriptor<?>> clone(List<MojoDescriptor> mojos, PluginDescriptor pluginDescriptor) {
List<ComponentDescriptor<?>> clones = null;
if (mojos != null) {
clones = new ArrayList<>(mojos.size());
for (MojoDescriptor mojo : mojos) {
MojoDescriptor clone = mojo.clone();
clone.setPluginDescriptor(pluginDescriptor);
clones.add(clone);
}
}
return clones;
}
public PluginDescriptor(org.apache.maven.api.plugin.descriptor.PluginDescriptor original) {
this.setGroupId(original.getGroupId());
this.setArtifactId(original.getArtifactId());
this.setVersion(original.getVersion());
this.setGoalPrefix(original.getGoalPrefix());
this.setInheritedByDefault(original.isInheritedByDefault());
this.setName(original.getName());
this.setDescription(original.getDescription());
this.setRequiredMavenVersion(original.getRequiredMavenVersion());
this.setRequiredJavaVersion(original.getRequiredJavaVersion());
this.setPluginArtifact(null); // TODO: v4
this.setComponents(Collections.emptyList()); // TODO: v4
this.setComponents(original.getMojos().stream()
.map(m -> new MojoDescriptor(this, m))
.collect(Collectors.toList()));
this.setId(original.getId());
this.setIsolatedRealm(original.isIsolatedRealm());
this.setSource(null);
this.setDependencies(Collections.emptyList()); // TODO: v4
this.setDependencyNode(null); // TODO: v4
this.pluginDescriptorV4 = original;
}
// ----------------------------------------------------------------------
//
// ----------------------------------------------------------------------
@SuppressWarnings({"unchecked", "rawtypes"}) @SuppressWarnings({"unchecked", "rawtypes"})
public List<MojoDescriptor> getMojos() { public List<MojoDescriptor> getMojos() {
return (List) getComponents(); return (List) getComponents();
@ -220,6 +287,14 @@ public class PluginDescriptor extends ComponentSetDescriptor implements Cloneabl
artifactMap = null; artifactMap = null;
} }
public DependencyNode getDependencyNode() {
return dependencyNode;
}
public void setDependencyNode(DependencyNode dependencyNode) {
this.dependencyNode = dependencyNode;
}
/** /**
* The map of artifacts accessible by the versionlessKey, i.e. groupId:artifactId * The map of artifacts accessible by the versionlessKey, i.e. groupId:artifactId
* *
@ -326,11 +401,15 @@ public class PluginDescriptor extends ComponentSetDescriptor implements Cloneabl
} }
public Lifecycle getLifecycleMapping(String lifecycleId) throws IOException, XMLStreamException { public Lifecycle getLifecycleMapping(String lifecycleId) throws IOException, XMLStreamException {
return getLifecycleMappings().get(lifecycleId);
}
public Map<String, Lifecycle> getLifecycleMappings() throws IOException, XMLStreamException {
if (lifecycleMappings == null) { if (lifecycleMappings == null) {
LifecycleConfiguration lifecycleConfiguration; LifecycleConfiguration lifecycleConfiguration;
try (InputStream input = getDescriptorStream(LIFECYCLE_DESCRIPTOR)) { try (InputStream input = getDescriptorStream(LIFECYCLE_DESCRIPTOR)) {
lifecycleConfiguration = new LifecycleMappingsStaxReader().read(input); lifecycleConfiguration = new LifecycleStaxReader().read(input);
} }
lifecycleMappings = new HashMap<>(); lifecycleMappings = new HashMap<>();
@ -339,8 +418,7 @@ public class PluginDescriptor extends ComponentSetDescriptor implements Cloneabl
lifecycleMappings.put(lifecycle.getId(), lifecycle); lifecycleMappings.put(lifecycle.getId(), lifecycle);
} }
} }
return lifecycleMappings;
return lifecycleMappings.get(lifecycleId);
} }
private InputStream getDescriptorStream(String descriptor) throws IOException { private InputStream getDescriptorStream(String descriptor) throws IOException {
@ -377,4 +455,33 @@ public class PluginDescriptor extends ComponentSetDescriptor implements Cloneabl
addMojo(mojoDescriptor); addMojo(mojoDescriptor);
} }
} }
private volatile org.apache.maven.api.plugin.descriptor.PluginDescriptor pluginDescriptorV4;
public org.apache.maven.api.plugin.descriptor.PluginDescriptor getPluginDescriptorV4() {
if (pluginDescriptorV4 == null) {
synchronized (this) {
if (pluginDescriptorV4 == null) {
pluginDescriptorV4 = org.apache.maven.api.plugin.descriptor.PluginDescriptor.newBuilder()
.namespaceUri(null)
.modelEncoding(null)
.name(name)
.description(description)
.groupId(groupId)
.artifactId(artifactId)
.version(version)
.goalPrefix(goalPrefix)
.isolatedRealm(isIsolatedRealm())
.inheritedByDefault(inheritedByDefault)
.requiredJavaVersion(requiredJavaVersion)
.requiredMavenVersion(requiredMavenVersion)
.mojos(getMojos().stream()
.map(MojoDescriptor::getMojoDescriptorV4)
.collect(Collectors.toList()))
.build();
}
}
}
return pluginDescriptorV4;
}
} }

View File

@ -21,6 +21,9 @@ package org.apache.maven.plugin.descriptor;
import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader; import javax.xml.stream.XMLStreamReader;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.Reader; import java.io.Reader;
import java.util.ArrayList; import java.util.ArrayList;
@ -28,8 +31,10 @@ import java.util.List;
import java.util.Optional; import java.util.Optional;
import com.ctc.wstx.stax.WstxInputFactory; import com.ctc.wstx.stax.WstxInputFactory;
import org.apache.maven.api.xml.XmlNode;
import org.apache.maven.internal.xml.XmlNodeBuilder; import org.apache.maven.internal.xml.XmlNodeBuilder;
import org.apache.maven.internal.xml.XmlPlexusConfiguration; import org.apache.maven.internal.xml.XmlPlexusConfiguration;
import org.apache.maven.plugin.descriptor.io.PluginDescriptorStaxReader;
import org.codehaus.plexus.component.repository.ComponentDependency; import org.codehaus.plexus.component.repository.ComponentDependency;
import org.codehaus.plexus.component.repository.ComponentRequirement; import org.codehaus.plexus.component.repository.ComponentRequirement;
import org.codehaus.plexus.configuration.PlexusConfiguration; import org.codehaus.plexus.configuration.PlexusConfiguration;
@ -38,16 +43,109 @@ import org.codehaus.plexus.configuration.PlexusConfigurationException;
/** /**
*/ */
public class PluginDescriptorBuilder { public class PluginDescriptorBuilder {
public static final String PLUGIN_2_0_0 = "http://maven.apache.org/PLUGIN/2.0.0";
private static final int BUFFER_SIZE = 8192;
public interface StreamSupplier {
InputStream open() throws IOException;
}
public interface ReaderSupplier {
Reader open() throws IOException;
}
/**
* @deprecated use {@link #build(ReaderSupplier)}
*/
@Deprecated
public PluginDescriptor build(Reader reader) throws PlexusConfigurationException { public PluginDescriptor build(Reader reader) throws PlexusConfigurationException {
return build(reader, null); return build(reader, null);
} }
/**
* @deprecated use {@link #build(ReaderSupplier, String)}
*/
@Deprecated
public PluginDescriptor build(Reader reader, String source) throws PlexusConfigurationException { public PluginDescriptor build(Reader reader, String source) throws PlexusConfigurationException {
return build(source, buildConfiguration(reader)); return build(() -> reader, source);
} }
public PluginDescriptor build(ReaderSupplier readerSupplier) throws PlexusConfigurationException {
return build(readerSupplier, null);
}
public PluginDescriptor build(ReaderSupplier readerSupplier, String source) throws PlexusConfigurationException {
try (BufferedReader br = new BufferedReader(readerSupplier.open(), BUFFER_SIZE)) {
br.mark(BUFFER_SIZE);
XMLStreamReader xsr = WstxInputFactory.newFactory().createXMLStreamReader(br);
xsr.nextTag();
String nsUri = xsr.getNamespaceURI();
try (BufferedReader br2 = reset(readerSupplier, br)) {
xsr = WstxInputFactory.newFactory().createXMLStreamReader(br2);
return build(source, nsUri, xsr);
}
} catch (XMLStreamException | IOException e) {
throw new PlexusConfigurationException(e.getMessage(), e);
}
}
/**
* @deprecated use {@link #build(StreamSupplier, String)}
*/
@Deprecated
public PluginDescriptor build(InputStream input, String source) throws PlexusConfigurationException { public PluginDescriptor build(InputStream input, String source) throws PlexusConfigurationException {
return build(source, buildConfiguration(input)); return build(() -> input, source);
}
public PluginDescriptor build(StreamSupplier inputSupplier) throws PlexusConfigurationException {
return build(inputSupplier, null);
}
public PluginDescriptor build(StreamSupplier inputSupplier, String source) throws PlexusConfigurationException {
try (BufferedInputStream bis = new BufferedInputStream(inputSupplier.open(), BUFFER_SIZE)) {
bis.mark(BUFFER_SIZE);
XMLStreamReader xsr = WstxInputFactory.newFactory().createXMLStreamReader(bis);
xsr.nextTag();
String nsUri = xsr.getNamespaceURI();
try (BufferedInputStream bis2 = reset(inputSupplier, bis)) {
xsr = WstxInputFactory.newFactory().createXMLStreamReader(bis2);
return build(source, nsUri, xsr);
}
} catch (XMLStreamException | IOException e) {
throw new PlexusConfigurationException(e.getMessage(), e);
}
}
private static BufferedInputStream reset(StreamSupplier inputSupplier, BufferedInputStream bis) throws IOException {
try {
bis.reset();
return bis;
} catch (IOException e) {
return new BufferedInputStream(inputSupplier.open(), BUFFER_SIZE);
}
}
private static BufferedReader reset(ReaderSupplier readerSupplier, BufferedReader br) throws IOException {
try {
br.reset();
return br;
} catch (IOException e) {
return new BufferedReader(readerSupplier.open(), BUFFER_SIZE);
}
}
private PluginDescriptor build(String source, String nsUri, XMLStreamReader xsr)
throws XMLStreamException, PlexusConfigurationException {
if (PLUGIN_2_0_0.equals(nsUri)) {
org.apache.maven.api.plugin.descriptor.PluginDescriptor pd =
new PluginDescriptorStaxReader().read(xsr, true);
return new PluginDescriptor(pd);
} else {
XmlNode node = XmlNodeBuilder.build(xsr, true, null);
PlexusConfiguration cfg = XmlPlexusConfiguration.toPlexusConfiguration(node);
return build(source, cfg);
}
} }
private PluginDescriptor build(String source, PlexusConfiguration c) throws PlexusConfigurationException { private PluginDescriptor build(String source, PlexusConfiguration c) throws PlexusConfigurationException {

View File

@ -162,10 +162,11 @@ under the License.
<classWorldsVersion>2.6.0</classWorldsVersion> <classWorldsVersion>2.6.0</classWorldsVersion>
<commonsCliVersion>1.5.0</commonsCliVersion> <commonsCliVersion>1.5.0</commonsCliVersion>
<commonsIoVersion>2.11.0</commonsIoVersion> <commonsIoVersion>2.11.0</commonsIoVersion>
<guiceVersion>5.1.0</guiceVersion> <guiceVersion>6.0.0</guiceVersion>
<guavaVersion>32.0.1-jre</guavaVersion> <guavaVersion>32.0.1-jre</guavaVersion>
<guavafailureaccessVersion>1.0.1</guavafailureaccessVersion> <guavafailureaccessVersion>1.0.1</guavafailureaccessVersion>
<hamcrestVersion>2.2</hamcrestVersion> <hamcrestVersion>2.2</hamcrestVersion>
<jakartaInjectApiVersion>2.0.1</jakartaInjectApiVersion>
<jansiVersion>2.4.1</jansiVersion> <jansiVersion>2.4.1</jansiVersion>
<javaxAnnotationApiVersion>1.3.2</javaxAnnotationApiVersion> <javaxAnnotationApiVersion>1.3.2</javaxAnnotationApiVersion>
<junitVersion>5.10.1</junitVersion> <junitVersion>5.10.1</junitVersion>
@ -287,6 +288,11 @@ under the License.
<version>${sisuVersion}</version> <version>${sisuVersion}</version>
<classifier>no_asm</classifier> <classifier>no_asm</classifier>
</dependency> </dependency>
<dependency>
<groupId>jakarta.inject</groupId>
<artifactId>jakarta.inject-api</artifactId>
<version>${jakartaInjectApiVersion}</version>
</dependency>
<dependency> <dependency>
<groupId>org.ow2.asm</groupId> <groupId>org.ow2.asm</groupId>
<artifactId>asm</artifactId> <artifactId>asm</artifactId>

View File

@ -27,6 +27,16 @@
#set ( $rootUcapName = $Helper.capitalise( $root.name ) ) #set ( $rootUcapName = $Helper.capitalise( $root.name ) )
#set ( $rootLcapName = $Helper.uncapitalise( $root.name ) ) #set ( $rootLcapName = $Helper.uncapitalise( $root.name ) )
# #
#set ( $needXmlContext = false )
#foreach ( $class in $model.allClasses )
#set ( $allFields = $Helper.xmlFields( $class ) )
#foreach ( $field in $allFields )
#if ( $Helper.xmlFieldMetadata( $field ).format )
#set ( $needXmlContext = true )
#end
#end
#end
#
#MODELLO-VELOCITY#SAVE-OUTPUT-TO ${package.replace('.','/')}/${className}.java #MODELLO-VELOCITY#SAVE-OUTPUT-TO ${package.replace('.','/')}/${className}.java
// =================== DO NOT EDIT THIS FILE ==================== // =================== DO NOT EDIT THIS FILE ====================
// Generated by Modello Velocity from ${template} // Generated by Modello Velocity from ${template}
@ -38,9 +48,15 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.Reader; import java.io.Reader;
import java.text.DateFormat; import java.text.DateFormat;
#if ( $needXmlContext )
import java.util.ArrayDeque;
#end
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.Date; import java.util.Date;
#if ( $needXmlContext )
import java.util.Deque;
#end
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
@ -470,6 +486,9 @@ public class ${className} {
public ${root.name} read(XMLStreamReader parser, boolean strict, InputSource source) throws XMLStreamException { public ${root.name} read(XMLStreamReader parser, boolean strict, InputSource source) throws XMLStreamException {
#else #else
public ${root.name} read(XMLStreamReader parser, boolean strict) throws XMLStreamException { public ${root.name} read(XMLStreamReader parser, boolean strict) throws XMLStreamException {
#end
#if ( $needXmlContext )
Deque<Object> context = new ArrayDeque<>();
#end #end
$rootUcapName $rootLcapName = null; $rootUcapName $rootLcapName = null;
int eventType = parser.getEventType(); int eventType = parser.getEventType();
@ -484,6 +503,8 @@ public class ${className} {
} }
#if ( $locationTracking ) #if ( $locationTracking )
$rootLcapName = parse${rootUcapName}(parser, strict, source); $rootLcapName = parse${rootUcapName}(parser, strict, source);
#elseif ( $needXmlContext )
$rootLcapName = parse${rootUcapName}(parser, strict, context);
#else #else
$rootLcapName = parse${rootUcapName}(parser, strict); $rootLcapName = parse${rootUcapName}(parser, strict);
#end #end
@ -505,6 +526,8 @@ public class ${className} {
#set ( $allFields = $Helper.xmlFields( $class ) ) #set ( $allFields = $Helper.xmlFields( $class ) )
#if ( $locationTracking ) #if ( $locationTracking )
private ${classUcapName} parse${classUcapName}(XMLStreamReader parser, boolean strict, InputSource source) throws XMLStreamException { private ${classUcapName} parse${classUcapName}(XMLStreamReader parser, boolean strict, InputSource source) throws XMLStreamException {
#elseif ( $needXmlContext )
private ${classUcapName} parse${classUcapName}(XMLStreamReader parser, boolean strict, Deque<Object> context) throws XMLStreamException {
#else #else
private ${classUcapName} parse${classUcapName}(XMLStreamReader parser, boolean strict) throws XMLStreamException { private ${classUcapName} parse${classUcapName}(XMLStreamReader parser, boolean strict) throws XMLStreamException {
#end #end
@ -553,6 +576,9 @@ public class ${className} {
#if ( $Helper.isFlatItems( $field ) ) #if ( $Helper.isFlatItems( $field ) )
List<$field.to> ${field.name} = new ArrayList<>(); List<$field.to> ${field.name} = new ArrayList<>();
#end #end
#end
#if ( $needXmlContext )
context.addLast( ${classLcapName} );
#end #end
while ((strict ? parser.nextTag() : nextTag(parser)) == XMLStreamReader.START_ELEMENT) { while ((strict ? parser.nextTag() : nextTag(parser)) == XMLStreamReader.START_ELEMENT) {
String childName = checkDuplicate(parser.getLocalName(), parser, parsed); String childName = checkDuplicate(parser.getLocalName(), parser, parsed);
@ -564,7 +590,7 @@ public class ${className} {
switch (childName) { switch (childName) {
#set( $ift = "if" ) #set( $ift = "if" )
#foreach ( $field in $allFields ) #foreach ( $field in $allFields )
#if ( ! $Helper.xmlFieldMetadata( $field ).attribute && ! $Helper.xmlFieldMetadata( $field ).transient ) #if ( ! $Helper.xmlFieldMetadata( $field ).attribute && ! $Helper.xmlFieldMetadata( $field ).transient && ! $Helper.xmlFieldMetadata( $field ).format )
#set ( $fieldTagName = $Helper.xmlFieldMetadata( $field ).tagName ) #set ( $fieldTagName = $Helper.xmlFieldMetadata( $field ).tagName )
#if ( ! $fieldTagName ) #if ( ! $fieldTagName )
#set ( $fieldTagName = $field.name ) #set ( $fieldTagName = $field.name )
@ -629,6 +655,8 @@ public class ${className} {
#elseif ( $field.to && $field.multiplicity == "1" ) #elseif ( $field.to && $field.multiplicity == "1" )
#if ( $locationTracking ) #if ( $locationTracking )
${classLcapName}.${field.name}(parse${field.toClass.name}(parser, strict, source)); ${classLcapName}.${field.name}(parse${field.toClass.name}(parser, strict, source));
#elseif ( $needXmlContext )
${classLcapName}.${field.name}(parse${field.toClass.name}(parser, strict, context));
#else #else
${classLcapName}.${field.name}(parse${field.toClass.name}(parser, strict)); ${classLcapName}.${field.name}(parse${field.toClass.name}(parser, strict));
#end #end
@ -642,6 +670,8 @@ public class ${className} {
if ("${Helper.singular($fieldTagName)}".equals(parser.getLocalName())) { if ("${Helper.singular($fieldTagName)}".equals(parser.getLocalName())) {
#if ( $locationTracking ) #if ( $locationTracking )
${field.name}.add(parse${field.toClass.name}(parser, strict, source)); ${field.name}.add(parse${field.toClass.name}(parser, strict, source));
#elseif ( $needXmlContext )
${field.name}.add(parse${field.toClass.name}(parser, strict, context));
#else #else
${field.name}.add(parse${field.toClass.name}(parser, strict)); ${field.name}.add(parse${field.toClass.name}(parser, strict));
#end #end
@ -670,11 +700,19 @@ public class ${className} {
} }
#end #end
} }
#if ( $needXmlContext )
context.removeLast();
#end
#foreach ( $field in $allFields ) #foreach ( $field in $allFields )
#if ( $Helper.isFlatItems( $field ) ) #if ( $Helper.isFlatItems( $field ) )
${classLcapName}.${field.name}(${field.name}); ${classLcapName}.${field.name}(${field.name});
#end #end
#end #end
#foreach ( $field in $allFields )
#if ( $Helper.xmlFieldMetadata( $field ).format )
${classLcapName}.${field.name}($Helper.xmlFieldMetadata( $field ).format);
#end
#end
#if ( $class == $root ) #if ( $class == $root )
${classLcapName}.namespaceUri(parser.getNamespaceURI()); ${classLcapName}.namespaceUri(parser.getNamespaceURI());
${classLcapName}.modelEncoding(parser.getEncoding()); ${classLcapName}.modelEncoding(parser.getEncoding());

View File

@ -224,7 +224,7 @@ public class ${className} {
serializer.writeStartElement(namespace, tagName); serializer.writeStartElement(namespace, tagName);
#end #end
#foreach ( $field in $allFields ) #foreach ( $field in $allFields )
#if ( $Helper.xmlFieldMetadata( $field ).attribute ) #if ( $Helper.xmlFieldMetadata( $field ).attribute && ! $Helper.xmlFieldMetadata( $field ).format )
#set ( $fieldTagName = $Helper.xmlFieldMetadata( $field ).tagName ) #set ( $fieldTagName = $Helper.xmlFieldMetadata( $field ).tagName )
#set ( $fieldCapName = $Helper.capitalise( $field.name ) ) #set ( $fieldCapName = $Helper.capitalise( $field.name ) )
#if ( $field.type == "String" ) #if ( $field.type == "String" )
@ -242,7 +242,8 @@ public class ${className} {
#end #end
#end #end
#foreach ( $field in $allFields ) #foreach ( $field in $allFields )
#if ( ! $Helper.xmlFieldMetadata( $field ).attribute && ! $Helper.xmlFieldMetadata( $field ).transient ) #if ( ! $Helper.xmlFieldMetadata( $field ).attribute && ! $Helper.xmlFieldMetadata( $field ).transient
&& ! $Helper.xmlFieldMetadata( $field ).format )
#set ( $fieldTagName = $Helper.xmlFieldMetadata( $field ).tagName ) #set ( $fieldTagName = $Helper.xmlFieldMetadata( $field ).tagName )
#if ( ! $fieldTagName ) #if ( ! $fieldTagName )
#set ( $fieldTagName = $field.name ) #set ( $fieldTagName = $field.name )