From c0a6a28f92cb4d8c8995c6ea03e42742c10aa62d Mon Sep 17 00:00:00 2001 From: Grzegorz Grzybek Date: Tue, 13 Jun 2023 08:42:41 +0200 Subject: [PATCH] [#1802] Switch pax-web-extender-war from javax to jakarta --- pax-web-extender-war/pom.xml | 47 +++++--- .../war/internal/WarExtenderContext.java | 4 +- .../war/internal/WebApplicationHelper.java | 4 +- .../AttributeCollectingServletContext.java | 40 ++----- .../internal/model/BundleWebApplication.java | 107 +++++++++--------- .../model/BundleWebApplicationClassSpace.java | 102 ++++++++--------- .../extender/war/internal/util/PathTest.java | 30 ++--- 7 files changed, 165 insertions(+), 169 deletions(-) diff --git a/pax-web-extender-war/pom.xml b/pax-web-extender-war/pom.xml index f8925239ff..b4e36201d0 100644 --- a/pax-web-extender-war/pom.xml +++ b/pax-web-extender-war/pom.xml @@ -43,27 +43,27 @@ org.ops4j.pax.web.extender.war.internal.Activator - - javax.servlet;version="[3.1,5)", - javax.servlet.descriptor;version="[3.1,5)", - javax.servlet.annotation;version="[3.1,5)", - javax.servlet.http;version="[3.1,5)", + + jakarta.servlet;version="[6,7)", + jakarta.servlet.annotation;version="[6,7)", + jakarta.servlet.descriptor;version="[6,7)", + jakarta.servlet.http;version="[6,7)", - javax.annotation;version="[1.3,2)", - javax.annotation.security;version="[1.3,2)", + jakarta.annotation;version="[2,3)", + jakarta.annotation.security;version="[2,3)", - - org.osgi.framework;version="[1.8,2)", + + org.osgi.framework;version="[1.10,2)", org.osgi.framework.wiring;version="[1.2,2)", org.osgi.util.tracker;version="[1.5,2)", - org.osgi.service.http;version="[1.2,2)", - org.osgi.service.http.context;version="[1.1,2)", + org.osgi.service.servlet.context;version="[2,3)", org.ops4j.pax.web.service;version="${pax-web.osgi.version}", + org.ops4j.pax.web.service.http;version="${pax-web.osgi.version}", org.ops4j.pax.web.utils;version="${pax-web.osgi.version}", @@ -79,7 +79,7 @@ org.ops4j.pax.web.service.spi.util;version="${pax-web.osgi.version}", - org.slf4j;version="[1.7,2)", + org.slf4j;version="[2,3)", org.apache.tomcat;version="${dependency.org.apache.tomcat}", @@ -129,13 +129,18 @@ osgi.core provided + + org.osgi + org.osgi.service.servlet + provided + org.apache.felix org.apache.felix.utils - + jakarta.annotation @@ -157,7 +162,7 @@ org.apache.logging.log4j - log4j-slf4j-impl + log4j-slf4j2-impl test @@ -181,8 +186,18 @@ - junit - junit + org.junit.jupiter + junit-jupiter-api + test + + + org.junit.jupiter + junit-jupiter-engine + test + + + org.assertj + assertj-core test diff --git a/pax-web-extender-war/src/main/java/org/ops4j/pax/web/extender/war/internal/WarExtenderContext.java b/pax-web-extender-war/src/main/java/org/ops4j/pax/web/extender/war/internal/WarExtenderContext.java index 0303248dee..c550ff5987 100644 --- a/pax-web-extender-war/src/main/java/org/ops4j/pax/web/extender/war/internal/WarExtenderContext.java +++ b/pax-web-extender-war/src/main/java/org/ops4j/pax/web/extender/war/internal/WarExtenderContext.java @@ -343,7 +343,7 @@ public Extension createExtension(Bundle bundle, Runnable cleanup) { return null; } - // before Pax Web 8 there was a check whether the bundle can see javax.servlet.Servlet class. But + // before Pax Web 8 there was a check whether the bundle can see jakarta.servlet.Servlet class. But // that's too harsh requirement, because a WAR can be used to serve static content only, without // registration of any servlet (at least explicitly - as the "default" server should be added for free) @@ -707,7 +707,7 @@ public boolean skipJarScanning(String jarName) { *

The {@link Extension} representing a "WAB" (Web Application Bundle) which (according to 128.3 Web Application * Bundle) is a {@link Bundle} with {@code Web-ContextPath} manifest header.

* - *

No other constraints are put onto the WAB (like visibility of {@link javax.servlet.Servlet} class or the + *

No other constraints are put onto the WAB (like visibility of {@link jakarta.servlet.Servlet} class or the * content). Also it doesn't matter whether the bundle originally contained the required manifest header or * the header was applied using some URL handler (like pax-url-war).

* diff --git a/pax-web-extender-war/src/main/java/org/ops4j/pax/web/extender/war/internal/WebApplicationHelper.java b/pax-web-extender-war/src/main/java/org/ops4j/pax/web/extender/war/internal/WebApplicationHelper.java index 6999636fb1..4b464a8e86 100644 --- a/pax-web-extender-war/src/main/java/org/ops4j/pax/web/extender/war/internal/WebApplicationHelper.java +++ b/pax-web-extender-war/src/main/java/org/ops4j/pax/web/extender/war/internal/WebApplicationHelper.java @@ -29,9 +29,9 @@ import org.slf4j.LoggerFactory; /** - *

This class adjusts {@link org.osgi.service.http.context.ServletContextHelper} from the Whiteboard specification + *

This class adjusts {@link org.osgi.service.servlet.context.ServletContextHelper} from the Whiteboard specification * (chapter 140) to OSGi CMPN Web Applications specification (chapter 128). The most important thing is that - * {@link org.osgi.service.http.context.ServletContextHelper#getResource} uses {@link Bundle#getEntry} method + * {@link org.osgi.service.servlet.context.ServletContextHelper#getResource} uses {@link Bundle#getEntry} method * which doesn't consider fragments, while chapter "128.3.5 Static Content" says:

* For a WAB, these resources must be found according to the findEntries method, this method includes fragments. *

diff --git a/pax-web-extender-war/src/main/java/org/ops4j/pax/web/extender/war/internal/model/AttributeCollectingServletContext.java b/pax-web-extender-war/src/main/java/org/ops4j/pax/web/extender/war/internal/model/AttributeCollectingServletContext.java index bca4a923d2..4f65e659a9 100644 --- a/pax-web-extender-war/src/main/java/org/ops4j/pax/web/extender/war/internal/model/AttributeCollectingServletContext.java +++ b/pax-web-extender-war/src/main/java/org/ops4j/pax/web/extender/war/internal/model/AttributeCollectingServletContext.java @@ -24,16 +24,16 @@ import java.util.HashMap; import java.util.Map; import java.util.Set; -import javax.servlet.Filter; -import javax.servlet.FilterRegistration; -import javax.servlet.RequestDispatcher; -import javax.servlet.Servlet; -import javax.servlet.ServletContext; -import javax.servlet.ServletException; -import javax.servlet.ServletRegistration; -import javax.servlet.SessionCookieConfig; -import javax.servlet.SessionTrackingMode; -import javax.servlet.descriptor.JspConfigDescriptor; +import jakarta.servlet.Filter; +import jakarta.servlet.FilterRegistration; +import jakarta.servlet.RequestDispatcher; +import jakarta.servlet.Servlet; +import jakarta.servlet.ServletContext; +import jakarta.servlet.ServletException; +import jakarta.servlet.ServletRegistration; +import jakarta.servlet.SessionCookieConfig; +import jakarta.servlet.SessionTrackingMode; +import jakarta.servlet.descriptor.JspConfigDescriptor; /** * Trivial context that can be passed to methods which populate it with attributes (like during web fragment parsing) @@ -102,31 +102,11 @@ public RequestDispatcher getNamedDispatcher(String name) { return null; } - @Override - public Servlet getServlet(String name) { - return null; - } - - @Override - public Enumeration getServlets() { - return null; - } - - @Override - public Enumeration getServletNames() { - return null; - } - @Override public void log(String msg) { } - @Override - public void log(Exception exception, String msg) { - - } - @Override public void log(String message, Throwable throwable) { diff --git a/pax-web-extender-war/src/main/java/org/ops4j/pax/web/extender/war/internal/model/BundleWebApplication.java b/pax-web-extender-war/src/main/java/org/ops4j/pax/web/extender/war/internal/model/BundleWebApplication.java index 7231cbab1e..cd75dbf2a1 100644 --- a/pax-web-extender-war/src/main/java/org/ops4j/pax/web/extender/war/internal/model/BundleWebApplication.java +++ b/pax-web-extender-war/src/main/java/org/ops4j/pax/web/extender/war/internal/model/BundleWebApplication.java @@ -45,21 +45,21 @@ import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; import java.util.stream.Collectors; -import javax.annotation.security.DeclareRoles; -import javax.annotation.security.RunAs; -import javax.servlet.DispatcherType; -import javax.servlet.Filter; -import javax.servlet.MultipartConfigElement; -import javax.servlet.Servlet; -import javax.servlet.ServletContainerInitializer; -import javax.servlet.ServletContext; -import javax.servlet.SessionCookieConfig; -import javax.servlet.annotation.HandlesTypes; -import javax.servlet.annotation.HttpConstraint; -import javax.servlet.annotation.HttpMethodConstraint; -import javax.servlet.annotation.ServletSecurity; -import javax.servlet.descriptor.JspConfigDescriptor; -import javax.servlet.descriptor.JspPropertyGroupDescriptor; +import jakarta.annotation.security.DeclareRoles; +import jakarta.annotation.security.RunAs; +import jakarta.servlet.DispatcherType; +import jakarta.servlet.Filter; +import jakarta.servlet.MultipartConfigElement; +import jakarta.servlet.Servlet; +import jakarta.servlet.ServletContainerInitializer; +import jakarta.servlet.ServletContext; +import jakarta.servlet.SessionCookieConfig; +import jakarta.servlet.annotation.HandlesTypes; +import jakarta.servlet.annotation.HttpConstraint; +import jakarta.servlet.annotation.HttpMethodConstraint; +import jakarta.servlet.annotation.ServletSecurity; +import jakarta.servlet.descriptor.JspConfigDescriptor; +import jakarta.servlet.descriptor.JspPropertyGroupDescriptor; import org.apache.felix.utils.extender.Extension; import org.apache.tomcat.util.descriptor.web.FilterMap; @@ -102,7 +102,7 @@ import org.osgi.framework.Bundle; import org.osgi.framework.FrameworkUtil; import org.osgi.framework.ServiceReference; -import org.osgi.service.http.whiteboard.HttpWhiteboardConstants; +import org.osgi.service.servlet.whiteboard.HttpWhiteboardConstants; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -207,8 +207,8 @@ public class BundleWebApplication { private Batch batch = null; /** - * Stored instance of {@link org.osgi.service.http.HttpContext} that wraps - * {@link org.osgi.service.http.context.ServletContextHelper}, so we're able to reference this context + * Stored instance of {@link org.ops4j.pax.web.service.http.HttpContext} that wraps + * {@link org.osgi.service.servlet.context.ServletContextHelper}, so we're able to reference this context * both in Whiteboard and HttpService scenarios. */ private WebContainerContext httpContext = null; @@ -866,13 +866,13 @@ private void processMetadata() { // WEB-INF/classes directory, or if they are packaged in a jar file located in WEB-INF/lib within the // application - in OSGi, we're processing jars (and locations) from Bundle-ClassPath // - Annotations that do not have equivalents in the deployment XSD include - // javax.servlet.annotation.HandlesTypes and all of the CDI-related annotations. These annotations must be + // jakarta.servlet.annotation.HandlesTypes and all of the CDI-related annotations. These annotations must be // processed during annotation scanning, regardless of the value of "metadata-complete". // - there are annotations to be processed from different packages: - // - javax.servlet.annotation - // - javax.annotation - // - javax.annotation.security - // - javax.annotation.sql + // - jakarta.servlet.annotation + // - jakarta.annotation + // - jakarta.annotation.security + // - jakarta.annotation.sql // - javax.ejb // - javax.jms // - javax.mail @@ -880,6 +880,7 @@ private void processMetadata() { // - javax.resource // - javax.jws.* // - javax.xml.ws.* + // TODO: JakartaEE 10 // // Servlet spec, 8.2.1 Modularity of web.xml: // - A web fragment is a part or all of the web.xml that can be specified and included in a library or @@ -900,7 +901,7 @@ private void processMetadata() { // // // Servlet spec, 8.2.4 Shared libraries / runtimes pluggability: - // - The ServletContainerInitializer class is looked up via the jar services API. In JavaEE env, it's + // - The ServletContainerInitializer class is looked up via the jar services API. In JakartaEE env, it's // traversing up the ClassLoader hierarchy up to web container's top CL. But in OSGi there's no "top" // // There's something wrong with metadata-complete...: @@ -954,7 +955,7 @@ private void processMetadata() { // - /WEB-INF/tomcat-web.xml from context (org.apache.catalina.WebResourceRoot.getResource()) // - overridable=true, distributable=true, alwaysAddWelcomeFiles=false, replaceWelcomeFiles=true // 3. "context web.xml" - // - /WEB-INF/web.xml from context (javax.servlet.ServletContext.getResourceAsStream()) + // - /WEB-INF/web.xml from context (jakarta.servlet.ServletContext.getResourceAsStream()) // 4. ContextConfig.processJarsForWebFragments() - fragments from org.apache.tomcat.JarScanner.scan() // - META-INF/web-fragment.xml from each JAR in /WEB-INF/lib // - in Tomcat (standalone) 9.0.41, /examples context has /WEB-INF/lib/taglibs-standard-impl-1.2.5.jar @@ -962,25 +963,25 @@ private void processMetadata() { // (org.apache.tomcat.util.scan.StandardJarScanFilter.defaultSkip) // - As per http://java.net/jira/browse/SERVLET_SPEC-36, if the main web.xml is marked as metadata-complete, // JARs are still processed for SCIs. - // - Tomcat checks all classloaders starting from javax.servlet.ServletContext.getClassLoader() up to + // - Tomcat checks all classloaders starting from jakarta.servlet.ServletContext.getClassLoader() up to // the parent of java.lang.ClassLoader.getSystemClassLoader() // - fragments are ordered using org.apache.tomcat.util.descriptor.web.WebXml.orderWebFragments() // 5. org.apache.catalina.startup.ContextConfig.processServletContainerInitializers() - // - /META-INF/services/javax.servlet.ServletContainerInitializer files are loaded from CL hierarchy - // - order may be consulted from "javax.servlet.context.orderedLibs" attribute (see Servlet spec, + // - /META-INF/services/jakarta.servlet.ServletContainerInitializer files are loaded from CL hierarchy + // - order may be consulted from "jakarta.servlet.context.orderedLibs" attribute (see Servlet spec, // 8.3 JSP container pluggability) - this order affects SCIs // - these are found in Tomcat 9.0.41 hierarchy: - // - "jar:file:/data/servers/apache-tomcat-9.0.41/lib/tomcat-websocket.jar!/META-INF/services/javax.servlet.ServletContainerInitializer" - // - "jar:file:/data/servers/apache-tomcat-9.0.41/lib/jasper.jar!/META-INF/services/javax.servlet.ServletContainerInitializer" + // - "jar:file:/data/servers/apache-tomcat-9.0.41/lib/tomcat-websocket.jar!/META-INF/services/jakarta.servlet.ServletContainerInitializer" + // - "jar:file:/data/servers/apache-tomcat-9.0.41/lib/jasper.jar!/META-INF/services/jakarta.servlet.ServletContainerInitializer" // - these provide the following SCIs: // - org.apache.tomcat.websocket.server.WsSci - // - @javax.servlet.annotation.HandlesTypes is: - // - interface javax.websocket.server.ServerEndpoint - // - interface javax.websocket.server.ServerApplicationConfig - // - class javax.websocket.Endpoint + // - @jakarta.servlet.annotation.HandlesTypes is: + // - interface jakarta.websocket.server.ServerEndpoint + // - interface jakarta.websocket.server.ServerApplicationConfig + // - class jakarta.websocket.Endpoint // - org.apache.jasper.servlet.JasperInitializer // - the HandlesTypes are not yet scanned for the classes to pass to SCIs - // - META-INF/services/javax.servlet.ServletContainerInitializer is not loaded from the WAR itself, only from + // - META-INF/services/jakarta.servlet.ServletContainerInitializer is not loaded from the WAR itself, only from // its JARs - because java.lang.ClassLoader.getResources() is used both for parent classloaders and // the WAR itself. When orderedLibs are present, direct JAR access is used for the non-excluded /WEB-INF/lib/*.jar // 6. if metadata-complete == false, classes from /WEB-INF/classes are checked (Tomcat uses BCEL) @@ -1061,12 +1062,12 @@ private void processMetadata() { LOG.debug("Searching for web.xml descriptor in {}", bundle); mainWebXml = extenderContext.findBundleWebXml(bundle); - // at this stage, we don't have javax.servlet.ServletContext available yet. We don't even know + // at this stage, we don't have jakarta.servlet.ServletContext available yet. We don't even know // where this WAB is going to be deployed (Tomcat? Jetty? Undertow?). We don't even know whether // the contextPath for this WAB is available. // Let's start constructing WAB's "class path" which will eventually be transformed into complete - // WAB's ClassLoader accessible through javax.servlet.ServletContext.getClassLoader() - but this will + // WAB's ClassLoader accessible through jakarta.servlet.ServletContext.getClassLoader() - but this will // happen later, after the WAB is really deployed classSpace = new BundleWebApplicationClassSpace(bundle, extenderContext); @@ -1097,7 +1098,7 @@ private void processMetadata() { // is performed, each scanned class is either compared with @HandlesTypes or checked for // @HandlesTypes annotation - // This is direct mapping from values of @javax.servlet.annotation.HandlesTypes to SCIs that + // This is direct mapping from values of @jakarta.servlet.annotation.HandlesTypes to SCIs that // express their interest in these values Map, Set> htToSci = new HashMap<>(); @@ -1185,12 +1186,12 @@ private void processMetadata() { // we'll check all the JARs from Bundle-ClassPath and those reachable (via Import-Package or Require-Bundle) // bundles that have META-INF/web-fragment.xml - all locations that contain META-INF/resources will be added // to org.ops4j.pax.web.extender.war.internal.WebApplicationHelper, so they're searched for web resources - // 2) /META-INF/**/*.taglib.xml to set up javax.faces.FACELETS_LIBRARIES context parameter + // 2) /META-INF/**/*.taglib.xml to set up jakarta.faces.FACELETS_LIBRARIES context parameter // First, I wanted to provide /META-INF/services/org.apache.myfaces.spi.FaceletConfigResourceProvider // in pax-web-jsp (or pax-web-extender-war), but it wouldn't really work for WABs embedding // myfaces + primefaces. Pax Web bundle would need optional import of org.apache.myfaces.spi package // or we'd have to for WAB creators to import our package with the class implementing this service... - // That's why a better approach is to prepopulate javax.faces.FACELETS_LIBRARIES context init parameter + // That's why a better approach is to prepopulate jakarta.faces.FACELETS_LIBRARIES context init parameter try { for (URL url : classSpace.getWabClassPath()) { @@ -1270,7 +1271,7 @@ private void processMetadata() { * This method turns the raw data collected from descriptors and annotations into a model of elements from * {@code org.ops4j.pax.web.service.spi.model} package configured in a transactional {@link Batch}. */ - @SuppressWarnings("unchecked") + @SuppressWarnings({"unchecked", "removal"}) private void buildModel() { final Batch wabBatch = new Batch("Deployment of " + this); wabBatch.setShortDescription("deploy " + this.contextPath); @@ -1407,7 +1408,7 @@ private void buildModel() { return path; }) .collect(Collectors.joining(";")); - ocm.getContextParams().put("javax.faces.FACELETS_LIBRARIES", faceletsLibraries); + ocm.getContextParams().put("jakarta.faces.FACELETS_LIBRARIES", faceletsLibraries); ocm.getInitialContextAttributes().put(PaxWebConstants.CONTEXT_PARAM_PAX_WEB_FACELETS_LIBRARIES, faceletsUrlMapping); } @@ -1540,7 +1541,7 @@ private void buildModel() { // + login config // + metadata complete (a.k.a. "ignore annotations") - Tomcat calls org.apache.tomcat.InstanceManager.destroyInstance() // on an instance of filter/servlet after f.destroy()/s.destroy() if annotations are not ignored. - // the annotations are javax.annotation.PostConstruct/javax.annotation.PreDestroy + // the annotations are jakarta.annotation.PostConstruct/jakarta.annotation.PreDestroy // + mime mapping // + request character encoding // + response character encoding @@ -1571,23 +1572,23 @@ private void buildModel() { // additional annotations on servlets/filters/listeners // for all elements: // - class level: - // - @javax.annotation.Resource -> org.apache.catalina.deploy.NamingResourcesImpl.addEnvironment() + // - @jakarta.annotation.Resource -> org.apache.catalina.deploy.NamingResourcesImpl.addEnvironment() // or org.apache.catalina.deploy.NamingResourcesImpl.addService() // or org.apache.catalina.deploy.NamingResourcesImpl.addResource() // or org.apache.catalina.deploy.NamingResourcesImpl.addMessageDestinationRef() // or org.apache.catalina.deploy.NamingResourcesImpl.addResourceEnvRef() - // - @javax.annotation.Resources + // - @jakarta.annotation.Resources // - @EJB (commented out in Tomcat code) // - @WebServiceRef (commented out in Tomcat code) - // - @javax.annotation.security.DeclareRoles -> org.apache.catalina.Context.addSecurityRole() + // - @jakarta.annotation.security.DeclareRoles -> org.apache.catalina.Context.addSecurityRole() // - field level: - // - @javax.annotation.Resource + // - @jakarta.annotation.Resource // - method level: - // - @javax.annotation.Resource + // - @jakarta.annotation.Resource // additionally for servlets: // - class level: - // - @javax.annotation.security.RunAs -> org.apache.catalina.Wrapper.setRunAs() (only for EJB I guess) - // - @javax.servlet.annotation.ServletSecurity -> org.apache.catalina.Context.addServletSecurity() + // - @jakarta.annotation.security.RunAs -> org.apache.catalina.Wrapper.setRunAs() (only for EJB I guess) + // - @jakarta.servlet.annotation.ServletSecurity -> org.apache.catalina.Context.addServletSecurity() // // we will add relevant information below @@ -1665,16 +1666,16 @@ private void buildModel() { if (servletClass != null) { // scan for annotations - // @javax.annotation.security.DeclareRoles + // @jakarta.annotation.security.DeclareRoles collectDeclaredRoles(servletClass, securityConfiguration); - // @javax.annotation.security.RunAs + // @jakarta.annotation.security.RunAs RunAs runAs = servletClass.getAnnotation(RunAs.class); if (runAs != null) { builder.setRunAs(runAs.value()); } - // @javax.servlet.annotation.ServletSecurity + // @jakarta.servlet.annotation.ServletSecurity ServletSecurity servletSecurity = servletClass.getAnnotation(ServletSecurity.class); if (servletSecurity != null) { // similar to , but with the URLs taken from servlet mapping diff --git a/pax-web-extender-war/src/main/java/org/ops4j/pax/web/extender/war/internal/model/BundleWebApplicationClassSpace.java b/pax-web-extender-war/src/main/java/org/ops4j/pax/web/extender/war/internal/model/BundleWebApplicationClassSpace.java index cb6945a73d..578b519166 100644 --- a/pax-web-extender-war/src/main/java/org/ops4j/pax/web/extender/war/internal/model/BundleWebApplicationClassSpace.java +++ b/pax-web-extender-war/src/main/java/org/ops4j/pax/web/extender/war/internal/model/BundleWebApplicationClassSpace.java @@ -34,9 +34,9 @@ import java.util.List; import java.util.Map; import java.util.Set; -import javax.servlet.ServletContainerInitializer; -import javax.servlet.ServletContext; -import javax.servlet.annotation.MultipartConfig; +import jakarta.servlet.ServletContainerInitializer; +import jakarta.servlet.ServletContext; +import jakarta.servlet.annotation.MultipartConfig; import org.apache.tomcat.util.bcel.classfile.AnnotationElementValue; import org.apache.tomcat.util.bcel.classfile.AnnotationEntry; @@ -69,8 +69,8 @@ * *

The aspects include web fragments, ordered jars and reachable bundles and are used to:

    *
  • calculate final web descriptor from reachable fragments
  • - *
  • load {@link javax.servlet.ServletContainerInitializer ServletContainerInitializers (SCIs)}
  • - *
  • load annotated classes with annontations like {@link javax.servlet.annotation.WebServlet}.
  • + *
  • load {@link jakarta.servlet.ServletContainerInitializer ServletContainerInitializers (SCIs)}
  • + *
  • load annotated classes with annontations like {@link jakarta.servlet.annotation.WebServlet}.
  • *

* *

It is important to distinguish {@code web-fragment.xml} fragments, JAR fragments and OSGi bundle fragments here. @@ -261,7 +261,7 @@ public void initialize(WebXml mainWebXml, OsgiServletContextClassLoader wabClass // collect all the JARs and bundles that need to be scanned for web-fragments (if metadata-complete="false") or // that may provide SCIs (regardles of metadata-complete) - // In JavaEE it's quite easy: + // In JakartaEE it's quite easy: // - /WEB-INF/lib/*.jar files // - the JARs from URLClassLoaders of the ClassLoader hierarchy starting from web context's ClassLoader // (Tomcat doesn't scan WEB-INF/classes/META-INF for fragments) @@ -303,7 +303,7 @@ public void initialize(WebXml mainWebXml, OsgiServletContextClassLoader wabClass } // 2) The WAB itself may have attached bundle fragments, which should be treated (my decision) as webAppJars - // i.e., as /WEB-INF/lib/*.jar libs in JavaEE or (using Tomcat terms) shared libraries available to all webapps + // i.e., as /WEB-INF/lib/*.jar libs in JakartaEE or (using Tomcat terms) shared libraries available to all webapps LOG.trace("Searching for web fragments in WAB bundle fragments"); BundleWiring wiring = wabBundle.adapt(BundleWiring.class); @@ -331,7 +331,7 @@ public void initialize(WebXml mainWebXml, OsgiServletContextClassLoader wabClass } } - // 3) Scan reachable bundles (ClassPath hierarchy in JavaEE) - without the WAB itself and only directly + // 3) Scan reachable bundles (ClassPath hierarchy in JakartaEE) - without the WAB itself and only directly // wired bundles. So if we have a situation that: // - our WAB has Import-Package (or Require-Bundle) for bundle-A // - bundle-A has Import-Package (or Require-Bundle) for bundle-B @@ -420,7 +420,7 @@ public void initialize(WebXml mainWebXml, OsgiServletContextClassLoader wabClass } } - // ServletContext, when passed is used to set important "javax.servlet.context.orderedLibs" + // ServletContext, when passed is used to set important "jakarta.servlet.context.orderedLibs" // attribute, but at this stage, there's no real ServletContext yet. We should provide a mocked one AttributeCollectingServletContext context = new AttributeCollectingServletContext(); @@ -661,22 +661,22 @@ private void addFragment(WebXml fragment) { * @return */ public List loadSCIs() throws IOException { - // a list of URIs of /META-INF/service/javax.servlet.ServletContainerInitializer from reachable + // a list of URIs of /META-INF/service/jakarta.servlet.ServletContainerInitializer from reachable // "container" bundles (ones without META-INF/web-fragment.xml) each has to be loaded using relevant bundle Map> containerSCIURLs = new LinkedHashMap<>(); - // a list of URIs of /META-INF/service/javax.servlet.ServletContainerInitializer from reachable + // a list of URIs of /META-INF/service/jakarta.servlet.ServletContainerInitializer from reachable // "application" bundles (ones with META-INF/web-fragment.xml) Map> applicationSCIURLs = new LinkedHashMap<>(); - // a list of URIs of /META-INF/service/javax.servlet.ServletContainerInitializer from WAB's Bundle-ClassPath + // a list of URIs of /META-INF/service/jakarta.servlet.ServletContainerInitializer from WAB's Bundle-ClassPath // each has to be loaded using WAB itself List wabSCIURLs = new LinkedList<>(); // Tomcat loads: - // - all /META-INF/services/javax.servlet.ServletContainerInitializer files from + // - all /META-INF/services/jakarta.servlet.ServletContainerInitializer files from // the parent of webapp's class loader (the "container provided SCIs") // - SCIs from the webapp and its /WEB-INF/lib/*.jars (each or those mentioned in - // javax.servlet.context.orderedLibs context attribute) + // jakarta.servlet.context.orderedLibs context attribute) // - java.lang.ClassLoader.getResources() method is used // see: org.apache.catalina.startup.WebappServiceLoader.load() @@ -686,14 +686,14 @@ public List loadSCIs() throws IOException { // 1. container libs // 2. /WEB-INF/lib/*.jar libs (potentially filtered by the absolute ordering) // Tomcat ensures that a WAR may override an SCI implementation by using single - // javax.servlet.ServletContext.getClassLoader() to load SCI implementations whether the - // /META-INF/service/javax.servlet.ServletContainerInitializer was loaded from container or webapp lib + // jakarta.servlet.ServletContext.getClassLoader() to load SCI implementations whether the + // /META-INF/service/jakarta.servlet.ServletContainerInitializer was loaded from container or webapp lib // We can't load the services as entries (without using classloaders), because a bundle may have // custom Bundle-ClassPath (potentially with many entries). So while META-INF/web-fragment.xml has // fixed location in a bundle (or fragment of WAB's JAR), - // META-INF/services/javax.servlet.ServletContainerInitializer has to be found using classLoaders, to - // pick up for example WEB-INF/classes/META-INF/servcontainerSCIURLs = {java.util.LinkedHashMap@5634} size = 13ices/javax.servlet.ServletContainerInitializer if + // META-INF/services/jakarta.servlet.ServletContainerInitializer has to be found using classLoaders, to + // pick up for example WEB-INF/classes/META-INF/servcontainerSCIURLs = {java.util.LinkedHashMap@5634} size = 13ices/jakarta.servlet.ServletContainerInitializer if // WEB-INF/classes is on a Bundle-ClassPath String sciService = "META-INF/services/" + ServletContainerInitializer.class.getName(); @@ -740,7 +740,7 @@ public List loadSCIs() throws IOException { // all entries from Bundle-ClassPath, so ClassLoader kind of access - we can't impact the order // of Bundle-ClassPath entries, but it doesn't really matter. Tomcat uses - // javax.servlet.ServletContext.getClassLoader().getResources() + // jakarta.servlet.ServletContext.getClassLoader().getResources() LOG.trace("Searching for ServletContainerInitializers in the WAB"); LOG.trace(" Scanning the WAB"); List urls = ClassPathUtil.getResources(Collections.singletonList(wabBundle), sciService); @@ -754,7 +754,7 @@ public List loadSCIs() throws IOException { // we can't use ClassPathUtil.getResources() because maybe we have to skip some JARs from Bundle-ClassPath // before checking ORDERED_LIBS, we (and Tomcat) always checks WEB-INF/classes/META-INF/services - // Tomcat calls javax.servlet.ServletContext.getResource(), here we have to load the SCI service + // Tomcat calls jakarta.servlet.ServletContext.getResource(), here we have to load the SCI service // from the WAB itself, but ensure (which isn't straightforward) that we skip embedded JARs and // WAB bundle fragments) // - ClassPathUtil.listResources() uses BundleWiring.listResources() which removes duplicates, @@ -764,12 +764,12 @@ public List loadSCIs() throws IOException { // /WEB-INF/classes!) and (later) from jar entries listed in ORDERED_LIBS and even fragments // we (out of spec) list in ORDERED_LIST // Because we're checking roots from the WAB anyway (later), we can't use bundle.getResources(), as - // - bundle://46.0:5/META-INF/services/javax.servlet.ServletContainerInitializer, and - // - bundle://45.0:0/META-INF/services/javax.servlet.ServletContainerInitializer + // - bundle://46.0:5/META-INF/services/jakarta.servlet.ServletContainerInitializer, and + // - bundle://45.0:0/META-INF/services/jakarta.servlet.ServletContainerInitializer // are actually the same resources (first URL is WAB's fragemnt seen through WAB's classloader // and second is an URL of the fragment itself. Same for: - // - bundle://46.0:2/META-INF/services/javax.servlet.ServletContainerInitializer, and - // - jar:bundle://46.0:0/WEB-INF/lib/the-wab-jar-8.0.0-SNAPSHOT.jar!/META-INF/services/javax.servlet.ServletContainerInitializer + // - bundle://46.0:2/META-INF/services/jakarta.servlet.ServletContainerInitializer, and + // - jar:bundle://46.0:0/WEB-INF/lib/the-wab-jar-8.0.0-SNAPSHOT.jar!/META-INF/services/jakarta.servlet.ServletContainerInitializer LOG.trace("Searching for ServletContainerInitializers in the WAB"); LOG.trace(" Scanning the WAB directory entries"); @@ -782,7 +782,7 @@ public List loadSCIs() throws IOException { } } - // selected (also: none) entries from Bundle-ClassPath - only JARs (JavaEE compliant) and + // selected (also: none) entries from Bundle-ClassPath - only JARs (JakartaEE compliant) and // WAB-attached bundle fragments (Pax Web addition - we list them as "-.bundle" // entries) // ORDERED_LIBS contains jar names, so we have to translate them back @@ -890,18 +890,18 @@ private void loadSCI(URL url, Bundle bundle, List s *

Multi-purpose method to detect two kinds of types from the class space:

    *
  • Types annotated with annotations from "8.1 Annotations and pluggability" of the servlet spec (at least * those mentioned in 8.1.1-8.1.5 (See {@code org.apache.catalina.startup.ContextConfig#processClass()}).
  • - *
  • Types matching the configuration from {@link javax.servlet.annotation.HandlesTypes} specified for SCIs.
  • + *
  • Types matching the configuration from {@link jakarta.servlet.annotation.HandlesTypes} specified for SCIs.
  • *
*

* - * @param htToSci populated mapping of values from {@link javax.servlet.annotation.HandlesTypes} to SCIs that + * @param htToSci populated mapping of values from {@link jakarta.servlet.annotation.HandlesTypes} to SCIs that * are interested in related types * @param sciToHt newly constructed mapping of previously detected SCIs to actual types that have to be passed to * {@link ServletContainerInitializer#onStartup(Set, ServletContext)}. * @param thereAreHTClasses {@code true} if any of the SCIs has any non-annotation types among values of - * {@link javax.servlet.annotation.HandlesTypes} + * {@link jakarta.servlet.annotation.HandlesTypes} * @param thereAreHTAnnotations {@code true} if any of the SCIs has any annotation types among values of - * {@link javax.servlet.annotation.HandlesTypes} + * {@link jakarta.servlet.annotation.HandlesTypes} * @return */ public void scanClasses(Map, Set> htToSci, @@ -940,7 +940,7 @@ public void scanClasses(Map, Set> htToSci, } } - // 2. scan all ordered jars - not only those from javax.servlet.ServletContext.ORDERED_LIBS, but really + // 2. scan all ordered jars - not only those from jakarta.servlet.ServletContext.ORDERED_LIBS, but really // all "web fragments" - both with and without web-fragment.xml descriptors. // - always for types from @HandlesTypes // - annotated types are NOT scanned if: @@ -1016,8 +1016,8 @@ public void scanClasses(Map, Set> htToSci, } /** - * Check the class whether it's one of the types mentioned in {@link javax.servlet.annotation.HandlesTypes} - * and also potentially check it for annotations like {@link javax.servlet.annotation.WebServlet}. + * Check the class whether it's one of the types mentioned in {@link jakarta.servlet.annotation.HandlesTypes} + * and also potentially check it for annotations like {@link jakarta.servlet.annotation.WebServlet}. * @param url an URI for {@code *.class} file * @param fragment a {@link WebXml} representing a "web fragment" - whether or not it is associated with * {@code web-fragment.xml} @@ -1027,9 +1027,9 @@ public void scanClasses(Map, Set> htToSci, * @param sciToHt * @param javaClassCache * @param thereAreHTClasses {@code true} if any of the SCIs has any non-annotation types among values of - * {@link javax.servlet.annotation.HandlesTypes} + * {@link jakarta.servlet.annotation.HandlesTypes} * @param thereAreHTAnnotations {@code true} if any of the SCIs has any annotation types among values of - * {@link javax.servlet.annotation.HandlesTypes} + * {@link jakarta.servlet.annotation.HandlesTypes} */ private void processClass(URL url, WebXml fragment, Bundle bundle, boolean fragmentHtOnly, Map, Set> htToSci, @@ -1060,21 +1060,21 @@ private void processClass(URL url, WebXml fragment, Bundle bundle, boolean fragm /** *

Checks whether the passed {@link JavaClass} is indirectly referred to from an "interest list" of any - * SCI that has {@link javax.servlet.annotation.HandlesTypes} annoation.

+ * SCI that has {@link jakarta.servlet.annotation.HandlesTypes} annoation.

* - *

The goal is to turn the types mentioned in {@link javax.servlet.annotation.HandlesTypes} into actual types - * that are either annotated, extend or implement the types from {@link javax.servlet.annotation.HandlesTypes}.

+ *

The goal is to turn the types mentioned in {@link jakarta.servlet.annotation.HandlesTypes} into actual types + * that are either annotated, extend or implement the types from {@link jakarta.servlet.annotation.HandlesTypes}.

* * @param clazz * @param bundle - * @param htToSci input map of types from {@link javax.servlet.annotation.HandlesTypes} to SCIs + * @param htToSci input map of types from {@link jakarta.servlet.annotation.HandlesTypes} to SCIs * @param sciToHt map under construction of SCIs to actual types passed later to * {@link ServletContainerInitializer#onStartup(Set, ServletContext)} * @param javaClassCache * @param thereAreHTClasses {@code true} if any of the SCIs has any non-annotation types among values of - * {@link javax.servlet.annotation.HandlesTypes} + * {@link jakarta.servlet.annotation.HandlesTypes} * @param thereAreHTAnnotations {@code true} if any of the SCIs has any annotation types among values of - * {@link javax.servlet.annotation.HandlesTypes} + * {@link jakarta.servlet.annotation.HandlesTypes} */ private void checkHandlesTypes(JavaClass clazz, Bundle bundle, Map, Set> htToSci, @@ -1088,10 +1088,10 @@ private void checkHandlesTypes(JavaClass clazz, Bundle bundle, // check if this JavaClass: // - has a superclass mentioned in @HandlesTypes // - implements an interface mentioned in @HandlesTypes - // it's not that easy... for example, an SCI may have simply javax.servlet.Servlet in its @HandlesTypes + // it's not that easy... for example, an SCI may have simply jakarta.servlet.Servlet in its @HandlesTypes // and passed JavaClass is a class loaded from bundle-A that extends a class loaded from bundle-B, which // extends org.springframework.web.servlet.DispatcherServlet class loaded from spring-web, which - // *is* a javax.servlet.Servlet. we can get org/springframework/web/servlet/DispatcherServlet.class + // *is* a jakarta.servlet.Servlet. we can get org/springframework/web/servlet/DispatcherServlet.class // resource (to analyze using BCEL/ASM) using only spring-web bundle and while bundle-B *should* be wired // to spring-web, spring-B *doesn't have to*. @@ -1138,7 +1138,7 @@ private void checkHandlesTypes(JavaClass clazz, Bundle bundle, return; } for (AnnotationEntry ae : clazz.getAnnotationEntries()) { - // type is in "Ljavax/servlet/annotation/HandlesTypes;" form + // type is in "Ljakarta/servlet/annotation/HandlesTypes;" form String annotationClassName = className(ae.getAnnotationType()); if (annotationClassName != null) { // does any SCI have @HT with this exact annotation? @@ -1198,15 +1198,15 @@ private void checkClass(WebXml fragment, Bundle bundle, Map, Set