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 8f701164..084022ae 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 @@
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 @@
public class DependencyClassFileVisitor implements ClassFileVisitor {
private final ResultCollector resultCollector = new ResultCollector();
- private final Logger logger = LoggerFactory.getLogger(getClass());
+ private final ClassesPatterns excludedClasses;
/**
* Constructor for DependencyClassFileVisitor.
*/
- public DependencyClassFileVisitor() {}
+ public DependencyClassFileVisitor(ClassesPatterns excludedClasses) {
+
+ this.excludedClasses = excludedClasses;
+ }
+
+ /**
+ * Constructor for DependencyClassFileVisitor.
+ */
+ 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 constantPoolClassRefs = ConstantPoolParser.getConstantPoolClassReferences(byteCode);
@@ -71,14 +86,13 @@ public void visitClass(String className, InputStream in) {
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/asm/VisitClassException.java b/src/main/java/org/apache/maven/shared/dependency/analyzer/asm/VisitClassException.java
new file mode 100644
index 00000000..d68bf99c
--- /dev/null
+++ b/src/main/java/org/apache/maven/shared/dependency/analyzer/asm/VisitClassException.java
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ */
+package org.apache.maven.shared.dependency.analyzer.asm;
+
+/**
+ * Exception for processing class.
+ */
+public class VisitClassException extends RuntimeException {
+ /**
+ * A constructor
+ * @param message message
+ * @param cause cause of exception
+ */
+ public VisitClassException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/src/test/java/org/apache/maven/shared/dependency/analyzer/ClassesPatternsTest.java b/src/test/java/org/apache/maven/shared/dependency/analyzer/ClassesPatternsTest.java
new file mode 100644
index 00000000..19f6d4cc
--- /dev/null
+++ b/src/test/java/org/apache/maven/shared/dependency/analyzer/ClassesPatternsTest.java
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ */
+package org.apache.maven.shared.dependency.analyzer;
+
+import java.util.Arrays;
+
+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 05783318..30d19c56 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.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 @@ void verify_implicit_class_reference_included_in_used_classes() throws IOExcepti
Set 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 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 791d5936..7d8dc86f 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.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 @@ void testJava11Invoke() throws IOException {
}
}
- @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/test/java/org/apache/maven/shared/dependency/analyzer/testcases/analyze/ClassToExclude.java b/src/test/java/org/apache/maven/shared/dependency/analyzer/testcases/analyze/ClassToExclude.java
new file mode 100644
index 00000000..bf1771de
--- /dev/null
+++ b/src/test/java/org/apache/maven/shared/dependency/analyzer/testcases/analyze/ClassToExclude.java
@@ -0,0 +1,28 @@
+/*
+ * 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.
+ */
+package org.apache.maven.shared.dependency.analyzer.testcases.analyze;
+
+import java.util.regex.Pattern;
+
+/**
+ * Class to be skipped during analyzed in unit test.
+ */
+public class ClassToExclude {
+ private void doNothing(final Pattern pattern) {}
+}