From 27c871b068b13cb6d49e061f00e443699dd237bb Mon Sep 17 00:00:00 2001
From: Elliotte Rusty Harold
Date: Sun, 10 Nov 2024 19:23:37 -0500
Subject: [PATCH 1/8] Allowlist org.glassfish:javax.json
---
.../analyze/AbstractAnalyzeMojo.java | 29 ++-----------------
1 file changed, 3 insertions(+), 26 deletions(-)
diff --git a/src/main/java/org/apache/maven/plugins/dependency/analyze/AbstractAnalyzeMojo.java b/src/main/java/org/apache/maven/plugins/dependency/analyze/AbstractAnalyzeMojo.java
index ac79d7178..94a33086f 100644
--- a/src/main/java/org/apache/maven/plugins/dependency/analyze/AbstractAnalyzeMojo.java
+++ b/src/main/java/org/apache/maven/plugins/dependency/analyze/AbstractAnalyzeMojo.java
@@ -35,12 +35,10 @@
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.Parameter;
-import org.apache.maven.project.MavenProject;
import org.apache.maven.shared.artifact.filter.StrictPatternExcludesArtifactFilter;
import org.apache.maven.shared.dependency.analyzer.ProjectDependencyAnalysis;
import org.apache.maven.shared.dependency.analyzer.ProjectDependencyAnalyzer;
import org.apache.maven.shared.dependency.analyzer.ProjectDependencyAnalyzerException;
-import org.codehaus.plexus.PlexusContainer;
import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
import org.codehaus.plexus.util.xml.PrettyPrintXMLWriter;
@@ -105,7 +103,7 @@ public abstract class AbstractAnalyzeMojo extends AbstractMojo {
private boolean ignoreAllNonTestScoped;
/**
- * Output the xml for the missing dependencies (used but not declared).
+ * Output the XML for the missing dependencies (used but not declared).
*
* @since 2.0-alpha-5
*/
@@ -214,15 +212,10 @@ public abstract class AbstractAnalyzeMojo extends AbstractMojo {
* org.apache., and :::*-SNAPSHOT matches all snapshot artifacts.
*
*
- * Certain dependencies that are known to be used and loaded by reflection
- * are always ignored. This includes {@code org.slf4j:slf4j-simple::}.
- *
* @since 2.10
*/
@Parameter
- private String[] ignoredUnusedDeclaredDependencies = new String[0];
-
- private String[] unconditionallyIgnoredDeclaredDependencies = {"org.slf4j:slf4j-simple::"};
+ private String[] ignoredUnusedDeclaredDependencies;
/**
* List of dependencies that are ignored if they are in not test scope but are only used in test classes.
@@ -241,7 +234,7 @@ public abstract class AbstractAnalyzeMojo extends AbstractMojo {
*
* @since 3.3.0
*/
- @Parameter(defaultValue = "org.slf4j:slf4j-simple::")
+ @Parameter
private String[] ignoredNonTestScopedDependencies;
/**
@@ -262,22 +255,6 @@ public abstract class AbstractAnalyzeMojo extends AbstractMojo {
@Parameter(property = "mdep.analyze.excludedClasses")
private Set excludedClasses;
- /**
- * The plexusContainer to look up the {@link ProjectDependencyAnalyzer} implementation depending on the mojo
- * configuration.
- */
- private final PlexusContainer plexusContainer;
-
- /**
- * The Maven project to analyze.
- */
- private final MavenProject project;
-
- protected AbstractAnalyzeMojo(PlexusContainer plexusContainer, MavenProject project) {
- this.plexusContainer = plexusContainer;
- this.project = project;
- }
-
// Mojo methods -----------------------------------------------------------
/*
From 4d980980bc4481882af7cb9c9ef2ddbb6c596cee Mon Sep 17 00:00:00 2001
From: Elliotte Rusty Harold
Date: Sun, 10 Nov 2024 19:30:44 -0500
Subject: [PATCH 2/8] integration test
---
src/it/projects/analyze/pom.xml | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/src/it/projects/analyze/pom.xml b/src/it/projects/analyze/pom.xml
index e3072ae88..afc962850 100644
--- a/src/it/projects/analyze/pom.xml
+++ b/src/it/projects/analyze/pom.xml
@@ -58,6 +58,12 @@
slf4j-simple
2.0.16
+
+
+ org.glassfish
+ javax.json
+ 1.1.4
+
From b4a2465d2c40e51fe3d1293fd32d841bacdcc8f1 Mon Sep 17 00:00:00 2001
From: Elliotte Rusty Harold
Date: Mon, 7 Jul 2025 08:49:34 -0400
Subject: [PATCH 3/8] comments
---
src/it/projects/analyze/pom.xml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/it/projects/analyze/pom.xml b/src/it/projects/analyze/pom.xml
index afc962850..e3a134aea 100644
--- a/src/it/projects/analyze/pom.xml
+++ b/src/it/projects/analyze/pom.xml
@@ -52,13 +52,13 @@
maven-model
2.0.6
-
+
org.slf4j
slf4j-simple
2.0.16
-
+
org.glassfish
javax.json
From c7032616233dac3381b2b3e6b14e9e00ae46d838 Mon Sep 17 00:00:00 2001
From: Elliotte Rusty Harold
Date: Thu, 17 Jul 2025 06:52:45 -0400
Subject: [PATCH 4/8] spotless
---
.../analyze/AbstractAnalyzeMojo.java | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/src/main/java/org/apache/maven/plugins/dependency/analyze/AbstractAnalyzeMojo.java b/src/main/java/org/apache/maven/plugins/dependency/analyze/AbstractAnalyzeMojo.java
index 94a33086f..e49ddb4a8 100644
--- a/src/main/java/org/apache/maven/plugins/dependency/analyze/AbstractAnalyzeMojo.java
+++ b/src/main/java/org/apache/maven/plugins/dependency/analyze/AbstractAnalyzeMojo.java
@@ -35,10 +35,12 @@
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.Parameter;
+import org.apache.maven.project.MavenProject;
import org.apache.maven.shared.artifact.filter.StrictPatternExcludesArtifactFilter;
import org.apache.maven.shared.dependency.analyzer.ProjectDependencyAnalysis;
import org.apache.maven.shared.dependency.analyzer.ProjectDependencyAnalyzer;
import org.apache.maven.shared.dependency.analyzer.ProjectDependencyAnalyzerException;
+import org.codehaus.plexus.PlexusContainer;
import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
import org.codehaus.plexus.util.xml.PrettyPrintXMLWriter;
@@ -255,6 +257,22 @@ public abstract class AbstractAnalyzeMojo extends AbstractMojo {
@Parameter(property = "mdep.analyze.excludedClasses")
private Set excludedClasses;
+ /**
+ * The plexusContainer to look up the {@link ProjectDependencyAnalyzer} implementation depending on the mojo
+ * configuration.
+ */
+ private final PlexusContainer plexusContainer;
+
+ /**
+ * The Maven project to analyze.
+ */
+ private final MavenProject project;
+
+ protected AbstractAnalyzeMojo(PlexusContainer plexusContainer, MavenProject project) {
+ this.plexusContainer = plexusContainer;
+ this.project = project;
+ }
+
// Mojo methods -----------------------------------------------------------
/*
From d9b1e584c93077945382228abb46b4e3685a125b Mon Sep 17 00:00:00 2001
From: Elliotte Rusty Harold
Date: Thu, 17 Jul 2025 07:11:09 -0400
Subject: [PATCH 5/8] fix it
---
src/it/projects/analyze/verify.groovy | 3 ---
1 file changed, 3 deletions(-)
diff --git a/src/it/projects/analyze/verify.groovy b/src/it/projects/analyze/verify.groovy
index 4b430120a..68af167b8 100644
--- a/src/it/projects/analyze/verify.groovy
+++ b/src/it/projects/analyze/verify.groovy
@@ -36,8 +36,5 @@ assert buildLog.contains( '[WARNING] org.apache.maven:maven-repository-metada
assert buildLog.contains( '[WARNING] class org.apache.maven.artifact.repository.metadata.Metadata')
assert buildLog.contains( '[WARNING] Unused declared dependencies found:')
assert buildLog.contains( '[WARNING] org.apache.maven:maven-project:jar:2.0.6:compile')
-assert buildLog.contains( '[INFO] Ignored unused declared dependencies:')
-assert buildLog.contains( '[INFO] org.slf4j:slf4j-simple:jar:2.0.16:compile')
-assert !buildLog.contains( '[WARNING] org.slf4j:slf4j-simple:jar:2.0.16:compile')
return true
From f4fd3bd5255b70a8b7648fbe71d797deb98394fc Mon Sep 17 00:00:00 2001
From: Romain Manni-Bucau
Date: Mon, 6 Oct 2025 17:17:56 +0200
Subject: [PATCH 6/8] some draft of a more generic detection of used _unused_
dependencies
---
pom.xml | 25 ++-
.../analyze/AbstractAnalyzeMojo.java | 156 ++++++++++++-
.../TestAnalyzeIndirectDependency.java | 169 ++++++++++++++
.../dependency/analyze/main/JsonpMain.java | 31 +++
.../dependency/analyze/main/Slf4jMain.java | 31 +++
.../exclusion/AnalyzeExclusionsMojoTest.java | 183 +--------------
.../plugins/dependency/testUtils/TestLog.java | 208 ++++++++++++++++++
7 files changed, 611 insertions(+), 192 deletions(-)
create mode 100644 src/test/java/org/apache/maven/plugins/dependency/analyze/TestAnalyzeIndirectDependency.java
create mode 100644 src/test/java/org/apache/maven/plugins/dependency/analyze/main/JsonpMain.java
create mode 100644 src/test/java/org/apache/maven/plugins/dependency/analyze/main/Slf4jMain.java
create mode 100644 src/test/java/org/apache/maven/plugins/dependency/testUtils/TestLog.java
diff --git a/pom.xml b/pom.xml
index c0fbfc7ac..92d1825ee 100644
--- a/pom.xml
+++ b/pom.xml
@@ -65,7 +65,7 @@ under the License.
- 3.6.3
+ ${mavenVersion}
@@ -95,6 +95,9 @@ under the License.
1.9.24
1.7.36
9.4.58.v20250814
+ 9.4.57.v20241219
+ 2.0.1
+ 2.0.1
4.11.0
4.10.1
3.3.0
@@ -327,7 +330,13 @@ under the License.
org.glassfish
jakarta.json
- 2.0.1
+ ${glassfishVersion}
+ test
+
+
+ org.apache.johnzon
+ johnzon-core
+ ${johnzonVersion}
test
@@ -406,6 +415,13 @@ under the License.
${slf4jVersion}
test
+
+ org.tomitribe
+ tomitribe-util
+ 1.3.10
+ test
+
+
@@ -470,6 +486,11 @@ under the License.
-Xmx512m
+
+ ${slf4jVersion}
+ ${johnzonVersion}
+ ${glassfishVersion}
+
2
true
diff --git a/src/main/java/org/apache/maven/plugins/dependency/analyze/AbstractAnalyzeMojo.java b/src/main/java/org/apache/maven/plugins/dependency/analyze/AbstractAnalyzeMojo.java
index e49ddb4a8..9ffdabdfe 100644
--- a/src/main/java/org/apache/maven/plugins/dependency/analyze/AbstractAnalyzeMojo.java
+++ b/src/main/java/org/apache/maven/plugins/dependency/analyze/AbstractAnalyzeMojo.java
@@ -19,16 +19,27 @@
package org.apache.maven.plugins.dependency.analyze;
import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
import java.util.Set;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import java.util.stream.Stream;
+import org.objectweb.asm.ClassReader;
+import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.MethodVisitor;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
import org.apache.maven.plugin.AbstractMojo;
@@ -43,6 +54,14 @@
import org.codehaus.plexus.PlexusContainer;
import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
import org.codehaus.plexus.util.xml.PrettyPrintXMLWriter;
+import org.objectweb.asm.ModuleVisitor;
+import org.objectweb.asm.Type;
+
+import static java.util.Collections.list;
+import static java.util.stream.Collectors.toList;
+import static java.util.stream.Collectors.toSet;
+import static org.objectweb.asm.Opcodes.ASM9;
+import static org.objectweb.asm.Opcodes.INVOKESTATIC;
/**
* Analyzes the dependencies of this project and determines which are: used and declared; used and undeclared; unused
@@ -214,10 +233,14 @@ public abstract class AbstractAnalyzeMojo extends AbstractMojo {
* org.apache., and :::*-SNAPSHOT matches all snapshot artifacts.
*
*
+ * Certain dependencies that are known to be used and loaded by reflection
+ * are always ignored. This includes {@code org.slf4j:slf4j-simple::}
+ * and {@code org.glassfish:javax.json::}.
+ *
* @since 2.10
*/
@Parameter
- private String[] ignoredUnusedDeclaredDependencies;
+ private String[] ignoredUnusedDeclaredDependencies = new String[0];
/**
* List of dependencies that are ignored if they are in not test scope but are only used in test classes.
@@ -361,7 +384,6 @@ private boolean checkDependencies() throws MojoExecutionException {
ignoredUnusedDeclared.addAll(filterDependencies(unusedDeclared, ignoredDependencies));
ignoredUnusedDeclared.addAll(filterDependencies(unusedDeclared, ignoredUnusedDeclaredDependencies));
- ignoredUnusedDeclared.addAll(filterDependencies(unusedDeclared, unconditionallyIgnoredDeclaredDependencies));
if (ignoreAllNonTestScoped) {
ignoredNonTestScope.addAll(filterDependencies(nonTestScope, new String[] {"*"}));
@@ -393,11 +415,15 @@ private boolean checkDependencies() throws MojoExecutionException {
}
if (!unusedDeclared.isEmpty()) {
- logDependencyWarning("Unused declared dependencies found:");
-
- logArtifacts(unusedDeclared, true);
- reported = true;
- warning = true;
+ final Set declaredSpi = scanForSpiUsage(usedDeclared, usedUndeclaredWithClasses);
+ cleanupUnused(declaredSpi, unusedDeclared);
+ if (!unusedDeclared.isEmpty()) {
+ logDependencyWarning("Unused declared dependencies found:");
+
+ logArtifacts(unusedDeclared, true);
+ reported = true;
+ warning = true;
+ }
}
if (!nonTestScope.isEmpty()) {
@@ -444,6 +470,119 @@ private boolean checkDependencies() throws MojoExecutionException {
return warning;
}
+ // todo: enhance analyzer (dependency) to do it since it already visits classes
+ // will save some time
+ private Set scanForSpiUsage(final Set usedDeclared,
+ final Map> usedUndeclaredWithClasses) {
+ return Stream.concat(
+ usedDeclared.stream().flatMap(this::findUsedSpi),
+ usedUndeclaredWithClasses.keySet().stream().flatMap(this::findUsedSpi))
+ .collect(toSet());
+ }
+
+ private Stream findUsedSpi(final Artifact artifact) {
+ try (final JarFile jar = new JarFile(artifact.getFile())) {
+ return list(jar.entries()).stream()
+ .filter(entry -> entry.getName().endsWith(".class"))
+ .flatMap(entry -> {
+ final ClassReader classReader;
+ try {
+ classReader = new ClassReader(jar.getInputStream(entry));
+ } catch (IOException e) {
+ return Stream.empty();
+ }
+ final Set spi = new HashSet<>();
+ classReader.accept(new ClassVisitor(ASM9) {
+ @Override
+ public MethodVisitor visitMethod(final int access,
+ final String name,
+ final String descriptor,
+ final String signature,
+ final String[] exceptions) {
+ return new MethodVisitor(ASM9) {
+ private Type lastType = null;
+
+ @Override
+ public void visitLdcInsn(final Object value) {
+ if (value instanceof Type) {
+ lastType = (Type) value;
+ }
+ }
+
+ @Override
+ public void visitMethodInsn(final int opcode,
+ final String owner,
+ final String name,
+ final String descriptor,
+ final boolean isInterface) {
+ if (opcode == INVOKESTATIC &&
+ Objects.equals(owner, "java/util/ServiceLoader") &&
+ Objects.equals(name, "load")) {
+ spi.add(lastType.getClassName());
+ }
+ lastType = null;
+ }
+ };
+ }
+ }, 0);
+ return spi.stream();
+ })
+ .collect(toList()) // materialize before closing the jar
+ .stream();
+ } catch (final IOException ioe) {
+ return Stream.empty();
+ }
+ }
+
+ // here we try to detect "well-known" indirect patterns to remove false warnings
+ private void cleanupUnused(final Set spi, final Set unusedDeclared) {
+ unusedDeclared.removeIf(this::isSlf4jBinding);
+ unusedDeclared.removeIf(it -> hasUsedSPIImpl(spi, it));
+ }
+
+ // mainly for v1.x line but doesn't hurt much for v2
+ // TODO: enhance to ensure there is a single binding else just log a warning for all
+ // and maybe even handle version?
+ private boolean isSlf4jBinding(final Artifact artifact) {
+ try (final JarFile file = new JarFile(artifact.getFile())) {
+ return file.getEntry("org/slf4j/impl/StaticLoggerBinder.class") != null;
+ } catch (final IOException e) {
+ return false;
+ }
+ }
+
+ private boolean hasUsedSPIImpl(final Set usedSpi, final Artifact artifact) {
+ final Set spi;
+ try (final JarFile file = new JarFile(artifact.getFile())) {
+ spi = list(file.entries()).stream()
+ .filter(it -> it.getName().startsWith("META-INF/services/") && !it.isDirectory())
+ .map(it -> it.getName().substring("META-INF/services/".length()))
+ .collect(toSet());
+
+ // java >= 9
+ final JarEntry moduleEntry = file.getJarEntry("module-info.class");
+ if (moduleEntry != null) {
+ try (final InputStream in = file.getInputStream(moduleEntry)) {
+ final ClassReader cr = new ClassReader(in);
+ cr.accept(new ClassVisitor(ASM9) {
+ @Override
+ public ModuleVisitor visitModule(String name, int access, String version) {
+ return new ModuleVisitor(ASM9) {
+ @Override
+ public void visitProvide(final String service, final String[] providers) {
+ spi.add(service.replace('/', '.'));
+ }
+ };
+ }
+ }, 0);
+ }
+ }
+ } catch (final IOException e) {
+ return false;
+ }
+ return usedSpi.stream().anyMatch(spi::contains);
+ }
+
private void filterArtifactsByScope(Set artifacts, String scope) {
artifacts.removeIf(artifact -> artifact.getScope().equals(scope));
}
@@ -554,7 +693,8 @@ private void writeScriptableOutput(Set artifacts) {
}
private List filterDependencies(Set artifacts, String[] excludes) {
- ArtifactFilter filter = new StrictPatternExcludesArtifactFilter(Arrays.asList(excludes));
+ ArtifactFilter filter = new StrictPatternExcludesArtifactFilter(excludes == null ?
+ Collections.emptyList() :Arrays.asList(excludes));
List result = new ArrayList<>();
for (Iterator it = artifacts.iterator(); it.hasNext(); ) {
diff --git a/src/test/java/org/apache/maven/plugins/dependency/analyze/TestAnalyzeIndirectDependency.java b/src/test/java/org/apache/maven/plugins/dependency/analyze/TestAnalyzeIndirectDependency.java
new file mode 100644
index 000000000..09f6ff781
--- /dev/null
+++ b/src/test/java/org/apache/maven/plugins/dependency/analyze/TestAnalyzeIndirectDependency.java
@@ -0,0 +1,169 @@
+/*
+ * 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.plugins.dependency.analyze;
+
+import jakarta.json.spi.JsonProvider;
+import org.apache.johnzon.core.JsonProviderImpl;
+import org.apache.maven.artifact.Artifact;
+import org.apache.maven.artifact.DefaultArtifact;
+import org.apache.maven.artifact.handler.DefaultArtifactHandler;
+import org.apache.maven.model.Build;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.logging.Log;
+import org.apache.maven.plugin.testing.ResolverExpressionEvaluatorStub;
+import org.apache.maven.plugins.dependency.analyze.main.JsonpMain;
+import org.apache.maven.plugins.dependency.analyze.main.Slf4jMain;
+import org.apache.maven.plugins.dependency.testUtils.TestLog;
+import org.apache.maven.project.MavenProject;
+import org.apache.maven.shared.dependency.analyzer.DefaultClassAnalyzer;
+import org.apache.maven.shared.dependency.analyzer.DefaultProjectDependencyAnalyzer;
+import org.apache.maven.shared.dependency.analyzer.ProjectDependencyAnalyzer;
+import org.apache.maven.shared.dependency.analyzer.asm.ASMDependencyAnalyzer;
+import org.codehaus.plexus.component.configurator.BasicComponentConfigurator;
+import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluator;
+import org.codehaus.plexus.configuration.DefaultPlexusConfiguration;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
+import org.slf4j.LoggerFactory;
+import org.slf4j.impl.SimpleLoggerFactory;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.Field;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.StandardCopyOption;
+import java.util.HashSet;
+
+import static java.util.Arrays.asList;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.tomitribe.util.JarLocation.jarLocation;
+
+class TestAnalyzeIndirectDependency {
+ @Test
+ void jakartaJavaxEE(@TempDir final Path work) throws Exception {
+ final String glassfishVersion = System.getProperty("glassfishVersion", "2.0.1");
+ final String johnzonVersion = System.getProperty("johnzonVersion", "2.0.1");
+
+ assertEquals(
+ "[info] No dependency problems found",
+ exec(
+ work,
+ base -> {
+ final String resource = JsonpMain.class.getName().replace('.', '/') + ".class";
+ final Path target = base.resolve(resource);
+ Files.createDirectories(target.getParent());
+ try (final InputStream is = Thread.currentThread()
+ .getContextClassLoader()
+ .getResourceAsStream(resource)) {
+ Files.copy(is, target, StandardCopyOption.REPLACE_EXISTING);
+ }
+ },
+ artifact("org.glassfish", "jakarta.json", glassfishVersion, JsonProvider.class),
+ artifact("org.apache.johnzon", "johnzon-core", johnzonVersion, JsonProviderImpl.class)));
+ }
+
+ /* Ensure we do not have
+ [warn] Unused declared dependencies found:
+ [warn] org.slf4j:slf4j-simple:jar:1.7.36:compile
+ */
+ @Test
+ void slf4j(@TempDir final Path work) throws Exception {
+ final String slf4jVersion = System.getProperty("slf4jVersion", "1.7.36");
+ assertEquals(
+ "[info] No dependency problems found",
+ exec(
+ work,
+ base -> {
+ final String resource = Slf4jMain.class.getName().replace('.', '/') + ".class";
+ final Path target = base.resolve(resource);
+ Files.createDirectories(target.getParent());
+ try (final InputStream is = Thread.currentThread()
+ .getContextClassLoader()
+ .getResourceAsStream(resource)) {
+ Files.copy(is, target, StandardCopyOption.REPLACE_EXISTING);
+ }
+ },
+ artifact("org.slf4j", "slf4j-api", slf4jVersion, LoggerFactory.class),
+ artifact("org.slf4j", "slf4j-simple", slf4jVersion, SimpleLoggerFactory.class)));
+ }
+
+ private String exec(final Path work, final IOConsumer classesFiller, final Artifact... artifacts) throws Exception {
+ final Path classes = Files.createDirectories(work.resolve("target/classes"));
+ final Build build = new Build();
+ build.setOutputDirectory(classes.toString());
+ build.setTestOutputDirectory(Files.createDirectories(work.resolve("target/test-classes")).toString());
+
+ final MavenProject project = new MavenProject();
+ project.setGroupId("g");
+ project.setArtifactId("test");
+ project.setVersion("build");
+ project.setBuild(build);
+ project.setArtifacts(new HashSet<>(asList(artifacts)));
+ project.setDependencyArtifacts(project.getArtifacts());
+ classesFiller.accept(classes);
+
+ final Log log = new TestLog();
+
+ final DefaultProjectDependencyAnalyzer analyzer = new DefaultProjectDependencyAnalyzer();
+ final Field classAnalyzer = DefaultProjectDependencyAnalyzer.class.getDeclaredField("classAnalyzer");
+ classAnalyzer.setAccessible(true);
+ classAnalyzer.set(analyzer, new DefaultClassAnalyzer());
+ final Field dependencyAnalyzer = DefaultProjectDependencyAnalyzer.class.getDeclaredField("dependencyAnalyzer");
+ dependencyAnalyzer.setAccessible(true);
+ dependencyAnalyzer.set(analyzer, new ASMDependencyAnalyzer());
+
+ final AnalyzeMojo mojo = new AnalyzeMojo(null, project) {
+ @Override
+ protected ProjectDependencyAnalyzer createProjectDependencyAnalyzer() throws MojoExecutionException {
+ return analyzer;
+ }
+
+ @Override
+ public Log getLog() {
+ return log;
+ }
+ };
+
+ final ExpressionEvaluator evaluator = new ResolverExpressionEvaluatorStub();
+
+ final DefaultPlexusConfiguration configuration = new DefaultPlexusConfiguration("configuration");
+ configuration.addChild("ignoredPackagings", "pom");
+ configuration.addChild("outputDirectory", project.getBuild().getOutputDirectory());
+
+ new BasicComponentConfigurator()
+ .configureComponent(mojo, configuration, evaluator, null);
+
+ mojo.execute();
+
+ return log.toString().trim();
+ }
+
+ private DefaultArtifact artifact(final String groupId, final String artifactId, final String slf4jVersion, final Class> marker) {
+ final DefaultArtifact artifact = new DefaultArtifact(
+ groupId, artifactId, slf4jVersion,
+ "compile", "jar", "", new DefaultArtifactHandler());
+ artifact.setFile(jarLocation(marker));
+ return artifact;
+ }
+
+ private interface IOConsumer {
+ void accept(T arg) throws IOException;
+ }
+}
diff --git a/src/test/java/org/apache/maven/plugins/dependency/analyze/main/JsonpMain.java b/src/test/java/org/apache/maven/plugins/dependency/analyze/main/JsonpMain.java
new file mode 100644
index 000000000..2af60894b
--- /dev/null
+++ b/src/test/java/org/apache/maven/plugins/dependency/analyze/main/JsonpMain.java
@@ -0,0 +1,31 @@
+/*
+ * 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.plugins.dependency.analyze.main;
+
+import jakarta.json.Json;
+
+public final class JsonpMain {
+ private JsonpMain() {
+ // no-op
+ }
+
+ public static void main(final String... args) {
+ Json.createValue("");
+ }
+}
diff --git a/src/test/java/org/apache/maven/plugins/dependency/analyze/main/Slf4jMain.java b/src/test/java/org/apache/maven/plugins/dependency/analyze/main/Slf4jMain.java
new file mode 100644
index 000000000..b2aa4f34c
--- /dev/null
+++ b/src/test/java/org/apache/maven/plugins/dependency/analyze/main/Slf4jMain.java
@@ -0,0 +1,31 @@
+/*
+ * 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.plugins.dependency.analyze.main;
+
+import org.slf4j.LoggerFactory;
+
+public final class Slf4jMain {
+ private Slf4jMain() {
+ // no-op
+ }
+
+ public static void main(final String... args) {
+ LoggerFactory.getLogger(Slf4jMain.class).info("");
+ }
+}
diff --git a/src/test/java/org/apache/maven/plugins/dependency/exclusion/AnalyzeExclusionsMojoTest.java b/src/test/java/org/apache/maven/plugins/dependency/exclusion/AnalyzeExclusionsMojoTest.java
index d0da7947a..3f9621982 100644
--- a/src/test/java/org/apache/maven/plugins/dependency/exclusion/AnalyzeExclusionsMojoTest.java
+++ b/src/test/java/org/apache/maven/plugins/dependency/exclusion/AnalyzeExclusionsMojoTest.java
@@ -19,8 +19,6 @@
package org.apache.maven.plugins.dependency.exclusion;
import java.io.File;
-import java.io.PrintWriter;
-import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -35,8 +33,8 @@
import org.apache.maven.model.InputLocation;
import org.apache.maven.model.InputSource;
import org.apache.maven.plugin.MojoExecutionException;
-import org.apache.maven.plugin.logging.Log;
import org.apache.maven.plugins.dependency.AbstractDependencyMojoTestCase;
+import org.apache.maven.plugins.dependency.testUtils.TestLog;
import org.apache.maven.plugins.dependency.testUtils.stubs.DependencyProjectStub;
import org.apache.maven.plugins.dependency.utils.ResolverUtil;
import org.apache.maven.project.MavenProject;
@@ -234,183 +232,4 @@ private Exclusion exclusion(String groupId, String artifactId) {
exclusion.setLocation("", new InputLocation(1, 1, inputSource));
return exclusion;
}
-
- static class TestLog implements Log {
- StringBuilder sb = new StringBuilder();
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void debug(CharSequence content) {
- print("debug", content);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void debug(CharSequence content, Throwable error) {
- print("debug", content, error);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void debug(Throwable error) {
- print("debug", error);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void info(CharSequence content) {
- print("info", content);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void info(CharSequence content, Throwable error) {
- print("info", content, error);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void info(Throwable error) {
- print("info", error);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void warn(CharSequence content) {
- print("warn", content);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void warn(CharSequence content, Throwable error) {
- print("warn", content, error);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void warn(Throwable error) {
- print("warn", error);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void error(CharSequence content) {
- print("error", content);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void error(CharSequence content, Throwable error) {
- StringWriter sWriter = new StringWriter();
- PrintWriter pWriter = new PrintWriter(sWriter);
-
- error.printStackTrace(pWriter);
-
- System.err.println(
- "[error] " + content.toString() + System.lineSeparator() + System.lineSeparator() + sWriter);
- }
-
- /**
- * @see org.apache.maven.plugin.logging.Log#error(java.lang.Throwable)
- */
- @Override
- public void error(Throwable error) {
- StringWriter sWriter = new StringWriter();
- PrintWriter pWriter = new PrintWriter(sWriter);
-
- error.printStackTrace(pWriter);
-
- System.err.println("[error] " + sWriter);
- }
-
- /**
- * @see org.apache.maven.plugin.logging.Log#isDebugEnabled()
- */
- @Override
- public boolean isDebugEnabled() {
- return false;
- }
-
- /**
- * @see org.apache.maven.plugin.logging.Log#isInfoEnabled()
- */
- @Override
- public boolean isInfoEnabled() {
- return true;
- }
-
- /**
- * @see org.apache.maven.plugin.logging.Log#isWarnEnabled()
- */
- @Override
- public boolean isWarnEnabled() {
- return true;
- }
-
- /**
- * @see org.apache.maven.plugin.logging.Log#isErrorEnabled()
- */
- @Override
- public boolean isErrorEnabled() {
- return true;
- }
-
- private void print(String prefix, CharSequence content) {
- sb.append("[")
- .append(prefix)
- .append("] ")
- .append(content.toString())
- .append(System.lineSeparator());
- }
-
- private void print(String prefix, Throwable error) {
- StringWriter sWriter = new StringWriter();
- PrintWriter pWriter = new PrintWriter(sWriter);
-
- error.printStackTrace(pWriter);
-
- sb.append("[").append(prefix).append("] ").append(sWriter).append(System.lineSeparator());
- }
-
- private void print(String prefix, CharSequence content, Throwable error) {
- StringWriter sWriter = new StringWriter();
- PrintWriter pWriter = new PrintWriter(sWriter);
-
- error.printStackTrace(pWriter);
-
- sb.append("[")
- .append(prefix)
- .append("] ")
- .append(content.toString())
- .append(System.lineSeparator())
- .append(System.lineSeparator());
- sb.append(sWriter).append(System.lineSeparator());
- }
-
- protected String getContent() {
- return sb.toString();
- }
- }
}
diff --git a/src/test/java/org/apache/maven/plugins/dependency/testUtils/TestLog.java b/src/test/java/org/apache/maven/plugins/dependency/testUtils/TestLog.java
new file mode 100644
index 000000000..80e732236
--- /dev/null
+++ b/src/test/java/org/apache/maven/plugins/dependency/testUtils/TestLog.java
@@ -0,0 +1,208 @@
+/*
+ * 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.plugins.dependency.testUtils;
+
+import org.apache.maven.plugin.logging.Log;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+public class TestLog implements Log {
+ private final StringBuilder sb = new StringBuilder();
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void debug(CharSequence content) {
+ print("debug", content);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void debug(CharSequence content, Throwable error) {
+ print("debug", content, error);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void debug(Throwable error) {
+ print("debug", error);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void info(CharSequence content) {
+ print("info", content);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void info(CharSequence content, Throwable error) {
+ print("info", content, error);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void info(Throwable error) {
+ print("info", error);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void warn(CharSequence content) {
+ print("warn", content);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void warn(CharSequence content, Throwable error) {
+ print("warn", content, error);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void warn(Throwable error) {
+ print("warn", error);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void error(CharSequence content) {
+ print("error", content);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void error(CharSequence content, Throwable error) {
+ StringWriter sWriter = new StringWriter();
+ PrintWriter pWriter = new PrintWriter(sWriter);
+
+ error.printStackTrace(pWriter);
+
+ System.err.println(
+ "[error] " + content.toString() + System.lineSeparator() + System.lineSeparator() + sWriter);
+ }
+
+ /**
+ * @see org.apache.maven.plugin.logging.Log#error(java.lang.Throwable)
+ */
+ @Override
+ public void error(Throwable error) {
+ StringWriter sWriter = new StringWriter();
+ PrintWriter pWriter = new PrintWriter(sWriter);
+
+ error.printStackTrace(pWriter);
+
+ System.err.println("[error] " + sWriter);
+ }
+
+ /**
+ * @see org.apache.maven.plugin.logging.Log#isDebugEnabled()
+ */
+ @Override
+ public boolean isDebugEnabled() {
+ return false;
+ }
+
+ /**
+ * @see org.apache.maven.plugin.logging.Log#isInfoEnabled()
+ */
+ @Override
+ public boolean isInfoEnabled() {
+ return true;
+ }
+
+ /**
+ * @see org.apache.maven.plugin.logging.Log#isWarnEnabled()
+ */
+ @Override
+ public boolean isWarnEnabled() {
+ return true;
+ }
+
+ /**
+ * @see org.apache.maven.plugin.logging.Log#isErrorEnabled()
+ */
+ @Override
+ public boolean isErrorEnabled() {
+ return true;
+ }
+
+ private void print(String prefix, CharSequence content) {
+ sb.append("[")
+ .append(prefix)
+ .append("] ")
+ .append(content.toString())
+ .append(System.lineSeparator());
+ }
+
+ private void print(String prefix, Throwable error) {
+ StringWriter sWriter = new StringWriter();
+ PrintWriter pWriter = new PrintWriter(sWriter);
+
+ error.printStackTrace(pWriter);
+
+ sb.append("[").append(prefix).append("] ").append(sWriter).append(System.lineSeparator());
+ }
+
+ private void print(String prefix, CharSequence content, Throwable error) {
+ StringWriter sWriter = new StringWriter();
+ PrintWriter pWriter = new PrintWriter(sWriter);
+
+ error.printStackTrace(pWriter);
+
+ sb.append("[")
+ .append(prefix)
+ .append("] ")
+ .append(content.toString())
+ .append(System.lineSeparator())
+ .append(System.lineSeparator());
+ sb.append(sWriter).append(System.lineSeparator());
+ }
+
+ @Override
+ public String toString() {
+ return getContent();
+ }
+
+ public String getContent() {
+ return sb.toString();
+ }
+}
\ No newline at end of file
From 36b9deff3bc38534b9d5db5a946c9c2785c6c4f2 Mon Sep 17 00:00:00 2001
From: Romain Manni-Bucau
Date: Mon, 6 Oct 2025 20:51:03 +0200
Subject: [PATCH 7/8] rebase
---
pom.xml | 3 +-
.../analyze/AbstractAnalyzeMojo.java | 112 +++++++++---------
.../TestAnalyzeIndirectDependency.java | 35 +++---
.../plugins/dependency/testUtils/TestLog.java | 15 +--
4 files changed, 84 insertions(+), 81 deletions(-)
diff --git a/pom.xml b/pom.xml
index 92d1825ee..30291e1dd 100644
--- a/pom.xml
+++ b/pom.xml
@@ -96,7 +96,7 @@ under the License.
1.7.36
9.4.58.v20250814
9.4.57.v20241219
- 2.0.1
+ 1.2.21
2.0.1
4.11.0
4.10.1
@@ -337,6 +337,7 @@ under the License.
org.apache.johnzon
johnzon-core
${johnzonVersion}
+ jakarta
test
diff --git a/src/main/java/org/apache/maven/plugins/dependency/analyze/AbstractAnalyzeMojo.java b/src/main/java/org/apache/maven/plugins/dependency/analyze/AbstractAnalyzeMojo.java
index 9ffdabdfe..2c39d9273 100644
--- a/src/main/java/org/apache/maven/plugins/dependency/analyze/AbstractAnalyzeMojo.java
+++ b/src/main/java/org/apache/maven/plugins/dependency/analyze/AbstractAnalyzeMojo.java
@@ -37,9 +37,6 @@
import java.util.jar.JarFile;
import java.util.stream.Stream;
-import org.objectweb.asm.ClassReader;
-import org.objectweb.asm.ClassVisitor;
-import org.objectweb.asm.MethodVisitor;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
import org.apache.maven.plugin.AbstractMojo;
@@ -54,6 +51,9 @@
import org.codehaus.plexus.PlexusContainer;
import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
import org.codehaus.plexus.util.xml.PrettyPrintXMLWriter;
+import org.objectweb.asm.ClassReader;
+import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.ModuleVisitor;
import org.objectweb.asm.Type;
@@ -472,16 +472,16 @@ private boolean checkDependencies() throws MojoExecutionException {
// todo: enhance analyzer (dependency) to do it since it already visits classes
// will save some time
- private Set scanForSpiUsage(final Set usedDeclared,
- final Map> usedUndeclaredWithClasses) {
+ private Set scanForSpiUsage(
+ final Set usedDeclared, final Map> usedUndeclaredWithClasses) {
return Stream.concat(
- usedDeclared.stream().flatMap(this::findUsedSpi),
- usedUndeclaredWithClasses.keySet().stream().flatMap(this::findUsedSpi))
+ usedDeclared.stream().flatMap(this::findUsedSpi),
+ usedUndeclaredWithClasses.keySet().stream().flatMap(this::findUsedSpi))
.collect(toSet());
}
private Stream findUsedSpi(final Artifact artifact) {
- try (final JarFile jar = new JarFile(artifact.getFile())) {
+ try (JarFile jar = new JarFile(artifact.getFile())) {
return list(jar.entries()).stream()
.filter(entry -> entry.getName().endsWith(".class"))
.flatMap(entry -> {
@@ -492,39 +492,43 @@ private Stream findUsedSpi(final Artifact artifact) {
return Stream.empty();
}
final Set spi = new HashSet<>();
- classReader.accept(new ClassVisitor(ASM9) {
- @Override
- public MethodVisitor visitMethod(final int access,
- final String name,
- final String descriptor,
- final String signature,
- final String[] exceptions) {
- return new MethodVisitor(ASM9) {
- private Type lastType = null;
-
+ classReader.accept(
+ new ClassVisitor(ASM9) {
@Override
- public void visitLdcInsn(final Object value) {
- if (value instanceof Type) {
- lastType = (Type) value;
- }
+ public MethodVisitor visitMethod(
+ final int access,
+ final String name,
+ final String descriptor,
+ final String signature,
+ final String[] exceptions) {
+ return new MethodVisitor(ASM9) {
+ private Type lastType = null;
+
+ @Override
+ public void visitLdcInsn(final Object value) {
+ if (value instanceof Type) {
+ lastType = (Type) value;
+ }
+ }
+
+ @Override
+ public void visitMethodInsn(
+ final int opcode,
+ final String owner,
+ final String name,
+ final String descriptor,
+ final boolean isInterface) {
+ if (opcode == INVOKESTATIC
+ && Objects.equals(owner, "java/util/ServiceLoader")
+ && Objects.equals(name, "load")) {
+ spi.add(lastType.getClassName());
+ }
+ lastType = null;
+ }
+ };
}
-
- @Override
- public void visitMethodInsn(final int opcode,
- final String owner,
- final String name,
- final String descriptor,
- final boolean isInterface) {
- if (opcode == INVOKESTATIC &&
- Objects.equals(owner, "java/util/ServiceLoader") &&
- Objects.equals(name, "load")) {
- spi.add(lastType.getClassName());
- }
- lastType = null;
- }
- };
- }
- }, 0);
+ },
+ 0);
return spi.stream();
})
.collect(toList()) // materialize before closing the jar
@@ -544,7 +548,7 @@ private void cleanupUnused(final Set spi, final Set unusedDecl
// TODO: enhance to ensure there is a single binding else just log a warning for all
// and maybe even handle version?
private boolean isSlf4jBinding(final Artifact artifact) {
- try (final JarFile file = new JarFile(artifact.getFile())) {
+ try (JarFile file = new JarFile(artifact.getFile())) {
return file.getEntry("org/slf4j/impl/StaticLoggerBinder.class") != null;
} catch (final IOException e) {
return false;
@@ -553,7 +557,7 @@ private boolean isSlf4jBinding(final Artifact artifact) {
private boolean hasUsedSPIImpl(final Set usedSpi, final Artifact artifact) {
final Set spi;
- try (final JarFile file = new JarFile(artifact.getFile())) {
+ try (JarFile file = new JarFile(artifact.getFile())) {
spi = list(file.entries()).stream()
.filter(it -> it.getName().startsWith("META-INF/services/") && !it.isDirectory())
.map(it -> it.getName().substring("META-INF/services/".length()))
@@ -562,19 +566,21 @@ private boolean hasUsedSPIImpl(final Set usedSpi, final Artifact artifac
// java >= 9
final JarEntry moduleEntry = file.getJarEntry("module-info.class");
if (moduleEntry != null) {
- try (final InputStream in = file.getInputStream(moduleEntry)) {
+ try (InputStream in = file.getInputStream(moduleEntry)) {
final ClassReader cr = new ClassReader(in);
- cr.accept(new ClassVisitor(ASM9) {
- @Override
- public ModuleVisitor visitModule(String name, int access, String version) {
- return new ModuleVisitor(ASM9) {
+ cr.accept(
+ new ClassVisitor(ASM9) {
@Override
- public void visitProvide(final String service, final String[] providers) {
- spi.add(service.replace('/', '.'));
+ public ModuleVisitor visitModule(String name, int access, String version) {
+ return new ModuleVisitor(ASM9) {
+ @Override
+ public void visitProvide(final String service, final String[] providers) {
+ spi.add(service.replace('/', '.'));
+ }
+ };
}
- };
- }
- }, 0);
+ },
+ 0);
}
}
} catch (final IOException e) {
@@ -693,8 +699,8 @@ private void writeScriptableOutput(Set artifacts) {
}
private List filterDependencies(Set artifacts, String[] excludes) {
- ArtifactFilter filter = new StrictPatternExcludesArtifactFilter(excludes == null ?
- Collections.emptyList() :Arrays.asList(excludes));
+ ArtifactFilter filter = new StrictPatternExcludesArtifactFilter(
+ excludes == null ? Collections.emptyList() : Arrays.asList(excludes));
List result = new ArrayList<>();
for (Iterator it = artifacts.iterator(); it.hasNext(); ) {
diff --git a/src/test/java/org/apache/maven/plugins/dependency/analyze/TestAnalyzeIndirectDependency.java b/src/test/java/org/apache/maven/plugins/dependency/analyze/TestAnalyzeIndirectDependency.java
index 09f6ff781..dc2882d83 100644
--- a/src/test/java/org/apache/maven/plugins/dependency/analyze/TestAnalyzeIndirectDependency.java
+++ b/src/test/java/org/apache/maven/plugins/dependency/analyze/TestAnalyzeIndirectDependency.java
@@ -18,6 +18,14 @@
*/
package org.apache.maven.plugins.dependency.analyze;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.Field;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.StandardCopyOption;
+import java.util.HashSet;
+
import jakarta.json.spi.JsonProvider;
import org.apache.johnzon.core.JsonProviderImpl;
import org.apache.maven.artifact.Artifact;
@@ -43,14 +51,6 @@
import org.slf4j.LoggerFactory;
import org.slf4j.impl.SimpleLoggerFactory;
-import java.io.IOException;
-import java.io.InputStream;
-import java.lang.reflect.Field;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.StandardCopyOption;
-import java.util.HashSet;
-
import static java.util.Arrays.asList;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.tomitribe.util.JarLocation.jarLocation;
@@ -69,7 +69,7 @@ void jakartaJavaxEE(@TempDir final Path work) throws Exception {
final String resource = JsonpMain.class.getName().replace('.', '/') + ".class";
final Path target = base.resolve(resource);
Files.createDirectories(target.getParent());
- try (final InputStream is = Thread.currentThread()
+ try (InputStream is = Thread.currentThread()
.getContextClassLoader()
.getResourceAsStream(resource)) {
Files.copy(is, target, StandardCopyOption.REPLACE_EXISTING);
@@ -94,7 +94,7 @@ void slf4j(@TempDir final Path work) throws Exception {
final String resource = Slf4jMain.class.getName().replace('.', '/') + ".class";
final Path target = base.resolve(resource);
Files.createDirectories(target.getParent());
- try (final InputStream is = Thread.currentThread()
+ try (InputStream is = Thread.currentThread()
.getContextClassLoader()
.getResourceAsStream(resource)) {
Files.copy(is, target, StandardCopyOption.REPLACE_EXISTING);
@@ -104,11 +104,13 @@ void slf4j(@TempDir final Path work) throws Exception {
artifact("org.slf4j", "slf4j-simple", slf4jVersion, SimpleLoggerFactory.class)));
}
- private String exec(final Path work, final IOConsumer classesFiller, final Artifact... artifacts) throws Exception {
+ private String exec(final Path work, final IOConsumer classesFiller, final Artifact... artifacts)
+ throws Exception {
final Path classes = Files.createDirectories(work.resolve("target/classes"));
final Build build = new Build();
build.setOutputDirectory(classes.toString());
- build.setTestOutputDirectory(Files.createDirectories(work.resolve("target/test-classes")).toString());
+ build.setTestOutputDirectory(
+ Files.createDirectories(work.resolve("target/test-classes")).toString());
final MavenProject project = new MavenProject();
project.setGroupId("g");
@@ -147,18 +149,17 @@ public Log getLog() {
configuration.addChild("ignoredPackagings", "pom");
configuration.addChild("outputDirectory", project.getBuild().getOutputDirectory());
- new BasicComponentConfigurator()
- .configureComponent(mojo, configuration, evaluator, null);
+ new BasicComponentConfigurator().configureComponent(mojo, configuration, evaluator, null);
mojo.execute();
return log.toString().trim();
}
- private DefaultArtifact artifact(final String groupId, final String artifactId, final String slf4jVersion, final Class> marker) {
+ private DefaultArtifact artifact(
+ final String groupId, final String artifactId, final String slf4jVersion, final Class> marker) {
final DefaultArtifact artifact = new DefaultArtifact(
- groupId, artifactId, slf4jVersion,
- "compile", "jar", "", new DefaultArtifactHandler());
+ groupId, artifactId, slf4jVersion, "compile", "jar", "", new DefaultArtifactHandler());
artifact.setFile(jarLocation(marker));
return artifact;
}
diff --git a/src/test/java/org/apache/maven/plugins/dependency/testUtils/TestLog.java b/src/test/java/org/apache/maven/plugins/dependency/testUtils/TestLog.java
index 80e732236..58b58e440 100644
--- a/src/test/java/org/apache/maven/plugins/dependency/testUtils/TestLog.java
+++ b/src/test/java/org/apache/maven/plugins/dependency/testUtils/TestLog.java
@@ -18,11 +18,11 @@
*/
package org.apache.maven.plugins.dependency.testUtils;
-import org.apache.maven.plugin.logging.Log;
-
import java.io.PrintWriter;
import java.io.StringWriter;
+import org.apache.maven.plugin.logging.Log;
+
public class TestLog implements Log {
private final StringBuilder sb = new StringBuilder();
@@ -116,8 +116,7 @@ public void error(CharSequence content, Throwable error) {
error.printStackTrace(pWriter);
- System.err.println(
- "[error] " + content.toString() + System.lineSeparator() + System.lineSeparator() + sWriter);
+ System.err.println("[error] " + content.toString() + System.lineSeparator() + System.lineSeparator() + sWriter);
}
/**
@@ -166,11 +165,7 @@ public boolean isErrorEnabled() {
}
private void print(String prefix, CharSequence content) {
- sb.append("[")
- .append(prefix)
- .append("] ")
- .append(content.toString())
- .append(System.lineSeparator());
+ sb.append("[").append(prefix).append("] ").append(content.toString()).append(System.lineSeparator());
}
private void print(String prefix, Throwable error) {
@@ -205,4 +200,4 @@ public String toString() {
public String getContent() {
return sb.toString();
}
-}
\ No newline at end of file
+}
From 800ac56ec6925bc954b13910500a0172ae4879e0 Mon Sep 17 00:00:00 2001
From: Romain Manni-Bucau
Date: Mon, 6 Oct 2025 21:34:54 +0200
Subject: [PATCH 8/8] fix deps
---
pom.xml | 12 +++++++++++-
.../dependency/analyze/AbstractAnalyzeMojo.java | 6 +-----
2 files changed, 12 insertions(+), 6 deletions(-)
diff --git a/pom.xml b/pom.xml
index 30291e1dd..2eddc41a3 100644
--- a/pom.xml
+++ b/pom.xml
@@ -155,6 +155,11 @@ under the License.
doxia-sink-api
2.0.0
+
+ org.ow2.asm
+ asm
+ 9.8
+
@@ -422,7 +427,12 @@ under the License.
1.3.10
test
-
+
+ org.codehaus.plexus
+ plexus-classworlds
+ 2.9.0
+ test
+
diff --git a/src/main/java/org/apache/maven/plugins/dependency/analyze/AbstractAnalyzeMojo.java b/src/main/java/org/apache/maven/plugins/dependency/analyze/AbstractAnalyzeMojo.java
index 2c39d9273..fffd71819 100644
--- a/src/main/java/org/apache/maven/plugins/dependency/analyze/AbstractAnalyzeMojo.java
+++ b/src/main/java/org/apache/maven/plugins/dependency/analyze/AbstractAnalyzeMojo.java
@@ -124,7 +124,7 @@ public abstract class AbstractAnalyzeMojo extends AbstractMojo {
private boolean ignoreAllNonTestScoped;
/**
- * Output the XML for the missing dependencies (used but not declared).
+ * Output the xml for the missing dependencies (used but not declared).
*
* @since 2.0-alpha-5
*/
@@ -233,10 +233,6 @@ public abstract class AbstractAnalyzeMojo extends AbstractMojo {
* org.apache., and :::*-SNAPSHOT matches all snapshot artifacts.
*
*
- * Certain dependencies that are known to be used and loaded by reflection
- * are always ignored. This includes {@code org.slf4j:slf4j-simple::}
- * and {@code org.glassfish:javax.json::}.
- *
* @since 2.10
*/
@Parameter