View Javadoc
1   /*
2    * SPDX-FileCopyrightText: Copyright (c) 2011-2026 Yegor Bugayenko
3    * SPDX-License-Identifier: MIT
4    */
5   package com.qulice.maven;
6   
7   import com.jcabi.log.Logger;
8   import java.util.ArrayList;
9   import java.util.Collection;
10  import javax.inject.Inject;
11  import org.apache.maven.execution.MavenSession;
12  import org.apache.maven.plugin.AbstractMojo;
13  import org.apache.maven.plugin.MavenPluginManager;
14  import org.apache.maven.plugin.MojoFailureException;
15  import org.apache.maven.plugins.annotations.Parameter;
16  import org.apache.maven.project.MavenProject;
17  import org.codehaus.plexus.context.Context;
18  import org.codehaus.plexus.personality.plexus.lifecycle.phase.Contextualizable;
19  import org.slf4j.impl.StaticLoggerBinder;
20  
21  /**
22   * Abstract mojo.
23   *
24   * @since 0.3
25   */
26  public abstract class AbstractQuliceMojo extends AbstractMojo
27      implements Contextualizable {
28  
29      /**
30       * Name of the parameter that carries the extra ErrorProne flags of the
31       * project down to {@code ErrorProneValidator}.
32       */
33      private static final String ERRORPRONE = "qulice.errorprone";
34  
35      /**
36       * Environment to pass to validators.
37       */
38      private final DefaultMavenEnvironment environment;
39  
40      /**
41       * Maven project, to be injected by Maven itself.
42       */
43      @Parameter(defaultValue = "${project}", readonly = true)
44      private MavenProject project;
45  
46      /**
47       * Maven session, to be injected by Maven itself.
48       */
49      @Parameter(defaultValue = "${session}", readonly = true)
50      private MavenSession sess;
51  
52      /**
53       * Maven plugin manager, to be injected by Maven itself.
54       */
55      @Inject
56      private MavenPluginManager manager;
57  
58      /**
59       * Shall we skip execution?
60       */
61      @Parameter(property = "qulice.skip", defaultValue = "false")
62      private boolean skip;
63  
64      /**
65       * List of regular expressions to exclude.
66       */
67      @Parameter(property = "qulice.excludes")
68      private final Collection<String> excludes;
69  
70      /**
71       * List of xpath queries to validate pom.xml.
72       */
73      @Parameter(
74          property = "qulice.asserts",
75          required = false
76      )
77      private final Collection<String> asserts;
78  
79      /**
80       * List of ErrorProne flags to add to the ones Qulice already passes,
81       * e.g. {@code -Xep:UnicodeInCode:OFF} to switch a bug pattern off, or
82       * {@code -Xep:OperatorPrecedence:ERROR} to switch one back on.
83       */
84      @Parameter(
85          property = AbstractQuliceMojo.ERRORPRONE,
86          required = false
87      )
88      private final Collection<String> errorprone;
89  
90      /**
91       * The source encoding.
92       *
93       * @parameter expression="${project.build.sourceEncoding}" required="true"
94       */
95      @Parameter(property = "encoding", defaultValue = "${project.build.sourceEncoding}")
96      private String charset;
97  
98      /**
99       * Default constructor.
100      */
101     protected AbstractQuliceMojo() {
102         this.environment = new DefaultMavenEnvironment();
103         this.excludes = new ArrayList<>(0);
104         this.asserts = new ArrayList<>(0);
105         this.errorprone = new ArrayList<>(0);
106     }
107 
108     /**
109      * Set Maven Project (used mostly for unit testing).
110      *
111      * @param proj The project to set
112      */
113     public final void setProject(final MavenProject proj) {
114         this.project = proj;
115     }
116 
117     /**
118      * Set skip option (mostly for unit testing).
119      *
120      * @param skp The "skip" option
121      */
122     public final void setSkip(final boolean skp) {
123         this.skip = skp;
124     }
125 
126     /**
127      * Set asserts option.
128      *
129      * @param val Asserts to use
130      */
131     public final void setAsserts(final Collection<String> val) {
132         this.asserts.clear();
133         this.asserts.addAll(val);
134     }
135 
136     /**
137      * Set excludes.
138      *
139      * @param exprs Expressions
140      */
141     public final void setExcludes(final Collection<String> exprs) {
142         this.excludes.clear();
143         this.excludes.addAll(exprs);
144     }
145 
146     /**
147      * Set extra ErrorProne flags.
148      *
149      * @param flags Flags, e.g. {@code -Xep:UnicodeInCode:OFF}
150      */
151     public final void setErrorprone(final Collection<String> flags) {
152         this.errorprone.clear();
153         this.errorprone.addAll(flags);
154     }
155 
156     /**
157      * Set source code encoding.
158      *
159      * @param encoding Source code encoding
160      */
161     public void setEncoding(final String encoding) {
162         this.charset = encoding;
163     }
164 
165     @Override
166     public final void contextualize(final Context ctx) {
167         this.environment.setContext(ctx);
168     }
169 
170     @Override
171     public final void execute() throws MojoFailureException {
172         final long start = System.currentTimeMillis();
173         StaticLoggerBinder.getSingleton().setMavenLog(this.getLog());
174         if (this.skip) {
175             this.getLog().info("Execution skipped");
176             return;
177         }
178         this.environment.setProject(this.project);
179         this.environment.setMojoExecutor(
180             new MojoExecutor(this.manager, this.sess)
181         );
182         this.environment.setExcludes(this.excludes);
183         this.environment.setAssertion(this.asserts);
184         this.environment.setEncoding(this.charset);
185         if (!this.errorprone.isEmpty()) {
186             this.environment.setProperty(
187                 AbstractQuliceMojo.ERRORPRONE,
188                 String.join(" ", this.errorprone)
189             );
190         }
191         Logger.info(
192             this,
193             "Qulice %s in %[ms]s",
194             this.doExecute(),
195             System.currentTimeMillis() - start
196         );
197     }
198 
199     /**
200      * Current maven session.
201      *
202      * @return Current maven session
203      */
204     public final MavenSession session() {
205         return this.sess;
206     }
207 
208     /**
209      * Do the real execution.
210      *
211      * @return What was done, as the middle of the final log line, e.g.
212      *  {@code "checked 42 .java files against 385 rules"}
213      * @throws MojoFailureException If some failure inside
214      */
215     protected abstract String doExecute() throws MojoFailureException;
216 
217     /**
218      * Get the environment.
219      *
220      * @return The environment
221      */
222     protected final MavenEnvironment env() {
223         return this.environment;
224     }
225 }