You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by sj...@apache.org on 2024/05/11 07:49:36 UTC
(maven-dependency-analyzer) branch master updated: [MSHARED-1393] Allow to exclude classes from verification
This is an automated email from the ASF dual-hosted git repository.
sjaranowski pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/maven-dependency-analyzer.git
The following commit(s) were added to refs/heads/master by this push:
new 12f56d7 [MSHARED-1393] Allow to exclude classes from verification
12f56d7 is described below
commit 12f56d773a723d8ba65861ec87719b3301a35117
Author: Slawomir Jaranowski <s....@gmail.com>
AuthorDate: Thu May 9 21:42:36 2024 +0200
[MSHARED-1393] Allow to exclude classes from verification
---
pom.xml | 17 ++----
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, 378 insertions(+), 241 deletions(-)
diff --git a/pom.xml b/pom.xml
index 72068c4..1cdde6d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -58,7 +58,6 @@
<properties>
<mavenVersion>3.2.5</mavenVersion>
- <slf4jVersion>1.7.36</slf4jVersion>
<javaVersion>8</javaVersion>
<project.build.outputTimestamp>2023-04-30T22:19:57Z</project.build.outputTimestamp>
</properties>
@@ -104,12 +103,6 @@
<version>9.7</version>
</dependency>
- <dependency>
- <groupId>org.slf4j</groupId>
- <artifactId>slf4j-api</artifactId>
- <version>${slf4jVersion}</version>
- </dependency>
-
<!-- testing support -->
<dependency>
<groupId>org.junit.jupiter</groupId>
@@ -117,14 +110,13 @@
<scope>test</scope>
</dependency>
<dependency>
- <groupId>org.assertj</groupId>
- <artifactId>assertj-core</artifactId>
+ <groupId>org.junit.jupiter</groupId>
+ <artifactId>junit-jupiter-params</artifactId>
<scope>test</scope>
</dependency>
<dependency>
- <groupId>org.slf4j</groupId>
- <artifactId>slf4j-simple</artifactId>
- <version>${slf4jVersion}</version>
+ <groupId>org.assertj</groupId>
+ <artifactId>assertj-core</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
@@ -163,6 +155,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:markhobson@gmail.com">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:markhobson@gmail.com">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:markhobson@gmail.com">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:markhobson@gmail.com">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:markhobson@gmail.com">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:markhobson@gmail.com">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 20485b4..34dac5c 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
@@ -21,17 +21,17 @@ package org.apache.maven.shared.dependency.analyzer.asm;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.io.UncheckedIOException;
import java.util.Set;
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
@@ -45,18 +45,33 @@ 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 = toByteArray(in);
+
+ if (excludedClasses.isMatch(className)) {
+ return;
+ }
+
ClassReader reader = new ClassReader(byteCode);
final Set<String> constantPoolClassRefs = ConstantPoolParser.getConstantPoolClassReferences(byteCode);
@@ -73,14 +88,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:markhobson@gmail.com">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:markhobson@gmail.com">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:markhobson@gmail.com">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) {}
}