This is an automated email from the ASF dual-hosted git repository.
sjaranowski pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/maven-dependency-analyzer.git
The following commit(s) were added to refs/heads/master by this push:
new a1a1f98 Recognize classes used in web.xml as main classes (#264)
a1a1f98 is described below
commit a1a1f98e449850ae9885db16eb5cbf49327096fc
Author: Slawomir Jaranowski <[email protected]>
AuthorDate: Wed Jan 28 21:16:11 2026 +0100
Recognize classes used in web.xml as main classes (#264)
A web application may include classes provided by dependency artifacts.
Class references defined in web.xml are now recognized as main used classes.
---
pom.xml | 12 +-
src/it/web-application/pom.xml | 73 ++++++++++
src/it/web-application/verify.groovy | 56 ++++++++
src/it/web-application/web1/pom.xml | 38 +++++
.../web1/src/main/webapp/WEB-INF/web.xml | 54 +++++++
src/it/web-application/web2/pom.xml | 53 +++++++
src/it/web-application/web2/webapp/WEB-INF/web.xml | 54 +++++++
.../WarMainDependencyClassesProvider.java | 159 +++++++++++++++++++++
.../WarMainDependencyClassesProviderTest.java | 129 +++++++++++++++++
src/test/resources/webapp/examples/empty-web.xml | 25 ++++
.../resources/webapp/examples/multi-web-2.5.xml | 53 +++++++
.../resources/webapp/examples/multi-web-3.1.xml | 53 +++++++
src/test/resources/webapp/examples/nons-web.xml | 49 +++++++
src/test/resources/webapp/examples/wrong-web.xml | 23 +++
.../webapp/src/main/webapp/WEB-INF/web.xml | 50 +++++++
15 files changed, 875 insertions(+), 6 deletions(-)
diff --git a/pom.xml b/pom.xml
index a45a95c..026eca1 100644
--- a/pom.xml
+++ b/pom.xml
@@ -106,6 +106,12 @@
<artifactId>asm</artifactId>
<version>9.9.1</version>
</dependency>
+ <dependency>
+ <groupId>org.codehaus.plexus</groupId>
+ <artifactId>plexus-xml</artifactId>
+ <!-- only exported by Maven Xpp3Dom class is used, so can be provided -->
+ <scope>provided</scope>
+ </dependency>
<!-- testing support -->
<dependency>
@@ -141,12 +147,6 @@
<version>1.7.36</version>
<scope>test</scope>
</dependency>
- <dependency>
- <!-- used in test runtime -->
- <groupId>org.codehaus.plexus</groupId>
- <artifactId>plexus-xml</artifactId>
- <scope>test</scope>
- </dependency>
</dependencies>
<build>
diff --git a/src/it/web-application/pom.xml b/src/it/web-application/pom.xml
new file mode 100644
index 0000000..e0e13b7
--- /dev/null
+++ b/src/it/web-application/pom.xml
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements. See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership. The ASF licenses this file
+ ~ to you under the Apache License, Version 2.0 (the
+ ~ "License"); you may not use this file except in compliance
+ ~ with the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing,
+ ~ software distributed under the License is distributed on an
+ ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ ~ KIND, either express or implied. See the License for the
+ ~ specific language governing permissions and limitations
+ ~ under the License.
+ -->
+
+<project
+ xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>org.apache.maven.shared.dependency-analyzer.tests</groupId>
+ <artifactId>web-application</artifactId>
+ <version>1.0</version>
+ <packaging>pom</packaging>
+
+ <modules>
+ <module>web1</module>
+ <module>web2</module>
+ </modules>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-core</artifactId>
+ <version>3.9.12</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-model-builder</artifactId>
+ <version>3.9.12</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-settings-builder</artifactId>
+ <version>3.9.12</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.shared.dependency-analyzer.tests</groupId>
+ <artifactId>maven-mock-plugin</artifactId>
+ <version>1.0</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>mock-analyze</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
diff --git a/src/it/web-application/verify.groovy
b/src/it/web-application/verify.groovy
new file mode 100644
index 0000000..a55c2a3
--- /dev/null
+++ b/src/it/web-application/verify.groovy
@@ -0,0 +1,56 @@
+/*
+ * 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.
+ */
+
+def analysis = new File( basedir, 'target/analysis.txt' ).text
+
+def expected = '''
+UsedDeclaredArtifacts:
+
+UsedUndeclaredArtifactsWithClasses:
+
+UnusedDeclaredArtifacts:
+ org.apache.maven:maven-core:jar:3.9.12:compile
+ org.apache.maven:maven-model-builder:jar:3.9.12:compile
+ org.apache.maven:maven-settings-builder:jar:3.9.12:compile
+
+TestArtifactsWithNonTestScope:
+'''
+
+assert analysis == expected
+
+def analysisWeb1 = new File( basedir, 'web1/target/analysis.txt' ).text
+def analysisWeb2 = new File( basedir, 'web2/target/analysis.txt' ).text
+
+def expectedWeb = '''
+UsedDeclaredArtifacts:
+ org.apache.maven:maven-core:jar:3.9.12:compile
+ org.apache.maven:maven-model-builder:jar:3.9.12:compile
+
+UsedUndeclaredArtifactsWithClasses:
+ org.apache.maven:maven-model:jar:3.9.12:compile
+ org.apache.maven.model.Plugin
+
+UnusedDeclaredArtifacts:
+ org.apache.maven:maven-settings-builder:jar:3.9.12:compile
+
+TestArtifactsWithNonTestScope:
+'''
+
+assert analysisWeb1 == expectedWeb
+assert analysisWeb2 == expectedWeb
diff --git a/src/it/web-application/web1/pom.xml
b/src/it/web-application/web1/pom.xml
new file mode 100644
index 0000000..d3dba10
--- /dev/null
+++ b/src/it/web-application/web1/pom.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements. See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership. The ASF licenses this file
+ ~ to you under the Apache License, Version 2.0 (the
+ ~ "License"); you may not use this file except in compliance
+ ~ with the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing,
+ ~ software distributed under the License is distributed on an
+ ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ ~ KIND, either express or implied. See the License for the
+ ~ specific language governing permissions and limitations
+ ~ under the License.
+ -->
+
+<project
+ xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.apache.maven.shared.dependency-analyzer.tests</groupId>
+ <artifactId>web-application</artifactId>
+ <version>1.0</version>
+ </parent>
+
+ <artifactId>web1</artifactId>
+ <packaging>war</packaging>
+
+ <description>web application with standard web.xml location</description>
+</project>
diff --git a/src/it/web-application/web1/src/main/webapp/WEB-INF/web.xml
b/src/it/web-application/web1/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..f407667
--- /dev/null
+++ b/src/it/web-application/web1/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements. See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership. The ASF licenses this file
+ ~ to you under the Apache License, Version 2.0 (the
+ ~ "License"); you may not use this file except in compliance
+ ~ with the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing,
+ ~ software distributed under the License is distributed on an
+ ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ ~ KIND, either express or implied. See the License for the
+ ~ specific language governing permissions and limitations
+ ~ under the License.
+ -->
+
+<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee
https://jakarta.ee/xml/ns/jakartaee/web-app_6_0.xsd"
+ version="6.0">
+ <display-name>Archetype Created Web Application</display-name>
+
+ <filter>
+ <filter-name>test-filter</filter-name>
+ <!-- maven-model -->
+ <filter-class>org.apache.maven.model.Plugin</filter-class>
+ </filter>
+
+ <filter-mapping>
+ <filter-name>test-filter</filter-name>
+ <url-pattern>/</url-pattern>
+ </filter-mapping>
+
+ <listener>
+ <!-- maven-core -->
+ <listener-class>org.apache.maven.project.MavenProject</listener-class>
+ </listener>
+
+ <servlet>
+ <servlet-name>test-servlet</servlet-name>
+ <!-- maven-model-builder -->
+
<servlet-class>org.apache.maven.model.building.DefaultModelBuilder</servlet-class>
+ </servlet>
+
+ <servlet-mapping>
+ <servlet-name>test-servlet</servlet-name>
+ <url-pattern>/test</url-pattern>
+ </servlet-mapping>
+
+</web-app>
diff --git a/src/it/web-application/web2/pom.xml
b/src/it/web-application/web2/pom.xml
new file mode 100644
index 0000000..e5fe4cf
--- /dev/null
+++ b/src/it/web-application/web2/pom.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements. See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership. The ASF licenses this file
+ ~ to you under the Apache License, Version 2.0 (the
+ ~ "License"); you may not use this file except in compliance
+ ~ with the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing,
+ ~ software distributed under the License is distributed on an
+ ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ ~ KIND, either express or implied. See the License for the
+ ~ specific language governing permissions and limitations
+ ~ under the License.
+ -->
+
+<project
+ xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.apache.maven.shared.dependency-analyzer.tests</groupId>
+ <artifactId>web-application</artifactId>
+ <version>1.0</version>
+ </parent>
+
+ <artifactId>web2</artifactId>
+ <packaging>war</packaging>
+
+ <description>web application with custom web.xml location</description>
+
+ <build>
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-war-plugin</artifactId>
+ <version>@version.maven-war-plugin@</version>
+ <configuration>
+ <webXml>webapp/WEB-INF/web.xml</webXml>
+ </configuration>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ </build>
+</project>
diff --git a/src/it/web-application/web2/webapp/WEB-INF/web.xml
b/src/it/web-application/web2/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..f407667
--- /dev/null
+++ b/src/it/web-application/web2/webapp/WEB-INF/web.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements. See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership. The ASF licenses this file
+ ~ to you under the Apache License, Version 2.0 (the
+ ~ "License"); you may not use this file except in compliance
+ ~ with the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing,
+ ~ software distributed under the License is distributed on an
+ ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ ~ KIND, either express or implied. See the License for the
+ ~ specific language governing permissions and limitations
+ ~ under the License.
+ -->
+
+<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee
https://jakarta.ee/xml/ns/jakartaee/web-app_6_0.xsd"
+ version="6.0">
+ <display-name>Archetype Created Web Application</display-name>
+
+ <filter>
+ <filter-name>test-filter</filter-name>
+ <!-- maven-model -->
+ <filter-class>org.apache.maven.model.Plugin</filter-class>
+ </filter>
+
+ <filter-mapping>
+ <filter-name>test-filter</filter-name>
+ <url-pattern>/</url-pattern>
+ </filter-mapping>
+
+ <listener>
+ <!-- maven-core -->
+ <listener-class>org.apache.maven.project.MavenProject</listener-class>
+ </listener>
+
+ <servlet>
+ <servlet-name>test-servlet</servlet-name>
+ <!-- maven-model-builder -->
+
<servlet-class>org.apache.maven.model.building.DefaultModelBuilder</servlet-class>
+ </servlet>
+
+ <servlet-mapping>
+ <servlet-name>test-servlet</servlet-name>
+ <url-pattern>/test</url-pattern>
+ </servlet-mapping>
+
+</web-app>
diff --git
a/src/main/java/org/apache/maven/shared/dependency/analyzer/dependencyclasses/WarMainDependencyClassesProvider.java
b/src/main/java/org/apache/maven/shared/dependency/analyzer/dependencyclasses/WarMainDependencyClassesProvider.java
new file mode 100644
index 0000000..2489033
--- /dev/null
+++
b/src/main/java/org/apache/maven/shared/dependency/analyzer/dependencyclasses/WarMainDependencyClassesProvider.java
@@ -0,0 +1,159 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.maven.shared.dependency.analyzer.dependencyclasses;
+
+import javax.inject.Named;
+import javax.inject.Singleton;
+import javax.xml.XMLConstants;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import org.apache.maven.model.Plugin;
+import org.apache.maven.project.MavenProject;
+import org.apache.maven.shared.dependency.analyzer.ClassesPatterns;
+import org.apache.maven.shared.dependency.analyzer.DependencyUsage;
+import
org.apache.maven.shared.dependency.analyzer.MainDependencyClassesProvider;
+import org.codehaus.plexus.util.xml.Xpp3Dom;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.SAXException;
+
+/**
+ * Implementation of {@link MainDependencyClassesProvider} for web
applications.
+ */
+@Named
+@Singleton
+class WarMainDependencyClassesProvider implements
MainDependencyClassesProvider {
+
+ private static final Logger LOGGER =
LoggerFactory.getLogger(WarMainDependencyClassesProvider.class);
+
+ private static final List<String> WEB_XML_NAMESPACES = Arrays.asList(
+ "https://jakarta.ee/xml/ns/jakartaee", // Jakarta EE 9+
+ "http://xmlns.jcp.org/xml/ns/javaee", // Java EE 7–8
+ "http://java.sun.com/xml/ns/javaee" // Java EE 5–6
+ );
+
+ @Override
+ public Set<DependencyUsage> getDependencyClasses(MavenProject project,
ClassesPatterns excludedClasses)
+ throws IOException {
+ if (!"war".equals(project.getPackaging())) {
+ return Collections.emptySet();
+ }
+
+ File webXml = findWebXml(project);
+ if (webXml == null) {
+ LOGGER.debug("No web.xml found for project {}", project);
+ return Collections.emptySet();
+ }
+
+ if (!webXml.isFile()) {
+ LOGGER.debug("{} is not a file in project {}", webXml, project);
+ return Collections.emptySet();
+ }
+
+ try {
+ return processWebXml(webXml, excludedClasses);
+ } catch (SAXException | ParserConfigurationException e) {
+ LOGGER.warn("Error parsing web.xml file {}: {}", webXml,
e.getMessage());
+ return Collections.emptySet();
+ }
+ }
+
+ private File findWebXml(MavenProject project) {
+ // standard location
+ File webXmlFile = new File(project.getBasedir(),
"src/main/webapp/WEB-INF/web.xml");
+ if (webXmlFile.isFile()) {
+ return webXmlFile;
+ }
+
+ // check maven-war-plugin configuration for custom location of web.xml
+ Plugin plugin =
project.getBuild().getPluginsAsMap().get("org.apache.maven.plugins:maven-war-plugin");
+ if (plugin == null) {
+ // should not happen as we are in a war project
+ LOGGER.debug("No war plugin found for project {}", project);
+ return null;
+ }
+
+ return Optional.ofNullable(plugin.getConfiguration())
+ .map(Xpp3Dom.class::cast)
+ .map(config -> config.getChild("webXml"))
+ .map(Xpp3Dom::getValue)
+ .map(path -> new File(project.getBasedir(), path))
+ .orElse(null);
+ }
+
+ private Set<DependencyUsage> processWebXml(File webXml, ClassesPatterns
excludedClasses)
+ throws IOException, SAXException, ParserConfigurationException {
+
+ DocumentBuilderFactory documentBuilderFactory =
DocumentBuilderFactory.newInstance();
+
documentBuilderFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
+
documentBuilderFactory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd",
false);
+
documentBuilderFactory.setFeature("http://xml.org/sax/features/external-general-entities",
false);
+
documentBuilderFactory.setFeature("http://xml.org/sax/features/external-parameter-entities",
false);
+ documentBuilderFactory.setExpandEntityReferences(false);
+ documentBuilderFactory.setNamespaceAware(true);
+
+ DocumentBuilder documentBuilder =
documentBuilderFactory.newDocumentBuilder();
+
+ Document doc = documentBuilder.parse(webXml);
+
+ List<String> classes = new ArrayList<>();
+
+ processClassesFromTags(doc, classes, "filter-class");
+ processClassesFromTags(doc, classes, "listener-class");
+ processClassesFromTags(doc, classes, "servlet-class");
+
+ return classes.stream()
+ .filter(className -> !excludedClasses.isMatch(className))
+ .map(className -> new DependencyUsage(className,
webXml.toString()))
+ .collect(Collectors.toSet());
+ }
+
+ private void processClassesFromTags(Document doc, List<String> classes,
String tagName) {
+ for (String namespace : WEB_XML_NAMESPACES) {
+ NodeList tags = doc.getElementsByTagNameNS(namespace, tagName);
+ for (int i = 0; i < tags.getLength(); i++) {
+ Node node = tags.item(i);
+ Optional.ofNullable(node.getTextContent())
+ .map(String::trim)
+ .filter(s -> !s.isEmpty())
+ .ifPresent(classes::add);
+ }
+
+ if (tags.getLength() > 0) {
+ // if we found tags in this namespace, no need to check
further namespaces
+ return;
+ }
+ }
+ }
+}
diff --git
a/src/test/java/org/apache/maven/shared/dependency/analyzer/dependencyclasses/WarMainDependencyClassesProviderTest.java
b/src/test/java/org/apache/maven/shared/dependency/analyzer/dependencyclasses/WarMainDependencyClassesProviderTest.java
new file mode 100644
index 0000000..91a548e
--- /dev/null
+++
b/src/test/java/org/apache/maven/shared/dependency/analyzer/dependencyclasses/WarMainDependencyClassesProviderTest.java
@@ -0,0 +1,129 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.maven.shared.dependency.analyzer.dependencyclasses;
+
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Collections;
+import java.util.Set;
+import java.util.stream.Stream;
+
+import org.apache.maven.model.Build;
+import org.apache.maven.model.Plugin;
+import org.apache.maven.project.MavenProject;
+import org.apache.maven.shared.dependency.analyzer.ClassesPatterns;
+import org.apache.maven.shared.dependency.analyzer.DependencyUsage;
+import org.codehaus.plexus.util.xml.Xpp3Dom;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+@ExtendWith(MockitoExtension.class)
+class WarMainDependencyClassesProviderTest {
+
+ @Mock
+ private MavenProject project;
+
+ private final WarMainDependencyClassesProvider provider = new
WarMainDependencyClassesProvider();
+
+ @Test
+ void parseDefaultWebXml() throws IOException, URISyntaxException {
+ Path basePath = Paths.get(getClass().getResource("/webapp").toURI());
+ when(project.getBasedir()).thenReturn(basePath.toFile());
+ when(project.getPackaging()).thenReturn("war");
+
+ Set<DependencyUsage> classes =
+ provider.getDependencyClasses(project, new
ClassesPatterns(Collections.singleton(".*\\.Servlet$")));
+
+ assertThat(classes)
+ .map(DependencyUsage::getDependencyClass)
+ .containsExactlyInAnyOrder("org.example.test.Filter",
"org.example.test.Listener");
+ }
+
+ @Test
+ void noDefaultWebXml() throws IOException, URISyntaxException {
+ Path basePath =
Paths.get(getClass().getResource("/webapp/examples").toURI());
+ when(project.getBasedir()).thenReturn(basePath.toFile());
+ when(project.getPackaging()).thenReturn("war");
+ when(project.getBuild()).thenReturn(new Build());
+
+ Set<DependencyUsage> classes = provider.getDependencyClasses(project,
new ClassesPatterns());
+
+ assertThat(classes).isEmpty();
+ }
+
+ public static Stream<Arguments> examplesData() {
+ return Stream.of(
+ Arguments.of("empty-web.xml", new String[] {}),
+ Arguments.of("nons-web.xml", new String[] {}),
+ Arguments.of("multi-web-2.5.xml", new String[] {
+ "org.example.test.Filter1",
+ "org.example.test.Filter2",
+ "org.example.test.Listener1",
+ "org.example.test.Listener2"
+ }),
+ Arguments.of("multi-web-3.1.xml", new String[] {
+ "org.example.test.Filter1",
+ "org.example.test.Filter2",
+ "org.example.test.Listener1",
+ "org.example.test.Listener2"
+ }),
+ Arguments.of("wrong-web.xml", new String[] {}),
+ Arguments.of("no-exists-web.xml", new String[] {}));
+ }
+
+ @ParameterizedTest
+ @MethodSource("examplesData")
+ void examples(String webXmlName, String[] expectedClasses) throws
Exception {
+ setupProjectWithWebXml(webXmlName);
+
+ Set<DependencyUsage> classes = provider.getDependencyClasses(project,
new ClassesPatterns());
+
+
assertThat(classes).map(DependencyUsage::getDependencyClass).containsExactlyInAnyOrder(expectedClasses);
+ }
+
+ private void setupProjectWithWebXml(String webXmlName) throws
URISyntaxException {
+ Path basePath =
Paths.get(getClass().getResource("/webapp/examples").toURI());
+
+ when(project.getBasedir()).thenReturn(basePath.toFile());
+ when(project.getPackaging()).thenReturn("war");
+
+ Plugin plugin = new Plugin();
+ Xpp3Dom configuration = new Xpp3Dom("configuration");
+ Xpp3Dom webXmlConfig = new Xpp3Dom("webXml");
+ webXmlConfig.setValue(webXmlName);
+ configuration.addChild(webXmlConfig);
+ plugin.setConfiguration(configuration);
+
+ Build build = mock(Build.class);
+ when(project.getBuild()).thenReturn(build);
+ when(build.getPluginsAsMap())
+
.thenReturn(Collections.singletonMap("org.apache.maven.plugins:maven-war-plugin",
plugin));
+ }
+}
diff --git a/src/test/resources/webapp/examples/empty-web.xml
b/src/test/resources/webapp/examples/empty-web.xml
new file mode 100644
index 0000000..ff2d750
--- /dev/null
+++ b/src/test/resources/webapp/examples/empty-web.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements. See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership. The ASF licenses this file
+ ~ to you under the Apache License, Version 2.0 (the
+ ~ "License"); you may not use this file except in compliance
+ ~ with the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing,
+ ~ software distributed under the License is distributed on an
+ ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ ~ KIND, either express or implied. See the License for the
+ ~ specific language governing permissions and limitations
+ ~ under the License.
+ -->
+
+<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee
https://jakarta.ee/xml/ns/jakartaee/web-app_6_0.xsd"
+ version="6.0">
+</web-app>
diff --git a/src/test/resources/webapp/examples/multi-web-2.5.xml
b/src/test/resources/webapp/examples/multi-web-2.5.xml
new file mode 100644
index 0000000..96c9242
--- /dev/null
+++ b/src/test/resources/webapp/examples/multi-web-2.5.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements. See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership. The ASF licenses this file
+ ~ to you under the Apache License, Version 2.0 (the
+ ~ "License"); you may not use this file except in compliance
+ ~ with the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing,
+ ~ software distributed under the License is distributed on an
+ ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ ~ KIND, either express or implied. See the License for the
+ ~ specific language governing permissions and limitations
+ ~ under the License.
+ -->
+
+<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
+
+ <filter>
+ <filter-name>test-filter</filter-name>
+ <filter-class>org.example.test.Filter1</filter-class>
+ </filter>
+
+ <filter-mapping>
+ <filter-name>test-filter</filter-name>
+ <url-pattern>/</url-pattern>
+ </filter-mapping>
+
+ <filter>
+ <filter-name>test-filter2</filter-name>
+ <filter-class>
+ org.example.test.Filter2
+ </filter-class>
+ </filter>
+
+ <filter-mapping>
+ <filter-name>test-filter2</filter-name>
+ <url-pattern>/</url-pattern>
+ </filter-mapping>
+
+ <listener>
+ <listener-class>org.example.test.Listener1</listener-class>
+ </listener>
+
+ <listener>
+ <listener-class>org.example.test.Listener2</listener-class>
+ </listener>
+</web-app>
diff --git a/src/test/resources/webapp/examples/multi-web-3.1.xml
b/src/test/resources/webapp/examples/multi-web-3.1.xml
new file mode 100644
index 0000000..f4601d9
--- /dev/null
+++ b/src/test/resources/webapp/examples/multi-web-3.1.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements. See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership. The ASF licenses this file
+ ~ to you under the Apache License, Version 2.0 (the
+ ~ "License"); you may not use this file except in compliance
+ ~ with the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing,
+ ~ software distributed under the License is distributed on an
+ ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ ~ KIND, either express or implied. See the License for the
+ ~ specific language governing permissions and limitations
+ ~ under the License.
+ -->
+
+<web-app version="3.1" xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
https://www.oracle.com/webfolder/technetwork/jsc/xml/ns/javaee/web-app_3_1.xsd">
+
+ <filter>
+ <filter-name>test-filter</filter-name>
+ <filter-class>org.example.test.Filter1</filter-class>
+ </filter>
+
+ <filter-mapping>
+ <filter-name>test-filter</filter-name>
+ <url-pattern>/</url-pattern>
+ </filter-mapping>
+
+ <filter>
+ <filter-name>test-filter2</filter-name>
+ <filter-class>
+ org.example.test.Filter2
+ </filter-class>
+ </filter>
+
+ <filter-mapping>
+ <filter-name>test-filter2</filter-name>
+ <url-pattern>/</url-pattern>
+ </filter-mapping>
+
+ <listener>
+ <listener-class>org.example.test.Listener1</listener-class>
+ </listener>
+
+ <listener>
+ <listener-class>org.example.test.Listener2</listener-class>
+ </listener>
+</web-app>
diff --git a/src/test/resources/webapp/examples/nons-web.xml
b/src/test/resources/webapp/examples/nons-web.xml
new file mode 100644
index 0000000..6ba96c4
--- /dev/null
+++ b/src/test/resources/webapp/examples/nons-web.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements. See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership. The ASF licenses this file
+ ~ to you under the Apache License, Version 2.0 (the
+ ~ "License"); you may not use this file except in compliance
+ ~ with the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing,
+ ~ software distributed under the License is distributed on an
+ ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ ~ KIND, either express or implied. See the License for the
+ ~ specific language governing permissions and limitations
+ ~ under the License.
+ -->
+
+<web-app>
+ <filter>
+ <filter-name>test-filter</filter-name>
+ <filter-class>org.example.test.Filter</filter-class>
+ </filter>
+
+ <filter-mapping>
+ <filter-name>test-filter</filter-name>
+ <url-pattern>/</url-pattern>
+ </filter-mapping>
+
+ <listener>
+ <listener-class>org.example.test.Listener</listener-class>
+ </listener>
+
+ <listener>
+ <listener-class/>
+ </listener>
+
+ <servlet>
+ <servlet-name>test-servlet</servlet-name>
+ <servlet-class>org.example.test.Servlet</servlet-class>
+ </servlet>
+
+ <servlet-mapping>
+ <servlet-name>test-servlet</servlet-name>
+ <url-pattern>/test</url-pattern>
+ </servlet-mapping>
+</web-app>
diff --git a/src/test/resources/webapp/examples/wrong-web.xml
b/src/test/resources/webapp/examples/wrong-web.xml
new file mode 100644
index 0000000..1ba9ce5
--- /dev/null
+++ b/src/test/resources/webapp/examples/wrong-web.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements. See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership. The ASF licenses this file
+ ~ to you under the Apache License, Version 2.0 (the
+ ~ "License"); you may not use this file except in compliance
+ ~ with the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing,
+ ~ software distributed under the License is distributed on an
+ ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ ~ KIND, either express or implied. See the License for the
+ ~ specific language governing permissions and limitations
+ ~ under the License.
+ -->
+
+<web-app>
+<web-app>
+</web-app>
\ No newline at end of file
diff --git a/src/test/resources/webapp/src/main/webapp/WEB-INF/web.xml
b/src/test/resources/webapp/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..e351bf2
--- /dev/null
+++ b/src/test/resources/webapp/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements. See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership. The ASF licenses this file
+ ~ to you under the Apache License, Version 2.0 (the
+ ~ "License"); you may not use this file except in compliance
+ ~ with the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing,
+ ~ software distributed under the License is distributed on an
+ ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ ~ KIND, either express or implied. See the License for the
+ ~ specific language governing permissions and limitations
+ ~ under the License.
+ -->
+
+<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee
https://jakarta.ee/xml/ns/jakartaee/web-app_6_0.xsd"
+ version="6.0">
+
+ <filter>
+ <filter-name>test-filter</filter-name>
+ <filter-class>org.example.test.Filter</filter-class>
+ </filter>
+
+ <filter-mapping>
+ <filter-name>test-filter</filter-name>
+ <url-pattern>/</url-pattern>
+ </filter-mapping>
+
+ <listener>
+ <listener-class>org.example.test.Listener</listener-class>
+ </listener>
+
+ <servlet>
+ <servlet-name>test-servlet</servlet-name>
+ <servlet-class>org.example.test.Servlet</servlet-class>
+ </servlet>
+
+ <servlet-mapping>
+ <servlet-name>test-servlet</servlet-name>
+ <url-pattern>/test</url-pattern>
+ </servlet-mapping>
+
+</web-app>