This is an automated email from the ASF dual-hosted git repository.
gnodet pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/maven-plugin-tools.git
The following commit(s) were added to refs/heads/master by this push:
new 010c9b2e [MPLUGIN-508] Upgrade to 4.0.0-beta-3 (#286)
010c9b2e is described below
commit 010c9b2efe5a4baa264e5b9750e0bfc471590398
Author: Guillaume Nodet <[email protected]>
AuthorDate: Thu Jun 13 08:35:10 2024 +0200
[MPLUGIN-508] Upgrade to 4.0.0-beta-3 (#286)
---
.github/workflows/maven-verify.yml | 5 +
.../src/it/v4api/invoker.properties | 1 +
.../java/org/apache/maven/its/v4api/FirstMojo.java | 29 +-
maven-plugin-plugin/src/it/v4api/verify.groovy | 53 +---
.../plugin/plugin/DescriptorGeneratorMojo.java | 157 +++++++++-
.../src/it/plugin-report-annotations/pom.xml | 6 -
.../maven/plugin/plugin/report/PluginReport.java | 2 +-
.../EnhancedPluginDescriptorBuilder.java | 1 -
.../plugin/descriptor/PluginDescriptorBuilder.java | 325 +++++++++++++++++++++
maven-plugin-tools-annotations/pom.xml | 4 -
.../datamodel/ExecuteAnnotationContent.java | 15 +
.../datamodel/MojoAnnotationContent.java | 21 +-
.../scanner/DefaultMojoAnnotationsScanner.java | 17 +-
.../annotations/ParametersWithGenericsMojo.java | 3 +
.../scanner/DefaultMojoAnnotationsScannerTest.java | 6 +
.../tools/plugin/ExtendedPluginDescriptor.java | 14 +-
maven-plugin-tools-generators/pom.xml | 16 +
.../generator/PluginDescriptorFilesGenerator.java | 87 ++++--
.../src/main/resources/help-class-source-v4.vm | 33 ++-
.../generator/AbstractGeneratorTestCase.java | 72 ++++-
.../PluginDescriptorFilesGeneratorTest.java | 47 +--
pom.xml | 17 +-
22 files changed, 781 insertions(+), 150 deletions(-)
diff --git a/.github/workflows/maven-verify.yml
b/.github/workflows/maven-verify.yml
index 932827cf..89d9cfdb 100644
--- a/.github/workflows/maven-verify.yml
+++ b/.github/workflows/maven-verify.yml
@@ -25,3 +25,8 @@ jobs:
build:
name: Verify
uses: apache/maven-gh-actions-shared/.github/workflows/maven-verify.yml@v4
+ with:
+ maven-matrix: '[ "3.6.3", "3.9.7", "4.0.0-beta-3" ]'
+ jdk-matrix: '[ "8", "17", "21" ]'
+ matrix-exclude: '[ { maven: "4.0.0-beta-3", jdk: "8" } ]'
+
diff --git a/maven-plugin-plugin/src/it/v4api/invoker.properties
b/maven-plugin-plugin/src/it/v4api/invoker.properties
index 43be5b1d..e1b69341 100644
--- a/maven-plugin-plugin/src/it/v4api/invoker.properties
+++ b/maven-plugin-plugin/src/it/v4api/invoker.properties
@@ -15,4 +15,5 @@
# specific language governing permissions and limitations
# under the License.
+invoker.java.version = 17+
invoker.goals.1 = clean install
diff --git
a/maven-plugin-plugin/src/it/v4api/src/main/java/org/apache/maven/its/v4api/FirstMojo.java
b/maven-plugin-plugin/src/it/v4api/src/main/java/org/apache/maven/its/v4api/FirstMojo.java
index 879f3cef..abab3cee 100644
---
a/maven-plugin-plugin/src/it/v4api/src/main/java/org/apache/maven/its/v4api/FirstMojo.java
+++
b/maven-plugin-plugin/src/it/v4api/src/main/java/org/apache/maven/its/v4api/FirstMojo.java
@@ -22,13 +22,12 @@ import java.nio.file.Path;
import org.apache.maven.api.MojoExecution;
import org.apache.maven.api.Project;
-import org.apache.maven.api.ResolutionScope;
import org.apache.maven.api.Session;
+import org.apache.maven.api.di.Inject;
+import org.apache.maven.api.di.Named;
import org.apache.maven.api.plugin.Log;
import org.apache.maven.api.plugin.MojoException;
-import org.apache.maven.api.plugin.annotations.Component;
import org.apache.maven.api.plugin.annotations.Execute;
-import org.apache.maven.api.plugin.annotations.LifecyclePhase;
import org.apache.maven.api.plugin.annotations.Mojo;
import org.apache.maven.api.plugin.annotations.Parameter;
import org.apache.maven.api.services.ArtifactInstaller;
@@ -38,15 +37,12 @@ import org.apache.maven.api.settings.Settings;
* Test mojo for the v4 api plugin descriptor generation.
* This mojo is not actually runnable because:
* - it's using a custom lifecycle which is not defined
- * - it has a @Component dependency on ArtifactInstaller (hint=test) which
does not exist
+ * - it has a @Inject dependency on ArtifactInstaller (hint=test) which does
not exist
*
* @since 1.2
*/
-@Mojo(
- name = "first",
- requiresDependencyResolution = ResolutionScope.TEST,
- defaultPhase = LifecyclePhase.INTEGRATION_TEST)
-@Execute(phase = LifecyclePhase.GENERATE_SOURCES, lifecycle = "cobertura")
+@Mojo(name = "first", defaultPhase = "integration-test")
+@Execute(phase = "generate-sources", lifecycle = "cobertura")
public class FirstMojo implements org.apache.maven.api.plugin.Mojo {
/**
@@ -66,23 +62,24 @@ public class FirstMojo implements
org.apache.maven.api.plugin.Mojo {
@Parameter(name = "namedParam", alias = "alias")
private String aliasedParam;
- @Component
+ @Inject
private Session session;
- @Component
+ @Inject
private Project project;
- @Component
+ @Inject
private MojoExecution mojo;
- @Component
+ @Inject
private Settings settings;
- @Component
+ @Inject
private Log log;
- @Component(role = ArtifactInstaller.class, hint = "test")
- private Object custom;
+ @Inject
+ @Named("test")
+ private ArtifactInstaller custom;
public void execute() throws MojoException {}
}
diff --git a/maven-plugin-plugin/src/it/v4api/verify.groovy
b/maven-plugin-plugin/src/it/v4api/verify.groovy
index 1405e231..878ab95a 100644
--- a/maven-plugin-plugin/src/it/v4api/verify.groovy
+++ b/maven-plugin-plugin/src/it/v4api/verify.groovy
@@ -24,8 +24,8 @@ assert descriptorFile.isFile()
def pluginDescriptor = new XmlParser().parse( descriptorFile );
-assert pluginDescriptor.requiredJavaVersion.text() == '1.8'
-assert pluginDescriptor.requiredMavenVersion.text() == '4.0.0-alpha-4'
+assert pluginDescriptor.requiredJavaVersion.text() == '17'
+assert pluginDescriptor.requiredMavenVersion.text() == '4.0.0-beta-3'
def mojo = pluginDescriptor.mojos.mojo.findAll{ it.goal.text() == "first" }[0]
@@ -33,51 +33,12 @@ assert mojo.goal.text() == 'first'
assert mojo.implementation.text() == 'org.apache.maven.its.v4api.FirstMojo'
assert mojo.language.text() == 'java'
assert mojo.description.text().startsWith('Test mojo for the v4 api plugin
descriptor generation.')
-assert mojo.requiresDependencyResolution.text() == 'test'
-assert mojo.requiresDependencyCollection.text() == ''
-assert mojo.requiresProject.text() == 'true'
-assert mojo.requiresOnline.text() == 'false'
-assert mojo.requiresDirectInvocation.text() == 'false'
+assert mojo.projectRequired.text() == 'true'
+assert mojo.onlineRequired.text() == 'false'
assert mojo.aggregator.text() == 'false'
-assert mojo.threadSafe.text() == 'false'
assert mojo.phase.text() == 'integration-test'
assert mojo.executePhase.text() == 'generate-sources'
assert mojo.executeLifecycle.text() == 'cobertura'
-assert mojo.v4Api.text() == 'true'
-
-assert mojo.configuration.basedir[0].text() == ''
-assert mojo.configuration.basedir[0].'@implementation' == 'java.nio.file.Path'
-assert mojo.configuration.basedir[0].'@default-value' == '${basedir}'
-
-assert mojo.configuration.touchFile[0].text() == '${first.touchFile}'
-assert mojo.configuration.touchFile[0].'@implementation' ==
'java.nio.file.Path'
-assert mojo.configuration.touchFile[0].'@default-value' ==
'${project.build.directory}/touch.txt'
-
-assert mojo.requirements.requirement.size() == 6
-
-assert mojo.requirements.requirement[0].role.text() ==
'org.apache.maven.api.services.ArtifactInstaller'
-assert mojo.requirements.requirement[0].'role-hint'.text() == 'test'
-assert mojo.requirements.requirement[0].'field-name'.text() == 'custom'
-
-assert mojo.requirements.requirement[1].role.text() ==
'org.apache.maven.api.plugin.Log'
-assert mojo.requirements.requirement[1].'role-hint'.isEmpty()
-assert mojo.requirements.requirement[1].'field-name'.text() == 'log'
-
-assert mojo.requirements.requirement[2].role.text() ==
'org.apache.maven.api.MojoExecution'
-assert mojo.requirements.requirement[2].'role-hint'.isEmpty()
-assert mojo.requirements.requirement[2].'field-name'.text() == 'mojo'
-
-assert mojo.requirements.requirement[3].role.text() ==
'org.apache.maven.api.Project'
-assert mojo.requirements.requirement[3].'role-hint'.isEmpty()
-assert mojo.requirements.requirement[3].'field-name'.text() == 'project'
-
-assert mojo.requirements.requirement[4].role.text() ==
'org.apache.maven.api.Session'
-assert mojo.requirements.requirement[4].'role-hint'.isEmpty()
-assert mojo.requirements.requirement[4].'field-name'.text() == 'session'
-
-assert mojo.requirements.requirement[5].role.text() ==
'org.apache.maven.api.settings.Settings'
-assert mojo.requirements.requirement[5].'role-hint'.isEmpty()
-assert mojo.requirements.requirement[5].'field-name'.text() == 'settings'
assert mojo.parameters.parameter.size() == 3
@@ -90,6 +51,8 @@ assert parameter.deprecated.isEmpty()
assert parameter.required.text() == 'false'
assert parameter.editable.text() == 'false'
assert parameter.description.text() == 'Project directory.'
+assert parameter.defaultValue.text() == '${basedir}'
+assert parameter.expression.isEmpty()
parameter = mojo.parameters.parameter.findAll{ it.name.text() == "touchFile"
}[0]
assert parameter.name.text() == 'touchFile'
@@ -100,6 +63,8 @@ assert parameter.deprecated.isEmpty()
assert parameter.required.text() == 'true'
assert parameter.editable.text() == 'true'
assert parameter.description.text() == ''
+assert parameter.defaultValue.text() == '${project.build.directory}/touch.txt'
+assert parameter.expression.text() == '${first.touchFile}'
parameter = mojo.parameters.parameter.findAll{ it.name.text() == "namedParam"
}[0]
assert parameter.name.text() == 'namedParam'
@@ -110,6 +75,8 @@ assert parameter.deprecated.text() == 'As of 0.2'
assert parameter.required.text() == 'false'
assert parameter.editable.text() == 'true'
assert parameter.description.text() == ''
+assert parameter.defaultValue.isEmpty()
+assert parameter.expression.isEmpty()
// check help mojo source and class
assert new File( basedir,
"target/classes/org/apache/maven/its/v4api/HelpMojo.class" ).isFile()
diff --git
a/maven-plugin-plugin/src/main/java/org/apache/maven/plugin/plugin/DescriptorGeneratorMojo.java
b/maven-plugin-plugin/src/main/java/org/apache/maven/plugin/plugin/DescriptorGeneratorMojo.java
index 862edeae..73a0e561 100644
---
a/maven-plugin-plugin/src/main/java/org/apache/maven/plugin/plugin/DescriptorGeneratorMojo.java
+++
b/maven-plugin-plugin/src/main/java/org/apache/maven/plugin/plugin/DescriptorGeneratorMojo.java
@@ -19,12 +19,16 @@
package org.apache.maven.plugin.plugin;
import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
import java.net.URI;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Set;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.*;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
@@ -32,6 +36,7 @@ import
org.apache.maven.artifact.resolver.filter.IncludesArtifactFilter;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException;
+import org.apache.maven.plugin.descriptor.MojoDescriptor;
import org.apache.maven.plugin.descriptor.PluginDescriptor;
import org.apache.maven.plugins.annotations.Component;
import org.apache.maven.plugins.annotations.LifecyclePhase;
@@ -39,6 +44,7 @@ import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.plugins.annotations.ResolutionScope;
import org.apache.maven.tools.plugin.DefaultPluginToolsRequest;
+import org.apache.maven.tools.plugin.ExtendedMojoDescriptor;
import org.apache.maven.tools.plugin.ExtendedPluginDescriptor;
import org.apache.maven.tools.plugin.PluginToolsRequest;
import org.apache.maven.tools.plugin.extractor.ExtractionException;
@@ -48,8 +54,14 @@ import
org.apache.maven.tools.plugin.generator.PluginDescriptorFilesGenerator;
import org.apache.maven.tools.plugin.scanner.MojoScanner;
import org.codehaus.plexus.component.repository.ComponentDependency;
import org.codehaus.plexus.util.ReaderFactory;
+import org.codehaus.plexus.util.io.CachingOutputStream;
+import org.codehaus.plexus.util.io.CachingWriter;
+import org.objectweb.asm.*;
import org.sonatype.plexus.build.incremental.BuildContext;
+import static org.objectweb.asm.Opcodes.*;
+import static org.objectweb.asm.Opcodes.ACC_PUBLIC;
+
/**
* <p>
* Generate a plugin descriptor.
@@ -78,6 +90,12 @@ public class DescriptorGeneratorMojo extends
AbstractGeneratorMojo {
@Parameter(defaultValue =
"${project.build.outputDirectory}/META-INF/maven", readonly = true)
private File outputDirectory;
+ /**
+ * The directory where the generated class files will be put.
+ */
+ @Parameter(defaultValue = "${project.build.outputDirectory}", readonly =
true)
+ private File classesOutputDirectory;
+
/**
* The file encoding of the source files.
*
@@ -269,7 +287,6 @@ public class DescriptorGeneratorMojo extends
AbstractGeneratorMojo {
protected BuildContext buildContext;
public void generate() throws MojoExecutionException {
-
if (!"maven-plugin".equalsIgnoreCase(project.getArtifactId())
&& project.getArtifactId().toLowerCase().startsWith("maven-")
&& project.getArtifactId().toLowerCase().endsWith("-plugin")
@@ -352,6 +369,12 @@ public class DescriptorGeneratorMojo extends
AbstractGeneratorMojo {
PluginDescriptorFilesGenerator pluginDescriptorGenerator = new
PluginDescriptorFilesGenerator();
pluginDescriptorGenerator.execute(outputDirectory, request);
+ // Generate the additional factories for v4 mojos
+ generateFactories(request.getPluginDescriptor());
+
+ // Generate index for v4 beans
+ generateIndex();
+
buildContext.refresh(outputDirectory);
} catch (GeneratorException e) {
throw new MojoExecutionException("Error writing plugin
descriptor", e);
@@ -367,6 +390,128 @@ public class DescriptorGeneratorMojo extends
AbstractGeneratorMojo {
}
}
+ private void generateIndex() throws GeneratorException {
+ try {
+ Set<String> diBeans = new TreeSet<>();
+ try (Stream<Path> paths =
Files.walk(classesOutputDirectory.toPath())) {
+ List<Path> classes = paths.filter(
+ p ->
p.getFileName().toString().endsWith(".class"))
+ .collect(Collectors.toList());
+ for (Path classFile : classes) {
+ String fileString = classFile.toString();
+ String className = fileString
+ .substring(0, fileString.length() -
".class".length())
+ .replace('/', '.');
+ try (InputStream is = Files.newInputStream(classFile)) {
+ ClassReader rdr = new ClassReader(is);
+ rdr.accept(
+ new ClassVisitor(Opcodes.ASM9) {
+ String className;
+
+ @Override
+ public void visit(
+ int version,
+ int access,
+ String name,
+ String signature,
+ String superName,
+ String[] interfaces) {
+ super.visit(version, access, name,
signature, superName, interfaces);
+ className = name;
+ }
+
+ @Override
+ public AnnotationVisitor
visitAnnotation(String descriptor, boolean visible) {
+ if
("Lorg/apache/maven/api/di/Named;".equals(descriptor)) {
+ diBeans.add(className.replace('/',
'.'));
+ }
+ return null;
+ }
+ },
+ ClassReader.SKIP_FRAMES |
ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG);
+ }
+
+ // Class<?> clazz =
project.getClassRealm().loadClass(className);
+ // boolean hasQualifier =
Stream.of(clazz.getAnnotations())
+ // .flatMap(ann ->
Stream.of(ann.getClass().getAnnotations()))
+ // .anyMatch(ann ->
"org.apache.maven.api.di.Qualifier"
+ //
.equals(ann.annotationType().getName()));
+ // if (hasQualifier) {
+ // diBeans.add(className);
+ // }
+ }
+ }
+ Path path =
outputDirectory.toPath().resolve("org.apache.maven.api.di.Inject");
+ if (diBeans.isEmpty()) {
+ Files.deleteIfExists(path);
+ } else {
+ String nl = System.lineSeparator();
+ try (CachingWriter w = new CachingWriter(path,
StandardCharsets.UTF_8)) {
+ String content =
diBeans.stream().collect(Collectors.joining(nl, "", nl));
+ w.write(content);
+ }
+ }
+ } catch (Exception e) {
+ throw new GeneratorException("Unable to generate index for v4
beans", e);
+ }
+ }
+
+ private void generateFactories(PluginDescriptor pd) throws
GeneratorException {
+ try {
+ for (MojoDescriptor md : pd.getMojos()) {
+ if (md instanceof ExtendedMojoDescriptor &&
((ExtendedMojoDescriptor) md).isV4Api()) {
+ generateFactory(md);
+ }
+ }
+ } catch (IOException e) {
+ throw new GeneratorException("Unable to generate factories for v4
mojos", e);
+ }
+ }
+
+ private void generateFactory(MojoDescriptor md) throws IOException {
+ String mojoClassName = md.getImplementation();
+ String packageName = mojoClassName.substring(0,
mojoClassName.lastIndexOf('.'));
+ String generatorClassName =
mojoClassName.substring(mojoClassName.lastIndexOf('.') + 1) + "Factory";
+ String mojoName = md.getId();
+
+ getLog().debug("Generating v4 factory for " + mojoClassName);
+
+ byte[] bin = computeGeneratorClassBytes(packageName,
generatorClassName, mojoName, mojoClassName);
+
+ try (OutputStream os = new CachingOutputStream(classesOutputDirectory
+ .toPath()
+ .resolve(packageName.replace('.', '/') + "/" +
generatorClassName + ".class"))) {
+ os.write(bin);
+ }
+ }
+
+ static byte[] computeGeneratorClassBytes(
+ String packageName, String generatorClassName, String mojoName,
String mojoClassName) {
+ String mojo = mojoClassName.replace('.', '/');
+ ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES |
ClassWriter.COMPUTE_MAXS);
+ cw.visitSource(generatorClassName + ".java", null);
+ AnnotationVisitor av =
cw.visitAnnotation("Lorg/apache/maven/api/di/Named;", true);
+ av.visit("value", mojoName);
+ av.visitEnd();
+ cw.visitAnnotation("Lorg/apache/maven/api/annotations/Generated;",
true).visitEnd();
+ cw.visit(
+ V1_8,
+ ACC_PUBLIC + ACC_SUPER + ACC_SYNTHETIC,
+ packageName.replace(".", "/") + "/" + generatorClassName,
+ null,
+ mojo,
+ null);
+ MethodVisitor mv = cw.visitMethod(ACC_PUBLIC + ACC_SYNTHETIC,
"<init>", "()V", null, null);
+ mv.visitCode();
+ mv.visitVarInsn(Opcodes.ALOAD, 0);
+ mv.visitMethodInsn(Opcodes.INVOKESPECIAL, mojo, "<init>", "()V",
false);
+ mv.visitInsn(Opcodes.RETURN);
+ mv.visitMaxs(-1, -1);
+ mv.visitEnd();
+ cw.visitEnd();
+ return cw.toByteArray();
+ }
+
private PluginDescriptor extendPluginDescriptor(PluginToolsRequest
request) {
ExtendedPluginDescriptor extendedPluginDescriptor = new
ExtendedPluginDescriptor(request.getPluginDescriptor());
extendedPluginDescriptor.setRequiredJavaVersion(getRequiredJavaVersion(request));
diff --git
a/maven-plugin-report-plugin/src/it/plugin-report-annotations/pom.xml
b/maven-plugin-report-plugin/src/it/plugin-report-annotations/pom.xml
index 1f355686..3522d6ab 100644
--- a/maven-plugin-report-plugin/src/it/plugin-report-annotations/pom.xml
+++ b/maven-plugin-report-plugin/src/it/plugin-report-annotations/pom.xml
@@ -55,12 +55,6 @@ under the License.
<version>@maven3Version@</version>
<scope>provided</scope>
</dependency>
- <dependency>
- <groupId>org.apache.maven.plugin-tools</groupId>
- <artifactId>maven-plugin-annotations</artifactId>
- <version>@project.version@</version>
- <scope>provided</scope>
- </dependency>
<dependency>
<groupId>org.apache.maven.reporting</groupId>
<artifactId>maven-reporting-api</artifactId>
diff --git
a/maven-plugin-report-plugin/src/main/java/org/apache/maven/plugin/plugin/report/PluginReport.java
b/maven-plugin-report-plugin/src/main/java/org/apache/maven/plugin/plugin/report/PluginReport.java
index 5979fe70..6c747f4e 100644
---
a/maven-plugin-report-plugin/src/main/java/org/apache/maven/plugin/plugin/report/PluginReport.java
+++
b/maven-plugin-report-plugin/src/main/java/org/apache/maven/plugin/plugin/report/PluginReport.java
@@ -35,13 +35,13 @@ import org.apache.maven.execution.MavenSession;
import org.apache.maven.model.building.ModelBuildingRequest;
import org.apache.maven.plugin.descriptor.MojoDescriptor;
import org.apache.maven.plugin.descriptor.PluginDescriptor;
-import org.apache.maven.plugin.descriptor.PluginDescriptorBuilder;
import org.apache.maven.plugins.annotations.Component;
import org.apache.maven.plugins.annotations.Execute;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import
org.apache.maven.plugins.plugin.descriptor.EnhancedPluginDescriptorBuilder;
+import org.apache.maven.plugins.plugin.descriptor.PluginDescriptorBuilder;
import org.apache.maven.project.DefaultProjectBuildingRequest;
import org.apache.maven.project.MavenProject;
import org.apache.maven.project.ProjectBuilder;
diff --git
a/maven-plugin-report-plugin/src/main/java/org/apache/maven/plugins/plugin/descriptor/EnhancedPluginDescriptorBuilder.java
b/maven-plugin-report-plugin/src/main/java/org/apache/maven/plugins/plugin/descriptor/EnhancedPluginDescriptorBuilder.java
index 2f29303a..7c15b1b6 100644
---
a/maven-plugin-report-plugin/src/main/java/org/apache/maven/plugins/plugin/descriptor/EnhancedPluginDescriptorBuilder.java
+++
b/maven-plugin-report-plugin/src/main/java/org/apache/maven/plugins/plugin/descriptor/EnhancedPluginDescriptorBuilder.java
@@ -30,7 +30,6 @@ import java.util.Optional;
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.descriptor.PluginDescriptorBuilder;
import org.apache.maven.plugin.plugin.report.PluginReport;
import org.apache.maven.rtinfo.RuntimeInformation;
import org.apache.maven.tools.plugin.EnhancedParameterWrapper;
diff --git
a/maven-plugin-report-plugin/src/main/java/org/apache/maven/plugins/plugin/descriptor/PluginDescriptorBuilder.java
b/maven-plugin-report-plugin/src/main/java/org/apache/maven/plugins/plugin/descriptor/PluginDescriptorBuilder.java
new file mode 100644
index 00000000..037fdf6f
--- /dev/null
+++
b/maven-plugin-report-plugin/src/main/java/org/apache/maven/plugins/plugin/descriptor/PluginDescriptorBuilder.java
@@ -0,0 +1,325 @@
+/*
+ * 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.plugins.plugin.descriptor;
+
+import java.io.IOException;
+import java.io.Reader;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.maven.plugin.descriptor.MojoDescriptor;
+import org.apache.maven.plugin.descriptor.Parameter;
+import org.apache.maven.plugin.descriptor.PluginDescriptor;
+import org.codehaus.plexus.component.repository.ComponentDependency;
+import org.codehaus.plexus.component.repository.ComponentRequirement;
+import org.codehaus.plexus.configuration.PlexusConfiguration;
+import org.codehaus.plexus.configuration.PlexusConfigurationException;
+import org.codehaus.plexus.configuration.xml.XmlPlexusConfiguration;
+import org.codehaus.plexus.util.xml.Xpp3DomBuilder;
+import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
+
+/**
+ * Build plugin descriptor object from {@code plugin.xml}.
+ *
+ * @author Jason van Zyl
+ */
+public class PluginDescriptorBuilder {
+ public PluginDescriptor build(Reader reader) throws
PlexusConfigurationException {
+ return build(reader, null);
+ }
+
+ public PluginDescriptor build(Reader reader, String source) throws
PlexusConfigurationException {
+ PlexusConfiguration c = buildConfiguration(reader);
+
+ PluginDescriptor pluginDescriptor = new PluginDescriptor();
+
+ pluginDescriptor.setSource(source);
+ pluginDescriptor.setGroupId(c.getChild("groupId").getValue());
+ pluginDescriptor.setArtifactId(c.getChild("artifactId").getValue());
+ pluginDescriptor.setVersion(c.getChild("version").getValue());
+ pluginDescriptor.setGoalPrefix(c.getChild("goalPrefix").getValue());
+
+ pluginDescriptor.setName(c.getChild("name").getValue());
+ pluginDescriptor.setDescription(c.getChild("description").getValue());
+
+ String isolatedRealm = c.getChild("isolatedRealm").getValue();
+
+ if (isolatedRealm != null) {
+
pluginDescriptor.setIsolatedRealm(Boolean.parseBoolean(isolatedRealm));
+ }
+
+ String inheritedByDefault =
c.getChild("inheritedByDefault").getValue();
+
+ if (inheritedByDefault != null) {
+
pluginDescriptor.setInheritedByDefault(Boolean.parseBoolean(inheritedByDefault));
+ }
+
+ //
----------------------------------------------------------------------
+ // Components
+ //
----------------------------------------------------------------------
+
+ PlexusConfiguration[] mojoConfigurations =
c.getChild("mojos").getChildren("mojo");
+
+ for (PlexusConfiguration component : mojoConfigurations) {
+ MojoDescriptor mojoDescriptor =
buildComponentDescriptor(component, pluginDescriptor);
+
+ pluginDescriptor.addMojo(mojoDescriptor);
+ }
+
+ //
----------------------------------------------------------------------
+ // Dependencies
+ //
----------------------------------------------------------------------
+
+ PlexusConfiguration[] dependencyConfigurations =
+ c.getChild("dependencies").getChildren("dependency");
+
+ List<ComponentDependency> dependencies = new ArrayList<>();
+
+ for (PlexusConfiguration d : dependencyConfigurations) {
+ ComponentDependency cd = new ComponentDependency();
+
+ cd.setArtifactId(d.getChild("artifactId").getValue());
+
+ cd.setGroupId(d.getChild("groupId").getValue());
+
+ cd.setType(d.getChild("type").getValue());
+
+ cd.setVersion(d.getChild("version").getValue());
+
+ dependencies.add(cd);
+ }
+
+ pluginDescriptor.setDependencies(dependencies);
+
+ return pluginDescriptor;
+ }
+
+ @SuppressWarnings("checkstyle:methodlength")
+ public MojoDescriptor buildComponentDescriptor(PlexusConfiguration c,
PluginDescriptor pluginDescriptor)
+ throws PlexusConfigurationException {
+ MojoDescriptor mojo = new MojoDescriptor();
+ mojo.setPluginDescriptor(pluginDescriptor);
+
+ mojo.setGoal(c.getChild("goal").getValue());
+
+ mojo.setImplementation(c.getChild("implementation").getValue());
+
+ PlexusConfiguration langConfig = c.getChild("language");
+
+ if (langConfig != null) {
+ mojo.setLanguage(langConfig.getValue());
+ }
+
+ PlexusConfiguration configuratorConfig = c.getChild("configurator");
+
+ if (configuratorConfig != null) {
+ mojo.setComponentConfigurator(configuratorConfig.getValue());
+ }
+
+ PlexusConfiguration composerConfig = c.getChild("composer");
+
+ if (composerConfig != null) {
+ mojo.setComponentComposer(composerConfig.getValue());
+ }
+
+ String since = c.getChild("since").getValue();
+
+ if (since != null) {
+ mojo.setSince(since);
+ }
+
+ PlexusConfiguration deprecated = c.getChild("deprecated", false);
+
+ if (deprecated != null) {
+ mojo.setDeprecated(deprecated.getValue());
+ }
+
+ String phase = c.getChild("phase").getValue();
+
+ if (phase != null) {
+ mojo.setPhase(phase);
+ }
+
+ String executePhase = c.getChild("executePhase").getValue();
+
+ if (executePhase != null) {
+ mojo.setExecutePhase(executePhase);
+ }
+
+ String executeMojo = c.getChild("executeGoal").getValue();
+
+ if (executeMojo != null) {
+ mojo.setExecuteGoal(executeMojo);
+ }
+
+ String executeLifecycle = c.getChild("executeLifecycle").getValue();
+
+ if (executeLifecycle != null) {
+ mojo.setExecuteLifecycle(executeLifecycle);
+ }
+
+
mojo.setInstantiationStrategy(c.getChild("instantiationStrategy").getValue());
+
+ mojo.setDescription(c.getChild("description").getValue());
+
+ PlexusConfiguration dependencyResolution =
c.getChild("requiresDependencyResolution", false);
+
+ if (dependencyResolution != null) {
+
mojo.setDependencyResolutionRequired(dependencyResolution.getValue());
+ }
+
+ PlexusConfiguration dependencyCollection =
c.getChild("requiresDependencyCollection", false);
+
+ if (dependencyCollection != null) {
+
mojo.setDependencyCollectionRequired(dependencyCollection.getValue());
+ }
+
+ String directInvocationOnly =
c.getChild("requiresDirectInvocation").getValue();
+
+ if (directInvocationOnly != null) {
+
mojo.setDirectInvocationOnly(Boolean.parseBoolean(directInvocationOnly));
+ }
+
+ String requiresProject = c.getChild("requiresProject").getValue();
+
+ if (requiresProject != null) {
+ mojo.setProjectRequired(Boolean.parseBoolean(requiresProject));
+ }
+
+ String requiresReports = c.getChild("requiresReports").getValue();
+
+ if (requiresReports != null) {
+ mojo.setRequiresReports(Boolean.parseBoolean(requiresReports));
+ }
+
+ String aggregator = c.getChild("aggregator").getValue();
+
+ if (aggregator != null) {
+ mojo.setAggregator(Boolean.parseBoolean(aggregator));
+ }
+
+ String requiresOnline = c.getChild("requiresOnline").getValue();
+
+ if (requiresOnline != null) {
+ mojo.setOnlineRequired(Boolean.parseBoolean(requiresOnline));
+ }
+
+ String inheritedByDefault =
c.getChild("inheritedByDefault").getValue();
+
+ if (inheritedByDefault != null) {
+
mojo.setInheritedByDefault(Boolean.parseBoolean(inheritedByDefault));
+ }
+
+ String threadSafe = c.getChild("threadSafe").getValue();
+
+ if (threadSafe != null) {
+ mojo.setThreadSafe(Boolean.parseBoolean(threadSafe));
+ }
+
+ //
----------------------------------------------------------------------
+ // Configuration
+ //
----------------------------------------------------------------------
+
+ PlexusConfiguration mojoConfig = c.getChild("configuration");
+ mojo.setMojoConfiguration(mojoConfig);
+
+ //
----------------------------------------------------------------------
+ // Parameters
+ //
----------------------------------------------------------------------
+
+ PlexusConfiguration[] parameterConfigurations =
c.getChild("parameters").getChildren("parameter");
+
+ List<Parameter> parameters = new ArrayList<>();
+
+ for (PlexusConfiguration d : parameterConfigurations) {
+ Parameter parameter = new Parameter();
+
+ parameter.setName(d.getChild("name").getValue());
+
+ parameter.setAlias(d.getChild("alias").getValue());
+
+ parameter.setType(d.getChild("type").getValue());
+
+ String required = d.getChild("required").getValue();
+
+ parameter.setRequired(Boolean.parseBoolean(required));
+
+ PlexusConfiguration editableConfig = d.getChild("editable");
+
+ // we need the null check for pre-build legacy plugins...
+ if (editableConfig != null) {
+ String editable = d.getChild("editable").getValue();
+
+ parameter.setEditable(editable == null ||
Boolean.parseBoolean(editable));
+ }
+
+ parameter.setDescription(d.getChild("description").getValue());
+
+ parameter.setDeprecated(d.getChild("deprecated").getValue());
+
+
parameter.setImplementation(d.getChild("implementation").getValue());
+
+ parameter.setSince(d.getChild("since").getValue());
+
+ PlexusConfiguration paramConfig =
mojoConfig.getChild(parameter.getName(), false);
+ if (paramConfig != null) {
+ parameter.setExpression(paramConfig.getValue(null));
+
parameter.setDefaultValue(paramConfig.getAttribute("default-value"));
+ }
+
+ parameters.add(parameter);
+ }
+
+ mojo.setParameters(parameters);
+
+ // TODO this should not need to be handed off...
+
+ //
----------------------------------------------------------------------
+ // Requirements
+ //
----------------------------------------------------------------------
+
+ PlexusConfiguration[] requirements =
c.getChild("requirements").getChildren("requirement");
+
+ for (PlexusConfiguration requirement : requirements) {
+ ComponentRequirement cr = new ComponentRequirement();
+
+ cr.setRole(requirement.getChild("role").getValue());
+
+ cr.setRoleHint(requirement.getChild("role-hint").getValue());
+
+ cr.setFieldName(requirement.getChild("field-name").getValue());
+
+ mojo.addRequirement(cr);
+ }
+
+ return mojo;
+ }
+
+ // ----------------------------------------------------------------------
+ //
+ // ----------------------------------------------------------------------
+
+ public PlexusConfiguration buildConfiguration(Reader configuration) throws
PlexusConfigurationException {
+ try {
+ return new
XmlPlexusConfiguration(Xpp3DomBuilder.build(configuration));
+ } catch (IOException | XmlPullParserException e) {
+ throw new PlexusConfigurationException(e.getMessage(), e);
+ }
+ }
+}
diff --git a/maven-plugin-tools-annotations/pom.xml
b/maven-plugin-tools-annotations/pom.xml
index 732fdbe6..bff4e926 100644
--- a/maven-plugin-tools-annotations/pom.xml
+++ b/maven-plugin-tools-annotations/pom.xml
@@ -36,10 +36,6 @@
<groupId>org.apache.maven</groupId>
<artifactId>maven-plugin-api</artifactId>
</dependency>
- <dependency>
- <groupId>org.apache.maven</groupId>
- <artifactId>maven-core</artifactId>
- </dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-model</artifactId>
diff --git
a/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/datamodel/ExecuteAnnotationContent.java
b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/datamodel/ExecuteAnnotationContent.java
index c1e3c930..a8e7af4e 100644
---
a/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/datamodel/ExecuteAnnotationContent.java
+++
b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/datamodel/ExecuteAnnotationContent.java
@@ -19,6 +19,7 @@
package org.apache.maven.tools.plugin.extractor.annotations.datamodel;
import java.lang.annotation.Annotation;
+import java.util.Objects;
import org.apache.maven.plugins.annotations.Execute;
import org.apache.maven.plugins.annotations.LifecyclePhase;
@@ -57,6 +58,20 @@ public class ExecuteAnnotationContent implements Execute {
}
public void phase(String phase) {
+ if (phase != null && !phase.isEmpty()) {
+ for (LifecyclePhase p : LifecyclePhase.values()) {
+ if (Objects.equals(phase, p.id()) || Objects.equals(phase,
p.name())) {
+ this.phase = p;
+ this.customPhase = null;
+ return;
+ }
+ }
+ this.phase = null;
+ this.customPhase = phase;
+ } else {
+ this.phase = null;
+ this.customPhase = null;
+ }
this.phase = LifecyclePhase.valueOf(phase);
}
diff --git
a/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/datamodel/MojoAnnotationContent.java
b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/datamodel/MojoAnnotationContent.java
index a3b6f6e8..12196990 100644
---
a/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/datamodel/MojoAnnotationContent.java
+++
b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/datamodel/MojoAnnotationContent.java
@@ -19,6 +19,7 @@
package org.apache.maven.tools.plugin.extractor.annotations.datamodel;
import java.lang.annotation.Annotation;
+import java.util.Objects;
import org.apache.maven.plugins.annotations.InstantiationStrategy;
import org.apache.maven.plugins.annotations.LifecyclePhase;
@@ -69,7 +70,17 @@ public class MojoAnnotationContent extends AnnotatedContent
implements Mojo {
}
public void defaultPhase(String phase) {
- this.defaultPhase = LifecyclePhase.valueOf(phase);
+ if (phase != null && !phase.isEmpty()) {
+ for (LifecyclePhase p : LifecyclePhase.values()) {
+ if (Objects.equals(phase, p.id()) || Objects.equals(phase,
p.name())) {
+ this.defaultPhase = p;
+ return;
+ }
+ }
+ throw new IllegalArgumentException("Could not find a matching
phase for " + phase);
+ } else {
+ this.defaultPhase = null;
+ }
}
@Override
@@ -81,6 +92,10 @@ public class MojoAnnotationContent extends AnnotatedContent
implements Mojo {
this.requiresDependencyResolution =
ResolutionScope.valueOf(requiresDependencyResolution);
}
+ public void dependencyResolutionRequired(String
dependencyResolutionRequired) {
+ this.requiresDependencyResolution =
ResolutionScope.valueOf(dependencyResolutionRequired);
+ }
+
@Override
public ResolutionScope requiresDependencyCollection() {
return requiresDependencyCollection;
@@ -117,6 +132,10 @@ public class MojoAnnotationContent extends
AnnotatedContent implements Mojo {
this.requiresProject = requiresProject;
}
+ public void projectRequired(boolean requiresProject) {
+ this.requiresProject = requiresProject;
+ }
+
@Override
public boolean requiresReports() {
return requiresReports;
diff --git
a/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/DefaultMojoAnnotationsScanner.java
b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/DefaultMojoAnnotationsScanner.java
index a91aea24..75989011 100644
---
a/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/DefaultMojoAnnotationsScanner.java
+++
b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/DefaultMojoAnnotationsScanner.java
@@ -31,6 +31,7 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
import java.util.regex.Pattern;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
@@ -70,7 +71,6 @@ public class DefaultMojoAnnotationsScanner extends
AbstractLogEnabled implements
public static final String MOJO_V4 = MVN4_API + "Mojo";
public static final String EXECUTE_V4 = MVN4_API + "Execute";
public static final String PARAMETER_V4 = MVN4_API + "Parameter";
- public static final String COMPONENT_V4 = MVN4_API + "Component";
public static final String MOJO_V3 = Mojo.class.getName();
public static final String EXECUTE_V3 = Execute.class.getName();
@@ -88,15 +88,23 @@ public class DefaultMojoAnnotationsScanner extends
AbstractLogEnabled implements
Map<String, MojoAnnotatedClass> mojoAnnotatedClasses = new HashMap<>();
try {
+ String mavenApiVersion = null;
for (Artifact dependency : request.getDependencies()) {
scan(mojoAnnotatedClasses, dependency.getFile(),
request.getIncludePatterns(), dependency, true);
if (request.getMavenApiVersion() == null
&& dependency.getGroupId().equals("org.apache.maven")
&&
(dependency.getArtifactId().equals("maven-plugin-api")
||
dependency.getArtifactId().equals("maven-api-core"))) {
- request.setMavenApiVersion(dependency.getVersion());
+ String version = dependency.getVersion();
+ if (mavenApiVersion != null && !Objects.equals(version,
mavenApiVersion)) {
+ throw new UnsupportedOperationException("Mixing Maven
3 and Maven 4 plugins is not supported."
+ + " Fix your dependencies so that you depend
either on maven-plugin-api for a Maven 3 plugin,"
+ + " or maven-api-core for a Maven 4 plugin.");
+ }
+ mavenApiVersion = version;
}
}
+ request.setMavenApiVersion(mavenApiVersion);
for (File classDirectory : request.getClassesDirectories()) {
scan(
@@ -332,16 +340,13 @@ public class DefaultMojoAnnotationsScanner extends
AbstractLogEnabled implements
// @Component annotations
List<MojoFieldVisitor> mojoFieldVisitors =
- mojoClassVisitor.findFieldWithAnnotation(new
HashSet<>(Arrays.asList(COMPONENT_V3, COMPONENT_V4)));
+ mojoClassVisitor.findFieldWithAnnotation(new
HashSet<>(Arrays.asList(COMPONENT_V3)));
for (MojoFieldVisitor mojoFieldVisitor : mojoFieldVisitors) {
ComponentAnnotationContent componentAnnotationContent =
new
ComponentAnnotationContent(mojoFieldVisitor.getFieldName());
Map<String, MojoAnnotationVisitor> annotationVisitorMap =
mojoFieldVisitor.getAnnotationVisitorMap();
MojoAnnotationVisitor annotationVisitor =
annotationVisitorMap.get(COMPONENT_V3);
- if (annotationVisitor == null) {
- annotationVisitor = annotationVisitorMap.get(COMPONENT_V4);
- }
if (annotationVisitor != null) {
for (Map.Entry<String, Object> entry :
diff --git
a/maven-plugin-tools-annotations/src/test/java/org/apache/maven/tools/plugin/extractor/annotations/ParametersWithGenericsMojo.java
b/maven-plugin-tools-annotations/src/test/java/org/apache/maven/tools/plugin/extractor/annotations/ParametersWithGenericsMojo.java
index d5796ba5..5de14478 100644
---
a/maven-plugin-tools-annotations/src/test/java/org/apache/maven/tools/plugin/extractor/annotations/ParametersWithGenericsMojo.java
+++
b/maven-plugin-tools-annotations/src/test/java/org/apache/maven/tools/plugin/extractor/annotations/ParametersWithGenericsMojo.java
@@ -46,6 +46,9 @@ public class ParametersWithGenericsMojo extends AbstractMojo {
@Parameter
private Collection<Integer[]> integerArrayCollection;
+ @Parameter
+ private Map<String, List<String>> stringListStringMap;
+
@Override
public void execute() throws MojoExecutionException, MojoFailureException
{}
diff --git
a/maven-plugin-tools-annotations/src/test/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/DefaultMojoAnnotationsScannerTest.java
b/maven-plugin-tools-annotations/src/test/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/DefaultMojoAnnotationsScannerTest.java
index 83dd04c4..bc8c0723 100644
---
a/maven-plugin-tools-annotations/src/test/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/DefaultMojoAnnotationsScannerTest.java
+++
b/maven-plugin-tools-annotations/src/test/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/DefaultMojoAnnotationsScannerTest.java
@@ -132,6 +132,12 @@ class DefaultMojoAnnotationsScannerTest {
assertNotNull(parameter);
assertEquals("java.util.List", parameter.getClassName());
assertThat(parameter.getTypeParameters()).containsExactly("java.lang.Number");
+
+ parameter = annotatedClass.getParameters().get("stringListStringMap");
+ assertNotNull(parameter);
+ assertEquals("java.util.Map", parameter.getClassName());
+ assertThat(parameter.getTypeParameters())
+ .containsExactly("java.lang.String",
"java.util.List<java.lang.String>");
}
@Test
diff --git
a/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/ExtendedPluginDescriptor.java
b/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/ExtendedPluginDescriptor.java
index bb3dc5c0..0ae9e935 100644
---
a/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/ExtendedPluginDescriptor.java
+++
b/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/ExtendedPluginDescriptor.java
@@ -18,7 +18,6 @@
*/
package org.apache.maven.tools.plugin;
-import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@@ -29,9 +28,7 @@ import org.apache.maven.model.Plugin;
import org.apache.maven.plugin.descriptor.DuplicateMojoDescriptorException;
import org.apache.maven.plugin.descriptor.MojoDescriptor;
import org.apache.maven.plugin.descriptor.PluginDescriptor;
-import org.apache.maven.plugin.lifecycle.Lifecycle;
import org.codehaus.plexus.classworlds.realm.ClassRealm;
-import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
/**
* Extensions to {@link PluginDescriptor} not supported by Maven 3.2.5.
@@ -91,6 +88,12 @@ public class ExtendedPluginDescriptor extends
PluginDescriptor {
delegate.addMojo(mojoDescriptor);
}
+ public void addMojos(List<MojoDescriptor> mojos) throws
DuplicateMojoDescriptorException {
+ for (MojoDescriptor mojoDescriptor : mojos) {
+ addMojo(mojoDescriptor);
+ }
+ }
+
public String getGroupId() {
return delegate.getGroupId();
}
@@ -222,11 +225,6 @@ public class ExtendedPluginDescriptor extends
PluginDescriptor {
delegate.setPluginArtifact(pluginArtifact);
}
- @Override
- public Lifecycle getLifecycleMapping(String lifecycleId) throws
IOException, XmlPullParserException {
- return delegate.getLifecycleMapping(lifecycleId);
- }
-
public PluginDescriptor clone() {
return delegate.clone();
}
diff --git a/maven-plugin-tools-generators/pom.xml
b/maven-plugin-tools-generators/pom.xml
index b2af7953..dd1aabe9 100644
--- a/maven-plugin-tools-generators/pom.xml
+++ b/maven-plugin-tools-generators/pom.xml
@@ -54,6 +54,8 @@
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-plugin-api</artifactId>
+ <version>${maven3Version}</version>
+ <scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
@@ -89,6 +91,15 @@
<version>${slf4jVersion}</version>
</dependency>
+ <dependency>
+ <groupId>org.ow2.asm</groupId>
+ <artifactId>asm</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.ow2.asm</groupId>
+ <artifactId>asm-commons</artifactId>
+ </dependency>
+
<!-- for HTML to plain text conversion -->
<dependency>
<groupId>org.jsoup</groupId>
@@ -108,6 +119,11 @@
<artifactId>junit-jupiter-engine</artifactId>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.apache.maven.resolver</groupId>
+ <artifactId>maven-resolver-impl</artifactId>
+ <version>${resolverVersion}</version>
+ </dependency>
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-testing</artifactId>
diff --git
a/maven-plugin-tools-generators/src/main/java/org/apache/maven/tools/plugin/generator/PluginDescriptorFilesGenerator.java
b/maven-plugin-tools-generators/src/main/java/org/apache/maven/tools/plugin/generator/PluginDescriptorFilesGenerator.java
index c6923de6..ac83bc42 100644
---
a/maven-plugin-tools-generators/src/main/java/org/apache/maven/tools/plugin/generator/PluginDescriptorFilesGenerator.java
+++
b/maven-plugin-tools-generators/src/main/java/org/apache/maven/tools/plugin/generator/PluginDescriptorFilesGenerator.java
@@ -110,6 +110,9 @@ public class PluginDescriptorFilesGenerator implements
Generator {
destinationFile.getParentFile().mkdirs();
}
+ String apiVersion =
request.getPluginDescriptor().getRequiredMavenVersion();
+ boolean isV4 = apiVersion != null && apiVersion.startsWith("4.");
+
try (Writer writer = new OutputStreamWriter(new
CachingOutputStream(destinationFile), UTF_8)) {
XMLWriter w = new PrettyPrintXMLWriter(writer, UTF_8.name(), null);
@@ -128,6 +131,13 @@ public class PluginDescriptorFilesGenerator implements
Generator {
w.writeMarkup("\n<!-- Generated by maven-plugin-tools " +
getVersion() + additionalInfo + "-->\n\n");
w.startElement("plugin");
+ if (isV4) {
+ w.addAttribute("xmlns",
"http://maven.apache.org/PLUGIN/2.0.0");
+ w.addAttribute("xmlns:xsi",
"http://www.w3.org/2001/XMLSchema-instance");
+ w.addAttribute(
+ "xsi:location",
+ "http://maven.apache.org/PLUGIN/2.0.0
https://maven.apache.org/xsd/plugin-2.0.0.xsd");
+ }
GeneratorUtils.element(w, "name", pluginDescriptor.getName());
@@ -178,13 +188,13 @@ public class PluginDescriptorFilesGenerator implements
Generator {
PluginUtils.sortMojos(descriptors);
for (MojoDescriptor descriptor : descriptors) {
- processMojoDescriptor(descriptor, w, type,
javadocLinkGenerator);
+ processMojoDescriptor(descriptor, w, type,
javadocLinkGenerator, isV4);
}
}
w.endElement();
- if (type != DescriptorType.LIMITED_FOR_HELP_MOJO) {
+ if (!isV4 && type != DescriptorType.LIMITED_FOR_HELP_MOJO) {
GeneratorUtils.writeDependencies(w, pluginDescriptor);
}
@@ -221,7 +231,8 @@ public class PluginDescriptorFilesGenerator implements
Generator {
MojoDescriptor mojoDescriptor,
XMLWriter w,
DescriptorType type,
- JavadocLinkGenerator javadocLinkGenerator) {
+ JavadocLinkGenerator javadocLinkGenerator,
+ boolean isV4) {
boolean containsXhtmlTextValues = mojoDescriptor instanceof
ExtendedMojoDescriptor
&& ((ExtendedMojoDescriptor)
mojoDescriptor).containsXhtmlTextValues();
@@ -251,27 +262,36 @@ public class PluginDescriptorFilesGenerator implements
Generator {
//
//
----------------------------------------------------------------------
- if
(StringUtils.isNotEmpty(mojoDescriptor.isDependencyResolutionRequired())) {
- GeneratorUtils.element(w, "requiresDependencyResolution",
mojoDescriptor.isDependencyResolutionRequired());
+ if
(StringUtils.isNotEmpty(mojoDescriptor.getDependencyResolutionRequired())) {
+ GeneratorUtils.element(
+ w,
+ isV4 ? "dependencyResolution" :
"requiresDependencyResolution",
+ mojoDescriptor.getDependencyResolutionRequired());
}
//
----------------------------------------------------------------------
//
//
----------------------------------------------------------------------
- GeneratorUtils.element(w, "requiresDirectInvocation",
String.valueOf(mojoDescriptor.isDirectInvocationOnly()));
+ GeneratorUtils.element(
+ w,
+ isV4 ? "directInvocationOnly" : "requiresDirectInvocation",
+ String.valueOf(mojoDescriptor.isDirectInvocationOnly()));
//
----------------------------------------------------------------------
//
//
----------------------------------------------------------------------
- GeneratorUtils.element(w, "requiresProject",
String.valueOf(mojoDescriptor.isProjectRequired()));
+ GeneratorUtils.element(
+ w, isV4 ? "projectRequired" : "requiresProject",
String.valueOf(mojoDescriptor.isProjectRequired()));
//
----------------------------------------------------------------------
//
//
----------------------------------------------------------------------
- GeneratorUtils.element(w, "requiresReports",
String.valueOf(mojoDescriptor.isRequiresReports()));
+ if (!isV4) {
+ GeneratorUtils.element(w, "requiresReports",
String.valueOf(mojoDescriptor.isRequiresReports()));
+ }
//
----------------------------------------------------------------------
//
@@ -283,7 +303,8 @@ public class PluginDescriptorFilesGenerator implements
Generator {
//
//
----------------------------------------------------------------------
- GeneratorUtils.element(w, "requiresOnline",
String.valueOf(mojoDescriptor.isOnlineRequired()));
+ GeneratorUtils.element(
+ w, isV4 ? "onlineRequired" : "requiresOnline",
String.valueOf(mojoDescriptor.isOnlineRequired()));
//
----------------------------------------------------------------------
//
@@ -345,7 +366,7 @@ public class PluginDescriptorFilesGenerator implements
Generator {
//
//
----------------------------------------------------------------------
- if (StringUtils.isNotEmpty(mojoDescriptor.getComponentComposer())) {
+ if (!isV4 &&
StringUtils.isNotEmpty(mojoDescriptor.getComponentComposer())) {
w.startElement("composer");
w.writeText(mojoDescriptor.getComponentComposer());
w.endElement();
@@ -355,17 +376,22 @@ public class PluginDescriptorFilesGenerator implements
Generator {
//
//
----------------------------------------------------------------------
- w.startElement("instantiationStrategy");
- w.writeText(mojoDescriptor.getInstantiationStrategy());
- w.endElement();
+ if (!isV4) {
+ w.startElement("instantiationStrategy");
+ w.writeText(mojoDescriptor.getInstantiationStrategy());
+ w.endElement();
+ }
//
----------------------------------------------------------------------
// Strategy for handling repeated reference to mojo in
// the calculated (decorated, resolved) execution stack
//
----------------------------------------------------------------------
- w.startElement("executionStrategy");
- w.writeText(mojoDescriptor.getExecutionStrategy());
- w.endElement();
+
+ if (!isV4) {
+ w.startElement("executionStrategy");
+ w.writeText(mojoDescriptor.getExecutionStrategy());
+ w.endElement();
+ }
//
----------------------------------------------------------------------
//
@@ -407,14 +433,12 @@ public class PluginDescriptorFilesGenerator implements
Generator {
ExtendedMojoDescriptor extendedMojoDescriptor =
(ExtendedMojoDescriptor) mojoDescriptor;
if (extendedMojoDescriptor.getDependencyCollectionRequired() !=
null) {
GeneratorUtils.element(
- w, "requiresDependencyCollection",
extendedMojoDescriptor.getDependencyCollectionRequired());
+ w,
+ isV4 ? "dependencyCollection" :
"requiresDependencyCollection",
+
extendedMojoDescriptor.getDependencyCollectionRequired());
}
-
- GeneratorUtils.element(w, "threadSafe",
String.valueOf(extendedMojoDescriptor.isThreadSafe()));
-
- boolean v4Api = extendedMojoDescriptor.isV4Api();
- if (v4Api) {
- GeneratorUtils.element(w, "v4Api", String.valueOf(v4Api));
+ if (!isV4) {
+ GeneratorUtils.element(w, "threadSafe",
String.valueOf(extendedMojoDescriptor.isThreadSafe()));
}
}
@@ -495,7 +519,7 @@ public class PluginDescriptorFilesGenerator implements
Generator {
}
}
- if (parameter.getImplementation() != null) {
+ if (!isV4 && parameter.getImplementation() != null) {
GeneratorUtils.element(w, "implementation",
parameter.getImplementation());
}
@@ -506,9 +530,18 @@ public class PluginDescriptorFilesGenerator implements
Generator {
GeneratorUtils.element(
w, "description", getTextValue(type,
containsXhtmlTextValues, parameter.getDescription()));
- if (StringUtils.isNotEmpty(parameter.getDefaultValue())
- ||
StringUtils.isNotEmpty(parameter.getExpression())) {
- configuration.add(parameter);
+ if (isV4) {
+ if (StringUtils.isNotEmpty(parameter.getExpression()))
{
+ GeneratorUtils.element(w, "expression",
parameter.getExpression());
+ }
+ if
(StringUtils.isNotEmpty(parameter.getDefaultValue())) {
+ GeneratorUtils.element(w, "defaultValue",
parameter.getDefaultValue());
+ }
+ } else {
+ if (StringUtils.isNotEmpty(parameter.getDefaultValue())
+ ||
StringUtils.isNotEmpty(parameter.getExpression())) {
+ configuration.add(parameter);
+ }
}
w.endElement();
diff --git
a/maven-plugin-tools-generators/src/main/resources/help-class-source-v4.vm
b/maven-plugin-tools-generators/src/main/resources/help-class-source-v4.vm
index 0ac5b891..008c5219 100644
--- a/maven-plugin-tools-generators/src/main/resources/help-class-source-v4.vm
+++ b/maven-plugin-tools-generators/src/main/resources/help-class-source-v4.vm
@@ -18,8 +18,8 @@
package ${helpPackageName};
#end
+import org.apache.maven.api.di.Inject;
import org.apache.maven.api.plugin.MojoException;
-import org.apache.maven.api.plugin.annotations.Component;
import org.apache.maven.api.plugin.annotations.Mojo;
import org.apache.maven.api.plugin.annotations.Parameter;
import org.apache.maven.api.plugin.Log;
@@ -43,11 +43,11 @@ import java.util.List;
* Call <code>mvn ${goalPrefix}:help -Ddetail=true
-Dgoal=<goal-name></code> to display parameter details.
* @author maven-plugin-tools
*/
-@Mojo( name = "help", requiresProject = false )
+@Mojo( name = "help", projectRequired = false )
public class HelpMojo
implements org.apache.maven.api.plugin.Mojo
{
- @Component
+ @Inject
private Log logger;
/**
@@ -189,6 +189,21 @@ public class HelpMojo
return getSingleChild( node, elementName ).getTextContent();
}
+ private static String getValueOr( Node node, String elementName, String
def )
+ throws MojoException
+ {
+ List<Node> namedChild = findNamedChild( node, elementName );
+ if ( namedChild.isEmpty() )
+ {
+ return def;
+ }
+ if ( namedChild.size() > 1 )
+ {
+ throw new MojoException( "Multiple " + elementName + " in
plugin-help.xml" );
+ }
+ return namedChild.get( 0 ).getTextContent();
+ }
+
private static Node getSingleChild( Node node, String elementName )
throws MojoException
{
@@ -286,10 +301,10 @@ public class HelpMojo
fieldConfigurationElement = (Element) findSingleChild(
configurationElement, parameterName );
}
- String parameterDefaultValue = "";
- if ( fieldConfigurationElement != null &&
fieldConfigurationElement.hasAttribute( "default-value" ) )
+ String parameterDefaultValue = getValueOr( parameter, "defaultValue",
"" );
+ if ( isNotEmpty( parameterDefaultValue ) )
{
- parameterDefaultValue = " (Default: " +
fieldConfigurationElement.getAttribute( "default-value" ) + ")";
+ parameterDefaultValue = " (Default: " + parameterDefaultValue +
")";
}
append( sb, parameterName + parameterDefaultValue, 2 );
Node deprecated = findSingleChild( parameter, "deprecated" );
@@ -305,9 +320,11 @@ public class HelpMojo
{
append( sb, "Required: Yes", 3 );
}
- if ( ( fieldConfigurationElement != null ) && isNotEmpty(
fieldConfigurationElement.getTextContent() ) )
+
+ String parameterExpression = getValueOr( parameter, "expression", "" );
+ if ( isNotEmpty( parameterExpression ) )
{
- String property = getPropertyFromExpression(
fieldConfigurationElement.getTextContent() );
+ String property = getPropertyFromExpression( parameterExpression );
append( sb, "User property: " + property, 3 );
}
diff --git
a/maven-plugin-tools-generators/src/test/java/org/apache/maven/tools/plugin/generator/AbstractGeneratorTestCase.java
b/maven-plugin-tools-generators/src/test/java/org/apache/maven/tools/plugin/generator/AbstractGeneratorTestCase.java
index f592b631..4b63712f 100644
---
a/maven-plugin-tools-generators/src/test/java/org/apache/maven/tools/plugin/generator/AbstractGeneratorTestCase.java
+++
b/maven-plugin-tools-generators/src/test/java/org/apache/maven/tools/plugin/generator/AbstractGeneratorTestCase.java
@@ -36,6 +36,7 @@ import org.apache.maven.project.MavenProject;
import org.apache.maven.tools.plugin.DefaultPluginToolsRequest;
import org.codehaus.plexus.component.repository.ComponentDependency;
import org.codehaus.plexus.util.FileUtils;
+import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
/**
@@ -105,7 +106,74 @@ public abstract class AbstractGeneratorTestCase {
extendPluginDescriptor(pluginDescriptor);
generator.execute(destinationDirectory, new
DefaultPluginToolsRequest(mavenProject, pluginDescriptor));
- validate(destinationDirectory);
+ validate(destinationDirectory, false);
+
+ FileUtils.deleteDirectory(destinationDirectory);
+ }
+
+ @Test
+ @Disabled
+ public void testGeneratorV4() throws Exception {
+ setupGenerator();
+
+ MojoDescriptor mojoDescriptor = new MojoDescriptor();
+ mojoDescriptor.setGoal("testGoal");
+
mojoDescriptor.setImplementation("org.apache.maven.tools.plugin.generator.TestMojo");
+ mojoDescriptor.setDependencyResolutionRequired("compile");
+ mojoDescriptor.setSince("mojoSince");
+
+ List<Parameter> params = new ArrayList<>();
+
+ Parameter param = new Parameter();
+ param.setExpression("${project.build.directory}");
+ param.setDefaultValue("</markup-must-be-escaped>");
+ param.setName("dir");
+ param.setRequired(true);
+ param.setType("java.lang.String");
+ param.setDescription("Test parameter description");
+ param.setAlias("some.alias");
+ param.setSince("paramDirSince");
+ params.add(param);
+
+ param = new Parameter();
+ param.setName("withoutSince");
+ param.setType("java.lang.String");
+ params.add(param);
+
+ mojoDescriptor.setParameters(params);
+
+ PluginDescriptor pluginDescriptor = new PluginDescriptor();
+ mojoDescriptor.setPluginDescriptor(pluginDescriptor);
+
+ pluginDescriptor.addMojo(mojoDescriptor);
+
+ pluginDescriptor.setArtifactId("maven-unitTesting-plugin");
+ pluginDescriptor.setGoalPrefix("test");
+
+ ComponentDependency dependency = new ComponentDependency();
+ dependency.setGroupId("testGroup");
+ dependency.setArtifactId("testArtifact");
+ dependency.setVersion("0.0.0");
+
+
pluginDescriptor.setDependencies(Collections.singletonList(dependency));
+
+ File destinationDirectory =
+ Files.createTempDirectory("testGenerator-outDir").toFile();
+ destinationDirectory.mkdir();
+
+ MavenProject mavenProject = new MavenProject();
+ mavenProject.setGroupId("foo");
+ mavenProject.setArtifactId("bar");
+ Build build = new Build();
+ build.setDirectory(basedir + "/target");
+ build.setOutputDirectory(basedir + "/target");
+ mavenProject.setBuild(build);
+ extendPluginDescriptor(pluginDescriptor);
+ DefaultPluginToolsRequest request = new
DefaultPluginToolsRequest(mavenProject, pluginDescriptor);
+ pluginDescriptor.setRequiredMavenVersion("4.0.0");
+ generator.execute(destinationDirectory, request);
+
+ validate(destinationDirectory, true);
FileUtils.deleteDirectory(destinationDirectory);
}
@@ -145,7 +213,7 @@ public abstract class AbstractGeneratorTestCase {
//
// ----------------------------------------------------------------------
- protected void validate(File destinationDirectory) throws Exception {
+ protected void validate(File destinationDirectory, boolean isV4) throws
Exception {
// empty
}
}
diff --git
a/maven-plugin-tools-generators/src/test/java/org/apache/maven/tools/plugin/generator/PluginDescriptorFilesGeneratorTest.java
b/maven-plugin-tools-generators/src/test/java/org/apache/maven/tools/plugin/generator/PluginDescriptorFilesGeneratorTest.java
index eb35539e..98fd2e41 100644
---
a/maven-plugin-tools-generators/src/test/java/org/apache/maven/tools/plugin/generator/PluginDescriptorFilesGeneratorTest.java
+++
b/maven-plugin-tools-generators/src/test/java/org/apache/maven/tools/plugin/generator/PluginDescriptorFilesGeneratorTest.java
@@ -60,35 +60,33 @@ public class PluginDescriptorFilesGeneratorTest extends
AbstractGeneratorTestCas
}
@Override
- protected void validate(File destinationDirectory) throws Exception {
+ protected void validate(File destinationDirectory, boolean isV4) throws
Exception {
PluginDescriptorBuilder pdb = new PluginDescriptorBuilder();
File pluginDescriptorFile = new File(destinationDirectory,
"plugin.xml");
String pd = readFile(pluginDescriptorFile);
+ System.err.println(pd);
+
PluginDescriptor pluginDescriptor = pdb.build(new StringReader(pd));
assertEquals(1, pluginDescriptor.getMojos().size());
MojoDescriptor mojoDescriptor = pluginDescriptor.getMojos().get(0);
- checkMojo(mojoDescriptor);
+ checkMojo(mojoDescriptor, isV4);
//
----------------------------------------------------------------------
// Dependencies
//
----------------------------------------------------------------------
- List<ComponentDependency> dependencies =
pluginDescriptor.getDependencies();
-
- checkDependency("testGroup", "testArtifact", "0.0.0",
dependencies.get(0));
+ if (!isV4) {
+ List<ComponentDependency> dependencies =
pluginDescriptor.getDependencies();
- assertEquals(1, dependencies.size());
-
- ComponentDependency dependency = dependencies.get(0);
- assertEquals("testGroup", dependency.getGroupId());
- assertEquals("testArtifact", dependency.getArtifactId());
- assertEquals("0.0.0", dependency.getVersion());
+ assertEquals(1, dependencies.size());
+ checkDependency("testGroup", "testArtifact", "0.0.0",
dependencies.get(0));
+ }
}
private String readFile(File pluginDescriptorFile) throws IOException {
@@ -105,15 +103,19 @@ public class PluginDescriptorFilesGeneratorTest extends
AbstractGeneratorTestCas
return sWriter.toString();
}
- private void checkMojo(MojoDescriptor mojoDescriptor) {
+ private void checkMojo(MojoDescriptor mojoDescriptor, boolean isV4) {
assertEquals("test:testGoal", mojoDescriptor.getFullGoalName());
assertEquals("org.apache.maven.tools.plugin.generator.TestMojo",
mojoDescriptor.getImplementation());
// The following should be defaults
- assertEquals("per-lookup", mojoDescriptor.getInstantiationStrategy());
+ if (!isV4) {
+ assertEquals("per-lookup",
mojoDescriptor.getInstantiationStrategy());
+ }
- assertNotNull(mojoDescriptor.isDependencyResolutionRequired());
+ if (!isV4) {
+ assertNotNull(mojoDescriptor.getDependencyResolutionRequired());
+ }
// check the default parameter
checkParameter(mojoDescriptor.getParameters().get(0));
@@ -124,12 +126,17 @@ public class PluginDescriptorFilesGeneratorTest extends
AbstractGeneratorTestCas
assertEquals("parameterWithGenerics", parameterWithGenerics.getName());
assertEquals("java.util.Collection", parameterWithGenerics.getType());
- PlexusConfiguration configurations =
mojoDescriptor.getMojoConfiguration();
- assertNotNull(configurations);
- PlexusConfiguration configuration =
configurations.getChild("parameterWithGenerics");
- assertEquals("java.util.Collection",
configuration.getAttribute("implementation"));
- assertEquals("a,b,c", configuration.getAttribute("default-value"));
- assertEquals("${customParam}", configuration.getValue());
+ if (isV4) {
+ assertEquals("${customParam}",
parameterWithGenerics.getExpression());
+ assertEquals("a,b,c", parameterWithGenerics.getDefaultValue());
+ } else {
+ PlexusConfiguration configurations =
mojoDescriptor.getMojoConfiguration();
+ assertNotNull(configurations);
+ PlexusConfiguration configuration =
configurations.getChild("parameterWithGenerics");
+ assertEquals("java.util.Collection",
configuration.getAttribute("implementation"));
+ assertEquals("a,b,c", configuration.getAttribute("default-value"));
+ assertEquals("${customParam}", configuration.getValue());
+ }
}
private void checkParameter(Parameter parameter) {
diff --git a/pom.xml b/pom.xml
index a4cfceb6..4def9de6 100644
--- a/pom.xml
+++ b/pom.xml
@@ -90,7 +90,7 @@
<properties>
<javaVersion>8</javaVersion>
<pluginTestingHarnessVersion>3.3.0</pluginTestingHarnessVersion>
- <maven4Version>4.0.0-alpha-4</maven4Version>
+ <maven4Version>4.0.0-beta-3</maven4Version>
<maven3Version>3.9.6</maven3Version>
<resolverVersion>1.9.18</resolverVersion>
<slf4jVersion>1.7.36</slf4jVersion>
@@ -308,6 +308,21 @@
<build>
<pluginManagement>
<plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-enforcer-plugin</artifactId>
+ <configuration>
+ <rules>
+ <enforceBytecodeVersion>
+ <maxJdkVersion>${maven.compiler.target}</maxJdkVersion>
+ <excludes>
+ <exclude>org.apache.maven:*</exclude>
+ </excludes>
+ </enforceBytecodeVersion>
+ </rules>
+ <fail>true</fail>
+ </configuration>
+ </plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>