1   
2   
3   
4   
5   
6   
7   
8   
9   
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  package org.apache.maven.plugins.checkstyle;
20  
21  import java.io.BufferedReader;
22  import java.io.ByteArrayOutputStream;
23  import java.io.File;
24  import java.io.FileNotFoundException;
25  import java.io.FileOutputStream;
26  import java.io.IOException;
27  import java.io.OutputStream;
28  import java.io.Reader;
29  import java.nio.file.Files;
30  import java.nio.file.Path;
31  import java.util.ArrayList;
32  import java.util.Collections;
33  import java.util.List;
34  import java.util.Map;
35  
36  import com.puppycrawl.tools.checkstyle.DefaultLogger;
37  import com.puppycrawl.tools.checkstyle.XMLLogger;
38  import com.puppycrawl.tools.checkstyle.api.AuditListener;
39  import com.puppycrawl.tools.checkstyle.api.AutomaticBean.OutputStreamOptions;
40  import com.puppycrawl.tools.checkstyle.api.CheckstyleException;
41  import org.apache.maven.artifact.Artifact;
42  import org.apache.maven.model.Dependency;
43  import org.apache.maven.model.Plugin;
44  import org.apache.maven.model.PluginManagement;
45  import org.apache.maven.model.Resource;
46  import org.apache.maven.plugin.AbstractMojo;
47  import org.apache.maven.plugin.MojoExecutionException;
48  import org.apache.maven.plugin.MojoFailureException;
49  import org.apache.maven.plugin.descriptor.PluginDescriptor;
50  import org.apache.maven.plugins.annotations.Component;
51  import org.apache.maven.plugins.annotations.LifecyclePhase;
52  import org.apache.maven.plugins.annotations.Mojo;
53  import org.apache.maven.plugins.annotations.Parameter;
54  import org.apache.maven.plugins.annotations.ResolutionScope;
55  import org.apache.maven.plugins.checkstyle.exec.CheckstyleExecutor;
56  import org.apache.maven.plugins.checkstyle.exec.CheckstyleExecutorException;
57  import org.apache.maven.plugins.checkstyle.exec.CheckstyleExecutorRequest;
58  import org.apache.maven.project.MavenProject;
59  import org.codehaus.plexus.configuration.PlexusConfiguration;
60  import org.codehaus.plexus.util.FileUtils;
61  import org.codehaus.plexus.util.PathTool;
62  import org.codehaus.plexus.util.ReaderFactory;
63  import org.codehaus.plexus.util.xml.pull.MXParser;
64  import org.codehaus.plexus.util.xml.pull.XmlPullParser;
65  import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
66  
67  
68  
69  
70  
71  
72  
73  
74  
75  @Mojo(
76          name = "check",
77          defaultPhase = LifecyclePhase.VERIFY,
78          requiresDependencyResolution = ResolutionScope.NONE,
79          threadSafe = true)
80  public class CheckstyleViolationCheckMojo extends AbstractMojo {
81  
82      private static final String JAVA_FILES = "**\\/*.java";
83      private static final String DEFAULT_CONFIG_LOCATION = "sun_checks.xml";
84  
85      
86  
87  
88  
89  
90      @Parameter(property = "checkstyle.output.file", defaultValue = "${project.build.directory}/checkstyle-result.xml")
91      private File outputFile;
92  
93      
94  
95  
96  
97      @Parameter(property = "checkstyle.output.format", defaultValue = "xml")
98      private String outputFileFormat;
99  
100     
101 
102 
103 
104 
105 
106     @Parameter(property = "checkstyle.failOnViolation", defaultValue = "true")
107     private boolean failOnViolation;
108 
109     
110 
111 
112 
113 
114 
115     @Parameter(property = "checkstyle.maxAllowedViolations", defaultValue = "0")
116     private int maxAllowedViolations;
117 
118     
119 
120 
121 
122 
123 
124     @Parameter(property = "checkstyle.violationSeverity", defaultValue = "error")
125     private String violationSeverity = "error";
126 
127     
128 
129 
130 
131 
132 
133     @Parameter(property = "checkstyle.violation.ignore")
134     private String violationIgnore;
135 
136     
137 
138 
139 
140 
141     @Parameter(property = "checkstyle.skip", defaultValue = "false")
142     private boolean skip;
143 
144     
145 
146 
147 
148 
149     @Parameter(property = "checkstyle.skipExec", defaultValue = "false")
150     private boolean skipExec;
151 
152     
153 
154 
155 
156 
157     @Parameter(property = "checkstyle.console", defaultValue = "true")
158     private boolean logViolationsToConsole;
159 
160     
161 
162 
163 
164 
165     @Parameter(property = "checkstyle.logViolationCount", defaultValue = "true")
166     private boolean logViolationCountToConsole;
167 
168     
169 
170 
171 
172 
173     @Parameter(defaultValue = "${project.resources}", readonly = true)
174     protected List<Resource> resources;
175 
176     
177 
178 
179 
180 
181     @Parameter(defaultValue = "${project.testResources}", readonly = true)
182     protected List<Resource> testResources;
183 
184     
185 
186 
187 
188 
189 
190 
191 
192 
193 
194 
195 
196 
197 
198 
199 
200 
201 
202 
203 
204 
205 
206 
207     @Parameter(property = "checkstyle.config.location", defaultValue = DEFAULT_CONFIG_LOCATION)
208     private String configLocation;
209 
210     
211 
212 
213 
214 
215 
216 
217 
218 
219 
220 
221 
222 
223 
224 
225 
226     @Parameter(property = "checkstyle.properties.location")
227     private String propertiesLocation;
228 
229     
230 
231 
232     @Parameter
233     private String propertyExpansion;
234 
235     
236 
237 
238 
239 
240 
241 
242 
243 
244 
245 
246 
247 
248 
249 
250 
251 
252 
253     @Parameter(property = "checkstyle.header.file", defaultValue = "LICENSE.txt")
254     private String headerLocation;
255 
256     
257 
258 
259     @Parameter(defaultValue = "${project.build.directory}/checkstyle-cachefile")
260     private String cacheFile;
261 
262     
263 
264 
265 
266 
267     @Parameter(property = "checkstyle.suppression.expression", defaultValue = "checkstyle.suppressions.file")
268     private String suppressionsFileExpression;
269 
270     
271 
272 
273 
274 
275 
276 
277 
278 
279 
280 
281 
282 
283 
284     @Parameter(property = "checkstyle.suppressions.location")
285     private String suppressionsLocation;
286 
287     
288 
289 
290 
291 
292 
293 
294     @Parameter(property = "encoding", defaultValue = "${project.build.sourceEncoding}")
295     private String inputEncoding;
296 
297     
298 
299 
300     @Component(role = CheckstyleExecutor.class, hint = "default")
301     protected CheckstyleExecutor checkstyleExecutor;
302 
303     
304 
305 
306     @Parameter(property = "checkstyle.consoleOutput", defaultValue = "false")
307     private boolean consoleOutput;
308 
309     
310 
311 
312     @Parameter(defaultValue = "${project}", readonly = true, required = true)
313     protected MavenProject project;
314 
315     
316 
317 
318     @Parameter(defaultValue = "${plugin}", readonly = true, required = true)
319     private PluginDescriptor plugin;
320 
321     
322 
323 
324 
325     @Parameter
326     private File useFile;
327 
328     
329 
330 
331 
332     @Parameter(property = "checkstyle.excludes")
333     private String excludes;
334 
335     
336 
337 
338     @Parameter(property = "checkstyle.includes", defaultValue = JAVA_FILES, required = true)
339     private String includes;
340 
341     
342 
343 
344 
345 
346     @Parameter(property = "checkstyle.resourceExcludes")
347     private String resourceExcludes;
348 
349     
350 
351 
352 
353     @Parameter(property = "checkstyle.resourceIncludes", defaultValue = "**/*.properties", required = true)
354     private String resourceIncludes;
355 
356     
357 
358 
359 
360 
361 
362     @Parameter(defaultValue = "false")
363     private boolean failsOnError;
364 
365     
366 
367 
368 
369 
370 
371 
372     @Deprecated
373     @Parameter
374     private File testSourceDirectory;
375 
376     
377 
378 
379 
380 
381     
382     @Parameter
383     private List<String> testSourceDirectories;
384 
385     
386 
387 
388 
389 
390     @Parameter(defaultValue = "false")
391     private boolean includeTestSourceDirectory;
392 
393     
394 
395 
396 
397 
398 
399     @Deprecated
400     @Parameter
401     private File sourceDirectory;
402 
403     
404 
405 
406 
407 
408     
409     @Parameter
410     private List<String> sourceDirectories;
411 
412     
413 
414 
415 
416     @Parameter(property = "checkstyle.includeResources", defaultValue = "true", required = true)
417     private boolean includeResources = true;
418 
419     
420 
421 
422 
423     @Parameter(property = "checkstyle.includeTestResources", defaultValue = "true", required = true)
424     private boolean includeTestResources = true;
425 
426     
427 
428 
429 
430 
431 
432 
433 
434 
435 
436 
437 
438 
439 
440 
441 
442 
443 
444 
445 
446 
447 
448 
449 
450     @Parameter
451     private PlexusConfiguration checkstyleRules;
452 
453     
454 
455 
456     @Parameter(
457             property = "checkstyle.output.rules.file",
458             defaultValue = "${project.build.directory}/checkstyle-rules.xml")
459     private File rulesFiles;
460 
461     
462 
463 
464 
465     @Parameter(
466             defaultValue = "<?xml version=\"1.0\"?>\n"
467                     + "<!DOCTYPE module PUBLIC \"-//Checkstyle//DTD Checkstyle Configuration 1.3//EN\"\n"
468                     + "        \"https://checkstyle.org/dtds/configuration_1_3.dtd\">\n")
469     private String checkstyleRulesHeader;
470 
471     
472 
473 
474 
475 
476 
477     @Parameter(defaultValue = "false")
478     private boolean omitIgnoredModules;
479 
480     
481 
482 
483 
484 
485     @Parameter(property = "checkstyle.excludeGeneratedSources", defaultValue = "false")
486     private boolean excludeGeneratedSources;
487 
488     private ByteArrayOutputStream stringOutputStream;
489 
490     private File outputXmlFile;
491 
492     
493     public void execute() throws MojoExecutionException, MojoFailureException {
494         checkDeprecatedParameterUsage(sourceDirectory, "sourceDirectory", "sourceDirectories");
495         checkDeprecatedParameterUsage(testSourceDirectory, "testSourceDirectory", "testSourceDirectories");
496         if (skip) {
497             return;
498         }
499 
500         outputXmlFile = outputFile;
501 
502         if (!skipExec) {
503             String effectiveConfigLocation = configLocation;
504             if (checkstyleRules != null) {
505                 if (!DEFAULT_CONFIG_LOCATION.equals(configLocation)) {
506                     throw new MojoExecutionException(
507                             "If you use inline configuration for rules, don't specify " + "a configLocation");
508                 }
509                 if (checkstyleRules.getChildCount() > 1) {
510                     throw new MojoExecutionException("Currently only one root module is supported");
511                 }
512 
513                 PlexusConfiguration checkerModule = checkstyleRules.getChild(0);
514 
515                 try {
516                     FileUtils.forceMkdir(rulesFiles.getParentFile());
517                     FileUtils.fileWrite(rulesFiles, checkstyleRulesHeader + checkerModule.toString());
518                 } catch (final IOException e) {
519                     throw new MojoExecutionException(e.getMessage(), e);
520                 }
521                 effectiveConfigLocation = rulesFiles.getAbsolutePath();
522             }
523 
524             ClassLoader currentClassLoader = Thread.currentThread().getContextClassLoader();
525 
526             try {
527                 CheckstyleExecutorRequest request = new CheckstyleExecutorRequest();
528                 request.setConsoleListener(getConsoleListener())
529                         .setConsoleOutput(consoleOutput)
530                         .setExcludes(excludes)
531                         .setFailsOnError(failsOnError)
532                         .setIncludes(includes)
533                         .setResourceIncludes(resourceIncludes)
534                         .setResourceExcludes(resourceExcludes)
535                         .setIncludeResources(includeResources)
536                         .setIncludeTestResources(includeTestResources)
537                         .setIncludeTestSourceDirectory(includeTestSourceDirectory)
538                         .setListener(getListener())
539                         .setProject(project)
540                         .setSourceDirectories(getSourceDirectories())
541                         .setResources(resources)
542                         .setTestResources(testResources)
543                         .setStringOutputStream(stringOutputStream)
544                         .setSuppressionsLocation(suppressionsLocation)
545                         .setTestSourceDirectories(getTestSourceDirectories())
546                         .setConfigLocation(effectiveConfigLocation)
547                         .setConfigurationArtifacts(collectArtifacts("config"))
548                         .setPropertyExpansion(propertyExpansion)
549                         .setHeaderLocation(headerLocation)
550                         .setLicenseArtifacts(collectArtifacts("license"))
551                         .setCacheFile(cacheFile)
552                         .setSuppressionsFileExpression(suppressionsFileExpression)
553                         .setEncoding(inputEncoding)
554                         .setPropertiesLocation(propertiesLocation)
555                         .setOmitIgnoredModules(omitIgnoredModules);
556                 checkstyleExecutor.executeCheckstyle(request);
557 
558             } catch (CheckstyleException e) {
559                 throw new MojoExecutionException("Failed during checkstyle configuration", e);
560             } catch (CheckstyleExecutorException e) {
561                 throw new MojoExecutionException("Failed during checkstyle execution", e);
562             } finally {
563                 
564                 Thread.currentThread().setContextClassLoader(currentClassLoader);
565             }
566         }
567 
568         if (!"xml".equals(outputFileFormat) && skipExec) {
569             throw new MojoExecutionException("Output format is '" + outputFileFormat
570                     + "', checkstyle:check requires format to be 'xml' when using skipExec.");
571         }
572 
573         if (!outputXmlFile.exists()) {
574             getLog().info("Unable to perform checkstyle:check, unable to find checkstyle:checkstyle outputFile.");
575             return;
576         }
577 
578         try (Reader reader = new BufferedReader(ReaderFactory.newXmlReader(outputXmlFile))) {
579             XmlPullParser xpp = new MXParser();
580             xpp.setInput(reader);
581 
582             final List<Violation> violationsList = getViolations(xpp);
583             long violationCount = countViolations(violationsList);
584             printViolations(violationsList);
585 
586             String msg = "You have " + violationCount + " Checkstyle violation"
587                     + ((violationCount > 1 || violationCount == 0) ? "s" : "") + ".";
588 
589             if (violationCount > maxAllowedViolations) {
590                 if (failOnViolation) {
591                     if (maxAllowedViolations > 0) {
592                         msg += " The maximum number of allowed violations is " + maxAllowedViolations + ".";
593                     }
594                     throw new MojoFailureException(msg);
595                 }
596 
597                 getLog().warn("checkstyle:check violations detected but failOnViolation set to false");
598             }
599             if (logViolationCountToConsole) {
600                 if (maxAllowedViolations > 0) {
601                     msg += " The maximum number of allowed violations is " + maxAllowedViolations + ".";
602                 }
603                 getLog().info(msg);
604             }
605         } catch (IOException | XmlPullParserException e) {
606             throw new MojoExecutionException(
607                     "Unable to read Checkstyle results xml: " + outputXmlFile.getAbsolutePath(), e);
608         }
609     }
610 
611     private void checkDeprecatedParameterUsage(Object parameter, String name, String replacement)
612             throws MojoFailureException {
613         if (parameter != null) {
614             throw new MojoFailureException("You are using '" + name + "' which has been removed"
615                     + " from the maven-checkstyle-plugin. " + "Please use '" + replacement
616                     + "' and refer to the >>Major Version Upgrade to version 3.0.0<< " + "on the plugin site.");
617         }
618     }
619 
620     private List<Violation> getViolations(XmlPullParser xpp) throws XmlPullParserException, IOException {
621         List<Violation> violations = new ArrayList<>();
622 
623         String basedir = project.getBasedir().getAbsolutePath();
624         String file = "";
625 
626         for (int eventType = xpp.getEventType(); eventType != XmlPullParser.END_DOCUMENT; eventType = xpp.next()) {
627             if (eventType != XmlPullParser.START_TAG) {
628                 continue;
629             } else if ("file".equals(xpp.getName())) {
630                 file = PathTool.getRelativeFilePath(basedir, xpp.getAttributeValue("", "name"));
631                 continue;
632             } else if (!"error".equals(xpp.getName())) {
633                 continue;
634             }
635 
636             String severity = xpp.getAttributeValue("", "severity");
637             String source = xpp.getAttributeValue("", "source");
638             String line = xpp.getAttributeValue("", "line");
639             
640             String column = xpp.getAttributeValue("", "column");
641             String message = xpp.getAttributeValue("", "message");
642             String rule = RuleUtil.getName(source);
643             String category = RuleUtil.getCategory(source);
644 
645             Violation violation = new Violation(source, file, line, severity, message, rule, category);
646             if (column != null) {
647                 violation.setColumn(column);
648             }
649 
650             violations.add(violation);
651         }
652 
653         return violations;
654     }
655 
656     private int countViolations(List<Violation> violations) {
657         List<RuleUtil.Matcher> ignores = violationIgnore == null
658                 ? Collections.<RuleUtil.Matcher>emptyList()
659                 : RuleUtil.parseMatchers(violationIgnore.split(","));
660 
661         int ignored = 0;
662         int countedViolations = 0;
663 
664         for (Violation violation : violations) {
665             if (!isViolation(violation.getSeverity())) {
666                 continue;
667             }
668 
669             if (ignore(ignores, violation.getSource())) {
670                 ignored++;
671                 continue;
672             }
673 
674             countedViolations++;
675         }
676 
677         if (ignored > 0) {
678             getLog().info("Ignored " + ignored + " error" + ((ignored > 1L) ? "s" : "") + ", " + countedViolations
679                     + " violation" + ((countedViolations > 1) ? "s" : "") + " remaining.");
680         }
681 
682         return countedViolations;
683     }
684 
685     private void printViolations(List<Violation> violations) {
686         if (!logViolationsToConsole) {
687             return;
688         }
689 
690         List<RuleUtil.Matcher> ignores = violationIgnore == null
691                 ? Collections.<RuleUtil.Matcher>emptyList()
692                 : RuleUtil.parseMatchers(violationIgnore.split(","));
693 
694         violations.stream()
695                 .filter(violation -> isViolation(violation.getSeverity()))
696                 .filter(violation -> !ignore(ignores, violation.getSource()))
697                 .forEach(violation -> {
698                     final String message = String.format(
699                             "%s:[%s%s] (%s) %s: %s",
700                             violation.getFile(),
701                             violation.getLine(),
702                             (Violation.NO_COLUMN.equals(violation.getColumn())) ? "" : (',' + violation.getColumn()),
703                             violation.getCategory(),
704                             violation.getRuleName(),
705                             violation.getMessage());
706                     log(violation.getSeverity(), message);
707                 });
708     }
709 
710     private void log(String severity, String message) {
711         if ("info".equals(severity)) {
712             getLog().info(message);
713         } else if ("warning".equals(severity)) {
714             getLog().warn(message);
715         } else {
716             getLog().error(message);
717         }
718     }
719 
720     
721 
722 
723 
724 
725 
726     private boolean isViolation(String severity) {
727         if ("error".equals(severity)) {
728             return "error".equals(violationSeverity)
729                     || "warning".equals(violationSeverity)
730                     || "info".equals(violationSeverity);
731         } else if ("warning".equals(severity)) {
732             return "warning".equals(violationSeverity) || "info".equals(violationSeverity);
733         } else if ("info".equals(severity)) {
734             return "info".equals(violationSeverity);
735         } else {
736             return false;
737         }
738     }
739 
740     private boolean ignore(List<RuleUtil.Matcher> ignores, String source) {
741         for (RuleUtil.Matcher ignore : ignores) {
742             if (ignore.match(source)) {
743                 return true;
744             }
745         }
746         return false;
747     }
748 
749     private DefaultLogger getConsoleListener() throws MojoExecutionException {
750         DefaultLogger consoleListener;
751 
752         if (useFile == null) {
753             stringOutputStream = new ByteArrayOutputStream();
754             consoleListener = new DefaultLogger(stringOutputStream, OutputStreamOptions.NONE);
755         } else {
756             OutputStream out = getOutputStream(useFile);
757 
758             consoleListener = new DefaultLogger(out, OutputStreamOptions.CLOSE);
759         }
760 
761         return consoleListener;
762     }
763 
764     private OutputStream getOutputStream(File file) throws MojoExecutionException {
765         File parentFile = file.getAbsoluteFile().getParentFile();
766 
767         if (!parentFile.exists()) {
768             parentFile.mkdirs();
769         }
770 
771         FileOutputStream fileOutputStream;
772         try {
773             fileOutputStream = new FileOutputStream(file);
774         } catch (FileNotFoundException e) {
775             throw new MojoExecutionException("Unable to create output stream: " + file, e);
776         }
777         return fileOutputStream;
778     }
779 
780     private AuditListener getListener() throws MojoFailureException, MojoExecutionException {
781         AuditListener listener = null;
782 
783         if (outputFileFormat != null && !outputFileFormat.isEmpty()) {
784             File resultFile = outputFile;
785 
786             OutputStream out = getOutputStream(resultFile);
787 
788             if ("xml".equals(outputFileFormat)) {
789                 listener = new XMLLogger(out, OutputStreamOptions.CLOSE);
790             } else if ("plain".equals(outputFileFormat)) {
791                 try {
792                     
793                     
794                     outputXmlFile =
795                             Files.createTempFile("checkstyle-result", ".xml").toFile();
796                     outputXmlFile.deleteOnExit();
797                     OutputStream xmlOut = getOutputStream(outputXmlFile);
798                     CompositeAuditListener compoundListener = new CompositeAuditListener();
799                     compoundListener.addListener(new XMLLogger(xmlOut, OutputStreamOptions.CLOSE));
800                     compoundListener.addListener(new DefaultLogger(out, OutputStreamOptions.CLOSE));
801                     listener = compoundListener;
802                 } catch (IOException e) {
803                     throw new MojoExecutionException("Unable to create temporary file", e);
804                 }
805             } else {
806                 throw new MojoFailureException(
807                         "Invalid output file format: (" + outputFileFormat + "). Must be 'plain' or 'xml'.");
808             }
809         }
810 
811         return listener;
812     }
813 
814     private List<Artifact> collectArtifacts(String hint) {
815         List<Artifact> artifacts = new ArrayList<>();
816 
817         PluginManagement pluginManagement = project.getBuild().getPluginManagement();
818         if (pluginManagement != null) {
819             artifacts.addAll(getCheckstylePluginDependenciesAsArtifacts(pluginManagement.getPluginsAsMap(), hint));
820         }
821 
822         artifacts.addAll(
823                 getCheckstylePluginDependenciesAsArtifacts(project.getBuild().getPluginsAsMap(), hint));
824 
825         return artifacts;
826     }
827 
828     private List<Artifact> getCheckstylePluginDependenciesAsArtifacts(Map<String, Plugin> plugins, String hint) {
829         List<Artifact> artifacts = new ArrayList<>();
830 
831         Plugin checkstylePlugin = plugins.get(plugin.getGroupId() + ":" + plugin.getArtifactId());
832         if (checkstylePlugin != null) {
833             for (Dependency dep : checkstylePlugin.getDependencies()) {
834                 
835                 String depKey = dep.getGroupId() + ":" + dep.getArtifactId();
836                 artifacts.add(plugin.getArtifactMap().get(depKey));
837             }
838         }
839         return artifacts;
840     }
841 
842     private List<File> getSourceDirectories() {
843         if (sourceDirectories == null) {
844             sourceDirectories = filterBuildTarget(project.getCompileSourceRoots());
845         }
846         List<File> sourceDirs = new ArrayList<>(sourceDirectories.size());
847         for (String sourceDir : sourceDirectories) {
848             sourceDirs.add(FileUtils.resolveFile(project.getBasedir(), sourceDir));
849         }
850         return sourceDirs;
851     }
852 
853     private List<File> getTestSourceDirectories() {
854         if (testSourceDirectories == null) {
855             testSourceDirectories = filterBuildTarget(project.getTestCompileSourceRoots());
856         }
857         List<File> testSourceDirs = new ArrayList<>(testSourceDirectories.size());
858         for (String testSourceDir : testSourceDirectories) {
859             testSourceDirs.add(FileUtils.resolveFile(project.getBasedir(), testSourceDir));
860         }
861         return testSourceDirs;
862     }
863 
864     private List<String> filterBuildTarget(List<String> sourceDirectories) {
865         if (!excludeGeneratedSources) {
866             return sourceDirectories;
867         }
868 
869         List<String> filtered = new ArrayList<>(sourceDirectories.size());
870         Path buildTarget = FileUtils.resolveFile(
871                         project.getBasedir(), project.getBuild().getDirectory())
872                 .toPath();
873 
874         for (String sourceDir : sourceDirectories) {
875             Path src = FileUtils.resolveFile(project.getBasedir(), sourceDir).toPath();
876             if (!src.startsWith(buildTarget)) {
877                 filtered.add(sourceDir);
878             }
879         }
880         return filtered;
881     }
882 }