You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by sj...@apache.org on 2022/07/28 16:25:35 UTC
[maven-plugin-tools] 01/01: [MPLUGIN-408] helpmojo improvement
This is an automated email from the ASF dual-hosted git repository.
sjaranowski pushed a commit to branch MPLUGIN-408
in repository https://gitbox.apache.org/repos/asf/maven-plugin-tools.git
commit 2c996dd55a390579936a24ba92205ecd6f85cf77
Author: Slawomir Jaranowski <s....@gmail.com>
AuthorDate: Thu Jul 28 18:14:48 2022 +0200
[MPLUGIN-408] helpmojo improvement
- use groupId + artifactId for calculating package name
- discover mojos only ones by descriptor mojo
- simplify in AbstractGeneratorMojo
- remove unneeded code
---
maven-plugin-plugin/pom.xml | 2 +-
.../verify.groovy | 7 +-
.../it/annotation-with-inheritance/verify.groovy | 7 +-
.../java-basic-annotations-jdk8/invoker.properties | 4 +-
.../src/it/java-basic-annotations-jdk8/pom.xml | 2 +-
.../it/java-basic-annotations-jdk8/verify.groovy | 5 +-
.../verify.groovy | 5 +-
.../src/it/java-basic-annotations/verify.groovy | 10 +-
.../it/mplugin-363_help-reproducible/verify.groovy | 4 +-
.../maven/plugin/plugin/AbstractGeneratorMojo.java | 302 +-----------------
.../plugin/plugin/DescriptorGeneratorMojo.java | 288 ++++++++++++++++--
.../maven/plugin/plugin/HelpGeneratorMojo.java | 85 ++++--
.../maven/plugin/plugin/HelpGeneratorMojoTest.java | 63 ++++
.../generator/PluginDescriptorGenerator.java | 28 +-
.../plugin/generator/PluginHelpGenerator.java | 336 ++-------------------
.../plugin/generator/PluginHelpGeneratorTest.java | 46 ---
.../javadoc/JavaMojoDescriptorExtractorTest.java | 2 +-
pom.xml | 9 +-
18 files changed, 463 insertions(+), 742 deletions(-)
diff --git a/maven-plugin-plugin/pom.xml b/maven-plugin-plugin/pom.xml
index 448f6bd9..5642641e 100644
--- a/maven-plugin-plugin/pom.xml
+++ b/maven-plugin-plugin/pom.xml
@@ -179,7 +179,7 @@
<!-- tests -->
<dependency>
<groupId>org.junit.jupiter</groupId>
- <artifactId>junit-jupiter-engine</artifactId>
+ <artifactId>junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
<dependency>
diff --git a/maven-plugin-plugin/src/it/annotation-with-inheritance-from-deps/verify.groovy b/maven-plugin-plugin/src/it/annotation-with-inheritance-from-deps/verify.groovy
index 1ef2944d..b941b803 100644
--- a/maven-plugin-plugin/src/it/annotation-with-inheritance-from-deps/verify.groovy
+++ b/maven-plugin-plugin/src/it/annotation-with-inheritance-from-deps/verify.groovy
@@ -20,11 +20,8 @@
File descriptorFile = new File( basedir, "target/classes/META-INF/maven/plugin.xml" );
assert descriptorFile.isFile()
-File oldHelpClass = new File( basedir, "target/classes/HelpMojo.class" );
-assert !oldHelpClass.exists()
-
-File newHelpClass = new File( basedir, "target/classes/org/apache/maven/plugin/coreit/HelpMojo.class" );
-assert newHelpClass.exists()
+File helpClass = new File( basedir, "target/classes/org/apache/maven/its/annotation_with_inheritance_from_deps/annotation_with_inheritance_from_deps/HelpMojo.class" );
+assert helpClass.exists()
def pluginDescriptor = new XmlParser().parse( descriptorFile );
diff --git a/maven-plugin-plugin/src/it/annotation-with-inheritance/verify.groovy b/maven-plugin-plugin/src/it/annotation-with-inheritance/verify.groovy
index d066901a..689e0008 100644
--- a/maven-plugin-plugin/src/it/annotation-with-inheritance/verify.groovy
+++ b/maven-plugin-plugin/src/it/annotation-with-inheritance/verify.groovy
@@ -23,11 +23,8 @@ assert touchFile.isFile()
File descriptorFile = new File( basedir, "target/classes/META-INF/maven/plugin.xml" );
assert descriptorFile.isFile()
-File oldHelpClass = new File( basedir, "target/classes/HelpMojo.class" );
-assert !oldHelpClass.exists()
-
-File newHelpClass = new File( basedir, "target/classes/org/apache/maven/plugin/coreit/HelpMojo.class" );
-assert newHelpClass.exists()
+File helpClass = new File( basedir, "target/classes/org/apache/maven/its/annotation_with_inheritance/annotation_with_inheritance/HelpMojo.class" );
+assert helpClass.exists()
def pluginDescriptor = new XmlParser().parse( descriptorFile );
diff --git a/maven-plugin-plugin/src/it/java-basic-annotations-jdk8/invoker.properties b/maven-plugin-plugin/src/it/java-basic-annotations-jdk8/invoker.properties
index d0a9e140..6760204d 100644
--- a/maven-plugin-plugin/src/it/java-basic-annotations-jdk8/invoker.properties
+++ b/maven-plugin-plugin/src/it/java-basic-annotations-jdk8/invoker.properties
@@ -16,5 +16,5 @@
# under the License.
invoker.goals.1 = clean install
-invoker.goals.2 = org.apache.maven.its.basic-java-annotations:maven-it-basic-java-annotations:1.0-SNAPSHOT:it0014
-invoker.goals.3 = org.apache.maven.its.basic-java-annotations:maven-it-basic-java-annotations:1.0-SNAPSHOT:help
+invoker.goals.2 = org.apache.maven.its.basic-java-annotations:123-maven-it-basic-java-annotations:1.0-SNAPSHOT:it0014
+invoker.goals.3 = org.apache.maven.its.basic-java-annotations:123-maven-it-basic-java-annotations:1.0-SNAPSHOT:help
diff --git a/maven-plugin-plugin/src/it/java-basic-annotations-jdk8/pom.xml b/maven-plugin-plugin/src/it/java-basic-annotations-jdk8/pom.xml
index 124b37cc..dda14a8a 100644
--- a/maven-plugin-plugin/src/it/java-basic-annotations-jdk8/pom.xml
+++ b/maven-plugin-plugin/src/it/java-basic-annotations-jdk8/pom.xml
@@ -23,7 +23,7 @@ under the License.
<modelVersion>4.0.0</modelVersion>
<groupId>org.apache.maven.its.basic-java-annotations</groupId>
- <artifactId>maven-it-basic-java-annotations</artifactId>
+ <artifactId>123-maven-it-basic-java-annotations</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>maven-plugin</packaging>
diff --git a/maven-plugin-plugin/src/it/java-basic-annotations-jdk8/verify.groovy b/maven-plugin-plugin/src/it/java-basic-annotations-jdk8/verify.groovy
index 294f5386..b130e2c5 100644
--- a/maven-plugin-plugin/src/it/java-basic-annotations-jdk8/verify.groovy
+++ b/maven-plugin-plugin/src/it/java-basic-annotations-jdk8/verify.groovy
@@ -224,8 +224,7 @@ requirement = mojo.requirements.requirement.findAll{ it.'field-name'.text() == "
assert requirement.role.text() == 'org.apache.maven.project.MavenProjectHelper'
// check help mojo source and class
-assert new File( basedir, "target/classes/org/apache/maven/plugin/coreit/HelpMojo.class" ).isFile()
-assert new File( basedir, "target/generated-sources/plugin/org/apache/maven/plugin/coreit/HelpMojo.java" ).isFile()
-assert !new File( basedir, "target/generated-sources/plugin/HelpMojo.java" ).isFile()
+assert new File( basedir, "target/classes/org/apache/maven/its/basic_java_annotations/_123_maven_it_basic_java_annotations/HelpMojo.class" ).isFile()
+assert new File( basedir, "target/generated-sources/plugin/org/apache/maven/its/basic_java_annotations/_123_maven_it_basic_java_annotations/HelpMojo.java" ).isFile()
return true;
diff --git a/maven-plugin-plugin/src/it/java-basic-annotations-jdkcurrent/verify.groovy b/maven-plugin-plugin/src/it/java-basic-annotations-jdkcurrent/verify.groovy
index 294f5386..c498a221 100644
--- a/maven-plugin-plugin/src/it/java-basic-annotations-jdkcurrent/verify.groovy
+++ b/maven-plugin-plugin/src/it/java-basic-annotations-jdkcurrent/verify.groovy
@@ -224,8 +224,7 @@ requirement = mojo.requirements.requirement.findAll{ it.'field-name'.text() == "
assert requirement.role.text() == 'org.apache.maven.project.MavenProjectHelper'
// check help mojo source and class
-assert new File( basedir, "target/classes/org/apache/maven/plugin/coreit/HelpMojo.class" ).isFile()
-assert new File( basedir, "target/generated-sources/plugin/org/apache/maven/plugin/coreit/HelpMojo.java" ).isFile()
-assert !new File( basedir, "target/generated-sources/plugin/HelpMojo.java" ).isFile()
+assert new File( basedir, "target/classes/org/apache/maven/its/basic_java_annotations/maven_it_basic_java_annotations/HelpMojo.class" ).isFile()
+assert new File( basedir, "target/generated-sources/plugin/org/apache/maven/its/basic_java_annotations/maven_it_basic_java_annotations/HelpMojo.java" ).isFile()
return true;
diff --git a/maven-plugin-plugin/src/it/java-basic-annotations/verify.groovy b/maven-plugin-plugin/src/it/java-basic-annotations/verify.groovy
index 0541a8f1..4315bef7 100644
--- a/maven-plugin-plugin/src/it/java-basic-annotations/verify.groovy
+++ b/maven-plugin-plugin/src/it/java-basic-annotations/verify.groovy
@@ -224,9 +224,13 @@ requirement = mojo.requirements.requirement.findAll{ it.'field-name'.text() == "
assert requirement.role.text() == 'org.apache.maven.project.MavenProjectHelper'
// check help mojo source and class
-assert new File( basedir, "target/classes/org/apache/maven/plugin/coreit/HelpMojo.class" ).isFile()
-assert new File( basedir, "target/generated-sources/plugin/org/apache/maven/plugin/coreit/HelpMojo.java" ).isFile()
-assert !new File( basedir, "target/generated-sources/plugin/HelpMojo.java" ).isFile()
+assert new File( basedir, "target/classes/org/apache/maven/its/basic_java_annotations/maven_it_basic_java_annotations/HelpMojo.class" ).isFile()
+assert new File( basedir, "target/generated-sources/plugin/org/apache/maven/its/basic_java_annotations/maven_it_basic_java_annotations/HelpMojo.java" ).isFile()
+
+mojo = pluginDescriptor.mojos.mojo.findAll{ it.goal.text() == "help"}[0]
+assert mojo.goal.text() == 'help'
+assert mojo.implementation.text() == 'org.apache.maven.its.basic_java_annotations.maven_it_basic_java_annotations.HelpMojo'
+assert mojo.language.text() == 'java'
// check values set by deprecated annotation only
mojo = pluginDescriptor.mojos.mojo.findAll{ it.goal.text() == "mplugin-396"}[0]
diff --git a/maven-plugin-plugin/src/it/mplugin-363_help-reproducible/verify.groovy b/maven-plugin-plugin/src/it/mplugin-363_help-reproducible/verify.groovy
index b64de436..b47f8a9d 100644
--- a/maven-plugin-plugin/src/it/mplugin-363_help-reproducible/verify.groovy
+++ b/maven-plugin-plugin/src/it/mplugin-363_help-reproducible/verify.groovy
@@ -17,7 +17,7 @@
* under the License.
*/
-firstRun = new File( basedir, "target/generated-sources-run1/plugin/test/HelpMojo.java" ).text;
-secondRun = new File( basedir, "target/generated-sources/plugin/test/HelpMojo.java" ).text;
+firstRun = new File( basedir, "target/generated-sources-run1/plugin/org/apache/maven/its/plugin/help/HelpMojo.java" ).text;
+secondRun = new File( basedir, "target/generated-sources/plugin/org/apache/maven/its/plugin/help/HelpMojo.java" ).text;
assert firstRun == secondRun;
diff --git a/maven-plugin-plugin/src/main/java/org/apache/maven/plugin/plugin/AbstractGeneratorMojo.java b/maven-plugin-plugin/src/main/java/org/apache/maven/plugin/plugin/AbstractGeneratorMojo.java
index bd1354d5..a62d923f 100644
--- a/maven-plugin-plugin/src/main/java/org/apache/maven/plugin/plugin/AbstractGeneratorMojo.java
+++ b/maven-plugin-plugin/src/main/java/org/apache/maven/plugin/plugin/AbstractGeneratorMojo.java
@@ -19,34 +19,14 @@ package org.apache.maven.plugin.plugin;
* under the License.
*/
-import org.apache.maven.artifact.Artifact;
-import org.apache.maven.artifact.repository.ArtifactRepository;
-import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
-import org.apache.maven.artifact.resolver.filter.IncludesArtifactFilter;
+import java.util.Collections;
+import java.util.List;
+
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
-import org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException;
import org.apache.maven.plugin.descriptor.PluginDescriptor;
-import org.apache.maven.plugins.annotations.Component;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.project.MavenProject;
-import org.apache.maven.tools.plugin.DefaultPluginToolsRequest;
-import org.apache.maven.tools.plugin.PluginToolsRequest;
-import org.apache.maven.tools.plugin.extractor.ExtractionException;
-import org.apache.maven.tools.plugin.generator.Generator;
-import org.apache.maven.tools.plugin.generator.GeneratorException;
-import org.apache.maven.tools.plugin.generator.GeneratorUtils;
-import org.apache.maven.tools.plugin.scanner.MojoScanner;
-import org.codehaus.plexus.component.repository.ComponentDependency;
-import org.codehaus.plexus.util.ReaderFactory;
-import org.sonatype.plexus.build.incremental.BuildContext;
-
-import java.io.File;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Set;
/**
* Abstract class for this Plugin.
@@ -63,100 +43,19 @@ public abstract class AbstractGeneratorMojo
@Parameter( defaultValue = "${project}", readonly = true )
protected MavenProject project;
- /**
- * The component used for scanning the source tree for mojos.
- */
- @Component
- protected MojoScanner mojoScanner;
-
- @Component
- protected BuildContext buildContext;
-
- /**
- * The file encoding of the source files.
- *
- * @since 2.5
- */
- @Parameter( property = "encoding", defaultValue = "${project.build.sourceEncoding}" )
- protected String encoding;
-
/**
* The goal prefix that will appear before the ":".
*/
@Parameter
protected String goalPrefix;
- /**
- * By default an exception is throw if no mojo descriptor is found. As the maven-plugin is defined in core, the
- * descriptor generator mojo is bound to generate-resources phase.
- * But for annotations, the compiled classes are needed, so skip error
- *
- * @since 3.0
- */
- @Parameter( property = "maven.plugin.skipErrorNoDescriptorsFound", defaultValue = "false" )
- protected boolean skipErrorNoDescriptorsFound;
-
- /**
- * <p>
- * The role names of mojo extractors to use.
- * </p>
- * <p>
- * If not set, all mojo extractors will be used. If set to an empty extractor name, no mojo extractors
- * will be used.
- * </p>
- * Example:
- * <pre>
- * <!-- Use all mojo extractors -->
- * <extractors/>
- *
- * <!-- Use no mojo extractors -->
- * <extractors>
- * <extractor/>
- * </extractors>
- *
- * <!-- Use only bsh mojo extractor -->
- * <extractors>
- * <extractor>bsh</extractor>
- * </extractors>
- * </pre>
- */
- @Parameter
- protected Set<String> extractors;
-
/**
* Set this to "true" to skip invoking any goals or reports of the plugin.
*
* @since 2.8
*/
@Parameter( defaultValue = "false", property = "maven.plugin.skip" )
- protected boolean skip;
-
- /**
- * Specify the dependencies as {@code groupId:artifactId} containing (abstract) Mojos, to filter
- * dependencies scanned at runtime and focus on dependencies that are really useful to Mojo analysis.
- * By default, the value is {@code null} and all dependencies are scanned (as before this parameter was added).
- * If specified in the configuration with no children, no dependencies are scanned.
- *
- * @since 3.5
- */
- @Parameter
- private List<String> mojoDependencies = null;
-
- /**
- * List of Remote Repositories used by the resolver
- *
- * @since 3.0
- */
- @Parameter( defaultValue = "${project.remoteArtifactRepositories}", required = true, readonly = true )
- protected List<ArtifactRepository> remoteRepos;
-
- /**
- * Location of the local repository.
- *
- * @since 3.0
- */
- @Parameter( defaultValue = "${localRepository}", required = true, readonly = true )
- protected ArtifactRepository local;
+ private boolean skip;
/**
* Maven plugin packaging types. Default is single "maven-plugin".
@@ -164,55 +63,15 @@ public abstract class AbstractGeneratorMojo
* @since 3.3
*/
@Parameter
- protected List<String> packagingTypes = Collections.singletonList( "maven-plugin" );
-
- /**
- * Flag controlling is "expected dependencies in provided scope" check to be performed or not. Default value:
- * {@code true}.
- *
- * @since 3.6.3
- */
- @Parameter( defaultValue = "true", property = "maven.plugin.checkExpectedProvidedScope" )
- private boolean checkExpectedProvidedScope = true;
-
- /**
- * List of {@code groupId} strings of artifact coordinates that are expected to be in "provided" scope. Default
- * value: {@code ["org.apache.maven"]}.
- *
- * @since 3.6.3
- */
- @Parameter
- private List<String> expectedProvidedScopeGroupIds = Collections.singletonList( "org.apache.maven" );
-
- /**
- * List of {@code groupId:artifactId} strings of artifact coordinates that are to be excluded from "expected
- * provided scope" check. Default value: {@code ["org.apache.maven:maven-archiver", "org.apache.maven:maven-jxr"]}.
- *
- * @since 3.6.3
- */
- @Parameter
- private List<String> expectedProvidedScopeExclusions = Arrays.asList(
- "org.apache.maven:maven-archiver",
- "org.apache.maven:maven-jxr" );
-
- /**
- * @return the output directory where files will be generated.
- */
- protected abstract File getOutputDirectory();
-
- /**
- * @return the wanted <code>Generator</code> implementation.
- */
- protected abstract Generator createGenerator();
+ private List<String> packagingTypes = Collections.singletonList( "maven-plugin" );
/**
* System/OS line separator: used to format console messages.
*/
- private static final String LS = System.lineSeparator();
+ protected static final String LS = System.lineSeparator();
+
+ protected abstract void generate() throws MojoExecutionException;
- /**
- * {@inheritDoc}
- */
@Override
public void execute()
throws MojoExecutionException
@@ -222,6 +81,7 @@ public abstract class AbstractGeneratorMojo
getLog().info( "Unsupported packaging type " + project.getPackaging() + ", execution skipped" );
return;
}
+
if ( skip )
{
getLog().warn( "Execution skipped" );
@@ -230,7 +90,7 @@ public abstract class AbstractGeneratorMojo
if ( !"maven-plugin".equalsIgnoreCase( project.getArtifactId() )
&& project.getArtifactId().toLowerCase().startsWith( "maven-" )
- && project.getArtifactId().toLowerCase().endsWith( "-plugin" )
+ && project.getArtifactId().toLowerCase().endsWith( "-plugin" )
&& !"org.apache.maven.plugins".equals( project.getGroupId() ) )
{
getLog().error( LS + LS + "Artifact Ids of the format maven-___-plugin are reserved for" + LS
@@ -239,29 +99,8 @@ public abstract class AbstractGeneratorMojo
+ "In the future this error will break the build." + LS + LS );
}
- if ( checkExpectedProvidedScope )
- {
- Set<Artifact> wrongScopedArtifacts = dependenciesNotInProvidedScope();
- if ( !wrongScopedArtifacts.isEmpty() )
- {
- StringBuilder errorMessage = new StringBuilder(
- LS + LS + "Some dependencies of Maven Plugins are expected to be in provided scope." + LS
- + "Please make sure that dependencies listed below declared in POM" + LS
- + "have set '<scope>provided</scope>' as well." + LS + LS
- + "The following dependencies are in wrong scope:" + LS
- );
- for ( Artifact artifact : wrongScopedArtifacts )
- {
- errorMessage.append( " * " ).append( artifact ).append( LS );
- }
- errorMessage.append( LS ).append( LS );
-
- getLog().error( errorMessage.toString() );
- }
- }
-
String defaultGoalPrefix = getDefaultGoalPrefix( project );
-
+
if ( goalPrefix == null )
{
goalPrefix = defaultGoalPrefix;
@@ -273,67 +112,7 @@ public abstract class AbstractGeneratorMojo
+ defaultGoalPrefix + "'." + LS );
}
- mojoScanner.setActiveExtractors( extractors );
-
- // TODO: could use this more, eg in the writing of the plugin descriptor!
- PluginDescriptor pluginDescriptor = new PluginDescriptor();
-
- pluginDescriptor.setGroupId( project.getGroupId() );
-
- pluginDescriptor.setArtifactId( project.getArtifactId() );
-
- pluginDescriptor.setVersion( project.getVersion() );
-
- pluginDescriptor.setGoalPrefix( goalPrefix );
-
- pluginDescriptor.setName( project.getName() );
-
- pluginDescriptor.setDescription( project.getDescription() );
-
- if ( encoding == null || encoding.length() < 1 )
- {
- getLog().warn( "Using platform encoding (" + ReaderFactory.FILE_ENCODING
- + " actually) to read mojo source files, i.e. build is platform dependent!" );
- }
- else
- {
- getLog().info( "Using '" + encoding + "' encoding to read mojo source files." );
- }
-
- try
- {
- List<ComponentDependency> deps = GeneratorUtils.toComponentDependencies( project.getArtifacts() );
- pluginDescriptor.setDependencies( deps );
-
- PluginToolsRequest request = new DefaultPluginToolsRequest( project, pluginDescriptor );
- request.setEncoding( encoding );
- request.setSkipErrorNoDescriptorsFound( skipErrorNoDescriptorsFound );
- request.setDependencies( filterMojoDependencies() );
- request.setLocal( this.local );
- request.setRemoteRepos( this.remoteRepos );
-
- mojoScanner.populatePluginDescriptor( request );
-
- File outputDirectory = getOutputDirectory();
- outputDirectory.mkdirs();
-
- createGenerator().execute( outputDirectory, request );
- buildContext.refresh( outputDirectory );
- }
- catch ( GeneratorException e )
- {
- throw new MojoExecutionException( "Error writing plugin descriptor", e );
- }
- catch ( InvalidPluginDescriptorException | ExtractionException e )
- {
- throw new MojoExecutionException( "Error extracting plugin descriptor: '" + e.getLocalizedMessage() + "'",
- e );
- }
- catch ( LinkageError e )
- {
- throw new MojoExecutionException( "The API of the mojo scanner is not compatible with this plugin version."
- + " Please check the plugin dependencies configured in the POM and ensure the versions match.", e );
- }
+ generate();
}
static String getDefaultGoalPrefix( MavenProject project )
@@ -349,61 +128,4 @@ public abstract class AbstractGeneratorMojo
}
return defaultGoalPrefix;
}
-
- /**
- * Collects all dependencies expected to be in "provided" scope but are NOT in "provided" scope.
- */
- private Set<Artifact> dependenciesNotInProvidedScope()
- {
- LinkedHashSet<Artifact> wrongScopedDependencies = new LinkedHashSet<>();
-
- for ( Artifact dependency : project.getArtifacts() )
- {
- String ga = dependency.getGroupId() + ":" + dependency.getArtifactId();
- if ( expectedProvidedScopeGroupIds.contains( dependency.getGroupId() )
- && !expectedProvidedScopeExclusions.contains( ga )
- && !Artifact.SCOPE_PROVIDED.equals( dependency.getScope() ) )
- {
- wrongScopedDependencies.add( dependency );
- }
- }
-
- return wrongScopedDependencies;
- }
-
- /**
- * Get dependencies filtered with mojoDependencies configuration.
- *
- * @return eventually filtered dependencies, or even <code>null</code> if configured with empty mojoDependencies
- * list
- * @see #mojoDependencies
- */
- private Set<Artifact> filterMojoDependencies()
- {
- Set<Artifact> filteredArtifacts;
- if ( mojoDependencies == null )
- {
- filteredArtifacts = new LinkedHashSet<>( project.getArtifacts() );
- }
- else if ( mojoDependencies.size() == 0 )
- {
- filteredArtifacts = null;
- }
- else
- {
- filteredArtifacts = new LinkedHashSet<>();
-
- ArtifactFilter filter = new IncludesArtifactFilter( mojoDependencies );
-
- for ( Artifact artifact : project.getArtifacts() )
- {
- if ( filter.include( artifact ) )
- {
- filteredArtifacts.add( artifact );
- }
- }
- }
-
- return filteredArtifacts;
- }
}
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 9827a77f..1a6f3298 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
@@ -20,13 +20,34 @@ package org.apache.maven.plugin.plugin;
*/
import java.io.File;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.maven.artifact.Artifact;
+import org.apache.maven.artifact.repository.ArtifactRepository;
+import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
+import org.apache.maven.artifact.resolver.filter.IncludesArtifactFilter;
import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException;
+import org.apache.maven.plugin.descriptor.PluginDescriptor;
+import org.apache.maven.plugins.annotations.Component;
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.annotations.ResolutionScope;
-import org.apache.maven.tools.plugin.generator.Generator;
+import org.apache.maven.tools.plugin.DefaultPluginToolsRequest;
+import org.apache.maven.tools.plugin.PluginToolsRequest;
+import org.apache.maven.tools.plugin.extractor.ExtractionException;
+import org.apache.maven.tools.plugin.generator.GeneratorException;
+import org.apache.maven.tools.plugin.generator.GeneratorUtils;
import org.apache.maven.tools.plugin.generator.PluginDescriptorGenerator;
+import org.apache.maven.tools.plugin.scanner.MojoScanner;
+import org.codehaus.plexus.component.repository.ComponentDependency;
+import org.codehaus.plexus.util.ReaderFactory;
+import org.sonatype.plexus.build.incremental.BuildContext;
/**
* <p>
@@ -51,7 +72,15 @@ public class DescriptorGeneratorMojo
* The directory where the generated <code>plugin.xml</code> file will be put.
*/
@Parameter( defaultValue = "${project.build.outputDirectory}/META-INF/maven", readonly = true )
- protected File outputDirectory;
+ private File outputDirectory;
+
+ /**
+ * The file encoding of the source files.
+ *
+ * @since 2.5
+ */
+ @Parameter( property = "encoding", defaultValue = "${project.build.sourceEncoding}" )
+ private String encoding;
/**
* A flag to disable generation of the <code>plugin.xml</code> in favor of a hand authored plugin descriptor.
@@ -62,36 +91,259 @@ public class DescriptorGeneratorMojo
private boolean skipDescriptor;
/**
- * {@inheritDoc}
+ * <p>
+ * The role names of mojo extractors to use.
+ * </p>
+ * <p>
+ * If not set, all mojo extractors will be used. If set to an empty extractor name, no mojo extractors
+ * will be used.
+ * </p>
+ * Example:
+ * <pre>
+ * <!-- Use all mojo extractors -->
+ * <extractors/>
+ *
+ * <!-- Use no mojo extractors -->
+ * <extractors>
+ * <extractor/>
+ * </extractors>
+ *
+ * <!-- Use only bsh mojo extractor -->
+ * <extractors>
+ * <extractor>bsh</extractor>
+ * </extractors>
+ * </pre>
*/
- @Override
- protected File getOutputDirectory()
- {
- return outputDirectory;
- }
+ @Parameter
+ private Set<String> extractors;
+
/**
- * {@inheritDoc}
+ * By default, an exception is throw if no mojo descriptor is found. As the maven-plugin is defined in core, the
+ * descriptor generator mojo is bound to generate-resources phase.
+ * But for annotations, the compiled classes are needed, so skip error
+ *
+ * @since 3.0
*/
- @Override
- protected Generator createGenerator()
- {
- return new PluginDescriptorGenerator( getLog() );
- }
+ @Parameter( property = "maven.plugin.skipErrorNoDescriptorsFound", defaultValue = "false" )
+ private boolean skipErrorNoDescriptorsFound;
+
+ /**
+ * Flag controlling is "expected dependencies in provided scope" check to be performed or not. Default value:
+ * {@code true}.
+ *
+ * @since 3.6.3
+ */
+ @Parameter( defaultValue = "true", property = "maven.plugin.checkExpectedProvidedScope" )
+ private boolean checkExpectedProvidedScope = true;
+
+ /**
+ * List of {@code groupId} strings of artifact coordinates that are expected to be in "provided" scope. Default
+ * value: {@code ["org.apache.maven"]}.
+ *
+ * @since 3.6.3
+ */
+ @Parameter
+ private List<String> expectedProvidedScopeGroupIds = Collections.singletonList( "org.apache.maven" );
/**
- * {@inheritDoc}
+ * List of {@code groupId:artifactId} strings of artifact coordinates that are to be excluded from "expected
+ * provided scope" check. Default value: {@code ["org.apache.maven:maven-archiver", "org.apache.maven:maven-jxr"]}.
+ *
+ * @since 3.6.3
*/
- @Override
- public void execute()
+ @Parameter
+ private List<String> expectedProvidedScopeExclusions = Arrays.asList(
+ "org.apache.maven:maven-archiver",
+ "org.apache.maven:maven-jxr" );
+
+ /**
+ * Specify the dependencies as {@code groupId:artifactId} containing (abstract) Mojos, to filter
+ * dependencies scanned at runtime and focus on dependencies that are really useful to Mojo analysis.
+ * By default, the value is {@code null} and all dependencies are scanned (as before this parameter was added).
+ * If specified in the configuration with no children, no dependencies are scanned.
+ *
+ * @since 3.5
+ */
+ @Parameter
+ private List<String> mojoDependencies = null;
+
+ /**
+ * List of Remote Repositories used by the resolver
+ *
+ * @since 3.0
+ */
+ @Parameter( defaultValue = "${project.remoteArtifactRepositories}", required = true, readonly = true )
+ private List<ArtifactRepository> remoteRepos;
+
+ /**
+ * Location of the local repository.
+ *
+ * @since 3.0
+ */
+ @Parameter( defaultValue = "${localRepository}", required = true, readonly = true )
+ private ArtifactRepository local;
+
+ /**
+ * The component used for scanning the source tree for mojos.
+ */
+ @Component
+ private MojoScanner mojoScanner;
+
+ @Component
+ protected BuildContext buildContext;
+
+ public void generate()
throws MojoExecutionException
{
+
if ( skipDescriptor )
{
+ getLog().warn( "Execution skipped" );
return;
}
- super.execute();
+ if ( checkExpectedProvidedScope )
+ {
+ Set<Artifact> wrongScopedArtifacts = dependenciesNotInProvidedScope();
+ if ( !wrongScopedArtifacts.isEmpty() )
+ {
+ StringBuilder errorMessage = new StringBuilder(
+ LS + LS + "Some dependencies of Maven Plugins are expected to be in provided scope." + LS
+ + "Please make sure that dependencies listed below declared in POM" + LS
+ + "have set '<scope>provided</scope>' as well." + LS + LS
+ + "The following dependencies are in wrong scope:" + LS
+ );
+ for ( Artifact artifact : wrongScopedArtifacts )
+ {
+ errorMessage.append( " * " ).append( artifact ).append( LS );
+ }
+ errorMessage.append( LS ).append( LS );
+
+ getLog().error( errorMessage.toString() );
+ }
+ }
+
+ mojoScanner.setActiveExtractors( extractors );
+
+ // TODO: could use this more, eg in the writing of the plugin descriptor!
+ PluginDescriptor pluginDescriptor = new PluginDescriptor();
+
+ pluginDescriptor.setGroupId( project.getGroupId() );
+
+ pluginDescriptor.setArtifactId( project.getArtifactId() );
+
+ pluginDescriptor.setVersion( project.getVersion() );
+
+ pluginDescriptor.setGoalPrefix( goalPrefix );
+
+ pluginDescriptor.setName( project.getName() );
+
+ pluginDescriptor.setDescription( project.getDescription() );
+
+ if ( encoding == null || encoding.length() < 1 )
+ {
+ getLog().warn( "Using platform encoding (" + ReaderFactory.FILE_ENCODING
+ + " actually) to read mojo source files, i.e. build is platform dependent!" );
+ }
+ else
+ {
+ getLog().info( "Using '" + encoding + "' encoding to read mojo source files." );
+ }
+
+ try
+ {
+ List<ComponentDependency> deps = GeneratorUtils.toComponentDependencies( project.getArtifacts() );
+ pluginDescriptor.setDependencies( deps );
+
+ PluginToolsRequest request = new DefaultPluginToolsRequest( project, pluginDescriptor );
+ request.setEncoding( encoding );
+ request.setSkipErrorNoDescriptorsFound( skipErrorNoDescriptorsFound );
+ request.setDependencies( filterMojoDependencies() );
+ request.setLocal( this.local );
+ request.setRemoteRepos( this.remoteRepos );
+
+ mojoScanner.populatePluginDescriptor( request );
+
+ outputDirectory.mkdirs();
+
+ PluginDescriptorGenerator pluginDescriptorGenerator = new PluginDescriptorGenerator();
+ pluginDescriptorGenerator.execute( outputDirectory, request );
+
+ buildContext.refresh( outputDirectory );
+ }
+ catch ( GeneratorException e )
+ {
+ throw new MojoExecutionException( "Error writing plugin descriptor", e );
+ }
+ catch ( InvalidPluginDescriptorException | ExtractionException e )
+ {
+ throw new MojoExecutionException( "Error extracting plugin descriptor: '" + e.getLocalizedMessage() + "'",
+ e );
+ }
+ catch ( LinkageError e )
+ {
+ throw new MojoExecutionException( "The API of the mojo scanner is not compatible with this plugin version."
+ + " Please check the plugin dependencies configured"
+ + " in the POM and ensure the versions match.",
+ e );
+ }
}
+ /**
+ * Collects all dependencies expected to be in "provided" scope but are NOT in "provided" scope.
+ */
+ private Set<Artifact> dependenciesNotInProvidedScope()
+ {
+ LinkedHashSet<Artifact> wrongScopedDependencies = new LinkedHashSet<>();
+
+ for ( Artifact dependency : project.getArtifacts() )
+ {
+ String ga = dependency.getGroupId() + ":" + dependency.getArtifactId();
+ if ( expectedProvidedScopeGroupIds.contains( dependency.getGroupId() )
+ && !expectedProvidedScopeExclusions.contains( ga )
+ && !Artifact.SCOPE_PROVIDED.equals( dependency.getScope() ) )
+ {
+ wrongScopedDependencies.add( dependency );
+ }
+ }
+
+ return wrongScopedDependencies;
+ }
+
+ /**
+ * Get dependencies filtered with mojoDependencies configuration.
+ *
+ * @return eventually filtered dependencies, or even <code>null</code> if configured with empty mojoDependencies
+ * list
+ * @see #mojoDependencies
+ */
+ private Set<Artifact> filterMojoDependencies()
+ {
+ Set<Artifact> filteredArtifacts;
+ if ( mojoDependencies == null )
+ {
+ filteredArtifacts = new LinkedHashSet<>( project.getArtifacts() );
+ }
+ else if ( mojoDependencies.isEmpty() )
+ {
+ filteredArtifacts = null;
+ }
+ else
+ {
+ filteredArtifacts = new LinkedHashSet<>();
+
+ ArtifactFilter filter = new IncludesArtifactFilter( mojoDependencies );
+
+ for ( Artifact artifact : project.getArtifacts() )
+ {
+ if ( filter.include( artifact ) )
+ {
+ filteredArtifacts.add( artifact );
+ }
+ }
+ }
+
+ return filteredArtifacts;
+ }
}
diff --git a/maven-plugin-plugin/src/main/java/org/apache/maven/plugin/plugin/HelpGeneratorMojo.java b/maven-plugin-plugin/src/main/java/org/apache/maven/plugin/plugin/HelpGeneratorMojo.java
index 7cc472e5..2d8a2913 100644
--- a/maven-plugin-plugin/src/main/java/org/apache/maven/plugin/plugin/HelpGeneratorMojo.java
+++ b/maven-plugin-plugin/src/main/java/org/apache/maven/plugin/plugin/HelpGeneratorMojo.java
@@ -19,7 +19,11 @@ package org.apache.maven.plugin.plugin;
* under the License.
*/
+import javax.lang.model.SourceVersion;
+
import java.io.File;
+import java.util.Arrays;
+import java.util.stream.Collectors;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugins.annotations.Component;
@@ -27,19 +31,19 @@ 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.annotations.ResolutionScope;
-import org.apache.maven.tools.plugin.generator.Generator;
+import org.apache.maven.tools.plugin.generator.GeneratorException;
import org.apache.maven.tools.plugin.generator.PluginHelpGenerator;
+import org.codehaus.plexus.util.StringUtils;
import org.codehaus.plexus.velocity.VelocityComponent;
/**
* Generates a <code>HelpMojo</code> class.
- *
- * @author <a href="mailto:vincent.siveton@gmail.com">Vincent Siveton</a>
*
+ * @author <a href="mailto:vincent.siveton@gmail.com">Vincent Siveton</a>
* @since 2.4
*/
@Mojo( name = "helpmojo", defaultPhase = LifecyclePhase.GENERATE_SOURCES, threadSafe = true,
- requiresDependencyResolution = ResolutionScope.COMPILE )
+ requiresDependencyResolution = ResolutionScope.COMPILE )
public class HelpGeneratorMojo
extends AbstractGeneratorMojo
{
@@ -50,9 +54,14 @@ public class HelpGeneratorMojo
protected File outputDirectory;
/**
- * The name of the package for the generated <code>HelpMojo</code>. By default, the package will be calculated based
- * on the packages of the other plugin goals.
- *
+ * The name of the package for the generated <code>HelpMojo</code>.
+ * <p>
+ * By default, the package name will be calculated as <code>groupId + "." + artifactId</code> with additional
+ * <ul>
+ * <li><code>-</code> (dashes) will be replaced by <code>_</code> (underscores)</li>
+ * <li><code>_</code> (underscore) will be added before each number or Java keyword at the beginning of name</li>
+ * </ul>
+ *
* @since 2.6
*/
@Parameter
@@ -64,41 +73,59 @@ public class HelpGeneratorMojo
@Component
private VelocityComponent velocity;
- /**
- * {@inheritDoc}
- */
- @Override
- protected File getOutputDirectory()
+ String getHelpPackageName()
{
- return outputDirectory;
+ String packageName = null;
+ if ( StringUtils.isNotBlank( helpPackageName ) )
+ {
+ packageName = helpPackageName;
+ }
+
+ if ( packageName == null )
+ {
+ packageName = project.getGroupId() + "." + project.getArtifactId();
+ packageName = packageName.replace( "-", "_" );
+
+ String[] packageItems = packageName.split( "\\." );
+ packageName = Arrays.stream( packageItems )
+ .map( this::prefixSpecialCase )
+ .collect( Collectors.joining( "." ) );
+ }
+
+ return packageName;
}
- /**
- * {@inheritDoc}
- */
- @Override
- protected Generator createGenerator()
+ private String prefixSpecialCase( String name )
{
- return new PluginHelpGenerator().setHelpPackageName( helpPackageName ).setVelocityComponent( this.velocity );
+ if ( SourceVersion.isKeyword( name ) || !Character.isJavaIdentifierStart( name.charAt( 0 ) ) )
+ {
+ name = "_" + name;
+ }
+ return name;
}
- /**
- * {@inheritDoc}
- */
@Override
- public void execute()
- throws MojoExecutionException
+ protected void generate() throws MojoExecutionException
{
- // force value for this plugin
- skipErrorNoDescriptorsFound = true;
+ PluginHelpGenerator pluginHelpGenerator = new PluginHelpGenerator()
+ .setMavenProject( project )
+ .setHelpPackageName( getHelpPackageName() )
+ .setGoalPrefix( goalPrefix )
+ .setVelocityComponent( velocity );
- super.execute();
+ try
+ {
+ pluginHelpGenerator.execute( outputDirectory );
+ }
+ catch ( GeneratorException e )
+ {
+ throw new MojoExecutionException( e.getMessage(), e );
+ }
- if ( !project.getCompileSourceRoots().contains( outputDirectory.getAbsolutePath() ) && !skip )
+ if ( !project.getCompileSourceRoots().contains( outputDirectory.getAbsolutePath() ) )
{
project.addCompileSourceRoot( outputDirectory.getAbsolutePath() );
}
-
}
}
diff --git a/maven-plugin-plugin/src/test/java/org/apache/maven/plugin/plugin/HelpGeneratorMojoTest.java b/maven-plugin-plugin/src/test/java/org/apache/maven/plugin/plugin/HelpGeneratorMojoTest.java
new file mode 100644
index 00000000..5d657091
--- /dev/null
+++ b/maven-plugin-plugin/src/test/java/org/apache/maven/plugin/plugin/HelpGeneratorMojoTest.java
@@ -0,0 +1,63 @@
+package org.apache.maven.plugin.plugin;
+
+/*
+ * 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.
+ */
+
+import java.util.stream.Stream;
+
+import org.apache.maven.project.MavenProject;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class HelpGeneratorMojoTest
+{
+
+ public static Stream<Arguments> packageNameShouldBeCorrect()
+ {
+ return Stream.of(
+ Arguments.of( aProject( "groupId", "artifactId" ), "groupId.artifactId" ),
+ Arguments.of( aProject( "groupId", "123-artifactId" ), "groupId._123_artifactId" ),
+ Arguments.of( aProject( "group-Id", "artifact-Id" ), "group_Id.artifact_Id" ),
+ Arguments.of( aProject( "group-Id", "int" ), "group_Id._int" )
+ );
+ }
+
+ @ParameterizedTest
+ @MethodSource
+ void packageNameShouldBeCorrect( MavenProject project, String expectedPackageName )
+ {
+ HelpGeneratorMojo mojo = new HelpGeneratorMojo();
+ mojo.project = project;
+
+ String packageName = mojo.getHelpPackageName();
+ assertEquals( expectedPackageName, packageName );
+ }
+
+ private static MavenProject aProject( String groupId, String artifactId )
+ {
+
+ MavenProject mavenProject = new MavenProject();
+ mavenProject.setGroupId( groupId );
+ mavenProject.setArtifactId( artifactId );
+ return mavenProject;
+ }
+}
diff --git a/maven-plugin-tools-generators/src/main/java/org/apache/maven/tools/plugin/generator/PluginDescriptorGenerator.java b/maven-plugin-tools-generators/src/main/java/org/apache/maven/tools/plugin/generator/PluginDescriptorGenerator.java
index 6e777c08..70581131 100644
--- a/maven-plugin-tools-generators/src/main/java/org/apache/maven/tools/plugin/generator/PluginDescriptorGenerator.java
+++ b/maven-plugin-tools-generators/src/main/java/org/apache/maven/tools/plugin/generator/PluginDescriptorGenerator.java
@@ -19,8 +19,6 @@ package org.apache.maven.tools.plugin.generator;
* under the License.
*/
-import static java.nio.charset.StandardCharsets.UTF_8;
-
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
@@ -31,12 +29,11 @@ import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
-import org.apache.maven.plugin.descriptor.DuplicateMojoDescriptorException;
+
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.Requirement;
-import org.apache.maven.plugin.logging.Log;
import org.apache.maven.project.MavenProject;
import org.apache.maven.tools.plugin.ExtendedMojoDescriptor;
import org.apache.maven.tools.plugin.PluginToolsRequest;
@@ -45,6 +42,8 @@ import org.codehaus.plexus.util.StringUtils;
import org.codehaus.plexus.util.xml.PrettyPrintXMLWriter;
import org.codehaus.plexus.util.xml.XMLWriter;
+import static java.nio.charset.StandardCharsets.UTF_8;
+
/**
* Generate a <a href="/ref/current/maven-plugin-api/plugin.html">Maven Plugin Descriptor XML file</a> and
* corresponding <code>plugin-help.xml</code> help content for {@link PluginHelpGenerator}.
@@ -54,20 +53,10 @@ public class PluginDescriptorGenerator
implements Generator
{
- private final Log log;
-
- public PluginDescriptorGenerator( Log log )
- {
- this.log = log;
- }
-
@Override
public void execute( File destinationDirectory, PluginToolsRequest request )
throws GeneratorException
{
- // eventually rewrite help mojo class to match actual package name
- PluginHelpGenerator.rewriteHelpMojo( request, log );
-
try
{
// write complete plugin.xml descriptor
@@ -86,10 +75,6 @@ public class PluginDescriptorGenerator
{
throw new GeneratorException( e.getMessage(), e );
}
- catch ( DuplicateMojoDescriptorException e )
- {
- throw new GeneratorException( e.getMessage(), e );
- }
}
private String getVersion()
@@ -100,7 +85,7 @@ public class PluginDescriptorGenerator
}
public void writeDescriptor( File destinationFile, PluginToolsRequest request, boolean helpDescriptor )
- throws IOException, DuplicateMojoDescriptorException
+ throws IOException
{
PluginDescriptor pluginDescriptor = request.getPluginDescriptor();
@@ -169,11 +154,6 @@ public class PluginDescriptorGenerator
}
}
- protected void processMojoDescriptor( MojoDescriptor mojoDescriptor, XMLWriter w )
- {
- processMojoDescriptor( mojoDescriptor, w, false );
- }
-
/**
* @param mojoDescriptor not null
* @param w not null
diff --git a/maven-plugin-tools-generators/src/main/java/org/apache/maven/tools/plugin/generator/PluginHelpGenerator.java b/maven-plugin-tools-generators/src/main/java/org/apache/maven/tools/plugin/generator/PluginHelpGenerator.java
index d430e5a0..9149712c 100644
--- a/maven-plugin-tools-generators/src/main/java/org/apache/maven/tools/plugin/generator/PluginHelpGenerator.java
+++ b/maven-plugin-tools-generators/src/main/java/org/apache/maven/tools/plugin/generator/PluginHelpGenerator.java
@@ -19,79 +19,42 @@ package org.apache.maven.tools.plugin.generator;
* under the License.
*/
-import static java.nio.charset.StandardCharsets.UTF_8;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.StringWriter;
-import org.apache.maven.plugin.descriptor.MojoDescriptor;
-import org.apache.maven.plugin.descriptor.PluginDescriptor;
-import org.apache.maven.plugin.logging.Log;
import org.apache.maven.project.MavenProject;
-import org.apache.maven.tools.plugin.PluginToolsRequest;
import org.apache.velocity.VelocityContext;
import org.codehaus.plexus.logging.AbstractLogEnabled;
import org.codehaus.plexus.logging.Logger;
import org.codehaus.plexus.logging.console.ConsoleLogger;
import org.codehaus.plexus.util.FileUtils;
-import org.codehaus.plexus.util.IOUtil;
-import org.codehaus.plexus.util.PropertyUtils;
import org.codehaus.plexus.util.StringUtils;
import org.codehaus.plexus.velocity.VelocityComponent;
-import org.objectweb.asm.ClassReader;
-import org.objectweb.asm.ClassVisitor;
-import org.objectweb.asm.ClassWriter;
-import org.objectweb.asm.commons.ClassRemapper;
-import org.objectweb.asm.commons.Remapper;
-import org.objectweb.asm.commons.SimpleRemapper;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.OutputStreamWriter;
-import java.io.PrintWriter;
-import java.io.Reader;
-import java.io.StringWriter;
-import java.nio.charset.Charset;
-import java.util.List;
-import java.util.Properties;
+import static java.nio.charset.StandardCharsets.UTF_8;
/**
* Generates an <code>HelpMojo</code> class from <code>help-class-source.vm</code> template.
* The generated mojo reads help content from <code>META-INF/maven/${groupId}/${artifactId}/plugin-help.xml</code>
* resource, which is generated by this {@link PluginDescriptorGenerator}.
- * <p>Notice that the help mojo source needs to be generated before compilation, but when Java annotations are used,
- * plugin descriptor content is available only after compilation (detecting annotations in .class files):
- * help mojo source can be generated with empty package only (and no plugin descriptor available yet), then needs
- * to be updated after compilation - through {@link #rewriteHelpMojo(PluginToolsRequest, Log)} which is called from
- * plugin descriptor XML generation.</p>
*
* @author <a href="mailto:vincent.siveton@gmail.com">Vincent Siveton</a>
* @since 2.4
*/
public class PluginHelpGenerator
extends AbstractLogEnabled
- implements Generator
{
/**
* Default generated class name
*/
private static final String HELP_MOJO_CLASS_NAME = "HelpMojo";
- /**
- * Help properties file, to store data about generated source.
- */
- private static final String HELP_PROPERTIES_FILENAME = "maven-plugin-help.properties";
-
- /**
- * Default goal
- */
- private static final String HELP_GOAL = "help";
-
private String helpPackageName;
-
- private boolean useAnnotations;
-
+ private String goalPrefix;
+ private MavenProject mavenProject;
private VelocityComponent velocityComponent;
/**
@@ -106,41 +69,10 @@ public class PluginHelpGenerator
// Public methods
// ----------------------------------------------------------------------
- /**
- * {@inheritDoc}
- */
- @Override
- public void execute( File destinationDirectory, PluginToolsRequest request )
+ public void execute( File destinationDirectory )
throws GeneratorException
{
- PluginDescriptor pluginDescriptor = request.getPluginDescriptor();
-
- String helpImplementation = getImplementation( pluginDescriptor );
-
- List<MojoDescriptor> mojoDescriptors = pluginDescriptor.getMojos();
-
- if ( mojoDescriptors != null )
- {
- // Verify that no help goal already exists
- MojoDescriptor descriptor = pluginDescriptor.getMojo( HELP_GOAL );
-
- if ( ( descriptor != null ) && !descriptor.getImplementation().equals( helpImplementation ) )
- {
- if ( getLogger().isWarnEnabled() )
- {
- getLogger().warn( "\n\nA help goal (" + descriptor.getImplementation()
- + ") already exists in this plugin. SKIPPED THE " + helpImplementation
- + " GENERATION.\n" );
- }
-
- return;
- }
- }
-
- writeHelpPropertiesFile( request, destinationDirectory );
-
- useAnnotations = request.getProject().getArtifactMap().containsKey(
- "org.apache.maven.plugin-tools:maven-plugin-annotations" );
+ String helpImplementation = getImplementation();
try
{
@@ -150,9 +82,9 @@ public class PluginHelpGenerator
helpClass.getParentFile().mkdirs();
String helpClassSources =
- getHelpClassSources( getPluginHelpPath( request.getProject() ), pluginDescriptor );
+ getHelpClassSources( getPluginHelpPath( mavenProject ) );
- FileUtils.fileWrite( helpClass, request.getEncoding(), helpClassSources );
+ FileUtils.fileWrite( helpClass, UTF_8.name(), helpClassSources );
}
catch ( IOException e )
{
@@ -166,14 +98,21 @@ public class PluginHelpGenerator
return this;
}
- public VelocityComponent getVelocityComponent()
+ public PluginHelpGenerator setVelocityComponent( VelocityComponent velocityComponent )
{
- return velocityComponent;
+ this.velocityComponent = velocityComponent;
+ return this;
}
- public PluginHelpGenerator setVelocityComponent( VelocityComponent velocityComponent )
+ public PluginHelpGenerator setGoalPrefix( String goalPrefix )
{
- this.velocityComponent = velocityComponent;
+ this.goalPrefix = goalPrefix;
+ return this;
+ }
+
+ public PluginHelpGenerator setMavenProject( MavenProject mavenProject )
+ {
+ this.mavenProject = mavenProject;
return this;
}
@@ -181,21 +120,17 @@ public class PluginHelpGenerator
// Private methods
// ----------------------------------------------------------------------
- private String getHelpClassSources( String pluginHelpPath, PluginDescriptor pluginDescriptor )
+ private String getHelpClassSources( String pluginHelpPath )
throws IOException
{
VelocityContext context = new VelocityContext();
- if ( this.helpPackageName != null )
- {
- context.put( "helpPackageName", this.helpPackageName );
- }
- else
- {
- context.put( "helpPackageName", "" );
- }
+ boolean useAnnotations = mavenProject.getArtifactMap().containsKey(
+ "org.apache.maven.plugin-tools:maven-plugin-annotations" );
+
+ context.put( "helpPackageName", helpPackageName );
context.put( "pluginHelpPath", pluginHelpPath );
- context.put( "artifactId", pluginDescriptor.getArtifactId() );
- context.put( "goalPrefix", pluginDescriptor.getGoalPrefix() );
+ context.put( "artifactId", mavenProject.getArtifactId() );
+ context.put( "goalPrefix", goalPrefix );
context.put( "useAnnotations", useAnnotations );
StringWriter stringWriter = new StringWriter();
@@ -214,226 +149,17 @@ public class PluginHelpGenerator
}
/**
- * @param pluginDescriptor The descriptor of the plugin for which to generate a help goal, must not be
- * <code>null</code>.
* @return The implementation.
*/
- private String getImplementation( PluginDescriptor pluginDescriptor )
+ private String getImplementation( )
{
- if ( StringUtils.isEmpty( helpPackageName ) )
- {
- helpPackageName = GeneratorUtils.discoverPackageName( pluginDescriptor );
- }
-
return StringUtils.isEmpty( helpPackageName )
? HELP_MOJO_CLASS_NAME
: helpPackageName + '.' + HELP_MOJO_CLASS_NAME;
}
- /**
- * Write help properties files for later use to eventually rewrite Help Mojo.
- *
- * @param request
- * @throws GeneratorException
- * @see {@link #rewriteHelpMojo(PluginToolsRequest, Log)}
- */
- private void writeHelpPropertiesFile( PluginToolsRequest request, File destinationDirectory )
- throws GeneratorException
- {
- Properties properties = new Properties();
- properties.put( "helpPackageName", helpPackageName == null ? "" : helpPackageName );
- properties.put( "destinationDirectory", destinationDirectory.getAbsolutePath() );
-
- File tmpPropertiesFile = new File( request.getProject().getBuild().getDirectory(), HELP_PROPERTIES_FILENAME );
-
- if ( tmpPropertiesFile.exists() )
- {
- tmpPropertiesFile.delete();
- }
- else if ( !tmpPropertiesFile.getParentFile().exists() )
- {
- tmpPropertiesFile.getParentFile().mkdirs();
- }
-
- try ( FileOutputStream fos = new FileOutputStream( tmpPropertiesFile ) )
- {
- properties.store( fos, "maven plugin help mojo generation informations" );
- }
- catch ( IOException e )
- {
- throw new GeneratorException( e.getMessage(), e );
- }
- }
-
static String getPluginHelpPath( MavenProject mavenProject )
{
return mavenProject.getGroupId() + "/" + mavenProject.getArtifactId() + "/plugin-help.xml";
}
-
- /**
- * Rewrite Help Mojo to match actual Mojos package name if it was not available at source generation
- * time. This is used at descriptor generation time.
- *
- * @param request
- * @throws GeneratorException
- */
- static void rewriteHelpMojo( PluginToolsRequest request, Log log )
- throws GeneratorException
- {
- File tmpPropertiesFile = new File( request.getProject().getBuild().getDirectory(), HELP_PROPERTIES_FILENAME );
-
- if ( !tmpPropertiesFile.exists() )
- {
- return;
- }
-
- Properties properties;
- try
- {
- properties = PropertyUtils.loadProperties( tmpPropertiesFile );
- }
- catch ( IOException e )
- {
- throw new GeneratorException( e.getMessage(), e );
- }
-
- String helpPackageName = properties.getProperty( "helpPackageName" );
-
- // if helpPackageName property is empty, we have to rewrite the class with a better package name than empty
- if ( StringUtils.isEmpty( helpPackageName ) )
- {
- String destDir = properties.getProperty( "destinationDirectory" );
- File destinationDirectory;
- if ( StringUtils.isEmpty( destDir ) )
- {
- // writeHelpPropertiesFile() creates 2 properties: find one without the other should not be possible
- log.warn( "\n\nUnexpected situation: destinationDirectory not defined in " + HELP_PROPERTIES_FILENAME
- + " during help mojo source generation but expected during XML descriptor generation." );
- log.warn( "Please check helpmojo goal version used in previous build phase." );
- log.warn( "If you just upgraded to plugin-tools >= 3.2 you must run a clean build at least once." );
- destinationDirectory = new File( "target/generated-sources/plugin" );
- log.warn( "Trying default location: " + destinationDirectory );
- }
- else
- {
- destinationDirectory = new File( destDir );
- }
- String helpMojoImplementation = rewriteHelpClassToMojoPackage( request, destinationDirectory, log );
-
- if ( helpMojoImplementation != null )
- {
- // rewrite plugin descriptor with new HelpMojo implementation class
- updateHelpMojoDescriptor( request.getPluginDescriptor(), helpMojoImplementation );
- }
- }
- }
-
- private static String rewriteHelpClassToMojoPackage( PluginToolsRequest request, File destinationDirectory,
- Log log )
- throws GeneratorException
- {
- String destinationPackage = GeneratorUtils.discoverPackageName( request.getPluginDescriptor() );
- if ( StringUtils.isEmpty( destinationPackage ) )
- {
- return null;
- }
- String packageAsDirectory = StringUtils.replace( destinationPackage, '.', '/' );
-
- String outputDirectory = request.getProject().getBuild().getOutputDirectory();
- File helpClassFile = new File( outputDirectory, HELP_MOJO_CLASS_NAME + ".class" );
- if ( !helpClassFile.exists() )
- {
- return null;
- }
-
- // rewrite help mojo source
- File helpSourceFile = new File( destinationDirectory, HELP_MOJO_CLASS_NAME + ".java" );
- if ( !helpSourceFile.exists() )
- {
- log.warn( "HelpMojo.java not found in default location: " + helpSourceFile.getAbsolutePath() );
- log.warn( "Help goal source won't be moved to package: " + destinationPackage );
- }
- else
- {
- File helpSourceFileNew =
- new File( destinationDirectory, packageAsDirectory + '/' + HELP_MOJO_CLASS_NAME + ".java" );
- if ( !helpSourceFileNew.getParentFile().exists() )
- {
- helpSourceFileNew.getParentFile().mkdirs();
- }
- Charset encoding = Charset.forName( request.getEncoding() );
- try ( Reader sourceReader = new InputStreamReader( new FileInputStream( helpSourceFile ), //
- encoding ); //
- PrintWriter sourceWriter = new PrintWriter(
- new OutputStreamWriter( new FileOutputStream( helpSourceFileNew ), //
- encoding ) ) )
- {
- sourceWriter.println( "package " + destinationPackage + ";" );
- IOUtil.copy( sourceReader, sourceWriter );
- }
- catch ( IOException e )
- {
- throw new GeneratorException( e.getMessage(), e );
- }
- helpSourceFileNew.setLastModified( helpSourceFile.lastModified() );
- helpSourceFile.delete();
- }
-
- // rewrite help mojo .class
- File rewriteHelpClassFile =
- new File( outputDirectory + '/' + packageAsDirectory, HELP_MOJO_CLASS_NAME + ".class" );
- if ( !rewriteHelpClassFile.getParentFile().exists() )
- {
- rewriteHelpClassFile.getParentFile().mkdirs();
- }
-
- ClassReader cr;
- try ( FileInputStream fileInputStream = new FileInputStream( helpClassFile ) )
- {
- cr = new ClassReader( fileInputStream );
- }
- catch ( IOException e )
- {
- throw new GeneratorException( e.getMessage(), e );
- }
-
- ClassWriter cw = new ClassWriter( 0 );
-
- Remapper packageRemapper =
- new SimpleRemapper( HELP_MOJO_CLASS_NAME, packageAsDirectory + '/' + HELP_MOJO_CLASS_NAME );
- ClassVisitor cv = new ClassRemapper( cw, packageRemapper );
-
- try
- {
- cr.accept( cv, ClassReader.EXPAND_FRAMES );
- }
- catch ( Throwable e )
- {
- throw new GeneratorException( "ASM issue processing class-file " + helpClassFile.getPath(), e );
- }
-
- byte[] renamedClass = cw.toByteArray();
- try ( FileOutputStream fos = new FileOutputStream( rewriteHelpClassFile ) )
- {
- fos.write( renamedClass );
- }
- catch ( IOException e )
- {
- throw new GeneratorException( "Error rewriting help class: " + e.getMessage(), e );
- }
-
- helpClassFile.delete();
-
- return destinationPackage + ".HelpMojo";
- }
-
- private static void updateHelpMojoDescriptor( PluginDescriptor pluginDescriptor, String helpMojoImplementation )
- {
- MojoDescriptor mojoDescriptor = pluginDescriptor.getMojo( HELP_GOAL );
-
- if ( mojoDescriptor != null )
- {
- mojoDescriptor.setImplementation( helpMojoImplementation );
- }
- }
}
diff --git a/maven-plugin-tools-generators/src/test/java/org/apache/maven/tools/plugin/generator/PluginHelpGeneratorTest.java b/maven-plugin-tools-generators/src/test/java/org/apache/maven/tools/plugin/generator/PluginHelpGeneratorTest.java
deleted file mode 100644
index e82453d0..00000000
--- a/maven-plugin-tools-generators/src/test/java/org/apache/maven/tools/plugin/generator/PluginHelpGeneratorTest.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package org.apache.maven.tools.plugin.generator;
-
-/*
- * 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.
- */
-
-import javax.inject.Inject;
-
-import org.codehaus.plexus.testing.PlexusTest;
-import org.codehaus.plexus.velocity.VelocityComponent;
-
-/**
- * @author <a href="mailto:vincent.siveton@gmail.com">Vincent Siveton</a>
- */
-@PlexusTest
-public class PluginHelpGeneratorTest
- extends AbstractGeneratorTestCase
-{
-
- @Inject
- VelocityComponent velocityComponent;
-
- // inherits tests from base class
- @Override
- protected void setupGenerator()
- throws Exception
- {
- generator = new PluginHelpGenerator().setVelocityComponent( velocityComponent );
-
- }
-}
diff --git a/maven-plugin-tools-java/src/test/java/org/apache/maven/tools/plugin/extractor/javadoc/JavaMojoDescriptorExtractorTest.java b/maven-plugin-tools-java/src/test/java/org/apache/maven/tools/plugin/extractor/javadoc/JavaMojoDescriptorExtractorTest.java
index b804d2f8..e734dc7f 100644
--- a/maven-plugin-tools-java/src/test/java/org/apache/maven/tools/plugin/extractor/javadoc/JavaMojoDescriptorExtractorTest.java
+++ b/maven-plugin-tools-java/src/test/java/org/apache/maven/tools/plugin/extractor/javadoc/JavaMojoDescriptorExtractorTest.java
@@ -128,7 +128,7 @@ public class JavaMojoDescriptorExtractorTest
request.getPluginDescriptor().addMojo( mojoDescriptor );
}
- Generator descriptorGenerator = new PluginDescriptorGenerator( new SystemStreamLog() );
+ Generator descriptorGenerator = new PluginDescriptorGenerator();
descriptorGenerator.execute( new File( root, directory ), request );
diff --git a/pom.xml b/pom.xml
index c1ea31da..943f5cc4 100644
--- a/pom.xml
+++ b/pom.xml
@@ -90,7 +90,7 @@
</distributionManagement>
<properties>
- <surefire.version>2.22.2</surefire.version>
+ <surefire.version>3.0.0-M7</surefire.version>
<javaVersion>8</javaVersion>
<pluginTestingHarnessVersion>3.3.0</pluginTestingHarnessVersion>
<mavenVersion>3.2.5</mavenVersion>
@@ -247,10 +247,11 @@
<scope>test</scope>
</dependency>
<dependency>
- <groupId>org.junit.jupiter</groupId>
- <artifactId>junit-jupiter-engine</artifactId>
+ <groupId>org.junit</groupId>
+ <artifactId>junit-bom</artifactId>
<version>5.8.2</version>
- <scope>test</scope>
+ <type>pom</type>
+ <scope>import</scope>
</dependency>
<dependency>
<groupId>org.codehaus.plexus</groupId>