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>


Reply via email to