This is an automated email from the ASF dual-hosted git repository.

sjaranowski pushed a commit to branch MSHARED-1393
in repository https://gitbox.apache.org/repos/asf/maven-dependency-analyzer.git

commit 2e4b082690a91f530bac4c0490ba42ee52cfb79b
Author: Slawomir Jaranowski <[email protected]>
AuthorDate: Thu May 9 21:42:36 2024 +0200

    [MSHARED-1393] Allow to exclude classes from verification
---
 pom.xml                                            |  6 ++
 src/it/excludeClassFromJar/pom.xml                 | 64 ++++++++++++++++++++++
 .../jarWithXmlTransitiveDependency/Project.java}   | 36 ++++++------
 .../excludeClassFromJar/verify.groovy}             | 31 ++++-------
 src/it/excludeClassFromProject/pom.xml             | 56 +++++++++++++++++++
 .../excludeClassFromProject/setup.groovy}          | 24 ++------
 .../excludeClassFromProject/verify.groovy}         | 30 ++++------
 .../src/main/java/it/test/MockAnalyzeMojo.java     |  6 +-
 .../shared/dependency/analyzer/ClassAnalyzer.java  | 13 ++++-
 ...rClassFileVisitor.java => ClassesPatterns.java} | 50 ++++++++---------
 .../analyzer/CollectorClassFileVisitor.java        |  9 ++-
 .../dependency/analyzer/DefaultClassAnalyzer.java  |  5 +-
 .../analyzer/DefaultProjectDependencyAnalyzer.java | 34 +++++++-----
 .../dependency/analyzer/DependencyAnalyzer.java    | 16 +++++-
 .../analyzer/ProjectDependencyAnalyzer.java        | 18 +++++-
 .../analyzer/asm/ASMDependencyAnalyzer.java        |  7 ++-
 .../analyzer/asm/DependencyClassFileVisitor.java   | 32 ++++++++---
 .../VisitClassException.java}                      | 25 +++------
 .../dependency/analyzer/ClassesPatternsTest.java}  | 47 ++++++++++------
 .../analyzer/asm/ASMDependencyAnalyzerTest.java    | 15 +++++
 .../analyzer/asm/ResultCollectorTest.java          | 62 +++++++--------------
 .../testcases/analyze/ClassToExclude.java}         | 22 ++------
 22 files changed, 379 insertions(+), 229 deletions(-)

diff --git a/pom.xml b/pom.xml
index 7df05e5..0887f4e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -122,6 +122,11 @@
       <artifactId>junit-jupiter-api</artifactId>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>org.junit.jupiter</groupId>
+      <artifactId>junit-jupiter-params</artifactId>
+      <scope>test</scope>
+    </dependency>
     <dependency>
       <groupId>org.assertj</groupId>
       <artifactId>assertj-core</artifactId>
@@ -169,6 +174,7 @@
               <localRepositoryPath>target/local-repo</localRepositoryPath>
               <settingsFile>src/it/settings.xml</settingsFile>
               <postBuildHookScript>verify</postBuildHookScript>
+              <preBuildHookScript>setup</preBuildHookScript>
               <goals>
                 <goal>verify</goal>
               </goals>
diff --git a/src/it/excludeClassFromJar/pom.xml 
b/src/it/excludeClassFromJar/pom.xml
new file mode 100644
index 0000000..7165d0a
--- /dev/null
+++ b/src/it/excludeClassFromJar/pom.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  ~ 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.
+  -->
+
+<project
+    xmlns="http://maven.apache.org/POM/4.0.0";
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";
+>
+  <modelVersion>4.0.0</modelVersion>
+
+  <groupId>org.apache.maven.shared.dependency-analyzer.tests</groupId>
+  <artifactId>jarWithXercesDependencies</artifactId>
+  <version>1.0</version>
+  <packaging>jar</packaging>
+
+  <dependencies>
+    <dependency>
+      <groupId>dom4j</groupId>
+      <artifactId>dom4j</artifactId>
+      <version>1.6.1</version>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.shared.dependency-analyzer.tests</groupId>
+        <artifactId>maven-mock-plugin</artifactId>
+        <version>1.0</version>
+        <executions>
+          <execution>
+            <goals>
+              <goal>mock-analyze</goal>
+            </goals>
+          </execution>
+        </executions>
+        <configuration>
+          <excludedClasses>
+            <exclude>org.xml.sax.*</exclude>
+          </excludedClasses>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+
+</project>
diff --git 
a/src/main/java/org/apache/maven/shared/dependency/analyzer/ClassAnalyzer.java 
b/src/it/excludeClassFromJar/src/main/java/jarWithXmlTransitiveDependency/Project.java
similarity index 55%
copy from 
src/main/java/org/apache/maven/shared/dependency/analyzer/ClassAnalyzer.java
copy to 
src/it/excludeClassFromJar/src/main/java/jarWithXmlTransitiveDependency/Project.java
index 679b4d6..35cd164 100644
--- 
a/src/main/java/org/apache/maven/shared/dependency/analyzer/ClassAnalyzer.java
+++ 
b/src/it/excludeClassFromJar/src/main/java/jarWithXmlTransitiveDependency/Project.java
@@ -1,3 +1,5 @@
+package jarWithXmlTransitiveDependency;
+
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
@@ -7,7 +9,7 @@
  * "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
+ *  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
@@ -16,25 +18,25 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.maven.shared.dependency.analyzer;
 
-import java.io.IOException;
-import java.net.URL;
-import java.util.Set;
+import org.dom4j.Text;
+import org.xml.sax.Parser;
 
 /**
- * Gets the set of classes contained in a library given either as a jar file 
or an exploded directory.
- *
- * @author <a href="mailto:[email protected]";>Mark Hobson</a>
+ * Dependency on dom4j gives xml-apis transitive dependency, which contains 
SAX Parser class. But SAX Parser is available in
+ * JDK: no need to declare a direct dependency.
+ * 
  */
-public interface ClassAnalyzer {
+public class Project
+{
+    public Text text;
+    
+    public Parser parser;
+
+    // constructors -----------------------------------------------------------
 
-    /**
-     * <p>analyze.</p>
-     *
-     * @param url the JAR file or directory to analyze
-     * @return a {@link java.util.Set} object
-     * @throws java.io.IOException if any
-     */
-    Set<String> analyze(URL url) throws IOException;
+    public Project()
+    {
+        // no op
+    }
 }
diff --git 
a/src/main/java/org/apache/maven/shared/dependency/analyzer/ClassAnalyzer.java 
b/src/it/excludeClassFromJar/verify.groovy
similarity index 58%
copy from 
src/main/java/org/apache/maven/shared/dependency/analyzer/ClassAnalyzer.java
copy to src/it/excludeClassFromJar/verify.groovy
index 679b4d6..088383c 100644
--- 
a/src/main/java/org/apache/maven/shared/dependency/analyzer/ClassAnalyzer.java
+++ b/src/it/excludeClassFromJar/verify.groovy
@@ -16,25 +16,18 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.maven.shared.dependency.analyzer;
 
-import java.io.IOException;
-import java.net.URL;
-import java.util.Set;
+def analysis = new File( basedir, 'target/analysis.txt' ).text
 
-/**
- * Gets the set of classes contained in a library given either as a jar file 
or an exploded directory.
- *
- * @author <a href="mailto:[email protected]";>Mark Hobson</a>
- */
-public interface ClassAnalyzer {
+def expected = '''
+UsedDeclaredArtifacts:
+ dom4j:dom4j:jar:1.6.1:compile
+
+UsedUndeclaredArtifactsWithClasses:
+
+UnusedDeclaredArtifacts:
+
+TestArtifactsWithNonTestScope:
+'''
 
-    /**
-     * <p>analyze.</p>
-     *
-     * @param url the JAR file or directory to analyze
-     * @return a {@link java.util.Set} object
-     * @throws java.io.IOException if any
-     */
-    Set<String> analyze(URL url) throws IOException;
-}
+assert analysis == expected
diff --git a/src/it/excludeClassFromProject/pom.xml 
b/src/it/excludeClassFromProject/pom.xml
new file mode 100644
index 0000000..3885761
--- /dev/null
+++ b/src/it/excludeClassFromProject/pom.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  ~ 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.
+  -->
+
+<project
+    xmlns="http://maven.apache.org/POM/4.0.0";
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";
+>
+  <modelVersion>4.0.0</modelVersion>
+
+  <groupId>org.apache.maven.shared.dependency-analyzer.tests</groupId>
+  <artifactId>jarWithXercesDependencies</artifactId>
+  <version>1.0</version>
+  <packaging>jar</packaging>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.shared.dependency-analyzer.tests</groupId>
+        <artifactId>maven-mock-plugin</artifactId>
+        <version>1.0</version>
+        <executions>
+          <execution>
+            <goals>
+              <goal>mock-analyze</goal>
+            </goals>
+          </execution>
+        </executions>
+        <configuration>
+          <excludedClasses>
+            <exclude>org.example.BadClass</exclude>
+          </excludedClasses>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+
+</project>
diff --git 
a/src/main/java/org/apache/maven/shared/dependency/analyzer/ClassAnalyzer.java 
b/src/it/excludeClassFromProject/setup.groovy
similarity index 58%
copy from 
src/main/java/org/apache/maven/shared/dependency/analyzer/ClassAnalyzer.java
copy to src/it/excludeClassFromProject/setup.groovy
index 679b4d6..f6eec9b 100644
--- 
a/src/main/java/org/apache/maven/shared/dependency/analyzer/ClassAnalyzer.java
+++ b/src/it/excludeClassFromProject/setup.groovy
@@ -16,25 +16,9 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.maven.shared.dependency.analyzer;
+def badClass = new File(basedir, 'target/classes/org/example/BadClass.class')
 
-import java.io.IOException;
-import java.net.URL;
-import java.util.Set;
+badClass.getParentFile().mkdirs()
+badClass << 'some content'
 
-/**
- * Gets the set of classes contained in a library given either as a jar file 
or an exploded directory.
- *
- * @author <a href="mailto:[email protected]";>Mark Hobson</a>
- */
-public interface ClassAnalyzer {
-
-    /**
-     * <p>analyze.</p>
-     *
-     * @param url the JAR file or directory to analyze
-     * @return a {@link java.util.Set} object
-     * @throws java.io.IOException if any
-     */
-    Set<String> analyze(URL url) throws IOException;
-}
+assert badClass.isFile()
diff --git 
a/src/main/java/org/apache/maven/shared/dependency/analyzer/ClassAnalyzer.java 
b/src/it/excludeClassFromProject/verify.groovy
similarity index 58%
copy from 
src/main/java/org/apache/maven/shared/dependency/analyzer/ClassAnalyzer.java
copy to src/it/excludeClassFromProject/verify.groovy
index 679b4d6..e545857 100644
--- 
a/src/main/java/org/apache/maven/shared/dependency/analyzer/ClassAnalyzer.java
+++ b/src/it/excludeClassFromProject/verify.groovy
@@ -16,25 +16,17 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.maven.shared.dependency.analyzer;
 
-import java.io.IOException;
-import java.net.URL;
-import java.util.Set;
+def analysis = new File( basedir, 'target/analysis.txt' ).text
 
-/**
- * Gets the set of classes contained in a library given either as a jar file 
or an exploded directory.
- *
- * @author <a href="mailto:[email protected]";>Mark Hobson</a>
- */
-public interface ClassAnalyzer {
+def expected = '''
+UsedDeclaredArtifacts:
+
+UsedUndeclaredArtifactsWithClasses:
+
+UnusedDeclaredArtifacts:
+
+TestArtifactsWithNonTestScope:
+'''
 
-    /**
-     * <p>analyze.</p>
-     *
-     * @param url the JAR file or directory to analyze
-     * @return a {@link java.util.Set} object
-     * @throws java.io.IOException if any
-     */
-    Set<String> analyze(URL url) throws IOException;
-}
+assert analysis == expected
diff --git 
a/src/it/setup-mock-plugin/src/main/java/it/test/MockAnalyzeMojo.java 
b/src/it/setup-mock-plugin/src/main/java/it/test/MockAnalyzeMojo.java
index 8d9fe65..27d78ee 100644
--- a/src/it/setup-mock-plugin/src/main/java/it/test/MockAnalyzeMojo.java
+++ b/src/it/setup-mock-plugin/src/main/java/it/test/MockAnalyzeMojo.java
@@ -24,6 +24,7 @@ import java.io.File;
 import java.io.FileNotFoundException;
 import java.io.PrintWriter;
 import java.nio.file.Files;
+import java.util.Set;
 
 import org.apache.maven.plugin.AbstractMojo;
 import org.apache.maven.plugin.MojoExecutionException;
@@ -63,12 +64,15 @@ public class MockAnalyzeMojo extends AbstractMojo
     @Parameter( defaultValue = "${project.build.directory}/analysis.txt", 
readonly = true )
     private File output;
 
+    @Parameter
+    private Set<String> excludedClasses;
+
     @Override
     public void execute() throws MojoExecutionException, MojoFailureException
     {
         try
         {
-            ProjectDependencyAnalysis analysis = analyzer.analyze( project );
+            ProjectDependencyAnalysis analysis = analyzer.analyze( project, 
excludedClasses );
 
             Files.createDirectories( output.toPath().getParent() );
             try ( PrintWriter printWriter = new UnixPrintWiter( output ) )
diff --git 
a/src/main/java/org/apache/maven/shared/dependency/analyzer/ClassAnalyzer.java 
b/src/main/java/org/apache/maven/shared/dependency/analyzer/ClassAnalyzer.java
index 679b4d6..af2b154 100644
--- 
a/src/main/java/org/apache/maven/shared/dependency/analyzer/ClassAnalyzer.java
+++ 
b/src/main/java/org/apache/maven/shared/dependency/analyzer/ClassAnalyzer.java
@@ -36,5 +36,16 @@ public interface ClassAnalyzer {
      * @return a {@link java.util.Set} object
      * @throws java.io.IOException if any
      */
-    Set<String> analyze(URL url) throws IOException;
+    default Set<String> analyze(URL url) throws IOException {
+        return analyze(url, new ClassesPatterns());
+    }
+
+    /**
+     * <p>analyze.</p>
+     *
+     * @param url the JAR file or directory to analyze
+     * @return a {@link java.util.Set} object
+     * @throws java.io.IOException if any
+     */
+    Set<String> analyze(URL url, ClassesPatterns excludedClasses) throws 
IOException;
 }
diff --git 
a/src/main/java/org/apache/maven/shared/dependency/analyzer/CollectorClassFileVisitor.java
 
b/src/main/java/org/apache/maven/shared/dependency/analyzer/ClassesPatterns.java
similarity index 50%
copy from 
src/main/java/org/apache/maven/shared/dependency/analyzer/CollectorClassFileVisitor.java
copy to 
src/main/java/org/apache/maven/shared/dependency/analyzer/ClassesPatterns.java
index 4adf2d2..ce69930 100644
--- 
a/src/main/java/org/apache/maven/shared/dependency/analyzer/CollectorClassFileVisitor.java
+++ 
b/src/main/java/org/apache/maven/shared/dependency/analyzer/ClassesPatterns.java
@@ -18,41 +18,39 @@
  */
 package org.apache.maven.shared.dependency.analyzer;
 
-import java.io.InputStream;
-import java.util.HashSet;
-import java.util.Set;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
 
 /**
- * Simply collects the set of visited classes.
- *
- * @author <a href="mailto:[email protected]";>Mark Hobson</a>
- * @see #getClasses()
+ * Patterns for classes
  */
-public class CollectorClassFileVisitor implements ClassFileVisitor {
-    private final Set<String> classes;
+public class ClassesPatterns {
+
+    private final Collection<Pattern> patterns;
 
     /**
-     * <p>Constructor for CollectorClassFileVisitor.</p>
+     * Default constructor.
+     *
+     * @param patterns a patterns to mach
      */
-    public CollectorClassFileVisitor() {
-        classes = new HashSet<>();
+    public ClassesPatterns(Collection<String> patterns) {
+        if (patterns == null) {
+            this.patterns = Collections.emptyList();
+        } else {
+            this.patterns = 
patterns.stream().map(Pattern::compile).collect(Collectors.toSet());
+        }
     }
 
-    /** {@inheritDoc} */
-    @Override
-    public void visitClass(String className, InputStream in) {
-        // inner classes have equivalent compilation requirement as container 
class
-        if (className.indexOf('$') < 0) {
-            classes.add(className);
-        }
+    public ClassesPatterns() {
+        this.patterns = Collections.emptySet();
     }
 
-    /**
-     * <p>Getter for the field <code>classes</code>.</p>
-     *
-     * @return a {@link java.util.Set} object.
-     */
-    public Set<String> getClasses() {
-        return classes;
+    public boolean isMatch(String className) {
+        if (patterns.isEmpty()) {
+            return false;
+        }
+        return patterns.stream().anyMatch(pattern -> 
pattern.matcher(className).matches());
     }
 }
diff --git 
a/src/main/java/org/apache/maven/shared/dependency/analyzer/CollectorClassFileVisitor.java
 
b/src/main/java/org/apache/maven/shared/dependency/analyzer/CollectorClassFileVisitor.java
index 4adf2d2..4af2ff4 100644
--- 
a/src/main/java/org/apache/maven/shared/dependency/analyzer/CollectorClassFileVisitor.java
+++ 
b/src/main/java/org/apache/maven/shared/dependency/analyzer/CollectorClassFileVisitor.java
@@ -31,18 +31,25 @@ import java.util.Set;
 public class CollectorClassFileVisitor implements ClassFileVisitor {
     private final Set<String> classes;
 
+    private final ClassesPatterns excludedClasses;
+
     /**
      * <p>Constructor for CollectorClassFileVisitor.</p>
      */
     public CollectorClassFileVisitor() {
+        this(new ClassesPatterns());
+    }
+
+    public CollectorClassFileVisitor(ClassesPatterns excludedClasses) {
         classes = new HashSet<>();
+        this.excludedClasses = excludedClasses;
     }
 
     /** {@inheritDoc} */
     @Override
     public void visitClass(String className, InputStream in) {
         // inner classes have equivalent compilation requirement as container 
class
-        if (className.indexOf('$') < 0) {
+        if (className.indexOf('$') < 0 && !excludedClasses.isMatch(className)) 
{
             classes.add(className);
         }
     }
diff --git 
a/src/main/java/org/apache/maven/shared/dependency/analyzer/DefaultClassAnalyzer.java
 
b/src/main/java/org/apache/maven/shared/dependency/analyzer/DefaultClassAnalyzer.java
index dfbed05..4302279 100644
--- 
a/src/main/java/org/apache/maven/shared/dependency/analyzer/DefaultClassAnalyzer.java
+++ 
b/src/main/java/org/apache/maven/shared/dependency/analyzer/DefaultClassAnalyzer.java
@@ -35,10 +35,9 @@ import java.util.zip.ZipException;
 @Singleton
 public class DefaultClassAnalyzer implements ClassAnalyzer {
 
-    /** {@inheritDoc} */
     @Override
-    public Set<String> analyze(URL url) throws IOException {
-        CollectorClassFileVisitor visitor = new CollectorClassFileVisitor();
+    public Set<String> analyze(URL url, ClassesPatterns excludedClasses) 
throws IOException {
+        CollectorClassFileVisitor visitor = new 
CollectorClassFileVisitor(excludedClasses);
 
         try {
             ClassFileVisitorUtils.accept(url, visitor);
diff --git 
a/src/main/java/org/apache/maven/shared/dependency/analyzer/DefaultProjectDependencyAnalyzer.java
 
b/src/main/java/org/apache/maven/shared/dependency/analyzer/DefaultProjectDependencyAnalyzer.java
index 489afd1..c792571 100644
--- 
a/src/main/java/org/apache/maven/shared/dependency/analyzer/DefaultProjectDependencyAnalyzer.java
+++ 
b/src/main/java/org/apache/maven/shared/dependency/analyzer/DefaultProjectDependencyAnalyzer.java
@@ -25,6 +25,7 @@ import javax.inject.Singleton;
 import java.io.File;
 import java.io.IOException;
 import java.net.URL;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.Enumeration;
 import java.util.HashMap;
@@ -61,12 +62,14 @@ public class DefaultProjectDependencyAnalyzer implements 
ProjectDependencyAnalyz
 
     /** {@inheritDoc} */
     @Override
-    public ProjectDependencyAnalysis analyze(MavenProject project) throws 
ProjectDependencyAnalyzerException {
+    public ProjectDependencyAnalysis analyze(MavenProject project, 
Collection<String> excludedClasses)
+            throws ProjectDependencyAnalyzerException {
         try {
-            Map<Artifact, Set<String>> artifactClassMap = 
buildArtifactClassMap(project);
+            ClassesPatterns excludedClassesPatterns = new 
ClassesPatterns(excludedClasses);
+            Map<Artifact, Set<String>> artifactClassMap = 
buildArtifactClassMap(project, excludedClassesPatterns);
 
-            Set<String> mainDependencyClasses = 
buildMainDependencyClasses(project);
-            Set<String> testDependencyClasses = 
buildTestDependencyClasses(project);
+            Set<String> mainDependencyClasses = 
buildMainDependencyClasses(project, excludedClassesPatterns);
+            Set<String> testDependencyClasses = 
buildTestDependencyClasses(project, excludedClassesPatterns);
 
             Set<String> dependencyClasses = new HashSet<>();
             dependencyClasses.addAll(mainDependencyClasses);
@@ -146,7 +149,8 @@ public class DefaultProjectDependencyAnalyzer implements 
ProjectDependencyAnalyz
         return nonTestScopeArtifacts;
     }
 
-    private Map<Artifact, Set<String>> buildArtifactClassMap(MavenProject 
project) throws IOException {
+    private Map<Artifact, Set<String>> buildArtifactClassMap(MavenProject 
project, ClassesPatterns excludedClasses)
+            throws IOException {
         Map<Artifact, Set<String>> artifactClassMap = new LinkedHashMap<>();
 
         Set<Artifact> dependencyArtifacts = project.getArtifacts();
@@ -167,7 +171,9 @@ public class DefaultProjectDependencyAnalyzer implements 
ProjectDependencyAnalyz
                         if (entry.endsWith(".class")) {
                             String className = entry.replace('/', '.');
                             className = className.substring(0, 
className.length() - ".class".length());
-                            classes.add(className);
+                            if (!excludedClasses.isMatch(className)) {
+                                classes.add(className);
+                            }
                         }
                     }
 
@@ -175,7 +181,7 @@ public class DefaultProjectDependencyAnalyzer implements 
ProjectDependencyAnalyz
                 }
             } else if (file != null && file.isDirectory()) {
                 URL url = file.toURI().toURL();
-                Set<String> classes = classAnalyzer.analyze(url);
+                Set<String> classes = classAnalyzer.analyze(url, 
excludedClasses);
 
                 artifactClassMap.put(artifact, classes);
             }
@@ -191,20 +197,22 @@ public class DefaultProjectDependencyAnalyzer implements 
ProjectDependencyAnalyz
         return testOnlyDependencyClasses;
     }
 
-    private Set<String> buildMainDependencyClasses(MavenProject project) 
throws IOException {
+    private Set<String> buildMainDependencyClasses(MavenProject project, 
ClassesPatterns excludedClasses)
+            throws IOException {
         String outputDirectory = project.getBuild().getOutputDirectory();
-        return buildDependencyClasses(outputDirectory);
+        return buildDependencyClasses(outputDirectory, excludedClasses);
     }
 
-    private Set<String> buildTestDependencyClasses(MavenProject project) 
throws IOException {
+    private Set<String> buildTestDependencyClasses(MavenProject project, 
ClassesPatterns excludedClasses)
+            throws IOException {
         String testOutputDirectory = 
project.getBuild().getTestOutputDirectory();
-        return buildDependencyClasses(testOutputDirectory);
+        return buildDependencyClasses(testOutputDirectory, excludedClasses);
     }
 
-    private Set<String> buildDependencyClasses(String path) throws IOException 
{
+    private Set<String> buildDependencyClasses(String path, ClassesPatterns 
excludedClasses) throws IOException {
         URL url = new File(path).toURI().toURL();
 
-        return dependencyAnalyzer.analyze(url);
+        return dependencyAnalyzer.analyze(url, excludedClasses);
     }
 
     private static Set<Artifact> buildDeclaredArtifacts(MavenProject project) {
diff --git 
a/src/main/java/org/apache/maven/shared/dependency/analyzer/DependencyAnalyzer.java
 
b/src/main/java/org/apache/maven/shared/dependency/analyzer/DependencyAnalyzer.java
index d366c6b..22a6a27 100644
--- 
a/src/main/java/org/apache/maven/shared/dependency/analyzer/DependencyAnalyzer.java
+++ 
b/src/main/java/org/apache/maven/shared/dependency/analyzer/DependencyAnalyzer.java
@@ -32,9 +32,21 @@ public interface DependencyAnalyzer {
     /**
      * <p>analyze.</p>
      *
-     * @param url the JAR file or directory to analyze
+     * @param url            the JAR file or directory to analyze
      * @return the set of class names referenced by the library
      * @throws IOException if an error occurs reading a JAR or .class file
      */
-    Set<String> analyze(URL url) throws IOException;
+    default Set<String> analyze(URL url) throws IOException {
+        return analyze(url, new ClassesPatterns());
+    }
+
+    /**
+     * <p>analyze.</p>
+     *
+     * @param url            the JAR file or directory to analyze
+     * @param excludeClasses a class list to exclude
+     * @return the set of class names referenced by the library
+     * @throws IOException if an error occurs reading a JAR or .class file
+     */
+    Set<String> analyze(URL url, ClassesPatterns excludeClasses) throws 
IOException;
 }
diff --git 
a/src/main/java/org/apache/maven/shared/dependency/analyzer/ProjectDependencyAnalyzer.java
 
b/src/main/java/org/apache/maven/shared/dependency/analyzer/ProjectDependencyAnalyzer.java
index 9503ea3..4b0d84a 100644
--- 
a/src/main/java/org/apache/maven/shared/dependency/analyzer/ProjectDependencyAnalyzer.java
+++ 
b/src/main/java/org/apache/maven/shared/dependency/analyzer/ProjectDependencyAnalyzer.java
@@ -18,6 +18,8 @@
  */
 package org.apache.maven.shared.dependency.analyzer;
 
+import java.util.Collection;
+
 import org.apache.maven.project.MavenProject;
 
 /**
@@ -32,12 +34,26 @@ import org.apache.maven.project.MavenProject;
  * @author <a href="mailto:[email protected]";>Mark Hobson</a>
  */
 public interface ProjectDependencyAnalyzer {
+
+    /**
+     * <p>analyze.</p>
+     *
+     * @param project a {@link org.apache.maven.project.MavenProject} object
+     * @return a {@link 
org.apache.maven.shared.dependency.analyzer.ProjectDependencyAnalysis} object
+     * @throws 
org.apache.maven.shared.dependency.analyzer.ProjectDependencyAnalyzerException 
if any
+     */
+    default ProjectDependencyAnalysis analyze(MavenProject project) throws 
ProjectDependencyAnalyzerException {
+        return analyze(project, null);
+    }
+
     /**
      * <p>analyze.</p>
      *
      * @param project a {@link org.apache.maven.project.MavenProject} object
+     * @param excludedClasses collection of regular expression of classes name 
to exclude
      * @return a {@link 
org.apache.maven.shared.dependency.analyzer.ProjectDependencyAnalysis} object
      * @throws 
org.apache.maven.shared.dependency.analyzer.ProjectDependencyAnalyzerException 
if any
      */
-    ProjectDependencyAnalysis analyze(MavenProject project) throws 
ProjectDependencyAnalyzerException;
+    ProjectDependencyAnalysis analyze(MavenProject project, Collection<String> 
excludedClasses)
+            throws ProjectDependencyAnalyzerException;
 }
diff --git 
a/src/main/java/org/apache/maven/shared/dependency/analyzer/asm/ASMDependencyAnalyzer.java
 
b/src/main/java/org/apache/maven/shared/dependency/analyzer/asm/ASMDependencyAnalyzer.java
index efd4869..7b542cd 100644
--- 
a/src/main/java/org/apache/maven/shared/dependency/analyzer/asm/ASMDependencyAnalyzer.java
+++ 
b/src/main/java/org/apache/maven/shared/dependency/analyzer/asm/ASMDependencyAnalyzer.java
@@ -26,6 +26,7 @@ import java.net.URL;
 import java.util.Set;
 
 import org.apache.maven.shared.dependency.analyzer.ClassFileVisitorUtils;
+import org.apache.maven.shared.dependency.analyzer.ClassesPatterns;
 import org.apache.maven.shared.dependency.analyzer.DependencyAnalyzer;
 
 /**
@@ -36,10 +37,10 @@ import 
org.apache.maven.shared.dependency.analyzer.DependencyAnalyzer;
 @Named
 @Singleton
 public class ASMDependencyAnalyzer implements DependencyAnalyzer {
-    /** {@inheritDoc} */
+
     @Override
-    public Set<String> analyze(URL url) throws IOException {
-        DependencyClassFileVisitor visitor = new DependencyClassFileVisitor();
+    public Set<String> analyze(URL url, ClassesPatterns excludeClasses) throws 
IOException {
+        DependencyClassFileVisitor visitor = new 
DependencyClassFileVisitor(excludeClasses);
 
         ClassFileVisitorUtils.accept(url, visitor);
 
diff --git 
a/src/main/java/org/apache/maven/shared/dependency/analyzer/asm/DependencyClassFileVisitor.java
 
b/src/main/java/org/apache/maven/shared/dependency/analyzer/asm/DependencyClassFileVisitor.java
index 8f70116..084022a 100644
--- 
a/src/main/java/org/apache/maven/shared/dependency/analyzer/asm/DependencyClassFileVisitor.java
+++ 
b/src/main/java/org/apache/maven/shared/dependency/analyzer/asm/DependencyClassFileVisitor.java
@@ -20,18 +20,18 @@ package org.apache.maven.shared.dependency.analyzer.asm;
 
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.UncheckedIOException;
 import java.util.Set;
 
 import org.apache.commons.io.IOUtils;
 import org.apache.maven.shared.dependency.analyzer.ClassFileVisitor;
+import org.apache.maven.shared.dependency.analyzer.ClassesPatterns;
 import org.objectweb.asm.AnnotationVisitor;
 import org.objectweb.asm.ClassReader;
 import org.objectweb.asm.ClassVisitor;
 import org.objectweb.asm.FieldVisitor;
 import org.objectweb.asm.MethodVisitor;
 import org.objectweb.asm.signature.SignatureVisitor;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 /**
  * Computes the set of classes referenced by visited class files, using
@@ -43,18 +43,33 @@ import org.slf4j.LoggerFactory;
 public class DependencyClassFileVisitor implements ClassFileVisitor {
     private final ResultCollector resultCollector = new ResultCollector();
 
-    private final Logger logger = LoggerFactory.getLogger(getClass());
+    private final ClassesPatterns excludedClasses;
 
     /**
      * <p>Constructor for DependencyClassFileVisitor.</p>
      */
-    public DependencyClassFileVisitor() {}
+    public DependencyClassFileVisitor(ClassesPatterns excludedClasses) {
+
+        this.excludedClasses = excludedClasses;
+    }
+
+    /**
+     * <p>Constructor for DependencyClassFileVisitor.</p>
+     */
+    public DependencyClassFileVisitor() {
+        this(new ClassesPatterns());
+    }
 
     /** {@inheritDoc} */
     @Override
     public void visitClass(String className, InputStream in) {
         try {
             byte[] byteCode = IOUtils.toByteArray(in);
+
+            if (excludedClasses.isMatch(className)) {
+                return;
+            }
+
             ClassReader reader = new ClassReader(byteCode);
 
             final Set<String> constantPoolClassRefs = 
ConstantPoolParser.getConstantPoolClassReferences(byteCode);
@@ -71,14 +86,13 @@ public class DependencyClassFileVisitor implements 
ClassFileVisitor {
 
             reader.accept(classVisitor, 0);
         } catch (IOException exception) {
-            exception.printStackTrace();
+            throw new UncheckedIOException(exception);
         } catch (IndexOutOfBoundsException e) {
-            // some bug inside ASM causes an IOB exception. Log it and move on?
+            // some bug inside ASM causes an IOB exception.
             // this happens when the class isn't valid.
-            logger.warn("Unable to process: " + className, e);
+            throw new VisitClassException("Unable to process: " + className, 
e);
         } catch (IllegalArgumentException e) {
-            // [MSHARED-1248] should log instead of failing when analyzing a 
corrupted jar file
-            logger.warn("Byte code of '" + className + "' is corrupt", e);
+            throw new VisitClassException("Byte code of '" + className + "' is 
corrupt", e);
         }
     }
 
diff --git 
a/src/main/java/org/apache/maven/shared/dependency/analyzer/ClassAnalyzer.java 
b/src/main/java/org/apache/maven/shared/dependency/analyzer/asm/VisitClassException.java
similarity index 60%
copy from 
src/main/java/org/apache/maven/shared/dependency/analyzer/ClassAnalyzer.java
copy to 
src/main/java/org/apache/maven/shared/dependency/analyzer/asm/VisitClassException.java
index 679b4d6..d68bf99 100644
--- 
a/src/main/java/org/apache/maven/shared/dependency/analyzer/ClassAnalyzer.java
+++ 
b/src/main/java/org/apache/maven/shared/dependency/analyzer/asm/VisitClassException.java
@@ -16,25 +16,18 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.maven.shared.dependency.analyzer;
-
-import java.io.IOException;
-import java.net.URL;
-import java.util.Set;
+package org.apache.maven.shared.dependency.analyzer.asm;
 
 /**
- * Gets the set of classes contained in a library given either as a jar file 
or an exploded directory.
- *
- * @author <a href="mailto:[email protected]";>Mark Hobson</a>
+ * Exception for processing class.
  */
-public interface ClassAnalyzer {
-
+public class VisitClassException extends RuntimeException {
     /**
-     * <p>analyze.</p>
-     *
-     * @param url the JAR file or directory to analyze
-     * @return a {@link java.util.Set} object
-     * @throws java.io.IOException if any
+     * A constructor
+     * @param message message
+     * @param cause cause of exception
      */
-    Set<String> analyze(URL url) throws IOException;
+    public VisitClassException(String message, Throwable cause) {
+        super(message, cause);
+    }
 }
diff --git 
a/src/main/java/org/apache/maven/shared/dependency/analyzer/DependencyAnalyzer.java
 
b/src/test/java/org/apache/maven/shared/dependency/analyzer/ClassesPatternsTest.java
similarity index 50%
copy from 
src/main/java/org/apache/maven/shared/dependency/analyzer/DependencyAnalyzer.java
copy to 
src/test/java/org/apache/maven/shared/dependency/analyzer/ClassesPatternsTest.java
index d366c6b..19f6d4c 100644
--- 
a/src/main/java/org/apache/maven/shared/dependency/analyzer/DependencyAnalyzer.java
+++ 
b/src/test/java/org/apache/maven/shared/dependency/analyzer/ClassesPatternsTest.java
@@ -18,23 +18,34 @@
  */
 package org.apache.maven.shared.dependency.analyzer;
 
-import java.io.IOException;
-import java.net.URL;
-import java.util.Set;
+import java.util.Arrays;
 
-/**
- * Gets the set of classes referenced by a library given either as a jar file 
or an exploded directory.
- *
- * @author <a href="mailto:[email protected]";>Mark Hobson</a>
- */
-public interface DependencyAnalyzer {
-
-    /**
-     * <p>analyze.</p>
-     *
-     * @param url the JAR file or directory to analyze
-     * @return the set of class names referenced by the library
-     * @throws IOException if an error occurs reading a JAR or .class file
-     */
-    Set<String> analyze(URL url) throws IOException;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+class ClassesPatternsTest {
+
+    @Test
+    void classPatternsTest() {
+        ClassesPatterns classesPatterns = new 
ClassesPatterns(Arrays.asList("Test1.*", "io.example.test.Test2"));
+
+        assertTrue(classesPatterns.isMatch("Test1.Test2"));
+        assertFalse(classesPatterns.isMatch("Test2.Test2"));
+        assertTrue(classesPatterns.isMatch("io.example.test.Test2"));
+    }
+
+    @Test
+    void emptyClassPatternsTest() {
+        ClassesPatterns classesPatterns = new ClassesPatterns();
+
+        assertFalse(classesPatterns.isMatch("Test"));
+    }
+
+    @Test
+    void nullClassPatternsTest() {
+        ClassesPatterns classesPatterns = new ClassesPatterns(null);
+
+        assertFalse(classesPatterns.isMatch("Test"));
+    }
 }
diff --git 
a/src/test/java/org/apache/maven/shared/dependency/analyzer/asm/ASMDependencyAnalyzerTest.java
 
b/src/test/java/org/apache/maven/shared/dependency/analyzer/asm/ASMDependencyAnalyzerTest.java
index 0578331..30d19c5 100644
--- 
a/src/test/java/org/apache/maven/shared/dependency/analyzer/asm/ASMDependencyAnalyzerTest.java
+++ 
b/src/test/java/org/apache/maven/shared/dependency/analyzer/asm/ASMDependencyAnalyzerTest.java
@@ -22,8 +22,10 @@ import java.io.IOException;
 import java.net.URL;
 import java.nio.file.Path;
 import java.nio.file.Paths;
+import java.util.Collections;
 import java.util.Set;
 
+import org.apache.maven.shared.dependency.analyzer.ClassesPatterns;
 import org.apache.maven.shared.dependency.analyzer.DependencyAnalyzer;
 import org.junit.jupiter.api.Test;
 
@@ -50,5 +52,18 @@ class ASMDependencyAnalyzerTest {
 
         Set<String> result = analyzer.analyze(file.toUri().toURL());
         
assertThat(result).contains("org.apache.maven.artifact.resolver.ArtifactResolutionRequest");
+        assertThat(result).contains("java.util.regex.Pattern");
+    }
+
+    @Test
+    void verify_excluded_classes() throws IOException {
+        Path file = 
Paths.get("target/test-classes/org/apache/maven/shared/dependency/analyzer/testcases/analyze");
+
+        Set<String> result =
+                analyzer.analyze(file.toUri().toURL(), new 
ClassesPatterns(Collections.singleton("ClassToExclude")));
+        
assertThat(result).contains("org.apache.maven.artifact.resolver.ArtifactResolutionRequest");
+        assertThat(result).doesNotContain("java.util.regex.Pattern");
+        assertThat(result)
+                
.doesNotContain("org.apache.maven.shared.dependency.analyzer.testcases.analyze.ClassToExclude");
     }
 }
diff --git 
a/src/test/java/org/apache/maven/shared/dependency/analyzer/asm/ResultCollectorTest.java
 
b/src/test/java/org/apache/maven/shared/dependency/analyzer/asm/ResultCollectorTest.java
index 791d593..7d8dc86 100644
--- 
a/src/test/java/org/apache/maven/shared/dependency/analyzer/asm/ResultCollectorTest.java
+++ 
b/src/test/java/org/apache/maven/shared/dependency/analyzer/asm/ResultCollectorTest.java
@@ -29,8 +29,11 @@ import 
org.apache.maven.shared.dependency.analyzer.testcases.ArrayCases;
 import org.apache.maven.shared.dependency.analyzer.testcases.InnerClassCase;
 import org.apache.maven.shared.dependency.analyzer.testcases.MethodHandleCases;
 import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
 
 import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatCode;
 
 class ResultCollectorTest {
 
@@ -56,50 +59,23 @@ class ResultCollectorTest {
         }
     }
 
-    @Test
-    public void testOssFuzz51980() throws IOException {
+    @ParameterizedTest
+    @ValueSource(
+            strings = {
+                "issue51980",
+                "issue51989",
+                "issue52168",
+                "issue53543",
+                "issue53544a",
+                "issue53620",
+                "issue53676",
+                "issue54119",
+                "issue54254"
+            })
+    void testOssFuzz(String name) {
         // Add a non-"class" suffix so that surefire does not try to read the 
file and fail the build
-        visitClass(ROOT + "/ossfuzz/issue51980/Test.class.clazz");
-    }
-
-    @Test
-    public void testOssFuzz51989() throws IOException {
-        visitClass(ROOT + "/ossfuzz/issue51989/Test.class.clazz");
-    }
-
-    @Test
-    public void testOssFuzz52168() throws IOException {
-        visitClass(ROOT + "/ossfuzz/issue52168/Test.class.clazz");
-    }
-
-    @Test
-    public void testOssFuzz53543() throws IOException {
-        visitClass(ROOT + "/ossfuzz/issue53543/Test.class.clazz");
-    }
-
-    @Test
-    public void testOssFuzz53544a() throws IOException {
-        visitClass(ROOT + "/ossfuzz/issue53544a/Test.class.clazz");
-    }
-
-    @Test
-    public void testOssFuzz53620() throws IOException {
-        visitClass(ROOT + "/ossfuzz/issue53620/Test.class.clazz");
-    }
-
-    @Test
-    public void testOssFuzz53676() throws IOException {
-        visitClass(ROOT + "/ossfuzz/issue53676/Test.class.clazz");
-    }
-
-    @Test
-    public void testOssFuzz54199() throws IOException {
-        visitClass(ROOT + "/ossfuzz/issue54119/Test.class.clazz");
-    }
-
-    @Test
-    public void testOssFuzz54254() throws IOException {
-        visitClass(ROOT + "/ossfuzz/issue54254/Test.class.clazz");
+        assertThatCode(() -> visitClass(ROOT + "/ossfuzz/" + name + 
"/Test.class.clazz"))
+                .isExactlyInstanceOf(VisitClassException.class);
     }
 
     private void visitClass(String location) throws IOException {
diff --git 
a/src/main/java/org/apache/maven/shared/dependency/analyzer/ClassAnalyzer.java 
b/src/test/java/org/apache/maven/shared/dependency/analyzer/testcases/analyze/ClassToExclude.java
similarity index 58%
copy from 
src/main/java/org/apache/maven/shared/dependency/analyzer/ClassAnalyzer.java
copy to 
src/test/java/org/apache/maven/shared/dependency/analyzer/testcases/analyze/ClassToExclude.java
index 679b4d6..bf1771d 100644
--- 
a/src/main/java/org/apache/maven/shared/dependency/analyzer/ClassAnalyzer.java
+++ 
b/src/test/java/org/apache/maven/shared/dependency/analyzer/testcases/analyze/ClassToExclude.java
@@ -16,25 +16,13 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.maven.shared.dependency.analyzer;
+package org.apache.maven.shared.dependency.analyzer.testcases.analyze;
 
-import java.io.IOException;
-import java.net.URL;
-import java.util.Set;
+import java.util.regex.Pattern;
 
 /**
- * Gets the set of classes contained in a library given either as a jar file 
or an exploded directory.
- *
- * @author <a href="mailto:[email protected]";>Mark Hobson</a>
+ * Class to be skipped during analyzed in unit test.
  */
-public interface ClassAnalyzer {
-
-    /**
-     * <p>analyze.</p>
-     *
-     * @param url the JAR file or directory to analyze
-     * @return a {@link java.util.Set} object
-     * @throws java.io.IOException if any
-     */
-    Set<String> analyze(URL url) throws IOException;
+public class ClassToExclude {
+    private void doNothing(final Pattern pattern) {}
 }


Reply via email to