[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>
<version>4.0.0-alpha-9-SNAPSHOT</version>
</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>
</project>

View File

@ -22,23 +22,37 @@ import java.util.Optional;
import org.apache.maven.api.annotations.Experimental;
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;
/**
* 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
public interface MojoExecution {
@Nonnull
Plugin getPlugin();
@Nonnull
PluginExecution getModel();
@Nonnull
MojoDescriptor getDescriptor();
@Nonnull
String getExecutionId();
@Nonnull
String getGoal();
@Nonnull
String getLifecyclePhase();
@Nonnull
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
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>
* @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
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.

View File

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

View File

@ -16,29 +16,26 @@
* specific language governing permissions and limitations
* 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
*/
@Experimental
public enum InstantiationStrategy {
PER_LOOKUP("per-lookup"),
SINGLETON("singleton"),
KEEP_ALIVE("keep-alive"),
POOLABLE("poolable");
private final String id;
InstantiationStrategy(String id) {
this.id = id;
}
public String id() {
return this.id;
}
}
@Scope
@Documented
@Retention(RUNTIME)
@Target({TYPE, METHOD})
public @interface SessionScoped {}

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.
*
* TODO: v4: remove experimental bit
*/
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).
* 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
*/
@ -59,27 +62,20 @@ public @interface Mojo {
* @return the required dependency resolution scope
*/
@Nonnull
ResolutionScope requiresDependencyResolution() default ResolutionScope.NONE;
ResolutionScope dependencyResolutionRequired() default ResolutionScope.NONE;
/**
* the required dependency collection scope.
* @return the required dependency collection scope
*/
@Nonnull
ResolutionScope requiresDependencyCollection() 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;
ResolutionScope dependencyCollectionRequired() default ResolutionScope.NONE;
/**
* does your mojo requires a project to be executed?
* @return requires a project
*/
boolean requiresProject() default true;
boolean projectRequired() default true;
/**
* 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?
* @return need to be online
*/
boolean requiresOnline() default false;
boolean onlineRequired() default false;
/**
* TODO: v4: add a SPI for the configurator
* 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.
-->
<model xmlns="http://codehaus-plexus.github.io/MODELLO/1.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"
<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/2.0.0 http://codehaus-plexus.github.io/modello/xsd/modello-2.0.0.xsd"
xml.namespace="http://maven.apache.org/LIFECYCLE/${version}"
xml.schemaLocation="http://maven.apache.org/xsd/lifecycle-${version}.xsd">
<id>lifecycle-mappings</id>
<name>LifecycleMappings</name>
<id>lifecycle</id>
<name>Lifecycle</name>
<description><![CDATA[
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.
]]></description>
<defaults>
<default>
<key>package</key>
<value>org.apache.maven.plugin.lifecycle</value>
</default>
</defaults>
<classes>
<class rootElement="true" xml.tagName="lifecycles" xsd.compositor="sequence">
<name>LifecycleConfiguration</name>

View File

@ -24,26 +24,15 @@ under the License.
<id>plugin</id>
<name>PluginDescriptor</name>
<description><![CDATA[
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
<a href="/plugins/maven-plugin-plugin/">maven-plugin-plugin</a>.
<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>
Maven 4 Plugin descriptor, stored in <code>META-INF/maven/plugin.xml</code> in a plugin's jar artifact.
This descriptor is generally using the information contained in the annotations of the plugin api.
<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>
]]></description>
<defaults>
<default>
<key>package</key>
<value>plugin descriptor XML documentation (no java generation)</value><!-- intentionally non-buildable value -->
</default>
</defaults>
<classes>
<class rootElement="true" xml.tagName="plugin" xdoc.anchorName="plugin">
<name>PluginDescriptor</name>
<version>1.0.0+</version>
<description><![CDATA[Root element of the <code>plugin.xml</code> file.]]></description>
<!-- see o.a.m.plugin.descriptor.PluginDescriptor -->
<fields>
<field>
<name>name</name>
@ -120,7 +109,7 @@ under the License.
</field>
<field xdoc.separator="blank">
<name>dependencies</name>
<version>1.0.0+</version>
<version>1.0.0/1.1.0</version>
<association>
<type>Dependency</type>
<multiplicity>*</multiplicity>
@ -131,6 +120,21 @@ under the License.
</description>
</field>
</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 xdoc.anchorName="mojo">
@ -139,7 +143,6 @@ under the License.
<description><![CDATA[
A Mojo description.
]]></description>
<!-- see o.a.m.plugin.descriptor.MojoDescriptor -->
<fields>
<field>
<name>goal</name>
@ -203,7 +206,18 @@ under the License.
</field>
<field>
<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>
<defaultValue>runtime</defaultValue>
<description><![CDATA[
@ -214,7 +228,20 @@ under the License.
</field>
<field>
<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>
<description><![CDATA[
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>
<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>
<description>Flags this Mojo to be invoked directly only.</description>
<defaultValue>false</defaultValue>
</field>
<field>
<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>
<description>Flags this Mojo to require running inside of a project.</description>
<defaultValue>true</defaultValue>
@ -248,7 +289,14 @@ under the License.
</field>
<field>
<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>
<description>Flags this Mojo to require online mode for its operation.</description>
<defaultValue>false</defaultValue>
@ -272,7 +320,7 @@ under the License.
</field>
<field>
<name>threadSafe</name>
<version>1.0.0+</version>
<version>1.0.0/1.1.0</version>
<type>boolean</type>
<description>
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>
<name>v4Api</name>
<version>1.1.0+</version>
<version>1.1.0</version>
<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>
<defaultValue>false</defaultValue>
</field>
<field>
<name>instantiationStrategy</name>
<version>1.0.0+</version>
<version>1.0.0/1.1.0</version>
<type>String</type>
<defaultValue>per-lookup</defaultValue>
<description>Specify the instantiation strategy.</description>
</field>
<field>
<name>executionStrategy</name>
<version>1.0.0+</version>
<version>1.0.0/1.1.0</version>
<type>String</type>
<description><![CDATA[
Specify the execution strategy: <code>once-per-session</code>, <code>always</code>.
@ -331,7 +379,7 @@ under the License.
</field>
<field>
<name>composer</name>
<version>1.0.0+</version>
<version>1.0.0/1.1.0</version>
<type>String</type>
<description></description>
</field>
@ -344,27 +392,27 @@ under the License.
<multiplicity>*</multiplicity>
</association>
</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">
<name>requirements</name>
<version>1.0.0+</version>
<version>1.0.0/1.1.0</version>
<description></description>
<association>
<type>Requirement</type>
<multiplicity>*</multiplicity>
</association>
</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>
</class>
@ -428,12 +476,6 @@ under the License.
full of Strings.
]]></description>
</field>
<field>
<name>implementation</name>
<version>1.0.0+</version>
<type>String</type>
<description></description>
</field>
<field>
<name>description</name>
<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.
]]></description>
</field>
</fields>
</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">
<field>
<name>expression</name>
<required>true</required>
<version>1.0.0+</version>
<version>2.0.0+</version>
<type>String</type>
<description>Parameter expression, to let user override default value with a user property, system property or project property.</description>
</field>
<field xml.attribute="true" xml.tagName="implementation">
<name>implementation</name>
<version>1.0.0+</version>
<type>String</type>
<description></description>
</field>
<field xml.attribute="true" xml.tagName="default-value">
<field>
<name>defaultValue</name>
<version>1.0.0+</version>
<version>2.0.0+</version>
<type>String</type>
<description>The default value, as an expression that will be evaluated at injection or run-time.</description>
</field>
@ -488,7 +514,7 @@ under the License.
<class xdoc.anchorName="requirement">
<name>Requirement</name>
<version>1.0.0+</version>
<version>1.0.0/1.1.0</version>
<description>Describes a component requirement.</description>
<!-- see o.a.m.plugin.descriptor.Requirement -->
<fields>
@ -517,7 +543,7 @@ under the License.
<class xdoc.anchorName="dependency">
<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>
<fields>
<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-xml</module>
<module>maven-api-model</module>
<module>maven-api-plugin</module>
<module>maven-api-settings</module>
<module>maven-api-toolchain</module>
<module>maven-api-core</module>

View File

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

View File

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

View File

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

View File

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

View File

@ -19,61 +19,122 @@
package org.apache.maven.internal.aether;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.stream.Collectors;
import org.apache.maven.model.Model;
import org.apache.maven.repository.internal.MavenWorkspaceReader;
import org.eclipse.aether.artifact.Artifact;
import org.eclipse.aether.repository.WorkspaceReader;
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.
*/
public final class MavenChainedWorkspaceReader implements MavenWorkspaceReader {
public class MavenChainedWorkspaceReader implements MavenWorkspaceReader {
private ChainedWorkspaceReader delegate;
private WorkspaceReader[] readers;
protected List<WorkspaceReader> readers;
protected WorkspaceRepository repository;
/**
* Creates a new workspace reader by chaining the specified readers.
*
* @param readers The readers to chain must not be {@code null}.
*/
private MavenChainedWorkspaceReader(WorkspaceReader... readers) {
this.delegate = new ChainedWorkspaceReader(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;
public MavenChainedWorkspaceReader(WorkspaceReader... readers) {
setReaders(Arrays.asList(readers));
}
@Override
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
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
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;
public abstract class AbstractSession implements Session {
public abstract class AbstractSession implements InternalSession {
private final List<Listener> listeners = new CopyOnWriteArrayList<>();
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.
*/
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 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.artifact = nonNull(artifact, "artifact can not be null");
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.
*/
public class DefaultArtifactCoordinate implements ArtifactCoordinate {
private final @Nonnull AbstractSession session;
private final @Nonnull InternalSession session;
private final @Nonnull org.eclipse.aether.artifact.Artifact coordinate;
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.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.eclipse.aether.artifact.ArtifactType;
import static org.apache.maven.internal.impl.Utils.cast;
import static org.apache.maven.internal.impl.Utils.nonNull;
@Named
@ -36,8 +35,7 @@ public class DefaultArtifactCoordinateFactory implements ArtifactCoordinateFacto
@Override
public ArtifactCoordinate create(@Nonnull ArtifactCoordinateFactoryRequest request) {
nonNull(request, "request can not be null");
DefaultSession session =
cast(DefaultSession.class, request.getSession(), "request.session should be a " + DefaultSession.class);
InternalSession session = InternalSession.from(request.getSession());
ArtifactType type = null;
if (request.getType() != null) {
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.DeploymentException;
import static org.apache.maven.internal.impl.Utils.cast;
import static org.apache.maven.internal.impl.Utils.nonNull;
/**
@ -54,8 +53,7 @@ public class DefaultArtifactDeployer implements ArtifactDeployer {
@Override
public void deploy(@Nonnull ArtifactDeployerRequest request) {
nonNull(request, "request can not be null");
DefaultSession session =
cast(DefaultSession.class, request.getSession(), "request.session should be a " + DefaultSession.class);
InternalSession session = InternalSession.from(request.getSession());
Collection<Artifact> artifacts = nonNull(request.getArtifacts(), "request.artifacts can not be null");
RemoteRepository repository = nonNull(request.getRepository(), "request.repository can not be null");
try {

View File

@ -27,7 +27,6 @@ import org.apache.maven.api.services.ArtifactFactory;
import org.apache.maven.api.services.ArtifactFactoryRequest;
import org.eclipse.aether.artifact.ArtifactType;
import static org.apache.maven.internal.impl.Utils.cast;
import static org.apache.maven.internal.impl.Utils.nonNull;
@Named
@ -36,8 +35,7 @@ public class DefaultArtifactFactory implements ArtifactFactory {
@Override
public Artifact create(@Nonnull ArtifactFactoryRequest request) {
nonNull(request, "request can not be null");
DefaultSession session =
cast(DefaultSession.class, request.getSession(), "request.session should be a " + DefaultSession.class);
InternalSession session = InternalSession.from(request.getSession());
ArtifactType type = null;
if (request.getType() != null) {
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.InstallationException;
import static org.apache.maven.internal.impl.Utils.cast;
import static org.apache.maven.internal.impl.Utils.nonNull;
@Named
@ -48,8 +47,7 @@ public class DefaultArtifactInstaller implements ArtifactInstaller {
@Override
public void install(ArtifactInstallerRequest request) throws ArtifactInstallerException, IllegalArgumentException {
nonNull(request, "request can not be null");
DefaultSession session =
cast(DefaultSession.class, request.getSession(), "request.session should be a " + DefaultSession.class);
InternalSession session = InternalSession.from(request.getSession());
try {
InstallRequest installRequest =
new InstallRequest().setArtifacts(session.toArtifacts(request.getArtifacts()));

View File

@ -24,26 +24,30 @@ import javax.inject.Named;
import java.io.File;
import java.nio.file.Path;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
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.annotations.Nonnull;
import org.apache.maven.api.di.SessionScoped;
import org.apache.maven.api.services.ArtifactManager;
import org.apache.maven.project.MavenProject;
import org.eclipse.sisu.Typed;
@Named
@Typed
@SessionScoped
public class DefaultArtifactManager implements ArtifactManager {
@Nonnull
private final DefaultSession session;
private final InternalSession session;
private final Map<String, Path> paths = new ConcurrentHashMap<>();
@Inject
public DefaultArtifactManager(@Nonnull DefaultSession session) {
public DefaultArtifactManager(@Nonnull InternalSession session) {
this.session = session;
}
@ -73,12 +77,10 @@ public class DefaultArtifactManager implements ArtifactManager {
public void setPath(@Nonnull Artifact artifact, Path path) {
String id = id(artifact);
if (session.getMavenSession().getAllProjects() != null) {
for (MavenProject project : session.getMavenSession().getAllProjects()) {
if (id.equals(id(project.getArtifact()))) {
project.getArtifact().setFile(path != null ? path.toFile() : null);
break;
}
}
session.getMavenSession().getAllProjects().stream()
.flatMap(this::getProjectArtifacts)
.filter(a -> Objects.equals(id, id(a)))
.forEach(a -> a.setFile(path != null ? path.toFile() : null));
}
if (path == null) {
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) {
return artifact.getGroupId()
+ ":" + artifact.getArtifactId()
+ ":" + artifact.getType()
+ ":" + artifact.getArtifactHandler().getExtension()
+ (artifact.getClassifier() == null || artifact.getClassifier().isEmpty()
? ""
: ":" + artifact.getClassifier())

View File

@ -23,12 +23,13 @@ import javax.inject.Named;
import javax.inject.Singleton;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.apache.maven.api.Artifact;
import org.apache.maven.api.ArtifactCoordinate;
import org.apache.maven.api.annotations.Nonnull;
import org.apache.maven.api.services.ArtifactManager;
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.ArtifactResult;
import static org.apache.maven.internal.impl.Utils.cast;
import static org.apache.maven.internal.impl.Utils.nonNull;
@Named
@ -58,27 +58,32 @@ public class DefaultArtifactResolver implements ArtifactResolver {
public ArtifactResolverResult resolve(ArtifactResolverRequest request)
throws ArtifactResolverException, IllegalArgumentException {
nonNull(request, "request can not be null");
DefaultSession session =
cast(DefaultSession.class, request.getSession(), "request.session should be a " + DefaultSession.class);
InternalSession session = InternalSession.from(request.getSession());
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<>();
for (ArtifactResult result : results) {
Artifact artifact = session.getArtifact(result.getArtifact());
Path path = result.getArtifact().getFile().toPath();
session.getService(ArtifactManager.class).setPath(artifact, path);
paths.put(artifact, path);
}
return new ArtifactResolverResult() {
@Override
public Map<Artifact, Path> getArtifacts() {
return paths;
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) {
Artifact artifact = session.getArtifact(result.getArtifact());
Path path = result.getArtifact().getFile().toPath();
artifactManager.setPath(artifact, path);
paths.put(artifact, path);
}
}
return () -> paths;
} catch (ArtifactResolutionException 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;
public class DefaultDependency implements Dependency {
private final AbstractSession session;
private final InternalSession session;
private final org.eclipse.aether.graph.Dependency dependency;
private final DependencyProperties dependencyProperties;
private final String key;
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.dependency = nonNull(dependency, "dependency");
this.dependencyProperties =
@ -50,7 +50,7 @@ public class DefaultDependency implements Dependency {
+ getArtifactId()
+ ':'
+ getExtension()
+ (getClassifier().length() > 0 ? ":" + getClassifier() : "")
+ (!getClassifier().isEmpty() ? ":" + getClassifier() : "")
+ ':'
+ 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.transformer.ConflictResolver;
import static org.apache.maven.internal.impl.Utils.cast;
import static org.apache.maven.internal.impl.Utils.nonNull;
@Named
@ -60,8 +59,7 @@ public class DefaultDependencyCollector implements DependencyCollector {
public DependencyCollectorResult collect(@Nonnull DependencyCollectorRequest request)
throws DependencyCollectorException, IllegalArgumentException {
nonNull(request, "request can not be null");
DefaultSession session =
cast(DefaultSession.class, request.getSession(), "request.session should be a " + DefaultSession.class);
InternalSession session = InternalSession.from(request.getSession());
Artifact rootArtifact =
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;
public class DefaultDependencyCoordinate implements DependencyCoordinate {
private final AbstractSession session;
private final InternalSession session;
private final org.eclipse.aether.graph.Dependency dependency;
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.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.eclipse.aether.artifact.ArtifactType;
import static org.apache.maven.internal.impl.Utils.cast;
import static org.apache.maven.internal.impl.Utils.nonNull;
@Named
@ -41,8 +40,7 @@ public class DefaultDependencyCoordinateFactory implements DependencyCoordinateF
@Override
public DependencyCoordinate create(@Nonnull DependencyCoordinateFactoryRequest request) {
nonNull(request, "request can not be null");
DefaultSession session =
cast(DefaultSession.class, request.getSession(), "request.session should be a " + DefaultSession.class);
InternalSession session = InternalSession.from(request.getSession());
ArtifactType type = null;
if (request.getType() != null) {

View File

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

View File

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

View File

@ -18,17 +18,34 @@
*/
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.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.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.codehaus.plexus.util.xml.Xpp3Dom;
import org.eclipse.aether.graph.DependencyNode;
public class DefaultMojoExecution implements MojoExecution {
private final InternalSession session;
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;
}
@ -38,7 +55,71 @@ public class DefaultMojoExecution implements MojoExecution {
@Override
public Plugin getPlugin() {
return delegate.getPlugin().getDelegate();
return new Plugin() {
@Override
public org.apache.maven.api.model.Plugin getModel() {
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

View File

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

View File

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

View File

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

View File

@ -30,7 +30,6 @@ import java.util.Set;
import java.util.stream.Collectors;
import org.apache.maven.RepositoryUtils;
import org.apache.maven.SessionScoped;
import org.apache.maven.api.Artifact;
import org.apache.maven.api.Node;
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.Session;
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.MavenException;
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.codehaus.plexus.PlexusContainer;
import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
import org.eclipse.sisu.Typed;
@Named
@Typed
@SessionScoped
public class DefaultProjectManager implements ProjectManager {
@ -73,7 +75,7 @@ public class DefaultProjectManager implements ProjectManager {
@Nonnull
@Override
public Collection<Artifact> getAttachedArtifacts(Project project) {
AbstractSession session = ((DefaultProject) project).getSession();
InternalSession session = ((DefaultProject) project).getSession();
Collection<Artifact> attached = getMavenProject(project).getAttachedArtifacts().stream()
.map(RepositoryUtils::toArtifact)
.map(session::getArtifact)
@ -129,12 +131,12 @@ public class DefaultProjectManager implements ProjectManager {
getMavenProject(project),
toResolve,
toResolve,
((DefaultSession) session).getMavenSession(),
InternalSession.from(session).getMavenSession(),
false,
Collections.emptySet());
return artifacts.stream()
.map(RepositoryUtils::toArtifact)
.map(((DefaultSession) session)::getArtifact)
.map(InternalSession.from(session)::getArtifact)
.collect(Collectors.toList());
} catch (LifecycleExecutionException | ComponentLookupException 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.time.Instant;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Supplier;
import java.util.stream.Collectors;
@ -65,7 +65,7 @@ public class DefaultSession extends AbstractSession {
private final MavenRepositorySystem mavenRepositorySystem;
private final PlexusContainer container;
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")
public DefaultSession(
@ -213,8 +213,7 @@ public class DefaultSession extends AbstractSession {
RepositorySystemSession repoSession =
new DefaultRepositorySystemSession(session).setLocalRepositoryManager(localRepositoryManager);
MavenSession newSession =
new MavenSession(() -> repoSession, mavenSession.getRequest(), mavenSession.getResult());
MavenSession newSession = new MavenSession(repoSession, mavenSession.getRequest(), mavenSession.getResult());
return new DefaultSession(
newSession, repositorySystem, repositories, mavenRepositorySystem, container, runtimeInformation);
}

View File

@ -53,7 +53,7 @@ public class DefaultSessionFactory {
public Session getSession(MavenSession mavenSession) {
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) {

View File

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

View File

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

View File

@ -52,7 +52,7 @@ public class DefaultTransportProvider implements TransportProvider {
return new DefaultTransport(
baseURI,
transporterProvider.newTransporter(
((DefaultSession) session).getSession(),
InternalSession.from(session).getSession(),
((DefaultRemoteRepository) repository).getRepository()));
} catch (URISyntaxException 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 {
if (arg instanceof ExecutionEvent) {
ExecutionEvent ee = (ExecutionEvent) arg;
AbstractSession session = (AbstractSession) sessionFactory.getSession(ee.getSession());
InternalSession session = InternalSession.from(sessionFactory.getSession(ee.getSession()));
Collection<Listener> listeners = session.getListeners();
if (!listeners.isEmpty()) {
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 java.io.IOException;
import java.util.ArrayList;
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 java.util.*;
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.execution.MavenSession;
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.Parameter;
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.version.PluginVersionResolutionException;
import org.apache.maven.project.MavenProject;
@ -340,7 +332,11 @@ public class DefaultLifecycleExecutionPlanCalculator implements LifecycleExecuti
}
private XmlNode getMojoConfiguration(MojoDescriptor mojoDescriptor) {
return MojoDescriptorCreator.convert(mojoDescriptor).getDom();
if (mojoDescriptor.isV4Api()) {
return MojoDescriptorCreator.convert(mojoDescriptor.getMojoDescriptorV4());
} else {
return MojoDescriptorCreator.convert(mojoDescriptor).getDom();
}
}
@Override
@ -459,7 +455,7 @@ public class DefaultLifecycleExecutionPlanCalculator implements LifecycleExecuti
return;
}
org.apache.maven.plugin.lifecycle.Lifecycle lifecycleOverlay;
org.apache.maven.api.plugin.descriptor.lifecycle.Lifecycle lifecycleOverlay;
try {
lifecycleOverlay = pluginDescriptor.getLifecycleMapping(forkedLifecycle);
@ -491,7 +487,7 @@ public class DefaultLifecycleExecutionPlanCalculator implements LifecycleExecuti
MojoExecution forkedExecution =
new MojoExecution(forkedMojoDescriptor, mojoExecution.getExecutionId());
XmlNodeImpl forkedConfiguration = (XmlNodeImpl) execution.getConfiguration();
XmlNode forkedConfiguration = execution.getConfiguration();
forkedExecution.setConfiguration(forkedConfiguration);
@ -501,7 +497,7 @@ public class DefaultLifecycleExecutionPlanCalculator implements LifecycleExecuti
}
}
XmlNodeImpl phaseConfiguration = (XmlNodeImpl) phase.getConfiguration();
XmlNode phaseConfiguration = phase.getConfiguration();
if (phaseConfiguration != null) {
for (MojoExecution forkedExecution : forkedExecutions) {

View File

@ -26,6 +26,7 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import org.apache.maven.api.xml.XmlNode;
import org.apache.maven.execution.MavenSession;
@ -91,6 +92,21 @@ public class MojoDescriptorCreator {
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) {
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.internal.impl.DefaultLog;
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.plugin.descriptor.MojoDescriptor;
import org.apache.maven.plugin.descriptor.PluginDescriptor;
@ -121,8 +121,9 @@ public class DefaultBuildPluginManager implements BuildPluginManager {
org.apache.maven.api.plugin.Log.class,
new DefaultLog(LoggerFactory.getLogger(
mojoExecution.getMojoDescriptor().getFullGoalName())));
scope.seed(Project.class, ((DefaultSession) session.getSession()).getProject(project));
scope.seed(org.apache.maven.api.MojoExecution.class, new DefaultMojoExecution(mojoExecution));
InternalSession sessionV4 = InternalSession.from(session.getSession());
scope.seed(Project.class, sessionV4.getProject(project));
scope.seed(org.apache.maven.api.MojoExecution.class, new DefaultMojoExecution(sessionV4, mojoExecution));
if (mojoDescriptor.isV4Api()) {
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 org.apache.maven.RepositoryUtils;
import org.apache.maven.artifact.ArtifactUtils;
import org.apache.maven.model.Plugin;
import org.apache.maven.plugin.descriptor.MojoDescriptor;
import org.apache.maven.plugin.descriptor.PluginDescriptor;
import org.codehaus.plexus.component.repository.ComponentDescriptor;
import org.eclipse.aether.RepositorySystemSession;
import org.eclipse.aether.repository.LocalRepository;
import org.eclipse.aether.repository.RemoteRepository;
@ -97,49 +94,7 @@ public class DefaultPluginDescriptorCache implements PluginDescriptorCache {
}
protected static PluginDescriptor clone(PluginDescriptor original) {
PluginDescriptor clone = null;
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;
return new PluginDescriptor(original);
}
private static final class CacheKey implements Key {

View File

@ -21,16 +21,15 @@ package org.apache.maven.plugin;
import java.io.File;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.Properties;
import org.apache.maven.api.MojoExecution;
import org.apache.maven.api.Project;
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.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.TypeAwareExpressionEvaluator;
@ -40,36 +39,18 @@ import org.codehaus.plexus.component.configurator.expression.TypeAwareExpression
* <table border="1">
* <caption>Expression matrix</caption>
* <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>(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>session.*</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>basedir</code></td> <td></td>
* <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>mojo.*</code></td> <td></td> <td>the actual {@link MojoExecution}</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>project properties</td></tr>
* </table>
* <i>Notice:</i> <code>reports</code> was supported in Maven 2.x but was removed in Maven 3
*
* @see Session
* @see Project
* @see org.apache.maven.api.settings.Settings
* @see MojoExecution
*/
public class PluginParameterExpressionEvaluatorV4 implements TypeAwareExpressionEvaluator {
@ -165,129 +146,34 @@ public class PluginParameterExpressionEvaluatorV4 implements TypeAwareExpression
return expression.replace("$$", "$");
}
if ("localRepository".equals(expression)) {
// TODO: v4
value = session.getLocalRepository();
} else if ("session".equals(expression)) {
value = session;
} else if (expression.startsWith("session")) {
// TODO: v4
try {
int pathSeparator = expression.indexOf('/');
if (pathSeparator > 0) {
String pathExpression = expression.substring(0, pathSeparator);
value = ReflectionValueExtractor.evaluate(pathExpression, session);
if (pathSeparator < expression.length() - 1) {
if (value instanceof Path) {
value = ((Path) value).resolve(expression.substring(pathSeparator + 1));
} else {
value = value + expression.substring(pathSeparator);
Map<String, Object> objects = new HashMap<>();
objects.put("session.", session);
objects.put("project.", project);
objects.put("mojo.", mojoExecution);
objects.put("settings.", session.getSettings());
for (Map.Entry<String, Object> ctx : objects.entrySet()) {
if (expression.startsWith(ctx.getKey())) {
try {
int pathSeparator = expression.indexOf('/');
if (pathSeparator > 0) {
String pathExpression = expression.substring(0, pathSeparator);
value = ReflectionValueExtractor.evaluate(pathExpression, ctx.getValue());
if (pathSeparator < expression.length() - 1) {
if (value instanceof Path) {
value = ((Path) value).resolve(expression.substring(pathSeparator + 1));
} else {
value = value + expression.substring(pathSeparator);
}
}
} else {
value = ReflectionValueExtractor.evaluate(expression, ctx.getValue());
}
} else {
value = ReflectionValueExtractor.evaluate(expression, session);
break;
} catch (Exception e) {
// TODO don't catch exception
throw new ExpressionEvaluationException(
"Error evaluating plugin parameter expression: " + expression, e);
}
} catch (Exception e) {
// TODO don't catch exception
throw new ExpressionEvaluationException(
"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.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.nio.file.Files;
import java.util.ArrayList;
@ -39,13 +38,16 @@ import java.util.jar.JarFile;
import java.util.stream.Collectors;
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.api.xml.XmlNode;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.classrealm.ClassRealmManager;
import org.apache.maven.execution.MavenSession;
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.model.Plugin;
import org.apache.maven.plugin.ContextEnabled;
@ -220,18 +222,18 @@ public class DefaultMavenPluginManager implements MavenPluginManager {
ZipEntry pluginDescriptorEntry = pluginJar.getEntry(getPluginDescriptorLocation());
if (pluginDescriptorEntry != null) {
InputStream is = pluginJar.getInputStream(pluginDescriptorEntry);
pluginDescriptor = parsePluginDescriptor(is, plugin, pluginFile.getAbsolutePath());
pluginDescriptor = parsePluginDescriptor(
() -> pluginJar.getInputStream(pluginDescriptorEntry),
plugin,
pluginFile.getAbsolutePath());
}
}
} else {
File pluginXml = new File(pluginFile, getPluginDescriptorLocation());
if (pluginXml.isFile()) {
try (InputStream is = Files.newInputStream(pluginXml.toPath())) {
pluginDescriptor = parsePluginDescriptor(is, plugin, pluginXml.getAbsolutePath());
}
pluginDescriptor = parsePluginDescriptor(
() -> Files.newInputStream(pluginXml.toPath()), plugin, pluginXml.getAbsolutePath());
}
}
@ -259,7 +261,8 @@ public class DefaultMavenPluginManager implements MavenPluginManager {
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 {
try {
return builder.build(is, descriptorLocation);
@ -410,6 +413,7 @@ public class DefaultMavenPluginManager implements MavenPluginManager {
discoverPluginComponents(pluginRealm, plugin, pluginDescriptor);
pluginDescriptor.setDependencyNode(root);
pluginDescriptor.setClassRealm(pluginRealm);
pluginDescriptor.setArtifacts(pluginArtifacts);
}
@ -419,15 +423,40 @@ public class DefaultMavenPluginManager implements MavenPluginManager {
throws PluginContainerException {
try {
if (pluginDescriptor != null) {
for (ComponentDescriptor<?> componentDescriptor : pluginDescriptor.getComponents()) {
componentDescriptor.setRealm(pluginRealm);
container.addComponentDescriptor(componentDescriptor);
for (MojoDescriptor mojo : pluginDescriptor.getMojos()) {
if (!mojo.isV4Api()) {
mojo.setRealm(pluginRealm);
container.addComponentDescriptor(mojo);
}
}
}
((DefaultPlexusContainer) container)
.discoverComponents(
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 MojoExecutionScopeModule(container),
new PluginConfigurationModule(plugin.getDelegate()));
@ -584,11 +613,12 @@ public class DefaultMavenPluginManager implements MavenPluginManager {
}
ExpressionEvaluator expressionEvaluator;
InternalSession sessionV4 = InternalSession.from(session.getSession());
if (mojoDescriptor.isV4Api()) {
expressionEvaluator = new PluginParameterExpressionEvaluatorV4(
session.getSession(),
((DefaultSession) session.getSession()).getProject(session.getCurrentProject()),
mojoExecution);
sessionV4,
sessionV4.getProject(session.getCurrentProject()),
new DefaultMojoExecution(sessionV4, mojoExecution));
} else {
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.repository.ArtifactRepository;
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.Dependency;
import org.apache.maven.model.DependencyManagement;
@ -860,7 +860,7 @@ public class DefaultProjectBuilder implements ProjectBuilder {
modelBuildingRequest.setModelCache(modelCacheFactory.createCache(session));
}
modelBuildingRequest.setTransformerContextBuilder(transformerContextBuilder);
DefaultSession session = (DefaultSession) this.session.getData().get(DefaultSession.class);
InternalSession session = (InternalSession) this.session.getData().get(InternalSession.class);
if (session != null) {
try {
modelBuildingRequest.setRootDirectory(session.getRootDirectory());

View File

@ -110,31 +110,41 @@ public class SessionScope implements Scope {
return method.invoke(getScopeState().scope(key, unscoped).get(), args);
};
Class<T> superType = (Class<T>) key.getTypeLiteral().getRawType();
for (Annotation a : superType.getAnnotations()) {
Class<? extends Annotation> annotationType = a.annotationType();
if ("org.eclipse.sisu.Typed".equals(annotationType.getName())
|| "javax.enterprise.inject.Typed".equals(annotationType.getName())) {
try {
Class<?>[] value =
(Class<?>[]) annotationType.getMethod("value").invoke(a);
if (value.length == 0) {
value = superType.getInterfaces();
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()) {
Class<? extends Annotation> annotationType = a.annotationType();
if ("org.eclipse.sisu.Typed".equals(annotationType.getName())
|| "javax.enterprise.inject.Typed".equals(annotationType.getName())
|| "jakarta.enterprise.inject.Typed".equals(annotationType.getName())) {
try {
Class<?>[] value =
(Class<?>[]) annotationType.getMethod("value").invoke(a);
if (value.length == 0) {
value = superType.getInterfaces();
}
List<Class<?>> nonInterfaces =
Stream.of(value).filter(c -> !c.isInterface()).collect(Collectors.toList());
if (!nonInterfaces.isEmpty()) {
throw new IllegalArgumentException(
"The Typed annotation must contain only interfaces but the following types are not: "
+ nonInterfaces);
}
return value;
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
throw new IllegalStateException(e);
}
List<Class<?>> nonInterfaces =
Stream.of(value).filter(c -> !c.isInterface()).collect(Collectors.toList());
if (!nonInterfaces.isEmpty()) {
throw new IllegalArgumentException(
"The Typed annotation must contain only interfaces but the following types are not: "
+ nonInterfaces);
}
return (T) java.lang.reflect.Proxy.newProxyInstance(superType.getClassLoader(), value, dispatcher);
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
throw new IllegalStateException(e);
}
}
throw new IllegalArgumentException("The use of session scoped proxies require "
+ "a org.eclipse.sisu.Typed or javax.enterprise.inject.Typed annotation");
}
throw new IllegalArgumentException("The use of session scoped proxies require "
+ "a org.eclipse.sisu.Typed or javax.enterprise.inject.Typed annotation");
}
/**
@ -170,4 +180,10 @@ public class SessionScope implements Scope {
public static <T> Provider<T> seededKeyProvider() {
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.api.Session;
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.component.repository.exception.ComponentLookupException;
@ -52,10 +52,17 @@ public class SessionScopeModule extends AbstractModule {
@Override
protected void configure() {
bindScope(SessionScoped.class, scope);
bindScope(org.apache.maven.api.di.SessionScoped.class, scope);
bind(SessionScope.class).toInstance(scope);
bind(MavenSession.class).toProvider(SessionScope.seededKeyProvider()).in(scope);
bind(Session.class).toProvider(SessionScope.seededKeyProvider()).in(scope);
bind(DefaultSession.class).toProvider(SessionScope.seededKeyProvider()).in(scope);
bind(MavenSession.class)
.toProvider(SessionScope.seededKeyProvider(MavenSession.class))
.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.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
| 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();
DefaultMavenExecutionRequest mer = new DefaultMavenExecutionRequest();
DefaultMavenExecutionResult meres = new DefaultMavenExecutionResult();
MavenSession ms = new MavenSession(() -> rss, mer, meres);
MavenSession ms = new MavenSession(rss, mer, meres);
DefaultSession session = new DefaultSession(
ms,
repositorySystem,
@ -114,7 +114,7 @@ class TestApi {
.withRemoteRepositories(Collections.singletonList(remoteRepository));
sessionScope.enter();
sessionScope.seed(DefaultSession.class, (DefaultSession) this.session);
sessionScope.seed(InternalSession.class, InternalSession.from(this.session));
}
@Test

View File

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

View File

@ -24,17 +24,19 @@ import java.io.File;
import java.net.URI;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Properties;
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.artifact.Artifact;
import org.apache.maven.artifact.ArtifactUtils;
import org.apache.maven.artifact.DefaultArtifact;
import org.apache.maven.artifact.handler.DefaultArtifactHandler;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.bridge.MavenRepositorySystem;
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.MavenExecutionRequest;
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.DefaultSession;
import org.apache.maven.model.Build;
import org.apache.maven.model.Dependency;
import org.apache.maven.model.Model;
import org.apache.maven.model.building.DefaultModelBuildingRequest;
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.eclipse.aether.DefaultRepositorySystemSession;
import org.eclipse.aether.RepositorySystem;
import org.eclipse.aether.graph.DefaultDependencyNode;
import org.eclipse.aether.internal.impl.SimpleLocalRepositoryManagerFactory;
import org.eclipse.aether.repository.LocalRepository;
import org.eclipse.aether.repository.NoLocalRepositoryManagerException;
@ -82,6 +86,9 @@ import static org.mockito.Mockito.mock;
public class PluginParameterExpressionEvaluatorV4Test extends AbstractCoreMavenComponentTestCase {
private static final String FS = File.separator;
@Inject
PlexusContainer container;
@Inject
private MavenRepositorySystem factory;
@ -89,83 +96,74 @@ public class PluginParameterExpressionEvaluatorV4Test extends AbstractCoreMavenC
@Test
public void testPluginDescriptorExpressionReference() throws Exception {
MojoExecution exec = newMojoExecution();
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);
assertSame(
exec.getMojoDescriptor().getPluginDescriptor(),
exec.getPlugin().getDescriptor(),
result,
"${plugin} expression does not return plugin descriptor.");
"${mojo.plugin.descriptor} expression does not return plugin descriptor.");
}
@Test
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();
MojoExecution exec = newMojoExecution(session);
@SuppressWarnings("unchecked")
List<Artifact> depResults = (List<Artifact>)
new PluginParameterExpressionEvaluatorV4(session, null, exec).evaluate("${plugin.artifacts}");
Collection<Artifact> depResults = (Collection<Artifact>)
new PluginParameterExpressionEvaluatorV4(session, null, exec).evaluate("${mojo.plugin.dependencies}");
System.out.println("Result: " + depResults);
assertNotNull(depResults);
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
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();
MojoExecution exec = newMojoExecution(session);
@SuppressWarnings("unchecked")
Map<String, Artifact> depResults = (Map<String, Artifact>)
new PluginParameterExpressionEvaluatorV4(session, null, exec).evaluate("${plugin.artifactMap}");
Map<String, org.apache.maven.api.Dependency> depResults = (Map<String, org.apache.maven.api.Dependency>)
new PluginParameterExpressionEvaluatorV4(session, null, exec)
.evaluate("${mojo.plugin.dependenciesMap}");
System.out.println("Result: " + depResults);
assertNotNull(depResults);
assertEquals(1, depResults.size());
assertSame(
depArtifact,
depResults.get(ArtifactUtils.versionlessKey(depArtifact)),
assertTrue(depResults.containsKey("org.myco.plugins:my-plugin"));
assertEquals(
exec.getPlugin().getArtifact().key(),
depResults.get("org.myco.plugins:my-plugin").key(),
"dependency artifact is wrong.");
}
@Test
public void testPluginArtifactIdExpressionReference() throws Exception {
MojoExecution exec = newMojoExecution();
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);
assertSame(
exec.getMojoDescriptor().getPluginDescriptor().getArtifactId(),
exec.getPlugin().getArtifact().getArtifactId(),
result,
"${plugin.artifactId} expression does not return plugin descriptor's artifactId.");
}
@ -183,7 +181,7 @@ public class PluginParameterExpressionEvaluatorV4Test extends AbstractCoreMavenC
MavenProject project = new MavenProject(model);
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");
String actual = new File(value.toString()).getCanonicalPath();
@ -200,7 +198,7 @@ public class PluginParameterExpressionEvaluatorV4Test extends AbstractCoreMavenC
MavenProject project = new MavenProject(model);
ExpressionEvaluator ee = createExpressionEvaluator(project, null, new Properties());
ExpressionEvaluator ee = createExpressionEvaluator(project, new Properties());
Object value = ee.evaluate("$" + var);
@ -217,7 +215,7 @@ public class PluginParameterExpressionEvaluatorV4Test extends AbstractCoreMavenC
MavenProject project = new MavenProject(model);
ExpressionEvaluator ee = createExpressionEvaluator(project, null, new Properties());
ExpressionEvaluator ee = createExpressionEvaluator(project, new Properties());
Object value = ee.evaluate("$" + key);
@ -234,7 +232,7 @@ public class PluginParameterExpressionEvaluatorV4Test extends AbstractCoreMavenC
MavenProject project = new MavenProject(model);
ExpressionEvaluator ee = createExpressionEvaluator(project, null, new Properties());
ExpressionEvaluator ee = createExpressionEvaluator(project, new Properties());
Object value = ee.evaluate(key);
@ -247,7 +245,7 @@ public class PluginParameterExpressionEvaluatorV4Test extends AbstractCoreMavenC
MavenProject project = new MavenProject(new Model());
ExpressionEvaluator ee = createExpressionEvaluator(project, null, new Properties());
ExpressionEvaluator ee = createExpressionEvaluator(project, new Properties());
Object value = ee.evaluate(expr);
@ -267,22 +265,13 @@ public class PluginParameterExpressionEvaluatorV4Test extends AbstractCoreMavenC
MavenProject project = new MavenProject(model);
ExpressionEvaluator ee = createExpressionEvaluator(project, null, new Properties());
ExpressionEvaluator ee = createExpressionEvaluator(project, new Properties());
Object value = ee.evaluate("${" + key + "}");
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
public void testValueExtractionFromSystemPropertiesWithMissingProject() throws Exception {
String sysprop = "PPEET_sysprop1";
@ -293,7 +282,7 @@ public class PluginParameterExpressionEvaluatorV4Test extends AbstractCoreMavenC
executionProperties.setProperty(sysprop, "value");
}
ExpressionEvaluator ee = createExpressionEvaluator(null, null, executionProperties);
ExpressionEvaluator ee = createExpressionEvaluator(null, executionProperties);
Object value = ee.evaluate("${" + sysprop + "}");
@ -310,7 +299,7 @@ public class PluginParameterExpressionEvaluatorV4Test extends AbstractCoreMavenC
executionProperties.setProperty(sysprop, "value");
}
ExpressionEvaluator ee = createExpressionEvaluator(null, null, executionProperties);
ExpressionEvaluator ee = createExpressionEvaluator(null, executionProperties);
Object value = ee.evaluate("${" + sysprop + "}");
@ -335,15 +324,6 @@ public class PluginParameterExpressionEvaluatorV4Test extends AbstractCoreMavenC
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
public void testTwoExpressions() throws Exception {
Build build = new Build();
@ -353,8 +333,7 @@ public class PluginParameterExpressionEvaluatorV4Test extends AbstractCoreMavenC
Model model = new Model();
model.setBuild(build);
ExpressionEvaluator expressionEvaluator =
createExpressionEvaluator(new MavenProject(model), null, new Properties());
ExpressionEvaluator expressionEvaluator = createExpressionEvaluator(new MavenProject(model), new Properties());
Object value = expressionEvaluator.evaluate("${project.build.directory}" + FS + "${project.build.finalName}");
@ -363,37 +342,31 @@ public class PluginParameterExpressionEvaluatorV4Test extends AbstractCoreMavenC
@Test
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));
ExpressionEvaluator ee = createExpressionEvaluator(createDefaultProject(), pd, new Properties());
Object value = ee.evaluate("${plugin.artifacts}");
assertTrue(value instanceof List);
assertTrue(value instanceof Collection);
@SuppressWarnings("unchecked")
List<Artifact> artifacts = (List<Artifact>) value;
Collection<Artifact> artifacts = (Collection<Artifact>) value;
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
void testRootDirectoryNotPrefixed() throws Exception {
ExpressionEvaluator ee = createExpressionEvaluator(createDefaultProject(), null, new Properties());
ExpressionEvaluator ee = createExpressionEvaluator(createDefaultProject(), new Properties());
assertNull(ee.evaluate("${rootDirectory}"));
}
@Test
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}"));
e = assertInstanceOf(IntrospectionException.class, e.getCause());
e = assertInstanceOf(IllegalStateException.class, e.getCause());
@ -403,7 +376,7 @@ public class PluginParameterExpressionEvaluatorV4Test extends AbstractCoreMavenC
@Test
void testRootDirectory() throws Exception {
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}"));
}
@ -411,54 +384,59 @@ public class PluginParameterExpressionEvaluatorV4Test extends AbstractCoreMavenC
return new MavenProject(new Model());
}
private ExpressionEvaluator createExpressionEvaluator(
MavenProject project, PluginDescriptor pluginDescriptor, Properties executionProperties) throws Exception {
private ExpressionEvaluator createExpressionEvaluator(MavenProject project, Properties executionProperties)
throws Exception {
ArtifactRepository repo = getLocalRepository();
MutablePlexusContainer container = (MutablePlexusContainer) getContainer();
MavenSession mavenSession = createSession(container, repo, executionProperties);
mavenSession.setCurrentProject(project);
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();
mojo.setPluginDescriptor(pluginDescriptor);
mojo.setGoal("goal");
MojoExecution mojoExecution = new MojoExecution(mojo);
MojoExecution mojoExecution = newMojoExecution(session);
return new PluginParameterExpressionEvaluatorV4(
session, project != null ? new DefaultProject(session, project) : null, mojoExecution);
}
protected Artifact createArtifact(String groupId, String artifactId, String version) throws Exception {
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() {
private MojoExecution newMojoExecution(Session session) {
PluginDescriptor pd = new PluginDescriptor();
pd.setArtifactId("my-plugin");
pd.setGroupId("org.myco.plugins");
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();
md.setGoal("my-goal");
md.setPluginDescriptor(pd);
pd.addComponentDescriptor(md);
return new MojoExecution(md);
return new DefaultMojoExecution((AbstractSession) session, new org.apache.maven.plugin.MojoExecution(md));
}
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 {

View File

@ -23,8 +23,8 @@ import javax.inject.Named;
import javax.inject.Singleton;
import com.google.inject.OutOfScopeException;
import org.apache.maven.SessionScoped;
import org.apache.maven.api.Session;
import org.apache.maven.api.di.SessionScoped;
import org.apache.maven.session.scope.internal.SessionScope;
import org.codehaus.plexus.PlexusContainer;
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.List;
import java.util.Map;
import java.util.Optional;
import java.util.WeakHashMap;
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;
}

View File

@ -32,6 +32,10 @@ under the License.
<description>The API for plugins - Mojos - development.</description>
<dependencies>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-api-plugin</artifactId>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-model</artifactId>
@ -54,6 +58,10 @@ under the License.
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-classworlds</artifactId>
</dependency>
<dependency>
<groupId>org.apache.maven.resolver</groupId>
<artifactId>maven-resolver-api</artifactId>
</dependency>
</dependencies>
<build>
@ -63,44 +71,55 @@ under the License.
<artifactId>modello-maven-plugin</artifactId>
<configuration>
<velocityBasedir>${project.basedir}/../src/mdo</velocityBasedir>
<models>
<model>src/main/mdo/lifecycle.mdo</model>
</models>
<version>1.0.0</version>
</configuration>
<executions>
<execution>
<id>velocity</id>
<id>velocity-lifecycle</id>
<goals>
<goal>velocity</goal>
</goals>
<phase>generate-sources</phase>
<configuration>
<templates>
<template>model.vm</template>
<template>reader-stax.vm</template>
<template>writer-stax.vm</template>
</templates>
<params>
<param>packageModelV3=org.apache.maven.plugin.lifecycle</param>
<param>packageModelV4=org.apache.maven.plugin.lifecycle</param>
<param>packageModelV4=org.apache.maven.api.plugin.descriptor.lifecycle</param>
<param>packageToolV4=org.apache.maven.plugin.lifecycle.io</param>
</params>
<models>
<model>../api/maven-api-plugin/src/main/mdo/lifecycle.mdo</model>
</models>
<version>1.0.0</version>
</configuration>
</execution>
<execution>
<id>modello-site-docs2</id>
<id>velocity-plugin</id>
<goals>
<goal>xdoc</goal>
<goal>velocity</goal>
</goals>
<phase>pre-site</phase>
<phase>generate-sources</phase>
<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>
<model>src/main/mdo/plugin.mdo</model>
<model>../api/maven-api-plugin/src/main/mdo/plugin.mdo</model>
</models>
<version>1.1.0</version>
<version>2.0.0</version>
</configuration>
</execution>
<execution>
<id>modello-site-docs</id>
<phase>none</phase>
</execution>
</executions>
</plugin>
<plugin>
@ -110,32 +129,8 @@ under the License.
<parameter>
<excludes>
<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.Execution#getConfiguration():METHOD_RETURN_TYPE_CHANGED</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>
<exclude>org.apache.maven.plugin.lifecycle</exclude>
<exclude>org.apache.maven.plugin.descriptor.PluginDescriptor#getLifecycleMapping(java.lang.String)</exclude>
</excludes>
</parameter>
</configuration>

View File

@ -23,6 +23,7 @@ import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
import org.apache.maven.plugin.Mojo;
import org.codehaus.plexus.component.repository.ComponentDescriptor;
@ -146,6 +147,34 @@ public class MojoDescriptor extends ComponentDescriptor<Mojo> implements Cloneab
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);
}
}
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() {
return name;
}
@ -168,4 +187,19 @@ public class Parameter implements Cloneable {
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.URL;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
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.ArtifactUtils;
import org.apache.maven.model.Plugin;
import org.apache.maven.plugin.lifecycle.Lifecycle;
import org.apache.maven.plugin.lifecycle.LifecycleConfiguration;
import org.apache.maven.plugin.lifecycle.io.LifecycleMappingsStaxReader;
import org.apache.maven.plugin.lifecycle.io.LifecycleStaxReader;
import org.codehaus.plexus.classworlds.realm.ClassRealm;
import org.codehaus.plexus.component.repository.ComponentDescriptor;
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 DependencyNode dependencyNode;
private ClassRealm classRealm;
// 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"})
public List<MojoDescriptor> getMojos() {
return (List) getComponents();
@ -220,6 +287,14 @@ public class PluginDescriptor extends ComponentSetDescriptor implements Cloneabl
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
*
@ -326,11 +401,15 @@ public class PluginDescriptor extends ComponentSetDescriptor implements Cloneabl
}
public Lifecycle getLifecycleMapping(String lifecycleId) throws IOException, XMLStreamException {
return getLifecycleMappings().get(lifecycleId);
}
public Map<String, Lifecycle> getLifecycleMappings() throws IOException, XMLStreamException {
if (lifecycleMappings == null) {
LifecycleConfiguration lifecycleConfiguration;
try (InputStream input = getDescriptorStream(LIFECYCLE_DESCRIPTOR)) {
lifecycleConfiguration = new LifecycleMappingsStaxReader().read(input);
lifecycleConfiguration = new LifecycleStaxReader().read(input);
}
lifecycleMappings = new HashMap<>();
@ -339,8 +418,7 @@ public class PluginDescriptor extends ComponentSetDescriptor implements Cloneabl
lifecycleMappings.put(lifecycle.getId(), lifecycle);
}
}
return lifecycleMappings.get(lifecycleId);
return lifecycleMappings;
}
private InputStream getDescriptorStream(String descriptor) throws IOException {
@ -377,4 +455,33 @@ public class PluginDescriptor extends ComponentSetDescriptor implements Cloneabl
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.XMLStreamReader;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.util.ArrayList;
@ -28,8 +31,10 @@ import java.util.List;
import java.util.Optional;
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.XmlPlexusConfiguration;
import org.apache.maven.plugin.descriptor.io.PluginDescriptorStaxReader;
import org.codehaus.plexus.component.repository.ComponentDependency;
import org.codehaus.plexus.component.repository.ComponentRequirement;
import org.codehaus.plexus.configuration.PlexusConfiguration;
@ -38,16 +43,109 @@ import org.codehaus.plexus.configuration.PlexusConfigurationException;
/**
*/
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 {
return build(reader, null);
}
/**
* @deprecated use {@link #build(ReaderSupplier, String)}
*/
@Deprecated
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 {
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 {

View File

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

View File

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

View File

@ -224,7 +224,7 @@ public class ${className} {
serializer.writeStartElement(namespace, tagName);
#end
#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 ( $fieldCapName = $Helper.capitalise( $field.name ) )
#if ( $field.type == "String" )
@ -242,7 +242,8 @@ public class ${className} {
#end
#end
#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 )
#if ( ! $fieldTagName )
#set ( $fieldTagName = $field.name )