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