[Git][java-team/undertow][upstream] New upstream version 2.2.4

Markus Koschany gitlab at salsa.debian.org
Fri Feb 12 01:09:14 GMT 2021



Markus Koschany pushed to branch upstream at Debian Java Maintainers / undertow


Commits:
bfdba6f0 by Markus Koschany at 2021-02-12T01:33:02+01:00
New upstream version 2.2.4
- - - - -


26 changed files:

- benchmarks/pom.xml
- core/pom.xml
- core/src/main/java/io/undertow/protocols/ssl/SslConduit.java
- core/src/main/java/io/undertow/server/protocol/ajp/AjpReadListener.java
- core/src/main/java/io/undertow/server/session/InMemorySessionManager.java
- core/src/test/java/io/undertow/server/protocol/http2/Http2EndExchangeTestCase.java
- coverage-report/pom.xml
- dist/pom.xml
- examples/pom.xml
- + jakartaee9/pom.xml
- + jakartaee9/src/main/java/io/undertow/jakartaee9/ArtifactNameTransformer.java
- + jakartaee9/src/main/java/io/undertow/jakartaee9/JakartaEE9Deployer.java
- + jakartaee9/src/main/java/io/undertow/jakartaee9/JakartaEE9Installer.java
- + jakartaee9/src/main/java/io/undertow/jakartaee9/JakartaEE9Transformer.java
- + jakartaee9/src/main/java/io/undertow/jakartaee9/PomTransformer.java
- + jakartaee9/src/main/java/io/undertow/jakartaee9/TransformConstants.java
- + jakartaee9/src/main/java/io/undertow/jakartaee9/UndertowJakartaEE9Logger.java
- + jakartaee9/src/main/resources/META-INF/services/org.wildfly.transformer.TransformerFactory
- + jakartaee9/src/main/resources/Version.properties
- parser-generator/pom.xml
- pom.xml
- servlet/pom.xml
- servlet/src/main/java/io/undertow/servlet/UndertowServletLogger.java
- servlet/src/main/java/io/undertow/servlet/spec/ServletContextImpl.java
- spotbugs-exclude.xml
- websockets-jsr/pom.xml


Changes:

=====================================
benchmarks/pom.xml
=====================================
@@ -25,11 +25,11 @@
     <parent>
         <groupId>io.undertow</groupId>
         <artifactId>undertow-parent</artifactId>
-        <version>2.2.3.Final</version>
+        <version>2.2.4.Final</version>
     </parent>
 
     <artifactId>undertow-benchmarks</artifactId>
-    <version>2.2.3.Final</version>
+    <version>2.2.4.Final</version>
 
     <name>Undertow Benchmarks</name>
 


=====================================
core/pom.xml
=====================================
@@ -25,12 +25,12 @@
     <parent>
         <groupId>io.undertow</groupId>
         <artifactId>undertow-parent</artifactId>
-        <version>2.2.3.Final</version>
+        <version>2.2.4.Final</version>
     </parent>
 
     <groupId>io.undertow</groupId>
     <artifactId>undertow-core</artifactId>
-    <version>2.2.3.Final</version>
+    <version>2.2.4.Final</version>
 
     <name>Undertow Core</name>
 


=====================================
core/src/main/java/io/undertow/protocols/ssl/SslConduit.java
=====================================
@@ -676,7 +676,7 @@ public class SslConduit implements StreamSourceConduit, StreamSinkConduit {
      * @return true if the unwrap operation made progress, false otherwise
      * @throws SSLException
      */
-    private long doUnwrap(ByteBuffer[] userBuffers, int off, int len) throws IOException {
+    private synchronized long doUnwrap(ByteBuffer[] userBuffers, int off, int len) throws IOException {
         if(anyAreSet(state, FLAG_CLOSED)) {
             throw new ClosedChannelException();
         }
@@ -887,7 +887,7 @@ public class SslConduit implements StreamSourceConduit, StreamSinkConduit {
      * @return The amount of data consumed
      * @throws IOException
      */
-    private long doWrap(ByteBuffer[] userBuffers, int off, int len) throws IOException {
+    private synchronized long doWrap(ByteBuffer[] userBuffers, int off, int len) throws IOException {
         if(anyAreSet(state, FLAG_CLOSED)) {
             throw new ClosedChannelException();
         }
@@ -896,7 +896,7 @@ public class SslConduit implements StreamSourceConduit, StreamSinkConduit {
         }
         if(anyAreSet(state, FLAG_WRITE_REQUIRES_READ)) {
             doUnwrap(null, 0, 0);
-            if(allAreClear(state, FLAG_READ_REQUIRES_WRITE)) { //unless a wrap is immediatly required we just return
+            if(allAreClear(state, FLAG_READ_REQUIRES_WRITE)) { //unless a wrap is immediately required we just return
                 return 0;
             }
         }
@@ -1051,31 +1051,33 @@ public class SslConduit implements StreamSourceConduit, StreamSinkConduit {
         if(anyAreSet(state, FLAG_CLOSED)) {
             return;
         }
-        state |= FLAG_CLOSED | FLAG_DELEGATE_SINK_SHUTDOWN | FLAG_DELEGATE_SOURCE_SHUTDOWN | FLAG_WRITE_SHUTDOWN | FLAG_READ_SHUTDOWN;
-        notifyReadClosed();
-        notifyWriteClosed();
-        if(dataToUnwrap != null) {
-            dataToUnwrap.close();
-            dataToUnwrap = null;
-        }
-        if(unwrappedData != null) {
-            unwrappedData.close();
-            unwrappedData = null;
-        }
-        if(wrappedData != null) {
-            wrappedData.close();
-            wrappedData = null;
-        }
-        if(allAreClear(state, FLAG_ENGINE_OUTBOUND_SHUTDOWN)) {
-            engine.closeOutbound();
-        }
-        if(allAreClear(state, FLAG_ENGINE_INBOUND_SHUTDOWN)) {
-            try {
-                engine.closeInbound();
-            } catch (SSLException e) {
-                UndertowLogger.REQUEST_LOGGER.ioException(e);
-            } catch (Throwable t) {
-                UndertowLogger.REQUEST_LOGGER.handleUnexpectedFailure(t);
+        synchronized (this) {
+            state |= FLAG_CLOSED | FLAG_DELEGATE_SINK_SHUTDOWN | FLAG_DELEGATE_SOURCE_SHUTDOWN | FLAG_WRITE_SHUTDOWN | FLAG_READ_SHUTDOWN;
+            notifyReadClosed();
+            notifyWriteClosed();
+            if (dataToUnwrap != null) {
+                dataToUnwrap.close();
+                dataToUnwrap = null;
+            }
+            if (unwrappedData != null) {
+                unwrappedData.close();
+                unwrappedData = null;
+            }
+            if (wrappedData != null) {
+                wrappedData.close();
+                wrappedData = null;
+            }
+            if (allAreClear(state, FLAG_ENGINE_OUTBOUND_SHUTDOWN)) {
+                engine.closeOutbound();
+            }
+            if (allAreClear(state, FLAG_ENGINE_INBOUND_SHUTDOWN)) {
+                try {
+                    engine.closeInbound();
+                } catch (SSLException e) {
+                    UndertowLogger.REQUEST_LOGGER.ioException(e);
+                } catch (Throwable t) {
+                    UndertowLogger.REQUEST_LOGGER.handleUnexpectedFailure(t);
+                }
             }
         }
         IoUtils.safeClose(delegate);


=====================================
core/src/main/java/io/undertow/server/protocol/ajp/AjpReadListener.java
=====================================
@@ -55,7 +55,10 @@ import static org.xnio.IoUtils.safeClose;
 
 final class AjpReadListener implements ChannelListener<StreamSourceChannel> {
 
-    private static final byte[] CPONG = {'A', 'B', 0, 1, 9}; //CPONG response data
+    private static final byte[] CPONG = {'A', 'B', 0, 1, 9};
+    private static final byte[] SEND_HEADERS_INTERNAL_SERVER_ERROR_MSG = {'A', 'B', 0, 8, 4, (byte)((500 >> 8) & 0xFF) , (byte)(500 & 0xFF), 0, 0, '\0', 0, 0};
+    private static final byte[] SEND_HEADERS_BAD_REQUEST_MSG = {'A', 'B', 0, 8, 4, (byte)((400 >> 8) & 0xFF) , (byte)(400 & 0xFF), 0, 0, '\0', 0, 0};
+    private static final byte[] END_RESPONSE = {'A', 'B', 0, 2, 5, 1};
 
     private final AjpServerConnection connection;
     private final String scheme;
@@ -119,13 +122,7 @@ final class AjpReadListener implements ChannelListener<StreamSourceChannel> {
             do {
                 if (existing == null) {
                     buffer.clear();
-                    try {
-                        res = channel.read(buffer);
-                    } catch (IOException e) {
-                        UndertowLogger.REQUEST_IO_LOGGER.ioException(e);
-                        safeClose(connection);
-                        return;
-                    }
+                    res = channel.read(buffer);
                 } else {
                     res = buffer.remaining();
                 }
@@ -141,17 +138,10 @@ final class AjpReadListener implements ChannelListener<StreamSourceChannel> {
                     return;
                 }
                 if (res == -1) {
-                    try {
-                        channel.shutdownReads();
-                        final StreamSinkChannel responseChannel = connection.getChannel().getSinkChannel();
-                        responseChannel.shutdownWrites();
-                        safeClose(connection);
-                    } catch (IOException e) {
-                        UndertowLogger.REQUEST_IO_LOGGER.ioException(e);
-                        // fuck it, it's all ruined
-                        safeClose(connection);
-                        return;
-                    }
+                    channel.shutdownReads();
+                    final StreamSinkChannel responseChannel = connection.getChannel().getSinkChannel();
+                    responseChannel.shutdownWrites();
+                    safeClose(connection);
                     return;
                 }
                 bytesRead = true;
@@ -216,64 +206,85 @@ final class AjpReadListener implements ChannelListener<StreamSourceChannel> {
             //we need to set the write ready handler. This allows the response conduit to wrap it
             responseConduit.setWriteReadyHandler(writeReadyHandler);
 
-            try {
-                connection.setSSLSessionInfo(state.createSslSessionInfo());
-                httpServerExchange.setSourceAddress(state.createPeerAddress());
-                httpServerExchange.setDestinationAddress(state.createDestinationAddress());
-                if(scheme != null) {
-                    httpServerExchange.setRequestScheme(scheme);
-                }
-                if(state.attributes != null) {
-                    httpServerExchange.putAttachment(HttpServerExchange.REQUEST_ATTRIBUTES, state.attributes);
-                }
-                AjpRequestParseState oldState = state;
-                state = null;
-                this.httpServerExchange = null;
-                httpServerExchange.setPersistent(true);
-
-                if(recordRequestStartTime) {
-                    Connectors.setRequestStartTime(httpServerExchange);
-                }
-                connection.setCurrentExchange(httpServerExchange);
-                if(connectorStatistics != null) {
-                    connectorStatistics.setup(httpServerExchange);
-                }
-                if(!Connectors.areRequestHeadersValid(httpServerExchange.getRequestHeaders())) {
-                    oldState.badRequest = true;
-                    UndertowLogger.REQUEST_IO_LOGGER.debugf("Invalid AJP request from %s, request contained invalid headers", connection.getPeerAddress());
-                }
+            connection.setSSLSessionInfo(state.createSslSessionInfo());
+            httpServerExchange.setSourceAddress(state.createPeerAddress());
+            httpServerExchange.setDestinationAddress(state.createDestinationAddress());
+            if(scheme != null) {
+                httpServerExchange.setRequestScheme(scheme);
+            }
+            if(state.attributes != null) {
+                httpServerExchange.putAttachment(HttpServerExchange.REQUEST_ATTRIBUTES, state.attributes);
+            }
+            AjpRequestParseState oldState = state;
+            state = null;
+            this.httpServerExchange = null;
+            httpServerExchange.setPersistent(true);
 
-                if(oldState.badRequest) {
-                    httpServerExchange.setStatusCode(StatusCodes.BAD_REQUEST);
-                    httpServerExchange.endExchange();
-                    safeClose(connection);
-                } else {
-                    Connectors.executeRootHandler(connection.getRootHandler(), httpServerExchange);
-                }
+            if(recordRequestStartTime) {
+                Connectors.setRequestStartTime(httpServerExchange);
+            }
+            connection.setCurrentExchange(httpServerExchange);
+            if(connectorStatistics != null) {
+                connectorStatistics.setup(httpServerExchange);
+            }
+            if(!Connectors.areRequestHeadersValid(httpServerExchange.getRequestHeaders())) {
+                oldState.badRequest = true;
+                UndertowLogger.REQUEST_IO_LOGGER.debugf("Invalid AJP request from %s, request contained invalid headers", connection.getPeerAddress());
+            }
 
-            } catch (Throwable t) {
-                //TODO: we should attempt to return a 500 status code in this situation
-                UndertowLogger.REQUEST_LOGGER.exceptionProcessingRequest(t);
+            if(oldState.badRequest) {
+                httpServerExchange.setStatusCode(StatusCodes.BAD_REQUEST);
+                httpServerExchange.endExchange();
+                handleBadRequest();
                 safeClose(connection);
+            } else {
+                Connectors.executeRootHandler(connection.getRootHandler(), httpServerExchange);
             }
         } catch (BadRequestException e) {
             UndertowLogger.REQUEST_IO_LOGGER.failedToParseRequest(e);
-            httpServerExchange.setStatusCode(StatusCodes.BAD_REQUEST);
-            httpServerExchange.endExchange();
+            handleBadRequest();
             safeClose(connection);
-        } catch (Exception e) {
-            UndertowLogger.REQUEST_LOGGER.exceptionProcessingRequest(e);
+        } catch (IOException e) {
+            UndertowLogger.REQUEST_IO_LOGGER.ioException(e);
+            handleInternalServerError();
+            safeClose(connection);
+        } catch (Throwable t) {
+            UndertowLogger.REQUEST_LOGGER.exceptionProcessingRequest(t);
+            handleInternalServerError();
             safeClose(connection);
         } finally {
             if (free) pooled.close();
         }
     }
 
+    private void handleInternalServerError() {
+        sendMessages(SEND_HEADERS_INTERNAL_SERVER_ERROR_MSG, END_RESPONSE);
+    }
+
+    private void handleBadRequest() {
+        sendMessages(SEND_HEADERS_BAD_REQUEST_MSG, END_RESPONSE);
+    }
+
     private void handleCPing() {
+        sendMessages(CPONG);
+    }
+
+    private void sendMessages(final byte[]... rawMessages) {
         state = new AjpRequestParseState();
         final StreamConnection underlyingChannel = connection.getChannel();
         underlyingChannel.getSourceChannel().suspendReads();
-        final ByteBuffer buffer = ByteBuffer.wrap(CPONG);
+        // detect buffer size
+        int bufferSize = 0;
+        for (int i = 0; i < rawMessages.length; i++) {
+            bufferSize += rawMessages[i].length;
+        }
+        // fill in buffer
+        final ByteBuffer buffer = ByteBuffer.allocate(bufferSize);
+        for (int i = 0; i < rawMessages.length; i++) {
+            buffer.put(rawMessages[i]);
+        }
+        buffer.flip();
+        // send buffer content
         int res;
         try {
             do {


=====================================
core/src/main/java/io/undertow/server/session/InMemorySessionManager.java
=====================================
@@ -468,6 +468,7 @@ public class InMemorySessionManager implements SessionManager, SessionManagerSta
                     serverExchange.putAttachment(FIRST_REQUEST_ACCESS, System.currentTimeMillis());
                 }
             }
+            bumpTimeout();
         }
 
         @Override


=====================================
core/src/test/java/io/undertow/server/protocol/http2/Http2EndExchangeTestCase.java
=====================================
@@ -28,7 +28,6 @@ import io.undertow.server.HttpServerExchange;
 import io.undertow.server.handlers.BlockingHandler;
 import io.undertow.testutils.DefaultServer;
 import io.undertow.testutils.HttpOneOnly;
-import io.undertow.util.AttachmentKey;
 import io.undertow.util.Headers;
 import io.undertow.util.Methods;
 import io.undertow.util.Protocols;
@@ -56,15 +55,11 @@ public class Http2EndExchangeTestCase {
 
 
     private static final Logger log = Logger.getLogger(Http2EndExchangeTestCase.class);
-    private static final String message = "Hello World!";
-    public static final String MESSAGE = "/message";
-    public static final String POST = "/post";
+    private static final String MESSAGE = "/message";
 
     private static final OptionMap DEFAULT_OPTIONS;
     private static URI ADDRESS;
 
-    private static final AttachmentKey<String> RESPONSE_BODY = AttachmentKey.create(String.class);
-
     static {
         final OptionMap.Builder builder = OptionMap.builder()
                 .set(Options.WORKER_IO_THREADS, 8)
@@ -92,7 +87,8 @@ public class Http2EndExchangeTestCase {
                     @Override
                     public void handleRequest(HttpServerExchange exchange) throws Exception {
                         if (!exchange.getProtocol().equals(Protocols.HTTP_2_0)) {
-                            throw new RuntimeException("Not HTTP/2");
+                            testResult.completeExceptionally(new RuntimeException("Not HTTP/2 request"));
+                            return;
                         }
                         requestStartedLatch.countDown();
                         log.debug("Received Request");
@@ -187,10 +183,6 @@ public class Http2EndExchangeTestCase {
     }
 
     static UndertowClient createClient() {
-        return createClient(OptionMap.EMPTY);
-    }
-
-    static UndertowClient createClient(final OptionMap options) {
         return UndertowClient.getInstance();
     }
 }


=====================================
coverage-report/pom.xml
=====================================
@@ -3,7 +3,7 @@
     <parent>
         <groupId>io.undertow</groupId>
         <artifactId>undertow-parent</artifactId>
-        <version>2.2.3.Final</version>
+        <version>2.2.4.Final</version>
     </parent>
     <artifactId>undertow-coverage-report</artifactId>
     <name>Undertow Test Coverage Report</name>


=====================================
dist/pom.xml
=====================================
@@ -25,12 +25,12 @@
     <parent>
         <groupId>io.undertow</groupId>
         <artifactId>undertow-parent</artifactId>
-        <version>2.2.3.Final</version>
+        <version>2.2.4.Final</version>
     </parent>
 
     <groupId>io.undertow</groupId>
     <artifactId>undertow-dist</artifactId>
-    <version>2.2.3.Final</version>
+    <version>2.2.4.Final</version>
 
     <name>Undertow: Distribution</name>
 


=====================================
examples/pom.xml
=====================================
@@ -25,12 +25,12 @@
     <parent>
         <groupId>io.undertow</groupId>
         <artifactId>undertow-parent</artifactId>
-        <version>2.2.3.Final</version>
+        <version>2.2.4.Final</version>
     </parent>
 
     <groupId>io.undertow</groupId>
     <artifactId>undertow-examples</artifactId>
-    <version>2.2.3.Final</version>
+    <version>2.2.4.Final</version>
 
     <name>Undertow Examples</name>
 


=====================================
jakartaee9/pom.xml
=====================================
@@ -0,0 +1,254 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ JBoss, Home of Professional Open Source.
+  ~ Copyright 2020 Red Hat, Inc., and individual contributors
+  ~ as indicated by the @author tags.
+  ~
+  ~ Licensed 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>io.undertow</groupId>
+        <artifactId>undertow-parent</artifactId>
+        <version>2.2.4.Final</version>
+    </parent>
+
+    <groupId>io.undertow</groupId>
+    <artifactId>undertow-jakartaee9</artifactId>
+    <version>2.2.4.Final</version>
+
+    <name>Undertow Jakarta EE9</name>
+
+    <properties>
+        <version.jakarta.servlet-api>5.0.0</version.jakarta.servlet-api>
+        <version.jakarta.websocket-client-api>2.0.0</version.jakarta.websocket-client-api>
+    </properties>
+
+    <dependencies>
+
+        <dependency>
+            <groupId>org.jboss.logging</groupId>
+            <artifactId>jboss-logging</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.jboss.logging</groupId>
+            <artifactId>jboss-logging-processor</artifactId>
+            <scope>provided</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>io.undertow</groupId>
+            <artifactId>undertow-examples</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>io.undertow</groupId>
+            <artifactId>undertow-servlet</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>io.undertow</groupId>
+            <artifactId>undertow-websockets-jsr</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.wildfly.extras.batavia</groupId>
+            <artifactId>transformer-api</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.wildfly.extras.batavia</groupId>
+            <artifactId>transformer-impl-eclipse</artifactId>
+            <scope>runtime</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.maven.shared</groupId>
+            <artifactId>maven-invoker</artifactId>
+            <version>3.0.1</version>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <resources>
+            <resource>
+                <directory>${project.basedir}/src/main/resources</directory>
+                <filtering>true</filtering>
+            </resource>
+        </resources>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-dependency-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>copy</id>
+                        <phase>compile</phase>
+                        <goals>
+                            <goal>copy</goal>
+                        </goals>
+                        <configuration>
+                            <artifactItems>
+                                <!-- pom files -->
+                                <artifactItem>
+                                    <groupId>io.undertow</groupId>
+                                    <artifactId>undertow-servlet</artifactId>
+                                    <version>${project.version}</version>
+                                    <type>pom</type>
+                                    <overWrite>true</overWrite>
+                                    <outputDirectory>${project.basedir}/target/input</outputDirectory>
+                                </artifactItem>
+                                <artifactItem>
+                                    <groupId>io.undertow</groupId>
+                                    <artifactId>undertow-examples</artifactId>
+                                    <version>${project.version}</version>
+                                    <type>pom</type>
+                                    <overWrite>true</overWrite>
+                                    <outputDirectory>${project.basedir}/target/input</outputDirectory>
+                                </artifactItem>
+                                <artifactItem>
+                                    <groupId>io.undertow</groupId>
+                                    <artifactId>undertow-websockets-jsr</artifactId>
+                                    <version>${project.version}</version>
+                                    <type>pom</type>
+                                    <overWrite>true</overWrite>
+                                    <outputDirectory>${project.basedir}/target/input</outputDirectory>
+                                </artifactItem>
+                                <!-- jar files -->
+                                <artifactItem>
+                                    <groupId>io.undertow</groupId>
+                                    <artifactId>undertow-servlet</artifactId>
+                                    <version>${project.version}</version>
+                                    <overWrite>true</overWrite>
+                                    <outputDirectory>${project.basedir}/target/input</outputDirectory>
+                                </artifactItem>
+                               <artifactItem>
+                                    <groupId>io.undertow</groupId>
+                                    <artifactId>undertow-examples</artifactId>
+                                    <version>${project.version}</version>
+                                    <overWrite>true</overWrite>
+                                    <outputDirectory>${project.basedir}/target/input</outputDirectory>
+                                </artifactItem>
+                                <artifactItem>
+                                    <groupId>io.undertow</groupId>
+                                    <artifactId>undertow-websockets-jsr</artifactId>
+                                    <version>${project.version}</version>
+                                    <overWrite>true</overWrite>
+                                    <outputDirectory>${project.basedir}/target/input</outputDirectory>
+                                </artifactItem>
+                                <!-- source files -->
+                                <artifactItem>
+                                    <groupId>io.undertow</groupId>
+                                    <artifactId>undertow-servlet</artifactId>
+                                    <version>${project.version}</version>
+                                    <overWrite>true</overWrite>
+                                    <classifier>sources</classifier>
+                                    <outputDirectory>${project.basedir}/target/output</outputDirectory>
+                                    <destFileName>undertow-servlet-jakartaee9-${project.version}-sources.jar</destFileName>
+                                </artifactItem>
+                                <artifactItem>
+                                    <groupId>io.undertow</groupId>
+                                    <artifactId>undertow-examples</artifactId>
+                                    <version>${project.version}</version>
+                                    <overWrite>true</overWrite>
+                                    <classifier>sources</classifier>
+                                    <outputDirectory>${project.basedir}/target/output</outputDirectory>
+                                    <destFileName>undertow-examples-jakartaee9-${project.version}-sources.jar</destFileName>
+                                </artifactItem>
+                                <artifactItem>
+                                    <groupId>io.undertow</groupId>
+                                    <artifactId>undertow-websockets-jsr</artifactId>
+                                    <version>${project.version}</version>
+                                    <overWrite>true</overWrite>
+                                    <classifier>sources</classifier>
+                                    <outputDirectory>${project.basedir}/target/output</outputDirectory>
+                                    <destFileName>undertow-websockets-jsr-jakartaee9-${project.version}-sources.jar</destFileName>
+                                </artifactItem>
+                            </artifactItems>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>exec-maven-plugin</artifactId>
+                <version>3.0.0</version>
+                <executions>
+                    <execution>
+                        <id>transform-artifacts</id>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>java</goal>
+                        </goals>
+                        <configuration>
+                            <mainClass>io.undertow.jakartaee9.JakartaEE9Transformer</mainClass>
+                        </configuration>
+                    </execution>
+                    <execution>
+                        <id>install-artifacts</id>
+                        <phase>install</phase>
+                        <goals>
+                            <goal>java</goal>
+                        </goals>
+                        <configuration>
+                            <mainClass>io.undertow.jakartaee9.JakartaEE9Installer</mainClass>
+                        </configuration>
+                    </execution>
+                </executions>
+                <configuration>
+                    <systemProperties>
+                        <systemProperty>
+                            <key>version.jakarta.servlet-api</key>
+                            <value>${version.jakarta.servlet-api}</value>
+                        </systemProperty>
+                        <systemProperty>
+                            <key>version.jakarta.websocket-client-api</key>
+                            <value>${version.jakarta.websocket-client-api}</value>
+                        </systemProperty>
+                    </systemProperties>
+                </configuration>
+            </plugin>
+            <!-- <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-deploy-plugin</artifactId>
+                <version>3.0.0-M1</version>
+                <executions>
+                    <execution>
+                        <id>run</id>
+                        <phase>deploy</phase>
+                        <goals>
+                            <goal>deploy-file</goal>
+                        </goals>
+                        <configuration>
+                            <file>${project.basedir}/target/output/undertow-examples-jakartaee9-${project.version}.jar</file>
+                            <pomFile>${project.basedir}/target/output/undertow-examples-jakartaee9-${project.version}.pom</pomFile>
+                            <sources>${project.basedir}/target/output/undertow-examples-jakartaee9-${project.version}-sources.jar</sources>
+                            <repositoryId>jboss-releases-repository</repositoryId>
+                            <url>https://repository.jboss.org/nexus/service/local/staging/deploy/maven2</url>
+                        </configuration>
+                    </execution>
+                </executions>
+                <configuration>
+                </configuration>
+            </plugin> -->
+        </plugins>
+    </build>
+
+
+</project>


=====================================
jakartaee9/src/main/java/io/undertow/jakartaee9/ArtifactNameTransformer.java
=====================================
@@ -0,0 +1,44 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2020 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed 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 io.undertow.jakartaee9;
+
+import static io.undertow.jakartaee9.TransformConstants.VERSION_STRING;
+
+/**
+ * Parses an Jakarta EE8 compatible artifact name and transforms it into the
+ * equivalent Jakarta EE9 compatible counterpart.
+ *
+ * @author Flavia Rainone
+ */
+class ArtifactNameTransformer {
+    private static final String JAKARTA_EE9_SUFFIX = "-jakartaee9";
+
+    static String transformArtifactName(String fileName, String artifactType) {
+        return getArtifactName(fileName, artifactType) + JAKARTA_EE9_SUFFIX;
+    }
+
+    static String transformArtifactFileName(String fileName, String artifactType) {
+        final String outputFileSuffix = JAKARTA_EE9_SUFFIX + "-" + VERSION_STRING + "." + artifactType;
+        return getArtifactName(fileName, artifactType) + outputFileSuffix;
+    }
+
+    static String getArtifactName(String fileName, String artifactType) {
+        final String inputFileSuffix = "-" + VERSION_STRING + "." +  artifactType;
+        return fileName.substring(0, fileName.length() - inputFileSuffix.length());
+    }
+}


=====================================
jakartaee9/src/main/java/io/undertow/jakartaee9/JakartaEE9Deployer.java
=====================================
@@ -0,0 +1,65 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2020 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed 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 io.undertow.jakartaee9;
+
+import java.io.File;
+import java.util.Collections;
+import java.util.Properties;
+
+import org.apache.maven.shared.invoker.DefaultInvocationRequest;
+import org.apache.maven.shared.invoker.DefaultInvoker;
+import org.apache.maven.shared.invoker.InvocationRequest;
+import org.apache.maven.shared.invoker.Invoker;
+import org.apache.maven.shared.invoker.MavenInvocationException;
+
+import static io.undertow.jakartaee9.TransformConstants.JAR_EXTENSION;
+import static io.undertow.jakartaee9.TransformConstants.OUTPUT_DIR;
+import static io.undertow.jakartaee9.TransformConstants.POM_EXTENSION;
+import static io.undertow.jakartaee9.UndertowJakartaEE9Logger.LOGGER;
+
+/**
+ * Deploys Jakarta EE9 compatible artifacts.
+ *
+ * @author Flavia Rainone
+ */
+public class JakartaEE9Deployer {
+
+    public static void main (String[] args)
+            throws MavenInvocationException {
+        final File[] pomFiles = OUTPUT_DIR.listFiles((dir, name) -> name.endsWith(POM_EXTENSION));
+        if (pomFiles == null) {
+            throw LOGGER.pomFilesNotFoundInOutputDir(OUTPUT_DIR.getAbsolutePath());
+        }
+        for (final File pomFile : pomFiles) {
+            final String pomFileName = pomFile.getAbsolutePath();
+            final String jarFileName = pomFile.getAbsolutePath().substring(0, pomFileName.length() - POM_EXTENSION
+                    .length()) + JAR_EXTENSION;
+            LOGGER.installingFile(jarFileName, pomFile.getAbsolutePath());
+
+            final Properties properties = new Properties();
+            properties.put("file", jarFileName);
+            properties.put("pomFile", pomFileName);
+
+            final InvocationRequest request = new DefaultInvocationRequest();
+            request.setGoals(Collections.singletonList("deploy:deploy-file"));
+            request.setProperties(properties);
+            final Invoker invoker = new DefaultInvoker();
+            invoker.execute( request );
+        }
+    }
+}


=====================================
jakartaee9/src/main/java/io/undertow/jakartaee9/JakartaEE9Installer.java
=====================================
@@ -0,0 +1,69 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2020 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed 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 io.undertow.jakartaee9;
+
+import java.io.File;
+import java.util.Collections;
+import java.util.Properties;
+
+import org.apache.maven.shared.invoker.DefaultInvocationRequest;
+import org.apache.maven.shared.invoker.DefaultInvoker;
+import org.apache.maven.shared.invoker.InvocationRequest;
+import org.apache.maven.shared.invoker.Invoker;
+import org.apache.maven.shared.invoker.MavenInvocationException;
+
+import static io.undertow.jakartaee9.TransformConstants.JAR_EXTENSION;
+import static io.undertow.jakartaee9.TransformConstants.OUTPUT_DIR;
+import static io.undertow.jakartaee9.TransformConstants.POM_EXTENSION;
+import static io.undertow.jakartaee9.TransformConstants.SOURCES_EXTENSION;
+import static io.undertow.jakartaee9.UndertowJakartaEE9Logger.LOGGER;
+
+/**
+ * Installs Jakarta EE9 artifacts.
+ *
+ * @author Flavia Rainone
+ */
+public class JakartaEE9Installer {
+
+    public static void main (String[] args)
+            throws MavenInvocationException {
+        final File[] pomFiles = OUTPUT_DIR.listFiles((File dir, String name) -> name.endsWith(POM_EXTENSION));
+        if (pomFiles == null) {
+            throw LOGGER.pomFilesNotFoundInOutputDir(OUTPUT_DIR.getAbsolutePath());
+        }
+        for (File pomFile : pomFiles) {
+            final String pomFileName = pomFile.getAbsolutePath();
+            final String jarFileName = pomFile.getAbsolutePath().substring(0, pomFileName.length() - POM_EXTENSION
+                    .length()) + JAR_EXTENSION;
+            final String sourcesJarFileName = pomFile.getAbsolutePath().substring(0, pomFileName.length() - POM_EXTENSION
+                    .length()) + SOURCES_EXTENSION;
+            LOGGER.installingFile(jarFileName, pomFile.getAbsolutePath());
+
+            final Properties properties = new Properties();
+            properties.put("file", jarFileName);
+            properties.put("sources", sourcesJarFileName);
+            properties.put("pomFile", pomFileName);
+
+            final InvocationRequest request = new DefaultInvocationRequest();
+            request.setGoals(Collections.singletonList("install:install-file"));
+            request.setProperties(properties);
+            final Invoker invoker = new DefaultInvoker();
+            invoker.execute( request );
+        }
+    }
+}


=====================================
jakartaee9/src/main/java/io/undertow/jakartaee9/JakartaEE9Transformer.java
=====================================
@@ -0,0 +1,73 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2020 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed 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 io.undertow.jakartaee9;
+
+import java.io.File;
+import java.io.IOException;
+
+import org.wildfly.extras.transformer.TransformerFactory;
+
+import static io.undertow.jakartaee9.TransformConstants.INPUT_DIR;
+import static io.undertow.jakartaee9.TransformConstants.JAR_EXTENSION;
+import static io.undertow.jakartaee9.TransformConstants.JAR_TYPE;
+import static io.undertow.jakartaee9.TransformConstants.OUTPUT_DIR;
+import static io.undertow.jakartaee9.TransformConstants.SERVLET_SPEC_JAKARTAEE9_ARTIFACT;
+import static io.undertow.jakartaee9.TransformConstants.SERVLET_SPEC_JAKARTAEE9_GROUP;
+import static io.undertow.jakartaee9.TransformConstants.SERVLET_SPEC_VERSION;
+import static io.undertow.jakartaee9.TransformConstants.WEBSOCKETS_SPEC_JAKARTAEE9_ARTIFACT;
+import static io.undertow.jakartaee9.TransformConstants.WEBSOCKETS_SPEC_JAKARTAEE9_GROUP;
+import static io.undertow.jakartaee9.TransformConstants.WEBSOCKETS_SPEC_VERSION;
+import static io.undertow.jakartaee9.UndertowJakartaEE9Logger.LOGGER;
+
+/**
+ * Transforms JakartaEE8 Undertow artifacts files into corresponding Jakarta EE9 compatible artifact files.
+ *
+ * @author Flavia Rainone
+ */
+public class JakartaEE9Transformer {
+
+    public static void main (String[] args) throws IOException {
+
+        LOGGER.greeting(TransformConstants.VERSION_STRING);
+        LOGGER.transformationInfo(SERVLET_SPEC_JAKARTAEE9_GROUP, SERVLET_SPEC_JAKARTAEE9_ARTIFACT,
+                SERVLET_SPEC_VERSION, WEBSOCKETS_SPEC_JAKARTAEE9_GROUP, WEBSOCKETS_SPEC_JAKARTAEE9_ARTIFACT,
+                WEBSOCKETS_SPEC_VERSION);
+
+
+        final PomTransformer pomTransformer = new PomTransformer(INPUT_DIR, OUTPUT_DIR);
+        pomTransformer.transformPoms();
+        final File[] inputFiles = INPUT_DIR.listFiles();
+        if (inputFiles == null) {
+            throw LOGGER.inputFilesNotFoundInDir(INPUT_DIR.getAbsolutePath());
+        }
+        for (File file : inputFiles) {
+            if (file.getName().endsWith(JAR_EXTENSION)) {
+                final String newFileName = ArtifactNameTransformer.transformArtifactFileName(file.getName(),
+                        JAR_TYPE);
+                LOGGER.transformingFile(file.getName(), newFileName);
+                final File generatedFile = new File(OUTPUT_DIR.getAbsolutePath() + File.separatorChar + file.getName());
+                TransformerFactory.getInstance().newTransformer().build().transform(file, generatedFile);
+                assert generatedFile.exists();
+                final File newGeneratedFile = new File(OUTPUT_DIR.getAbsolutePath() + File.separatorChar + newFileName);
+                if (!generatedFile.renameTo(newGeneratedFile)) {
+                    throw LOGGER.renamingFileFalied(generatedFile.getAbsolutePath(), newGeneratedFile.getAbsolutePath());
+                }
+            }
+        }
+    }
+}


=====================================
jakartaee9/src/main/java/io/undertow/jakartaee9/PomTransformer.java
=====================================
@@ -0,0 +1,170 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2020 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed 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 io.undertow.jakartaee9;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.stream.Stream;
+
+import static io.undertow.jakartaee9.ArtifactNameTransformer.getArtifactName;
+import static io.undertow.jakartaee9.ArtifactNameTransformer.transformArtifactFileName;
+import static io.undertow.jakartaee9.ArtifactNameTransformer.transformArtifactName;
+import static io.undertow.jakartaee9.TransformConstants.POM_EXTENSION;
+import static io.undertow.jakartaee9.TransformConstants.POM_TYPE;
+import static io.undertow.jakartaee9.TransformConstants.SERVLET_SPEC_JAKARTAEE8_ARTIFACT;
+import static io.undertow.jakartaee9.TransformConstants.SERVLET_SPEC_JAKARTAEE8_GROUP;
+import static io.undertow.jakartaee9.TransformConstants.SERVLET_SPEC_JAKARTAEE9_ARTIFACT;
+import static io.undertow.jakartaee9.TransformConstants.SERVLET_SPEC_JAKARTAEE9_GROUP;
+import static io.undertow.jakartaee9.TransformConstants.SERVLET_SPEC_VERSION;
+import static io.undertow.jakartaee9.TransformConstants.WEBSOCKETS_SPEC_JAKARTAEE8_ARTIFACT;
+import static io.undertow.jakartaee9.TransformConstants.WEBSOCKETS_SPEC_JAKARTAEE8_GROUP;
+import static io.undertow.jakartaee9.TransformConstants.WEBSOCKETS_SPEC_JAKARTAEE9_ARTIFACT;
+import static io.undertow.jakartaee9.TransformConstants.WEBSOCKETS_SPEC_JAKARTAEE9_GROUP;
+import static io.undertow.jakartaee9.TransformConstants.WEBSOCKETS_SPEC_VERSION;
+import static io.undertow.jakartaee9.UndertowJakartaEE9Logger.LOGGER;
+
+/**
+ * Transforms pom files, moving artifact dependencies from Jakarta EE8 to
+ * Jakarta EE9.
+ *
+ * @author Flavia Rainone
+ */
+class PomTransformer {
+    private static final String VERSION_LINE = "\\s*<version>.*</version>\\s*";
+
+    private static final String OPEN_ARTIFACT = "<artifactId>";
+    private static final String CLOSE_ARTIFACT = "</artifactId>";
+    private static final String SERVLET_SPEC_JAKARTAEE8_ARTIFACT_LINE = OPEN_ARTIFACT + SERVLET_SPEC_JAKARTAEE8_ARTIFACT + CLOSE_ARTIFACT;
+    private static final String SERVLET_SPEC_JAKARTAEE9_ARTIFACT_LINE = OPEN_ARTIFACT + SERVLET_SPEC_JAKARTAEE9_ARTIFACT + CLOSE_ARTIFACT;
+    private static final String WEBSOCKETS_SPEC_JAKARTAEE8_ARTIFACT_LINE = OPEN_ARTIFACT + WEBSOCKETS_SPEC_JAKARTAEE8_ARTIFACT + CLOSE_ARTIFACT;
+    private static final String WEBSOCKETS_SPEC_JAKARTAEE9_ARTIFACT_LINE = OPEN_ARTIFACT + WEBSOCKETS_SPEC_JAKARTAEE9_ARTIFACT + CLOSE_ARTIFACT;
+
+    private static final String OPEN_GROUP = "<groupId>";
+    private static final String CLOSE_GROUP = "</groupId>";
+    private static final String SERVLET_SPEC_JAKARTAEE8_GROUP_LINE = OPEN_GROUP + SERVLET_SPEC_JAKARTAEE8_GROUP + CLOSE_GROUP;
+    private static final String SERVLET_SPEC_JAKARTAEE9_GROUP_LINE = OPEN_GROUP + SERVLET_SPEC_JAKARTAEE9_GROUP + CLOSE_GROUP;
+    private static final String WEBSOCKETS_SPEC_JAKARTAEE8_GROUP_LINE = OPEN_GROUP + WEBSOCKETS_SPEC_JAKARTAEE8_GROUP + CLOSE_GROUP;
+    private static final String WEBSOCKETS_SPEC_JAKARTAEE9_GROUP_LINE = OPEN_GROUP + WEBSOCKETS_SPEC_JAKARTAEE9_GROUP + CLOSE_GROUP;
+
+    private static final String OPEN_VERSION = "<version>";
+    private static final String CLOSE_VERSION = "</version>";
+    private static final String SERVLET_SPEC_VERSION_LINE = OPEN_VERSION + SERVLET_SPEC_VERSION + CLOSE_VERSION;
+    private static final String WEBSOCKETS_SPEC_VERSION_LINE = OPEN_VERSION + WEBSOCKETS_SPEC_VERSION + CLOSE_VERSION;
+
+    private final File inputDir;
+    private final File outputDir;
+
+    PomTransformer(File inputDir, File outputDir) {
+        this.inputDir = inputDir;
+        this.outputDir = outputDir;
+    }
+
+    void transformPoms() throws IOException {
+        final Map<String, String> artifactMapping = new HashMap<>();
+        try (Stream<Path> paths = Files.walk(inputDir.toPath())) {
+            paths.forEach((Path p) -> {
+                final String fileName = p.getFileName().toString();
+                if (fileName.endsWith(POM_EXTENSION)) artifactMapping.put(getArtifactName(fileName, POM_TYPE), transformArtifactName(fileName, POM_TYPE));
+            });
+        }
+        final File[] inputFiles = inputDir.listFiles();
+        if (inputFiles == null)
+            throw LOGGER.inputFilesNotFoundInDir(inputDir.getCanonicalPath());
+        for (File file : inputFiles) {
+            if (file.getName().endsWith(POM_EXTENSION))
+                transformPom(file, artifactMapping);
+        }
+    }
+
+    private void transformPom(final File pomFile, Map<String, String> artifactMapping) throws IOException {
+        // input and output file names
+        final String pomFileName = pomFile.getName();
+        final String transformedPomFileName = transformArtifactFileName(pomFileName,
+                POM_TYPE);
+        final File transformedPomFile = new File(outputDir, transformedPomFileName);
+        if (!transformedPomFile.createNewFile()) {
+            // if there's already a pom file, the file is from a previous build, delete it and create a new one
+            if (!transformedPomFile.delete() || !transformedPomFile.createNewFile()) {
+                throw LOGGER.cannotCreateOutputFile(transformedPomFile.getAbsolutePath());
+            }
+        }
+
+        LOGGER.transformingFile(pomFileName, transformedPomFileName);
+
+        // process lines
+        final Stream<String> pomLines = Files.lines(pomFile.toPath());
+        final Stream<String> transformedPomLines = pomLines.map(line -> transformPomLine(line, artifactMapping));
+        try (Writer writer = new OutputStreamWriter(new FileOutputStream(transformedPomFile), "US-ASCII")) {
+            transformedPomLines.forEachOrdered(line -> {
+                if (line == null) return;
+                try {
+                    writer.write(line);
+                    writer.write('\n');
+                } catch (IOException e) {
+                    e.printStackTrace();
+                    System.exit(1);
+                }
+            });
+        }
+    }
+
+    private boolean skipVersion;
+
+    private String transformPomLine(String line, Map<String, String> artifactMapping) {
+        for (Map.Entry<String, String> mappedArtifact: artifactMapping.entrySet()) {
+            if (line.matches(".*" + mappedArtifact.getKey() + ".*")) {
+                return line.replaceAll(mappedArtifact.getKey(), mappedArtifact.getValue());
+            }
+        }
+        if (skipVersion) {
+            skipVersion = false;
+            if (line.matches(VERSION_LINE))
+                return null;
+        }
+        if (line.contains(SERVLET_SPEC_JAKARTAEE8_GROUP_LINE)) {
+            return getTabSpaces(line) + SERVLET_SPEC_JAKARTAEE9_GROUP_LINE;
+        }
+        if (line.contains (WEBSOCKETS_SPEC_JAKARTAEE8_GROUP_LINE)) {
+            return getTabSpaces(line) + WEBSOCKETS_SPEC_JAKARTAEE9_GROUP_LINE;
+        }
+        if (line.contains(SERVLET_SPEC_JAKARTAEE8_ARTIFACT_LINE)) {
+            final String spaces = getTabSpaces(line);
+            skipVersion = true;
+            return spaces + SERVLET_SPEC_JAKARTAEE9_ARTIFACT_LINE + "\n"
+                    + spaces + SERVLET_SPEC_VERSION_LINE;
+        }
+        if (line.contains(WEBSOCKETS_SPEC_JAKARTAEE8_ARTIFACT_LINE)) {
+            final String spaces = getTabSpaces(line);
+            skipVersion = true;
+            return spaces + WEBSOCKETS_SPEC_JAKARTAEE9_ARTIFACT_LINE + "\n"
+                    + spaces + WEBSOCKETS_SPEC_VERSION_LINE;
+        }
+        return line;
+    }
+
+    private String getTabSpaces(String inputLine) {
+        return inputLine.substring(0, inputLine.indexOf('<'));
+    }
+}
\ No newline at end of file


=====================================
jakartaee9/src/main/java/io/undertow/jakartaee9/TransformConstants.java
=====================================
@@ -0,0 +1,94 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2020 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed 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 io.undertow.jakartaee9;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.nio.charset.StandardCharsets;
+import java.util.Properties;
+
+/**
+ * Some static constants used by other classes.
+ *
+ * @author Flavia Rainone
+ */
+class TransformConstants {
+    private static final String MAVEN_PROJECT_DIR_PROPERTY = "maven.multiModuleProjectDirectory";
+    private static final String JAKARTAEE9_DIR_NAME = File.separator + "jakartaee9";
+    private static final String INPUT_DIR_NAME = File.separator + "target" + File.separator + "input";
+    private static final String OUTPUT_DIR_NAME = File.separator + "target" + File.separator + "output";
+
+    // input and output dirs
+    static final File INPUT_DIR;
+    static final File OUTPUT_DIR;
+
+    // artifact types and extensions
+    static final String JAR_TYPE = "jar";
+    static final String JAR_EXTENSION = "." + JAR_TYPE;
+    static final String POM_TYPE = "pom";
+    static final String POM_EXTENSION = "." + POM_TYPE;
+    static final String SOURCES_EXTENSION = "-sources." + JAR_TYPE;
+
+    // spec versions
+    private static final String SERVLET_SPEC_VERSION_PROPERTY = "version.jakarta.servlet-api";
+    private static final String WEBSOCKETS_SPEC_VERSION_PROPERTY = "version.jakarta.websocket-client-api";
+    static final String SERVLET_SPEC_VERSION = System.getProperty(SERVLET_SPEC_VERSION_PROPERTY);
+    static final String WEBSOCKETS_SPEC_VERSION = System.getProperty(WEBSOCKETS_SPEC_VERSION_PROPERTY);
+
+    // servlet spec constants
+    static final String SERVLET_SPEC_JAKARTAEE8_GROUP = "org.jboss.spec.javax.servlet";
+    static final String SERVLET_SPEC_JAKARTAEE9_GROUP = "jakarta.servlet";
+    static final String SERVLET_SPEC_JAKARTAEE8_ARTIFACT = "jboss-servlet-api_4.0_spec";
+    static final String SERVLET_SPEC_JAKARTAEE9_ARTIFACT = "jakarta.servlet-api";
+
+    // websockets constants
+    static final String WEBSOCKETS_SPEC_JAKARTAEE8_GROUP = "org.jboss.spec.javax.websocket";
+    static final String WEBSOCKETS_SPEC_JAKARTAEE9_GROUP = "jakarta.websocket";
+    static final String WEBSOCKETS_SPEC_JAKARTAEE8_ARTIFACT = "jboss-websocket-api_1.1_spec";
+    static final String WEBSOCKETS_SPEC_JAKARTAEE9_ARTIFACT = "jakarta.websocket-client-api";
+
+    // Undertow version
+    static final String VERSION_STRING;
+
+    static {
+        final Properties versionProps = new Properties();
+        String versionString = "(unknown)";
+        try (InputStream stream = TransformConstants.class.getClassLoader().getResourceAsStream("Version.properties")) {
+            if (stream != null) {
+                try (InputStreamReader reader = new InputStreamReader(stream, StandardCharsets.UTF_8)) {
+                    versionProps.load(reader);
+                    versionString = versionProps.getProperty("version", versionString);
+                }
+            }
+        } catch (IOException ignored) {
+        }
+        VERSION_STRING = versionString;
+
+        String projectDirectoryPath = System.getProperty(MAVEN_PROJECT_DIR_PROPERTY);
+        assert projectDirectoryPath != null;
+        if (!projectDirectoryPath.endsWith(JAKARTAEE9_DIR_NAME))
+            projectDirectoryPath = projectDirectoryPath + JAKARTAEE9_DIR_NAME;
+        INPUT_DIR = new File(projectDirectoryPath + INPUT_DIR_NAME);
+        OUTPUT_DIR = new File(projectDirectoryPath + OUTPUT_DIR_NAME);
+        assert INPUT_DIR.exists();
+        if (!OUTPUT_DIR.exists() && !OUTPUT_DIR.mkdir())
+            throw UndertowJakartaEE9Logger.LOGGER.cannotCreateOutputDir(OUTPUT_DIR_NAME);
+    }
+}


=====================================
jakartaee9/src/main/java/io/undertow/jakartaee9/UndertowJakartaEE9Logger.java
=====================================
@@ -0,0 +1,70 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2020 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed 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 io.undertow.jakartaee9;
+
+import org.jboss.logging.BasicLogger;
+import org.jboss.logging.Logger;
+import org.jboss.logging.annotations.LogMessage;
+import org.jboss.logging.annotations.Message;
+import org.jboss.logging.annotations.MessageLogger;
+
+import static org.jboss.logging.Logger.Level.INFO;
+
+/**
+ * Logger for Jakarta EE9 module.
+ *
+ * @author Flavia Rainone
+ */
+ at MessageLogger(projectCode = "Undertow Jakarta EE9")
+interface UndertowJakartaEE9Logger extends BasicLogger {
+    UndertowJakartaEE9Logger LOGGER = Logger.getMessageLogger(
+            UndertowJakartaEE9Logger.class, "io.undertow.jakartaee9");
+
+    // Greeting
+    @LogMessage(level = INFO)
+    @Message(value = "Undertow Jakarta EE9 Transformer Version %s")
+    void greeting(String version);
+
+    @LogMessage(level = INFO)
+    @Message(value = "Dependencies that will be used in the new generated modules:\n\t%s:%s-%s\n\t%s:%s-%s")
+    void transformationInfo (String servletDependencyGroupId, String servletDependencyArtifactId, String servletDependencyVersion,
+            String websocketsDependencyGroupId, String websocketsDependencyArtifactId, String websocketsDependencyVersion);
+
+    @LogMessage(level = INFO)
+    @Message(value = "Transforming %s into %s")
+    void transformingFile (String fileName, String newFileName);
+
+    @LogMessage(level = INFO)
+    @Message(value = "Installing artifact file %s with pom %s")
+    void installingFile (String artifactFileName, String pomFileName);
+
+    @Message(id = 0, value = "Pom files not present in output dir %s")
+    IllegalStateException pomFilesNotFoundInOutputDir(String outputDir);
+
+    @Message(id = 1, value = "Input files not found in input dir %s")
+    IllegalStateException inputFilesNotFoundInDir(String inputDir);
+
+    @Message(id = 2, value = "Renaming of file %s to %s failed")
+    RuntimeException renamingFileFalied(String originalName, String newName);
+
+    @Message(id = 3, value = "Creation of output dir %s failed")
+    RuntimeException cannotCreateOutputDir(String outputDir);
+
+    @Message(id = 4, value = "Creation of file %s failed")
+    RuntimeException cannotCreateOutputFile(String outputFile);
+}


=====================================
jakartaee9/src/main/resources/META-INF/services/org.wildfly.transformer.TransformerFactory
=====================================
@@ -0,0 +1 @@
+org.wildfly.transformer.asm.TransformerFactoryImpl
\ No newline at end of file


=====================================
jakartaee9/src/main/resources/Version.properties
=====================================
@@ -0,0 +1 @@
+version=${project.version}


=====================================
parser-generator/pom.xml
=====================================
@@ -25,12 +25,12 @@
     <parent>
         <groupId>io.undertow</groupId>
         <artifactId>undertow-parent</artifactId>
-        <version>2.2.3.Final</version>
+        <version>2.2.4.Final</version>
     </parent>
 
     <groupId>io.undertow</groupId>
     <artifactId>undertow-parser-generator</artifactId>
-    <version>2.2.3.Final</version>
+    <version>2.2.4.Final</version>
 
     <name>Undertow Parser Generator</name>
     <description>An annotation processor that is used to generate the HTTP parser</description>


=====================================
pom.xml
=====================================
@@ -28,7 +28,7 @@
 
     <groupId>io.undertow</groupId>
     <artifactId>undertow-parent</artifactId>
-    <version>2.2.3.Final</version>
+    <version>2.2.4.Final</version>
 
     <name>Undertow</name>
     <description>Undertow</description>
@@ -102,6 +102,7 @@
 
         <version.jmh>1.21</version.jmh>
 
+        <version.org.wildfly.extras.batavia>1.0.4.Final</version.org.wildfly.extras.batavia>
     </properties>
 
     <modules>
@@ -111,6 +112,7 @@
         <module>examples</module>
         <module>websockets-jsr</module>
         <module>benchmarks</module>
+        <module>jakartaee9</module>
     </modules>
 
     <build>
@@ -502,6 +504,18 @@
                 <scope>provided</scope>
             </dependency>
 
+            <dependency>
+                <groupId>org.wildfly.extras.batavia</groupId>
+                <artifactId>transformer-api</artifactId>
+                <version>${version.org.wildfly.extras.batavia}</version>
+            </dependency>
+
+            <dependency>
+                <groupId>org.wildfly.extras.batavia</groupId>
+                <artifactId>transformer-impl-eclipse</artifactId>
+                <version>${version.org.wildfly.extras.batavia}</version>
+            </dependency>
+
         </dependencies>
     </dependencyManagement>
 


=====================================
servlet/pom.xml
=====================================
@@ -25,12 +25,12 @@
     <parent>
         <groupId>io.undertow</groupId>
         <artifactId>undertow-parent</artifactId>
-        <version>2.2.3.Final</version>
+        <version>2.2.4.Final</version>
     </parent>
 
     <groupId>io.undertow</groupId>
     <artifactId>undertow-servlet</artifactId>
-    <version>2.2.3.Final</version>
+    <version>2.2.4.Final</version>
 
     <name>Undertow Servlet</name>
 


=====================================
servlet/src/main/java/io/undertow/servlet/UndertowServletLogger.java
=====================================
@@ -132,4 +132,7 @@ public interface UndertowServletLogger extends BasicLogger {
     @LogMessage(level = WARN)
     @Message(id = 15022, value = "Requested resource at %s does not exist for include method")
     void requestedResourceDoesNotExistForIncludeMethod(String path);
+
+    @Message(id = 15023, value = "This Context has been already destroyed")
+    IllegalStateException contextDestroyed();
 }


=====================================
servlet/src/main/java/io/undertow/servlet/spec/ServletContextImpl.java
=====================================
@@ -205,9 +205,16 @@ public class ServletContextImpl implements ServletContext {
         });
     }
 
+    private DeploymentInfo getDeploymentInfo() {
+        final DeploymentInfo deploymentInfo = this.deploymentInfo;
+        if (deploymentInfo == null)
+            throw UndertowServletLogger.ROOT_LOGGER.contextDestroyed();
+        return deploymentInfo;
+    }
+
     @Override
     public String getContextPath() {
-        String contextPath = deploymentInfo.getContextPath();
+        String contextPath = getDeploymentInfo().getContextPath();
         if (contextPath.equals("/")) {
             return "";
         }
@@ -225,22 +232,22 @@ public class ServletContextImpl implements ServletContext {
 
     @Override
     public int getMajorVersion() {
-        return deploymentInfo.getContainerMajorVersion();
+        return getDeploymentInfo().getContainerMajorVersion();
     }
 
     @Override
     public int getMinorVersion() {
-        return deploymentInfo.getContainerMinorVersion();
+        return getDeploymentInfo().getContainerMinorVersion();
     }
 
     @Override
     public int getEffectiveMajorVersion() {
-        return deploymentInfo.getMajorVersion();
+        return getDeploymentInfo().getMajorVersion();
     }
 
     @Override
     public int getEffectiveMinorVersion() {
-        return deploymentInfo.getMinorVersion();
+        return getDeploymentInfo().getMinorVersion();
     }
 
     @Override
@@ -260,7 +267,7 @@ public class ServletContextImpl implements ServletContext {
     public Set<String> getResourcePaths(final String path) {
         final Resource resource;
         try {
-            resource = deploymentInfo.getResourceManager().getResource(path);
+            resource = getDeploymentInfo().getResourceManager().getResource(path);
         } catch (IOException e) {
             return null;
         }
@@ -294,7 +301,7 @@ public class ServletContextImpl implements ServletContext {
         }
         Resource resource = null;
         try {
-            resource = deploymentInfo.getResourceManager().getResource(path);
+            resource = getDeploymentInfo().getResourceManager().getResource(path);
         } catch (IOException e) {
             return null;
         }
@@ -308,7 +315,7 @@ public class ServletContextImpl implements ServletContext {
     public InputStream getResourceAsStream(final String path) {
         Resource resource = null;
         try {
-            resource = deploymentInfo.getResourceManager().getResource(path);
+            resource = getDeploymentInfo().getResourceManager().getResource(path);
         } catch (IOException e) {
             return null;
         }
@@ -379,6 +386,7 @@ public class ServletContextImpl implements ServletContext {
         if (path == null) {
             return null;
         }
+        final DeploymentInfo deploymentInfo = getDeploymentInfo();
         String canonicalPath = CanonicalPathUtils.canonicalize(path);
         Resource resource;
         try {
@@ -414,7 +422,7 @@ public class ServletContextImpl implements ServletContext {
 
     @Override
     public String getServerInfo() {
-        return deploymentInfo.getServerName() + " - " + Version.getVersionString();
+        return getDeploymentInfo().getServerName() + " - " + Version.getVersionString();
     }
 
     @Override
@@ -422,12 +430,12 @@ public class ServletContextImpl implements ServletContext {
         if (name == null) {
             throw UndertowServletMessages.MESSAGES.nullName();
         }
-        return deploymentInfo.getInitParameters().get(name);
+        return getDeploymentInfo().getInitParameters().get(name);
     }
 
     @Override
     public Enumeration<String> getInitParameterNames() {
-        return new IteratorEnumeration<>(deploymentInfo.getInitParameters().keySet().iterator());
+        return new IteratorEnumeration<>(getDeploymentInfo().getInitParameters().keySet().iterator());
     }
 
     @Override
@@ -435,10 +443,10 @@ public class ServletContextImpl implements ServletContext {
         if(name == null) {
             throw UndertowServletMessages.MESSAGES.paramCannotBeNullNPE("name");
         }
-        if (deploymentInfo.getInitParameters().containsKey(name)) {
+        if (getDeploymentInfo().getInitParameters().containsKey(name)) {
             return false;
         }
-        deploymentInfo.addInitParameter(name, value);
+        getDeploymentInfo().addInitParameter(name, value);
         return true;
     }
 
@@ -487,7 +495,7 @@ public class ServletContextImpl implements ServletContext {
 
     @Override
     public String getServletContextName() {
-        return deploymentInfo.getDisplayName();
+        return getDeploymentInfo().getDisplayName();
     }
 
     @Override
@@ -500,6 +508,7 @@ public class ServletContextImpl implements ServletContext {
         ensureNotInitialized();
         ensureServletNameNotNull(servletName);
         try {
+            final DeploymentInfo deploymentInfo = getDeploymentInfo();
             if (deploymentInfo.getServlets().containsKey(servletName)) {
                 return null;
             }
@@ -508,7 +517,7 @@ public class ServletContextImpl implements ServletContext {
             for(HandlerWrapper i : wrappers) {
                 servlet.addHandlerChainWrapper(i);
             }
-            readServletAnnotations(servlet);
+            readServletAnnotations(servlet, deploymentInfo);
             deploymentInfo.addServlet(servlet);
             ServletHandler handler = deployment.getServlets().addServlet(servlet);
             return new ServletRegistrationImpl(servlet, handler.getManagedServlet(), deployment);
@@ -524,11 +533,12 @@ public class ServletContextImpl implements ServletContext {
         ensureNotProgramaticListener();
         ensureNotInitialized();
         ensureServletNameNotNull(servletName);
+        final DeploymentInfo deploymentInfo = getDeploymentInfo();
         if (deploymentInfo.getServlets().containsKey(servletName)) {
             return null;
         }
         ServletInfo s = new ServletInfo(servletName, servlet.getClass(), new ImmediateInstanceFactory<>(servlet));
-        readServletAnnotations(s);
+        readServletAnnotations(s, deploymentInfo);
         deploymentInfo.addServlet(s);
         ServletHandler handler = deployment.getServlets().addServlet(s);
         return new ServletRegistrationImpl(s, handler.getManagedServlet(), deployment);
@@ -539,12 +549,13 @@ public class ServletContextImpl implements ServletContext {
         ensureNotProgramaticListener();
         ensureNotInitialized();
         ensureServletNameNotNull(servletName);
+        final DeploymentInfo deploymentInfo = getDeploymentInfo();
         if (deploymentInfo.getServlets().containsKey(servletName)) {
             return null;
         }
         try {
             ServletInfo servlet = new ServletInfo(servletName, servletClass, deploymentInfo.getClassIntrospecter().createInstanceFactory(servletClass));
-            readServletAnnotations(servlet);
+            readServletAnnotations(servlet, deploymentInfo);
             deploymentInfo.addServlet(servlet);
             ServletHandler handler = deployment.getServlets().addServlet(servlet);
             return new ServletRegistrationImpl(servlet, handler.getManagedServlet(), deployment);
@@ -563,7 +574,7 @@ public class ServletContextImpl implements ServletContext {
     public <T extends Servlet> T createServlet(final Class<T> clazz) throws ServletException {
         ensureNotProgramaticListener();
         try {
-            return deploymentInfo.getClassIntrospecter().createInstanceFactory(clazz).createInstance().getInstance();
+            return getDeploymentInfo().getClassIntrospecter().createInstanceFactory(clazz).createInstance().getInstance();
         } catch (Exception e) {
             throw UndertowServletMessages.MESSAGES.couldNotInstantiateComponent(clazz.getName(), e);
         }
@@ -593,6 +604,7 @@ public class ServletContextImpl implements ServletContext {
     public FilterRegistration.Dynamic addFilter(final String filterName, final String className) {
         ensureNotProgramaticListener();
         ensureNotInitialized();
+        final DeploymentInfo deploymentInfo = getDeploymentInfo();
         if (deploymentInfo.getFilters().containsKey(filterName)) {
             return null;
         }
@@ -613,7 +625,7 @@ public class ServletContextImpl implements ServletContext {
     public FilterRegistration.Dynamic addFilter(final String filterName, final Filter filter) {
         ensureNotProgramaticListener();
         ensureNotInitialized();
-
+        final DeploymentInfo deploymentInfo = getDeploymentInfo();
         if (deploymentInfo.getFilters().containsKey(filterName)) {
             return null;
         }
@@ -628,6 +640,7 @@ public class ServletContextImpl implements ServletContext {
     public FilterRegistration.Dynamic addFilter(final String filterName, final Class<? extends Filter> filterClass) {
         ensureNotProgramaticListener();
         ensureNotInitialized();
+        final DeploymentInfo deploymentInfo = getDeploymentInfo();
         if (deploymentInfo.getFilters().containsKey(filterName)) {
             return null;
         }
@@ -645,7 +658,7 @@ public class ServletContextImpl implements ServletContext {
     public <T extends Filter> T createFilter(final Class<T> clazz) throws ServletException {
         ensureNotProgramaticListener();
         try {
-            return deploymentInfo.getClassIntrospecter().createInstanceFactory(clazz).createInstance().getInstance();
+            return getDeploymentInfo().getClassIntrospecter().createInstanceFactory(clazz).createInstance().getInstance();
         } catch (Exception e) {
             throw UndertowServletMessages.MESSAGES.couldNotInstantiateComponent(clazz.getName(), e);
         }
@@ -654,7 +667,7 @@ public class ServletContextImpl implements ServletContext {
     @Override
     public FilterRegistration getFilterRegistration(final String filterName) {
         ensureNotProgramaticListener();
-        final FilterInfo filterInfo = deploymentInfo.getFilters().get(filterName);
+        final FilterInfo filterInfo = getDeploymentInfo().getFilters().get(filterName);
         if (filterInfo == null) {
             return null;
         }
@@ -665,7 +678,7 @@ public class ServletContextImpl implements ServletContext {
     public Map<String, ? extends FilterRegistration> getFilterRegistrations() {
         ensureNotProgramaticListener();
         final Map<String, FilterRegistration> ret = new HashMap<>();
-        for (Map.Entry<String, FilterInfo> entry : deploymentInfo.getFilters().entrySet()) {
+        for (Map.Entry<String, FilterInfo> entry : getDeploymentInfo().getFilters().entrySet()) {
             ret.put(entry.getKey(), new FilterRegistrationImpl(entry.getValue(), deployment, this));
         }
         return ret;
@@ -703,7 +716,7 @@ public class ServletContextImpl implements ServletContext {
     @Override
     public void addListener(final String className) {
         try {
-            Class<? extends EventListener> clazz = (Class<? extends EventListener>) deploymentInfo.getClassLoader().loadClass(className);
+            Class<? extends EventListener> clazz = (Class<? extends EventListener>) getDeploymentInfo().getClassLoader().loadClass(className);
             addListener(clazz);
         } catch (ClassNotFoundException e) {
             throw new IllegalArgumentException(e);
@@ -719,7 +732,7 @@ public class ServletContextImpl implements ServletContext {
             throw UndertowServletMessages.MESSAGES.cannotAddServletContextListener();
         }
         ListenerInfo listener = new ListenerInfo(t.getClass(), new ImmediateInstanceFactory<EventListener>(t));
-        deploymentInfo.addListener(listener);
+        getDeploymentInfo().addListener(listener);
         deployment.getApplicationListeners().addListener(new ManagedListener(listener, true));
     }
 
@@ -731,6 +744,7 @@ public class ServletContextImpl implements ServletContext {
                 && ServletContextListener.class.isAssignableFrom(listenerClass)) {
             throw UndertowServletMessages.MESSAGES.cannotAddServletContextListener();
         }
+        final DeploymentInfo deploymentInfo = getDeploymentInfo();
         InstanceFactory<? extends EventListener> factory = null;
         try {
             factory = deploymentInfo.getClassIntrospecter().createInstanceFactory(listenerClass);
@@ -749,7 +763,7 @@ public class ServletContextImpl implements ServletContext {
             throw UndertowServletMessages.MESSAGES.listenerMustImplementListenerClass(clazz);
         }
         try {
-            return deploymentInfo.getClassIntrospecter().createInstanceFactory(clazz).createInstance().getInstance();
+            return getDeploymentInfo().getClassIntrospecter().createInstanceFactory(clazz).createInstance().getInstance();
         } catch (Exception e) {
             throw UndertowServletMessages.MESSAGES.couldNotInstantiateComponent(clazz.getName(), e);
         }
@@ -757,12 +771,12 @@ public class ServletContextImpl implements ServletContext {
 
     @Override
     public JspConfigDescriptor getJspConfigDescriptor() {
-        return deploymentInfo.getJspConfigDescriptor();
+        return getDeploymentInfo().getJspConfigDescriptor();
     }
 
     @Override
     public ClassLoader getClassLoader() {
-        return deploymentInfo.getClassLoader();
+        return getDeploymentInfo().getClassLoader();
     }
 
     @Override
@@ -796,6 +810,7 @@ public class ServletContextImpl implements ServletContext {
 
     @Override
     public String getRequestCharacterEncoding() {
+        final DeploymentInfo deploymentInfo = getDeploymentInfo();
         String enconding = deploymentInfo.getDefaultRequestEncoding();
         if(enconding != null) {
             return enconding;
@@ -807,11 +822,12 @@ public class ServletContextImpl implements ServletContext {
     public void setRequestCharacterEncoding(String encoding) {
         ensureNotInitialized();
         ensureNotProgramaticListener();
-        deploymentInfo.setDefaultRequestEncoding(encoding);
+        getDeploymentInfo().setDefaultRequestEncoding(encoding);
     }
 
     @Override
     public String getResponseCharacterEncoding() {
+        final DeploymentInfo deploymentInfo = getDeploymentInfo();
         String enconding = deploymentInfo.getDefaultResponseEncoding();
         if(enconding != null) {
             return enconding;
@@ -823,7 +839,7 @@ public class ServletContextImpl implements ServletContext {
     public void setResponseCharacterEncoding(String encoding) {
         ensureNotInitialized();
         ensureNotProgramaticListener();
-        deploymentInfo.setDefaultResponseEncoding(encoding);
+        getDeploymentInfo().setDefaultResponseEncoding(encoding);
     }
 
     @Override
@@ -909,7 +925,7 @@ public class ServletContextImpl implements ServletContext {
                         exchange.putAttachment(sessionAttachmentKey, httpSession);
                     }
                 } else if (existing != null) {
-                    if(deploymentInfo.isCheckOtherSessionManagers()) {
+                    if(getDeploymentInfo().isCheckOtherSessionManagers()) {
                         boolean found = false;
                         for (String deploymentName : deployment.getServletContainer().listDeployments()) {
                             DeploymentManager deployment = this.deployment.getServletContainer().getDeployment(deploymentName);
@@ -990,7 +1006,7 @@ public class ServletContextImpl implements ServletContext {
         deploymentInfo = null;
     }
 
-    private void readServletAnnotations(ServletInfo servlet) {
+    private void readServletAnnotations(ServletInfo servlet, DeploymentInfo deploymentInfo) {
         if (System.getSecurityManager() == null) {
             new ReadServletAnnotationsTask(servlet, deploymentInfo).run();
         } else {


=====================================
spotbugs-exclude.xml
=====================================
@@ -300,4 +300,12 @@
         <Class name="io.undertow.servlet.spec.HttpServletResponseImpl"/>
         <Method name="addCookie"/>
     </Match>
+    <!-- UNDERTOW-1839: we don't want to increase contention to synchronize all blocks that access the fields:
+         engine, invokingReadListenerHandshake, readListenerInvocationCount. The less contention the better,
+         the goal of the new synchronized blocks is to prevent writing to buffers that are being released
+         by another thread -->
+    <Match>
+        <Bug pattern="IS2_INCONSISTENT_SYNC"/>
+        <Class name="io.undertow.protocols.ssl.SslConduit"/>
+    </Match>
 </FindBugsFilter>


=====================================
websockets-jsr/pom.xml
=====================================
@@ -25,12 +25,12 @@
     <parent>
         <groupId>io.undertow</groupId>
         <artifactId>undertow-parent</artifactId>
-        <version>2.2.3.Final</version>
+        <version>2.2.4.Final</version>
     </parent>
 
     <groupId>io.undertow</groupId>
     <artifactId>undertow-websockets-jsr</artifactId>
-    <version>2.2.3.Final</version>
+    <version>2.2.4.Final</version>
 
     <name>Undertow WebSockets JSR356 implementations</name>
 



View it on GitLab: https://salsa.debian.org/java-team/undertow/-/commit/bfdba6f0b2b9ce36d627a86f5ca530f16beda6d6

-- 
View it on GitLab: https://salsa.debian.org/java-team/undertow/-/commit/bfdba6f0b2b9ce36d627a86f5ca530f16beda6d6
You're receiving this email because of your account on salsa.debian.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/pkg-java-commits/attachments/20210212/774fec9e/attachment.html>


More information about the pkg-java-commits mailing list