From ce0b27953216d3775b6f3c8e364752c826e0a685 Mon Sep 17 00:00:00 2001 From: Build Pipeline Date: Sun, 27 Jun 2021 22:11:55 +0200 Subject: [PATCH] PR #45 - add unit test --- pom.xml | 14 + processor/pom.xml | 22 + .../AbstractAnnotationProcessorMojo.java | 1755 ++++++++--------- .../AnnotationProcessorMojoTest.java | 39 +- processor/src/test/resources/pr45/pom.xml | 31 + 5 files changed, 957 insertions(+), 904 deletions(-) diff --git a/pom.xml b/pom.xml index 2d41c89..ef00e80 100644 --- a/pom.xml +++ b/pom.xml @@ -117,12 +117,26 @@ This plugin could be considered the 'alter ego' of maven apt plugin http://mojo. plexus-compiler-manager ${plexus.compiler.version} + org.codehaus.plexus plexus-compiler-javac ${plexus.compiler.version} compile + + + org.apache.maven.plugin-testing + maven-plugin-testing-harness + 3.3.0 + test + + + org.apache.maven + maven-compat + ${maven.version} + test + diff --git a/processor/pom.xml b/processor/pom.xml index f6458bb..a255e6e 100644 --- a/processor/pom.xml +++ b/processor/pom.xml @@ -47,6 +47,18 @@ This plugin could be considered the 'alter ego' of maven apt plugin http://mojo. ${project.version} + + org.apache.maven + maven-compat + test + + + + org.apache.maven.plugin-testing + maven-plugin-testing-harness + test + + @@ -70,6 +82,16 @@ This plugin could be considered the 'alter ego' of maven apt plugin http://mojo. + + + src/main/resources + + + + src/test/resources + true + + diff --git a/processor/src/main/java/org/bsc/maven/plugin/processor/AbstractAnnotationProcessorMojo.java b/processor/src/main/java/org/bsc/maven/plugin/processor/AbstractAnnotationProcessorMojo.java index 05b1ed5..127fe30 100644 --- a/processor/src/main/java/org/bsc/maven/plugin/processor/AbstractAnnotationProcessorMojo.java +++ b/processor/src/main/java/org/bsc/maven/plugin/processor/AbstractAnnotationProcessorMojo.java @@ -1,6 +1,6 @@ /* * Copyright (C) 2009 2010 2011 Bartolomeo Sorrentino - * + * * This file is part of maven-annotation-plugin. * * maven-annotation-plugin is free software: you can redistribute it and/or modify @@ -14,7 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License - * along with maven-annotation-plugin. If not, see . + * along with maven-annotation-plugin. If not, see . */ package org.bsc.maven.plugin.processor; @@ -89,996 +89,955 @@ /** - * * @author bsorrentino - * */ -public abstract class AbstractAnnotationProcessorMojo extends AbstractMojo -{ - - private static final String SOURCE_CLASSIFIER = "sources"; - - /** - * value of -release parameter in java 9+ - * - * @since 3.3.3 - */ - @Parameter - private String releaseVersion; - - /** - * - */ - @Parameter( defaultValue = "${project}", readonly = true ) - protected MavenProject project; - - /** - * - */ - @Parameter(property="plugin.artifacts", readonly=true) - private java.util.List pluginArtifacts; - - /** - * Specify the directory where to place generated source files (same behaviour of -s option) - * - */ - @Parameter - private File outputDirectory; - - /** - *

- * Classpath elements to supply as annotation processor path. If specified, the compiler will detect annotation - * processors only in those classpath elements. If omitted, the default classpath is used to detect annotation - * processors. The detection itself depends on the configuration of {@code processors}. - *

- *

- * Each classpath element is specified using their Maven coordinates (groupId, artifactId, version, classifier, - * type). Transitive dependencies are added automatically. Example: - *

- * - *
-     * <configuration>
-     *   <annotationProcessorPaths>
-     *     <path>
-     *       <groupId>org.sample</groupId>
-     *       <artifactId>sample-annotation-processor</artifactId>
-     *       <version>1.2.3</version>
-     *     </path>
-     *     <!-- ... more ... -->
-     *   </annotationProcessorPaths>
-     * </configuration>
-     * 
- * - * @since 5.0 - */ - @Parameter - private List annotationProcessorPaths; - - /** - * Annotation Processor FQN (Full Qualified Name) - when processors are not specified, the default discovery mechanism will be used - * - */ - @Parameter - private String[] processors; - - /** - * Additional compiler arguments - * - */ - @Parameter - private String compilerArguments; - - /** - * Additional processor options (see javax.annotation.processing.ProcessingEnvironment#getOptions() - * - */ - @Parameter( alias = "options" ) - private java.util.Map optionMap; - - /** - * Controls whether or not the output directory is added to compilation - */ - @Parameter - private Boolean addOutputDirectoryToCompilationSources; - - /** - * Indicates whether the build will continue even if there are compilation errors; defaults to true. - */ - @Parameter( defaultValue="true", required=true, property="annotation.failOnError" ) - private Boolean failOnError = true; - - /** - * Indicates whether the compiler output should be visible, defaults to true. - * - */ - @Parameter( defaultValue="true", required=true, property="annotation.outputDiagnostics" ) - private boolean outputDiagnostics = true; - - /** - * System properties set before processor invocation. - * - */ - @Parameter - private java.util.Map systemProperties; - - /** - * includes pattern - */ - @Parameter - private String[] includes; - - /** - * excludes pattern - */ - @Parameter - private String[] excludes; - - /** - * additional source directories for the annotation processors. - */ - @Parameter - private java.util.List additionalSourceDirectories; - - - /** - * if true add to the source directory of the annotation processor all compile source roots detected int the project - * This is useful when we plan to use build-helper-maven-plugin - * - * @since 2.1.1 - */ - @Parameter(defaultValue = "false") - private boolean addCompileSourceRoots = false; - - - /** - * append source artifacts to sources list - * - * @since 2.2.0 - */ - @Parameter( defaultValue = "false") - private boolean appendSourceArtifacts = false; - - /** - * The character set used for decoding sources - * - * @since 2.2.1 - */ - @Parameter(property = "project.build.sourceEncoding") - private String encoding; +public abstract class AbstractAnnotationProcessorMojo extends AbstractMojo { + + private static final String SOURCE_CLASSIFIER = "sources"; /** - * The entry point to Aether, i.e. the component doing all the work. - * - */ - @Component - private RepositorySystem repoSystem; - - /** - * The current repository/network configuration of Maven. - * - */ - @Parameter( defaultValue = "${repositorySystemSession}",readonly = true ) - private RepositorySystemSession repoSession; - - /** - * The project's remote repositories to use for the resolution of plugins and their dependencies. - * - */ - @Parameter( defaultValue = "${project.remoteProjectRepositories}",readonly = true ) - private List remoteRepos; - - /** - * List of artifacts on which perform sources scanning - * - * Each artifact must be specified in the form grouId:artifactId. - * If you need to include all artifacts belonging a groupId, specify as artifactId the character '*' - * - *
- * e.g. - *
-     * 
-     * org.bsc.maven:maven-confluence-plugin
-     * org.bsc.maven:*
-     * 
-     * 
- * - * @since 2.2.5 - */ - @Parameter() - private java.util.List processSourceArtifacts = Collections.emptyList(); - - /** - * Set this to true to skip annotation processing. - * - * @since 3.1.0 - */ - @Parameter(defaultValue = "false", property = "skipAnnotationProcessing") - protected boolean skip; - - /** - * Allows running the compiler in a separate process. - * If false it uses the built in compiler, while if true it will use an executable. - * - * to set source and target use - *
-     *  maven.processor.source
-     *  maven.processor.target
-     * 
- * @since 3.3 - */ - @Parameter(defaultValue = "false", property = "fork") - protected boolean fork; - - /** - * Set this to true to skip annotation processing when there are no changes in the source files - * compared to the generated files. - * - * @since 4.3 - */ - @Parameter(defaultValue = "false", property = "skipSourcesUnchangedAnnotationProcessing") - protected boolean skipSourcesUnchanged; - - /** - * Maven Session - * - * @since 3.3 - */ - @Parameter( defaultValue = "${session}", readonly = true ) - protected MavenSession session; - - /** - * Plexus compiler manager. - * - * @since 3.3 - */ - @Component - protected CompilerManager compilerManager; - - /** - * - * @since 3.3 - */ - @Component - private ToolchainManager toolchainManager; - - /** - * for execution synchronization - */ - private static final Lock syncExecutionLock = new ReentrantLock(); - - - /** - * - * @return supported source directories - */ - protected abstract java.util.Set getSourceDirectories( java.util.Set result ); - - /** - * - * @return output folder - */ - protected abstract File getOutputClassDirectory(); - - /** - * - * @param project - * @param dir - */ - protected abstract void addCompileSourceRoot(MavenProject project, String dir); - - /** - * - * @return - */ - public abstract File getDefaultOutputDirectory(); - - /** - * - * @return - */ - private Charset getCharsetFromEncoding() { - - return ofNullable(encoding).map( enc -> { - try { - return Charset.forName(encoding); - } - catch( IllegalCharsetNameException ex1 ) { - getLog().warn( format("the given charset name [%s] is illegal!. default is used", encoding )); - } - catch( UnsupportedCharsetException ex2 ) { - getLog().warn( format("the given charset name [%s] is unsupported!. default is used", encoding )); - } - return Charset.defaultCharset(); - }).orElseGet( () -> Charset.defaultCharset() ); + * value of -release parameter in java 9+ + * + * @since 3.3.3 + */ + @Parameter + private String releaseVersion; - } + /** + * + */ + @Parameter(defaultValue = "${project}", readonly = true) + protected MavenProject project; - private String buildProcessor() - { - if (processors == null || processors.length == 0) - { - return null; - } + /** + * + */ + @Parameter(property = "plugin.artifacts", readonly = true) + private java.util.List pluginArtifacts; + + /** + * Specify the directory where to place generated source files (same behaviour of -s option) + */ + @Parameter + private File outputDirectory; - StringBuilder result = new StringBuilder(); + /** + *

+ * Classpath elements to supply as annotation processor path. If specified, the compiler will detect annotation + * processors only in those classpath elements. If omitted, the default classpath is used to detect annotation + * processors. The detection itself depends on the configuration of {@code processors}. + *

+ *

+ * Each classpath element is specified using their Maven coordinates (groupId, artifactId, version, classifier, + * type). Transitive dependencies are added automatically. Example: + *

+ * + *
+   * <configuration>
+   *   <annotationProcessorPaths>
+   *     <path>
+   *       <groupId>org.sample</groupId>
+   *       <artifactId>sample-annotation-processor</artifactId>
+   *       <version>1.2.3</version>
+   *     </path>
+   *     <!-- ... more ... -->
+   *   </annotationProcessorPaths>
+   * </configuration>
+   * 
+ * + * @since 5.0 + */ + @Parameter + List annotationProcessorPaths; - int i; + /** + * Annotation Processor FQN (Full Qualified Name) - when processors are not specified, the default discovery mechanism will be used + */ + @Parameter + private String[] processors; - for ( i = 0; i < processors.length - 1; ++i) - { - result.append(processors[i]).append(','); - } + /** + * Additional compiler arguments + */ + @Parameter + private String compilerArguments; + + /** + * Additional processor options (see javax.annotation.processing.ProcessingEnvironment#getOptions() + */ + @Parameter(alias = "options") + private java.util.Map optionMap; + + /** + * Controls whether or not the output directory is added to compilation + */ + @Parameter + private Boolean addOutputDirectoryToCompilationSources; + + /** + * Indicates whether the build will continue even if there are compilation errors; defaults to true. + */ + @Parameter(defaultValue = "true", required = true, property = "annotation.failOnError") + private Boolean failOnError = true; + + /** + * Indicates whether the compiler output should be visible, defaults to true. + */ + @Parameter(defaultValue = "true", required = true, property = "annotation.outputDiagnostics") + private boolean outputDiagnostics = true; + + /** + * System properties set before processor invocation. + */ + @Parameter + private java.util.Map systemProperties; + + /** + * includes pattern + */ + @Parameter + private String[] includes; - result.append(processors[i]); + /** + * excludes pattern + */ + @Parameter + private String[] excludes; + + /** + * additional source directories for the annotation processors. + */ + @Parameter + private java.util.List additionalSourceDirectories; + + + /** + * if true add to the source directory of the annotation processor all compile source roots detected int the project + * This is useful when we plan to use build-helper-maven-plugin + * + * @since 2.1.1 + */ + @Parameter(defaultValue = "false") + private boolean addCompileSourceRoots = false; + + + /** + * append source artifacts to sources list + * + * @since 2.2.0 + */ + @Parameter(defaultValue = "false") + private boolean appendSourceArtifacts = false; + + /** + * The character set used for decoding sources + * + * @since 2.2.1 + */ + @Parameter(property = "project.build.sourceEncoding") + private String encoding; + + /** + * The entry point to Aether, i.e. the component doing all the work. + */ + @Component + private RepositorySystem repoSystem; + + /** + * The current repository/network configuration of Maven. + */ + @Parameter(defaultValue = "${repositorySystemSession}", readonly = true) + private RepositorySystemSession repoSession; + + /** + * The project's remote repositories to use for the resolution of plugins and their dependencies. + */ + @Parameter(defaultValue = "${project.remoteProjectRepositories}", readonly = true) + private List remoteRepos; + + /** + * List of artifacts on which perform sources scanning + *

+ * Each artifact must be specified in the form grouId:artifactId. + * If you need to include all artifacts belonging a groupId, specify as artifactId the character '*' + * + *


+ * e.g. + *
+   *
+   * org.bsc.maven:maven-confluence-plugin
+   * org.bsc.maven:*
+   *
+   * 
+ * + * @since 2.2.5 + */ + @Parameter() + private java.util.List processSourceArtifacts = Collections.emptyList(); + + /** + * Set this to true to skip annotation processing. + * + * @since 3.1.0 + */ + @Parameter(defaultValue = "false", property = "skipAnnotationProcessing") + protected boolean skip; + + /** + * Allows running the compiler in a separate process. + * If false it uses the built in compiler, while if true it will use an executable. + *

+ * to set source and target use + *

+   *  maven.processor.source
+   *  maven.processor.target
+   * 
+ * + * @since 3.3 + */ + @Parameter(defaultValue = "false", property = "fork") + protected boolean fork; + + /** + * Set this to true to skip annotation processing when there are no changes in the source files + * compared to the generated files. + * + * @since 4.3 + */ + @Parameter(defaultValue = "false", property = "skipSourcesUnchangedAnnotationProcessing") + protected boolean skipSourcesUnchanged; - return result.toString(); + /** + * Maven Session + * + * @since 3.3 + */ + @Parameter(defaultValue = "${session}", readonly = true) + protected MavenSession session; + + /** + * Plexus compiler manager. + * + * @since 3.3 + */ + @Component + protected CompilerManager compilerManager; + + /** + * @since 3.3 + */ + @Component + private ToolchainManager toolchainManager; + + /** + * for execution synchronization + */ + private static final Lock syncExecutionLock = new ReentrantLock(); + + + /** + * @return supported source directories + */ + protected abstract java.util.Set getSourceDirectories(java.util.Set result); + + /** + * @return output folder + */ + protected abstract File getOutputClassDirectory(); + + /** + * @param project + * @param dir + */ + protected abstract void addCompileSourceRoot(MavenProject project, String dir); + + /** + * @return + */ + public abstract File getDefaultOutputDirectory(); + + /** + * @return + */ + private Charset getCharsetFromEncoding() { + + return ofNullable(encoding).map(enc -> { + try { + return Charset.forName(encoding); + } catch (IllegalCharsetNameException ex1) { + getLog().warn(format("the given charset name [%s] is illegal!. default is used", encoding)); + } catch (UnsupportedCharsetException ex2) { + getLog().warn(format("the given charset name [%s] is unsupported!. default is used", encoding)); + } + return Charset.defaultCharset(); + }).orElseGet(() -> Charset.defaultCharset()); + + } + + private String buildProcessor() { + if (processors == null || processors.length == 0) { + return null; + } + + StringBuilder result = new StringBuilder(); + + int i; + + for (i = 0; i < processors.length - 1; ++i) { + result.append(processors[i]).append(','); } - protected abstract java.util.Set getResourcesElements( java.util.Set result ); + result.append(processors[i]); - protected abstract java.util.Set getClasspathElements( java.util.Set result ); + return result.toString(); + } - protected abstract java.util.List getAllCompileSourceRoots(); + protected abstract java.util.Set getResourcesElements(java.util.Set result); - private String buildCompileSourcepath( Consumer onSuccess) { - - final java.util.List roots = getAllCompileSourceRoots(); + protected abstract java.util.Set getClasspathElements(java.util.Set result); - if( roots == null || roots.isEmpty() ) { - return null; - } - - final String result = StringUtils.join(roots.iterator(), File.pathSeparator); - - onSuccess.accept( result ); - - return result; + protected abstract java.util.List getAllCompileSourceRoots(); + + private String buildCompileSourcepath(Consumer onSuccess) { + + final java.util.List roots = getAllCompileSourceRoots(); + + if (roots == null || roots.isEmpty()) { + return null; } - - private String buildCompileClasspath() - { - - final java.util.Set pathElements = new java.util.LinkedHashSet<>(); - getResourcesElements(pathElements); + final String result = StringUtils.join(roots.iterator(), File.pathSeparator); - getClasspathElements(pathElements); + onSuccess.accept(result); - if( pluginArtifacts!=null ) { + return result; + } - for( Artifact a : pluginArtifacts ) { - - if( "compile".equalsIgnoreCase(a.getScope()) || "runtime".equalsIgnoreCase(a.getScope()) ) { - - java.io.File f = a.getFile(); - - if( f!=null ) pathElements.add( a.getFile().getAbsolutePath() ); + private String buildCompileClasspath() { - } - - } - } + final java.util.Set pathElements = new java.util.LinkedHashSet<>(); + + getResourcesElements(pathElements); + + getClasspathElements(pathElements); + + if (pluginArtifacts != null) { + + for (Artifact a : pluginArtifacts) { + if ("compile".equalsIgnoreCase(a.getScope()) || "runtime".equalsIgnoreCase(a.getScope())) { + + java.io.File f = a.getFile(); + + if (f != null) pathElements.add(a.getFile().getAbsolutePath()); - final StringBuilder result = new StringBuilder(); - - for( String elem : pathElements ) { - result.append(elem).append(File.pathSeparator); } - return result.toString(); + + } } - private String buildModulePath() - { - return getClasspathElements(new java.util.LinkedHashSet<>()) - .stream() - .collect(joining( File.pathSeparator) ); + final StringBuilder result = new StringBuilder(); + + for (String elem : pathElements) { + result.append(elem).append(File.pathSeparator); } + return result.toString(); + } + + private String buildModulePath() { - /** - * - */ - @Override - public void execute() throws MojoExecutionException + return getClasspathElements(new java.util.LinkedHashSet<>()) + .stream() + .collect(joining(File.pathSeparator)); + } + + /** + * + */ + @Override + public void execute() throws MojoExecutionException { + if (skip) { + getLog().info("skipped"); + return; + } + + if ("pom".equalsIgnoreCase(project.getPackaging())) // Issue 17 { - if (skip) - { - getLog().info("skipped"); - return; - } + return; + } - if ("pom".equalsIgnoreCase(project.getPackaging())) // Issue 17 - { - return; - } + syncExecutionLock.lock(); + + try { + executeWithExceptionsHandled(); + } catch (Exception e1) { + super.getLog().error("error on execute: use -X to have details "); + super.getLog().debug(e1); + if (failOnError) { + throw new MojoExecutionException("Error executing", e1); + } + } finally { + syncExecutionLock.unlock(); + } - syncExecutionLock.lock(); - - try - { - executeWithExceptionsHandled(); - } - catch (Exception e1) - { - super.getLog().error("error on execute: use -X to have details " ); - super.getLog().debug(e1); - if (failOnError) - { - throw new MojoExecutionException("Error executing", e1); - } - } - finally { - syncExecutionLock.unlock(); + } + + /** + * TODO remove the part with ToolchainManager lookup once we depend on + * 3.0.9 (have it as prerequisite). Define as regular component field then. + * + * @param jdkToolchain + */ + private Toolchain getToolchain(final Map jdkToolchain) { + Toolchain tc = null; + + if (jdkToolchain != null && !jdkToolchain.isEmpty()) { + // Maven 3.3.1 has plugin execution scoped Toolchain Support + try { + final Method getToolchainsMethod = + toolchainManager.getClass().getMethod("getToolchains", + MavenSession.class, + String.class, + Map.class); + + @SuppressWarnings("unchecked") final List tcs = + (List) getToolchainsMethod.invoke(toolchainManager, + session, + "jdk", + jdkToolchain); + + if (tcs != null && tcs.size() > 0) { + tc = tcs.get(0); } + } catch (Exception e) { + // ignore + } + } + if (tc == null) { + tc = toolchainManager.getToolchainFromBuildContext("jdk", session); } - /** - * TODO remove the part with ToolchainManager lookup once we depend on - * 3.0.9 (have it as prerequisite). Define as regular component field then. - * - * @param jdkToolchain - */ - private Toolchain getToolchain(final Map jdkToolchain) - { - Toolchain tc = null; - - if ( jdkToolchain != null && !jdkToolchain.isEmpty()) - { - // Maven 3.3.1 has plugin execution scoped Toolchain Support - try - { - final Method getToolchainsMethod = - toolchainManager.getClass().getMethod( "getToolchains", - MavenSession.class, - String.class, - Map.class ); - - @SuppressWarnings( "unchecked" ) - final List tcs = - (List) getToolchainsMethod.invoke( toolchainManager, - session, - "jdk", - jdkToolchain ); - - if ( tcs != null && tcs.size() > 0 ) - { - tc = tcs.get( 0 ); - } - } - catch ( Exception e ) - { - // ignore - } - } - - if ( tc == null ) - { - tc = toolchainManager.getToolchainFromBuildContext( "jdk", session ); - } - - return tc; + return tc; + } + + private List prepareOptions(JavaCompiler compiler) throws MojoExecutionException { + + final List options = new ArrayList<>(10); + + final String compileClassPath = buildCompileClasspath(); + + final String processor = buildProcessor(); + + options.add("-cp"); + options.add(compileClassPath); + + if (compiler.isSupportedOption("--module-path") == 1) { + options.add("--module-path"); + options.add(buildModulePath()); } - private List prepareOptions( JavaCompiler compiler ) throws MojoExecutionException { + buildCompileSourcepath(sourcepath -> { + options.add("-sourcepath"); + options.add(sourcepath); + }); - final List options = new ArrayList<>(10); + options.add("-proc:only"); - final String compileClassPath = buildCompileClasspath(); + Optional processorPath = this.buildProcessorPath(); + processorPath.ifPresent(value -> { + options.add("-processorpath"); + options.add(value); + }); - final String processor = buildProcessor(); + addCompilerArguments(options); - options.add("-cp"); - options.add(compileClassPath); + if (processor != null) { + options.add("-processor"); + options.add(processor); + } else { + getLog().warn("No processors specified. Using default discovery mechanism."); + } + options.add("-d"); + options.add(getOutputClassDirectory().getPath()); + + options.add("-s"); + options.add(outputDirectory.getPath()); + + ofNullable(releaseVersion).ifPresent(release -> { + options.add("--release"); + options.add(releaseVersion); + }); + + ofNullable(project.getProperties()).ifPresent(properties -> { + + ofNullable(properties.getProperty("maven.compiler.source")).ifPresent(source -> { + options.add("-source"); + options.add(source); + }); + ofNullable(properties.getProperty("maven.compiler.target")).ifPresent(target -> { + options.add("-target"); + options.add(target); + }); + }); + + ofNullable(encoding).ifPresent(enc -> { + options.add("-encoding"); + options.add(getCharsetFromEncoding().name()); + }); + + if (getLog().isDebugEnabled()) { + for (String option : options) { + getLog().debug(format("javac option: %s", option)); + } + } - if( compiler.isSupportedOption("--module-path") == 1 ) { - options.add("--module-path"); - options.add(buildModulePath()); - } + return options; - buildCompileSourcepath( sourcepath -> { - options.add("-sourcepath"); - options.add(sourcepath); - }); + } - options.add("-proc:only"); - - Optional processorPath = this.buildProcessorPath(); - processorPath.ifPresent(value -> { - options.add("-processorpath"); - options.add(value); - }); + private boolean isSourcesUnchanged(List allSources) throws IOException { + if (!areSourceFilesSameAsPreviousRun(allSources)) + return false; - addCompilerArguments(options); + long maxSourceDate = allSources.stream() + .map(JavaFileObject::getLastModified) + .max(Long::compare) + .orElse(Long.MIN_VALUE); - if (processor != null) { - options.add("-processor"); - options.add(processor); - } - else - { - getLog().warn("No processors specified. Using default discovery mechanism."); - } - options.add("-d"); - options.add(getOutputClassDirectory().getPath()); - - options.add("-s"); - options.add(outputDirectory.getPath()); - - ofNullable(releaseVersion).ifPresent( release -> { - options.add("--release"); - options.add( releaseVersion ); - }); - - ofNullable(project.getProperties()).ifPresent( properties -> { - - ofNullable(properties.getProperty( "maven.compiler.source" )).ifPresent( source -> { - options.add("-source"); - options.add(source); - }); - ofNullable(properties.getProperty( "maven.compiler.target" )) .ifPresent( target -> { - options.add("-target"); - options.add(target); - }); - }); - - ofNullable(encoding).ifPresent( enc -> { - options.add("-encoding"); - options.add( getCharsetFromEncoding().name() ); - }); - - if( getLog().isDebugEnabled() ) { - for (String option : options) { - getLog().debug(format("javac option: %s", option)); - } + // use atomic long for effectively final wrapper around long variable + final AtomicLong maxOutputDate = new AtomicLong(Long.MIN_VALUE); + + Files.walkFileTree(outputDirectory.toPath(), new SimpleFileVisitor() { + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) + throws IOException { + if (Files.isRegularFile(file)) { + maxOutputDate.updateAndGet(t -> Math.max(t, file.toFile().lastModified())); } + return FileVisitResult.CONTINUE; + } + }); - return options; + if (getLog().isDebugEnabled()) { + getLog().debug("max source file date: " + maxSourceDate + ", max output date: " + maxOutputDate + .get()); + } + return maxSourceDate <= maxOutputDate.get(); + } + + /** + * Checks the list of {@code allSources} against the stored list of source files in a previous run. + * + * @param allSources + * @return {@code true} when the filenames of the previous run matches exactly with the current run. + * @throws IOException + */ + private boolean areSourceFilesSameAsPreviousRun(List allSources) throws IOException { + Path sourceFileList = outputDirectory.toPath().resolve(".maven-processor-source-files.txt"); + try { + if (!Files.exists(sourceFileList)) { + getLog().debug("File with previous sources " + sourceFileList + " not found, treating as first run"); + return false; + } + + Set previousSourceFiles = new HashSet<>(Files.readAllLines(sourceFileList)); + Set currentSourceFiles = allSources.stream().map(JavaFileObject::getName).collect(Collectors.toSet()); + if (getLog().isDebugEnabled()) { + final String removedSourceFiles = previousSourceFiles.stream() + .filter(f -> !currentSourceFiles.contains(f)) + .collect(joining("\n")); + getLog().debug(format("removed source files:\n%s", removedSourceFiles)); + + final String newSourceFiles = currentSourceFiles.stream() + .filter(f -> !previousSourceFiles.contains(f)) + .collect(joining("\n")); + getLog().debug(format("new source files:\n%s", newSourceFiles)); + } + return previousSourceFiles.equals(currentSourceFiles); + } finally { + outputDirectory.mkdirs(); + Files.write(sourceFileList, allSources.stream().map(JavaFileObject::getName).collect(Collectors.toSet())); } + } + + private void executeWithExceptionsHandled() throws Exception { + if (outputDirectory == null) { + outputDirectory = getDefaultOutputDirectory(); + } + + ensureOutputDirectoryExists(); + addOutputToSourcesIfNeeded(); + + // new Debug(project).printDebugInfo(); + + final String includesString = (includes == null || includes.length == 0) ? "**/*.java" : StringUtils.join(includes, ","); + final String excludesString = (excludes == null || excludes.length == 0) ? null : StringUtils.join(excludes, ","); + + java.util.Set sourceDirs = getSourceDirectories(new java.util.HashSet<>(5)); - private boolean isSourcesUnchanged( List allSources ) throws IOException { - if (!areSourceFilesSameAsPreviousRun(allSources)) - return false; - - long maxSourceDate = allSources.stream() - .map(JavaFileObject::getLastModified) - .max(Long::compare) - .orElse(Long.MIN_VALUE); - - // use atomic long for effectively final wrapper around long variable - final AtomicLong maxOutputDate = new AtomicLong(Long.MIN_VALUE); - - Files.walkFileTree(outputDirectory.toPath(), new SimpleFileVisitor() { - @Override public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) - throws IOException - { - if(Files.isRegularFile(file)) { - maxOutputDate.updateAndGet(t -> Math.max(t, file.toFile().lastModified())); - } - return FileVisitResult.CONTINUE; - } - }); - - if(getLog().isDebugEnabled()) - { - getLog().debug("max source file date: " + maxSourceDate + ", max output date: " + maxOutputDate - .get()); + if (addCompileSourceRoots) { + final java.util.List sourceRoots = project.getCompileSourceRoots(); + if (sourceRoots != null) { + for (String s : sourceRoots) { + sourceDirs.add(new File(s)); } + } + } - return maxSourceDate <= maxOutputDate.get(); + if (additionalSourceDirectories != null && !additionalSourceDirectories.isEmpty()) { + sourceDirs.addAll(additionalSourceDirectories); } - /** - * Checks the list of {@code allSources} against the stored list of source files in a previous run. - * - * @param allSources - * @return {@code true} when the filenames of the previous run matches exactly with the current run. - * @throws IOException - */ - private boolean areSourceFilesSameAsPreviousRun(List allSources) throws IOException { - Path sourceFileList = outputDirectory.toPath().resolve(".maven-processor-source-files.txt"); - try { - if (!Files.exists(sourceFileList)) { - getLog().debug("File with previous sources " + sourceFileList + " not found, treating as first run"); - return false; - } - - Set previousSourceFiles = new HashSet<>(Files.readAllLines(sourceFileList)); - Set currentSourceFiles = allSources.stream().map(JavaFileObject::getName).collect(Collectors.toSet()); - if (getLog().isDebugEnabled()) { - final String removedSourceFiles = previousSourceFiles.stream() - .filter(f -> !currentSourceFiles.contains(f)) - .collect(joining("\n")); - getLog().debug(format("removed source files:\n%s", removedSourceFiles)); - - final String newSourceFiles = currentSourceFiles.stream() - .filter(f -> !previousSourceFiles.contains(f)) - .collect(joining("\n")); - getLog().debug(format("new source files:\n%s", newSourceFiles)); - } - return previousSourceFiles.equals(currentSourceFiles); - } finally { - outputDirectory.mkdirs(); - Files.write(sourceFileList, allSources.stream().map(JavaFileObject::getName).collect(Collectors.toSet())); - } + if (sourceDirs == null) { + throw new IllegalStateException("getSourceDirectories is null!"); } - private void executeWithExceptionsHandled() throws Exception - { - if (outputDirectory == null) - { - outputDirectory = getDefaultOutputDirectory(); - } + final List files = new java.util.ArrayList<>(); - ensureOutputDirectoryExists(); - addOutputToSourcesIfNeeded(); + for (File sourceDir : sourceDirs) { - // new Debug(project).printDebugInfo(); + if (sourceDir == null) { + getLog().warn("source directory is null! Processor task will be skipped!"); + continue; + } - final String includesString = ( includes==null || includes.length==0) ? "**/*.java" : StringUtils.join(includes, ","); - final String excludesString = ( excludes==null || excludes.length==0) ? null : StringUtils.join(excludes, ","); + getLog().debug(format("processing source directory [%s]", sourceDir.getPath())); - java.util.Set sourceDirs = getSourceDirectories(new java.util.HashSet<>( 5 )); - - if( addCompileSourceRoots ) { - final java.util.List sourceRoots = project.getCompileSourceRoots(); - if( sourceRoots != null ) { - for( String s : sourceRoots ) { - sourceDirs.add( new File(s) ); - } - } - } + if (!sourceDir.exists()) { + getLog().warn(format("source directory [%s] doesn't exist! Processor task will be skipped!", sourceDir.getPath())); + continue; + } + if (!sourceDir.isDirectory()) { + getLog().warn(format("source directory [%s] is invalid! Processor task will be skipped!", sourceDir.getPath())); + continue; + } - if( additionalSourceDirectories != null && !additionalSourceDirectories.isEmpty() ) { - sourceDirs.addAll( additionalSourceDirectories ); - } + files.addAll(FileUtils.getFiles(sourceDir, includesString, excludesString)); + } - if( sourceDirs == null ) { - throw new IllegalStateException("getSourceDirectories is null!"); + final DiagnosticListener dl = diagnostic -> { + + if (!outputDiagnostics) { + return; + } + + final Kind kind = diagnostic.getKind(); + + if (null != kind) + switch (kind) { + case ERROR: + getLog().error(format("diagnostic: %s", diagnostic)); + break; + case MANDATORY_WARNING: + case WARNING: + getLog().warn(format("diagnostic: %s", diagnostic)); + break; + case NOTE: + getLog().info(format("diagnostic: %s", diagnostic)); + break; + case OTHER: + getLog().info(format("diagnostic: %s", diagnostic)); + break; + default: + break; } - final List files = new java.util.ArrayList<>(); - - for( File sourceDir : sourceDirs ) { - - if( sourceDir==null ) { - getLog().warn( "source directory is null! Processor task will be skipped!" ); - continue; - } - - getLog().debug( format( "processing source directory [%s]", sourceDir.getPath()) ); - - if( !sourceDir.exists() ) { - getLog().warn( format("source directory [%s] doesn't exist! Processor task will be skipped!", sourceDir.getPath())); - continue; - } - if( !sourceDir.isDirectory() ) { - getLog().warn( format("source directory [%s] is invalid! Processor task will be skipped!", sourceDir.getPath())); - continue; - } - - files.addAll( FileUtils.getFiles(sourceDir, includesString, excludesString) ); - } + }; - final DiagnosticListener dl = diagnostic -> { - - if (!outputDiagnostics) { - return; - } - - final Kind kind = diagnostic.getKind(); - - if (null != kind) - switch (kind) { - case ERROR: - getLog().error(format("diagnostic: %s", diagnostic)); - break; - case MANDATORY_WARNING: - case WARNING: - getLog().warn(format("diagnostic: %s", diagnostic)); - break; - case NOTE: - getLog().info(format("diagnostic: %s", diagnostic)); - break; - case OTHER: - getLog().info(format("diagnostic: %s", diagnostic)); - break; - default: - break; - } - - }; - - if (systemProperties != null) { - java.util.Set< Map.Entry> pSet = systemProperties.entrySet(); - - for ( Map.Entry e : pSet ) { - getLog().debug( format("set system property : [%s] = [%s]", e.getKey(), e.getValue() )); - System.setProperty(e.getKey(), e.getValue()); - } + if (systemProperties != null) { + java.util.Set> pSet = systemProperties.entrySet(); - } + for (Map.Entry e : pSet) { + getLog().debug(format("set system property : [%s] = [%s]", e.getKey(), e.getValue())); + System.setProperty(e.getKey(), e.getValue()); + } + } - final java.util.Map jdkToolchain = - java.util.Collections.emptyMap(); - - final Toolchain tc = getToolchain(jdkToolchain); - - // If toolchain is set force fork compilation - fork = ( tc != null ); - - if( fork ) { getLog().debug( "PROCESSOR COMPILER FORKED!"); } - // - // add to allSource the files coming out from source archives - // - final java.util.List allSources = new java.util.ArrayList<>(); + final java.util.Map jdkToolchain = + java.util.Collections.emptyMap(); - final UnzipService unzip = UnzipService.newInstance( getLog() ); + final Toolchain tc = getToolchain(jdkToolchain); - if( fork ) { - processSourceArtifacts( artifact -> unzip.extractSourcesFromArtifactToTempDirectory( artifact, allSources, - Paths.get( project.getBuild().getDirectory(), "extracted-sources" ) )); - } - else { - processSourceArtifacts( artifact -> unzip.extractSourcesFromArtifact(artifact, allSources) ); - } + // If toolchain is set force fork compilation + fork = (tc != null); - //compileLock.lock(); - - try { - - final JavaCompiler compiler = (fork) ? - AnnotationProcessorCompiler.createOutProcess( - tc, - compilerManager, - project, - session ) : - AnnotationProcessorCompiler.createInProcess(); - - - if( compiler==null ) { - getLog().error("JVM is not suitable for processing annotation! ToolProvider.getSystemJavaCompiler() is null."); - return; - } - - final StandardJavaFileManager fileManager = - compiler.getStandardFileManager(null, - null, - getCharsetFromEncoding()); - - if( files!=null && !files.isEmpty() ) { - - for( JavaFileObject f : fileManager.getJavaFileObjectsFromFiles(files) ) { - allSources.add(f); - }; - - } - - if( allSources.isEmpty() ) { - getLog().warn( "no source file(s) detected! Processor task will be skipped"); - return; - } - - if(skipSourcesUnchanged && isSourcesUnchanged(allSources)) { - getLog().info( "no source file(s) change(s) detected! Processor task will be skipped"); - return; - } - final java.util.List options = prepareOptions( compiler ); - - final CompilationTask task = compiler.getTask( - new PrintWriter(System.out), - fileManager, - dl, - options, - null, - allSources); - - /* - * //Create a list to hold annotation processors LinkedList processors = new - * LinkedList(); - * - * //Add an annotation processor to the list processors.add(p); - * - * //Set the annotation processor to the compiler task task.setProcessors(processors); - */ - - // Perform the compilation task. - if (!task.call()) { - throw new Exception("error during compilation"); - } - } - finally { - //compileLock.unlock(); - } - + if (fork) { + getLog().debug("PROCESSOR COMPILER FORKED!"); } - private List scanSourceDirectorySources(File sourceDir) throws IOException { - if( sourceDir==null ) { - getLog().warn( "source directory cannot be read (null returned)! Processor task will be skipped"); - return null; - } - if( !sourceDir.exists() ) { - getLog().warn( "source directory doesn't exist! Processor task will be skipped"); - return null; - } - if( !sourceDir.isDirectory() ) { - getLog().warn( "source directory is invalid! Processor task will be skipped"); - return null; - } + // + // add to allSource the files coming out from source archives + // + final java.util.List allSources = new java.util.ArrayList<>(); - final String includesString = ( includes==null || includes.length==0) ? "**/*.java" : StringUtils.join(includes, ","); - final String excludesString = ( excludes==null || excludes.length==0) ? null : StringUtils.join(excludes, ","); + final UnzipService unzip = UnzipService.newInstance(getLog()); - final List files = FileUtils.getFiles(sourceDir, includesString, excludesString); - return files; + if (fork) { + processSourceArtifacts(artifact -> unzip.extractSourcesFromArtifactToTempDirectory(artifact, allSources, + Paths.get(project.getBuild().getDirectory(), "extracted-sources"))); + } else { + processSourceArtifacts(artifact -> unzip.extractSourcesFromArtifact(artifact, allSources)); } - private void addCompilerArguments(List options) { - if (!StringUtils.isEmpty(compilerArguments)) { - for (String arg : compilerArguments.split(" ")) { - if (!StringUtils.isEmpty(arg)) { - arg = arg.trim(); - getLog().debug(format("Adding compiler arg: %s", arg)); - options.add(arg); - } - } - } - if( optionMap!=null && !optionMap.isEmpty() ) { - for( java.util.Map.Entry e : optionMap.entrySet() ) { - - if( !StringUtils.isEmpty(e.getKey()) && e.getValue()!=null ) { - String opt = format("-A%s=%s", e.getKey().trim(), e.getValue().toString().trim()); - options.add( opt ); - getLog().debug(format("Adding compiler arg: %s", opt)); - } - } - + //compileLock.lock(); + + try { + + final JavaCompiler compiler = (fork) ? + AnnotationProcessorCompiler.createOutProcess( + tc, + compilerManager, + project, + session) : + AnnotationProcessorCompiler.createInProcess(); + + + if (compiler == null) { + getLog().error("JVM is not suitable for processing annotation! ToolProvider.getSystemJavaCompiler() is null."); + return; + } + + final StandardJavaFileManager fileManager = + compiler.getStandardFileManager(null, + null, + getCharsetFromEncoding()); + + if (files != null && !files.isEmpty()) { + + for (JavaFileObject f : fileManager.getJavaFileObjectsFromFiles(files)) { + allSources.add(f); } + ; + + } + + if (allSources.isEmpty()) { + getLog().warn("no source file(s) detected! Processor task will be skipped"); + return; + } + + if (skipSourcesUnchanged && isSourcesUnchanged(allSources)) { + getLog().info("no source file(s) change(s) detected! Processor task will be skipped"); + return; + } + final java.util.List options = prepareOptions(compiler); + + final CompilationTask task = compiler.getTask( + new PrintWriter(System.out), + fileManager, + dl, + options, + null, + allSources); + + /* + * //Create a list to hold annotation processors LinkedList processors = new + * LinkedList(); + * + * //Add an annotation processor to the list processors.add(p); + * + * //Set the annotation processor to the compiler task task.setProcessors(processors); + */ + + // Perform the compilation task. + if (!task.call()) { + throw new Exception("error during compilation"); + } + } finally { + //compileLock.unlock(); } - private void addOutputToSourcesIfNeeded() - { - final Boolean add = addOutputDirectoryToCompilationSources; - if (add == null || add.booleanValue()) { - getLog().debug(format("Source directory: %s added", outputDirectory)); - addCompileSourceRoot(project, outputDirectory.getAbsolutePath()); - } + } + + private List scanSourceDirectorySources(File sourceDir) throws IOException { + if (sourceDir == null) { + getLog().warn("source directory cannot be read (null returned)! Processor task will be skipped"); + return null; + } + if (!sourceDir.exists()) { + getLog().warn("source directory doesn't exist! Processor task will be skipped"); + return null; + } + if (!sourceDir.isDirectory()) { + getLog().warn("source directory is invalid! Processor task will be skipped"); + return null; } - private void ensureOutputDirectoryExists() - { - final File f = outputDirectory; - if (!f.exists()) { - f.mkdirs(); - } - if( !getOutputClassDirectory().exists()) { - getOutputClassDirectory().mkdirs(); + final String includesString = (includes == null || includes.length == 0) ? "**/*.java" : StringUtils.join(includes, ","); + final String excludesString = (excludes == null || excludes.length == 0) ? null : StringUtils.join(excludes, ","); + + final List files = FileUtils.getFiles(sourceDir, includesString, excludesString); + return files; + } + + private void addCompilerArguments(List options) { + if (!StringUtils.isEmpty(compilerArguments)) { + for (String arg : compilerArguments.split(" ")) { + if (!StringUtils.isEmpty(arg)) { + arg = arg.trim(); + getLog().debug(format("Adding compiler arg: %s", arg)); + options.add(arg); } + } } + if (optionMap != null && !optionMap.isEmpty()) { + for (java.util.Map.Entry e : optionMap.entrySet()) { - private boolean matchArtifact( Artifact dep/*, ArtifactFilter filter*/ ) { - - if(processSourceArtifacts == null || processSourceArtifacts.isEmpty()) { - return false; - } - - for( String a : processSourceArtifacts ) { - - if( a == null || a.isEmpty() ) continue; - - final String [] token = a.split(":"); - - final boolean matchGroupId = dep.getGroupId().equals(token[0]); - - if( !matchGroupId ) continue; - - if( token.length == 1 ) return true; - - if( token[1].equals("*") ) return true; - - return dep.getArtifactId().equals(token[1]); - + if (!StringUtils.isEmpty(e.getKey()) && e.getValue() != null) { + String opt = format("-A%s=%s", e.getKey().trim(), e.getValue().toString().trim()); + options.add(opt); + getLog().debug(format("Adding compiler arg: %s", opt)); } - return false; + } + } - - private Optional resolveSourceArtifact( Artifact dep ) throws ArtifactResolutionException { - - if( !matchArtifact(dep) ) { - return empty(); - } - - final ArtifactTypeRegistry typeReg = repoSession.getArtifactTypeRegistry(); - - final DefaultArtifact artifact = - new DefaultArtifact( dep.getGroupId(), - dep.getArtifactId(), - SOURCE_CLASSIFIER, - null, - dep.getVersion(), - typeReg.get(dep.getType())); - - final ArtifactRequest request = new ArtifactRequest(); - request.setArtifact( artifact ); - request.setRepositories(remoteRepos); - - getLog().debug( format("Resolving artifact %s from %s", artifact, remoteRepos )); - - final ArtifactResult result = repoSystem.resolveArtifact( repoSession, request ); - - return ofNullable(RepositoryUtils.toArtifact(result.getArtifact())); + } + + private void addOutputToSourcesIfNeeded() { + final Boolean add = addOutputDirectoryToCompilationSources; + if (add == null || add.booleanValue()) { + getLog().debug(format("Source directory: %s added", outputDirectory)); + addCompileSourceRoot(project, outputDirectory.getAbsolutePath()); + } + } + + private void ensureOutputDirectoryExists() { + final File f = outputDirectory; + if (!f.exists()) { + f.mkdirs(); + } + if (!getOutputClassDirectory().exists()) { + getOutputClassDirectory().mkdirs(); + } + } + + private boolean matchArtifact(Artifact dep/*, ArtifactFilter filter*/) { + + if (processSourceArtifacts == null || processSourceArtifacts.isEmpty()) { + return false; + } + + for (String a : processSourceArtifacts) { + + if (a == null || a.isEmpty()) continue; + + final String[] token = a.split(":"); + + final boolean matchGroupId = dep.getGroupId().equals(token[0]); + + if (!matchGroupId) continue; + + if (token.length == 1) return true; + + if (token[1].equals("*")) return true; + + return dep.getArtifactId().equals(token[1]); + } - - private void processSourceArtifacts( Consumer closure ) { - - for (Artifact dep : this.project.getDependencyArtifacts()) { - if (dep.hasClassifier() && SOURCE_CLASSIFIER.equals(dep.getClassifier()) ) { - - if( appendSourceArtifacts ) { - closure.accept(dep); - } - //getLog().debug("Append source artifact to classpath: " + dep.getGroupId() + ":" + dep.getArtifactId()); - //this.sourceArtifacts.add(dep.getFile()); - } - else { - try { - resolveSourceArtifact(dep).ifPresent(closure::accept); - - } catch (ArtifactResolutionException ex) { - getLog().warn( format(" sources for artifact [%s] not found!", dep.toString())); - getLog().debug(ex); - - } - } + return false; + } + + private Optional resolveSourceArtifact(Artifact dep) throws ArtifactResolutionException { + + if (!matchArtifact(dep)) { + return empty(); + } + + final ArtifactTypeRegistry typeReg = repoSession.getArtifactTypeRegistry(); + + final DefaultArtifact artifact = + new DefaultArtifact(dep.getGroupId(), + dep.getArtifactId(), + SOURCE_CLASSIFIER, + null, + dep.getVersion(), + typeReg.get(dep.getType())); + + final ArtifactRequest request = new ArtifactRequest(); + request.setArtifact(artifact); + request.setRepositories(remoteRepos); + + getLog().debug(format("Resolving artifact %s from %s", artifact, remoteRepos)); + + final ArtifactResult result = repoSystem.resolveArtifact(repoSession, request); + + return ofNullable(RepositoryUtils.toArtifact(result.getArtifact())); + } + + private void processSourceArtifacts(Consumer closure) { + + final java.util.Set depArtifacts = this.project.getDependencyArtifacts(); + if (depArtifacts != null) { + + for (Artifact dep : depArtifacts) { + + if (dep.hasClassifier() && SOURCE_CLASSIFIER.equals(dep.getClassifier())) { + + if (appendSourceArtifacts) { + closure.accept(dep); + } + //getLog().debug("Append source artifact to classpath: " + dep.getGroupId() + ":" + dep.getArtifactId()); + //this.sourceArtifacts.add(dep.getFile()); + } else { + try { + resolveSourceArtifact(dep).ifPresent(closure::accept); + + } catch (ArtifactResolutionException ex) { + getLog().warn(format(" sources for artifact [%s] not found!", dep.toString())); + getLog().debug(ex); + + } } + } + } + } + + private Optional> resolveProcessorPathEntries() throws MojoExecutionException { + if (this.annotationProcessorPaths == null || this.annotationProcessorPaths.isEmpty()) { + return Optional.empty(); + } + + try { + Set requiredDependencies = new LinkedHashSet<>(); + + for (DependencyCoordinate coord : this.annotationProcessorPaths) { + //@formatter:off + DefaultArtifact artifact = new DefaultArtifact( + coord.getGroupId(), + coord.getArtifactId(), + coord.getClassifier(), + coord.getType(), + coord.getVersion()); + //@formatter:on + + requiredDependencies.add(new Dependency(artifact, Artifact.SCOPE_RUNTIME)); + } + CollectRequest collectRequest = new CollectRequest(requiredDependencies.iterator().next(), + new ArrayList<>(requiredDependencies), this.remoteRepos); + DependencyRequest dependencyRequest = new DependencyRequest(collectRequest, null); + + DependencyResult resolutionResult = this.repoSystem.resolveDependencies(this.repoSession, + dependencyRequest); + + List artifactPaths = new ArrayList<>(resolutionResult.getArtifactResults().size()); + for (ArtifactResult artifactResult : resolutionResult.getArtifactResults()) { + artifactPaths.add(artifactResult.getArtifact().getFile().getAbsolutePath()); + } + + return Optional.of(artifactPaths); + } catch (Exception e) { + throw new MojoExecutionException( + "Resolution of annotationProcessorPath dependencies failed: " + e.getLocalizedMessage(), e); } + } - private Optional> resolveProcessorPathEntries() throws MojoExecutionException { - if (this.annotationProcessorPaths == null || this.annotationProcessorPaths.isEmpty()) { - return Optional.empty(); - } - - try { - Set requiredDependencies = new LinkedHashSet<>(); - - for (DependencyCoordinate coord : this.annotationProcessorPaths) { - //@formatter:off - DefaultArtifact artifact = new DefaultArtifact( - coord.getGroupId(), - coord.getArtifactId(), - coord.getClassifier(), - coord.getType(), - coord.getVersion()); - //@formatter:on - - requiredDependencies.add(new Dependency(artifact, Artifact.SCOPE_RUNTIME)); - } - CollectRequest collectRequest = new CollectRequest(requiredDependencies.iterator().next(), - new ArrayList<>(requiredDependencies), this.remoteRepos); - DependencyRequest dependencyRequest = new DependencyRequest(collectRequest, null); - - DependencyResult resolutionResult = this.repoSystem.resolveDependencies(this.repoSession, - dependencyRequest); - - List artifactPaths = new ArrayList<>(resolutionResult.getArtifactResults().size()); - for (ArtifactResult artifactResult : resolutionResult.getArtifactResults()) { - artifactPaths.add(artifactResult.getArtifact().getFile().getAbsolutePath()); - } - - return Optional.of(artifactPaths); - } catch (Exception e) { - throw new MojoExecutionException( - "Resolution of annotationProcessorPath dependencies failed: " + e.getLocalizedMessage(), e); - } - } - - private Optional buildProcessorPath() throws MojoExecutionException { - Optional> processorPathEntries = this.resolveProcessorPathEntries(); - return processorPathEntries.map(value -> StringUtils.join(value.iterator(), File.pathSeparator)); - } + private Optional buildProcessorPath() throws MojoExecutionException { + Optional> processorPathEntries = this.resolveProcessorPathEntries(); + return processorPathEntries.map(value -> StringUtils.join(value.iterator(), File.pathSeparator)); + } } diff --git a/processor/src/test/java/org/bsc/maven/plugin/processor/AnnotationProcessorMojoTest.java b/processor/src/test/java/org/bsc/maven/plugin/processor/AnnotationProcessorMojoTest.java index 466590d..babc15b 100644 --- a/processor/src/test/java/org/bsc/maven/plugin/processor/AnnotationProcessorMojoTest.java +++ b/processor/src/test/java/org/bsc/maven/plugin/processor/AnnotationProcessorMojoTest.java @@ -1,23 +1,50 @@ package org.bsc.maven.plugin.processor; +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.Mojo; import org.apache.maven.plugin.testing.MojoRule; import org.apache.maven.plugin.testing.resources.TestResources; +import org.junit.Assert; import org.junit.Rule; import org.junit.Test; import java.io.File; +import java.nio.file.Path; +import java.nio.file.Paths; -public class MojoTest { +import static org.junit.Assert.*; + +public class AnnotationProcessorMojoTest { @Rule public MojoRule mojoRule = new MojoRule(); - @Rule public TestResources resources = new TestResources(); + @Rule + public TestResources resources = new TestResources(); + + final Path outputPath = Paths.get("target", "classes"); @Test - public void execute() throws Exception { - File pom = new File(resources.getBasedir("test-project-1"), "pom.xml"); -// MainMojo mojo = (MainMojo) mojoRule.lookupMojo("translate", pom); -// mojo.execute(); + public void testPR45() throws Exception { + final File pom = Paths.get(outputPath.toString(), "pr45", "pom.xml").toFile(); + + assertNotNull(pom); + + final File baseDir = Paths.get(outputPath.toString(), "pr45").toFile(); + assertNotNull(baseDir); + assertTrue( baseDir.exists() ); + assertTrue( baseDir.isDirectory() ); + + final Mojo mojo = mojoRule.lookupConfiguredMojo(baseDir, "process"); + + assertTrue(mojo instanceof MainAnnotationProcessorMojo); + + final MainAnnotationProcessorMojo myMojo = (MainAnnotationProcessorMojo) mojo; + + myMojo.execute(); + + assertNotNull( myMojo.annotationProcessorPaths ); + assertEquals( 1, myMojo.annotationProcessorPaths.size() ); + } } diff --git a/processor/src/test/resources/pr45/pom.xml b/processor/src/test/resources/pr45/pom.xml index e69de29..adbe061 100644 --- a/processor/src/test/resources/pr45/pom.xml +++ b/processor/src/test/resources/pr45/pom.xml @@ -0,0 +1,31 @@ + + + 4.0.0 + + org.bsc.maven + maven-processor-plugin-test + ${project.version} + jar + Test Processor Plugin + + + + + org.bsc.maven + maven-processor-plugin + ${project.version} + + + + org.mapstruct + mapstruct-processor + 1.0 + + + + + + + + \ No newline at end of file