You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tomee.apache.org by rz...@apache.org on 2024/03/31 08:19:12 UTC

(tomee) branch amq6 created (now 7326aedf7d)

This is an automated email from the ASF dual-hosted git repository.

rzo1 pushed a change to branch amq6
in repository https://gitbox.apache.org/repos/asf/tomee.git


      at 7326aedf7d Tomcat 10.1.20 (and drop patched DefaultServlet as the changes should already be in Tomcat itself)

This branch includes the following new commits:

     new a67b57bcc5 AMQ6 Fileupload 2 Drop related shades
     new 7326aedf7d Tomcat 10.1.20 (and drop patched DefaultServlet as the changes should already be in Tomcat itself)

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



(tomee) 01/02: AMQ6 Fileupload 2 Drop related shades

Posted by rz...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rzo1 pushed a commit to branch amq6
in repository https://gitbox.apache.org/repos/asf/tomee.git

commit a67b57bcc5a6296adc9bede25e62357bf118c2e1
Author: Richard Zowalla <rz...@apache.org>
AuthorDate: Sun Mar 31 10:10:58 2024 +0200

    AMQ6
    Fileupload 2
    Drop related shades
---
 arquillian/arquillian-tomee-tests/pom.xml          |   8 +-
 boms/tomee-plume/pom.xml                           |  98 ++++++---------
 boms/tomee-plus/pom.xml                            | 101 +---------------
 container/openejb-core/pom.xml                     |   8 +-
 deps/activemq-broker-shade/pom.xml                 | 125 -------------------
 deps/activemq-kahadb-store-shade/pom.xml           | 131 --------------------
 deps/activemq-ra-shade/pom.xml                     | 134 ---------------------
 deps/commons-fileupload-shade/pom.xml              | 109 -----------------
 deps/pom.xml                                       |   4 -
 examples/client-resource-lookup-preview/pom.xml    |   6 +-
 itests/openejb-itests-client/pom.xml               |   4 +-
 pom.xml                                            |  58 +++------
 server/openejb-activemq/pom.xml                    |   4 +-
 server/openejb-http/pom.xml                        |  10 +-
 .../server/httpd/part/CommonsFileUploadPart.java   |  12 +-
 .../httpd/part/CommonsFileUploadPartFactory.java   |  25 ++--
 tck/cdi-embedded/pom.xml                           |   8 +-
 .../src/main/assembly/war.xml                      |   4 -
 tomee/tomee-plume-webapp/pom.xml                   |   8 +-
 tomee/tomee-plume-webapp/src/main/assembly/war.xml |   4 -
 tomee/tomee-plus-webapp/pom.xml                    |   8 +-
 tomee/tomee-plus-webapp/src/main/assembly/war.xml  |   4 -
 tomee/tomee-webapp/src/main/assembly/war.xml       |   4 -
 23 files changed, 111 insertions(+), 766 deletions(-)

diff --git a/arquillian/arquillian-tomee-tests/pom.xml b/arquillian/arquillian-tomee-tests/pom.xml
index 56139bdcf7..fc7d983341 100644
--- a/arquillian/arquillian-tomee-tests/pom.xml
+++ b/arquillian/arquillian-tomee-tests/pom.xml
@@ -122,12 +122,12 @@
 
     <!-- ActiveMQ is optional in openejb-core -->
     <dependency>
-      <groupId>${project.groupId}</groupId>
-      <artifactId>activemq-ra-shade</artifactId>
+      <groupId>org.apache.activemq</groupId>
+      <artifactId>activemq-ra</artifactId>
     </dependency>
     <dependency>
-      <groupId>${project.groupId}</groupId>
-      <artifactId>activemq-broker-shade</artifactId>
+      <groupId>org.apache.activemq</groupId>
+      <artifactId>activemq-broker</artifactId>
     </dependency>
     <dependency>
       <groupId>org.apache.activemq</groupId>
diff --git a/boms/tomee-plume/pom.xml b/boms/tomee-plume/pom.xml
index 72ee26a1a5..651f82de18 100644
--- a/boms/tomee-plume/pom.xml
+++ b/boms/tomee-plume/pom.xml
@@ -188,17 +188,6 @@
         </exclusion>
       </exclusions>
     </dependency>
-    <dependency>
-      <groupId>commons-net</groupId>
-      <artifactId>commons-net</artifactId>
-      <version>3.8.0</version>
-      <exclusions>
-        <exclusion>
-          <artifactId>*</artifactId>
-          <groupId>*</groupId>
-        </exclusion>
-      </exclusions>
-    </dependency>
     <dependency>
       <groupId>io.churchkey</groupId>
       <artifactId>churchkey</artifactId>
@@ -486,9 +475,9 @@
       </exclusions>
     </dependency>
     <dependency>
-      <groupId>javax.activation</groupId>
-      <artifactId>javax.activation-api</artifactId>
-      <version>1.2.0</version>
+      <groupId>net.shibboleth.utilities</groupId>
+      <artifactId>java-support</artifactId>
+      <version>8.4.0</version>
       <exclusions>
         <exclusion>
           <artifactId>*</artifactId>
@@ -497,9 +486,9 @@
       </exclusions>
     </dependency>
     <dependency>
-      <groupId>javax.xml.bind</groupId>
-      <artifactId>jaxb-api</artifactId>
-      <version>2.3.1</version>
+      <groupId>org.apache.activemq.protobuf</groupId>
+      <artifactId>activemq-protobuf</artifactId>
+      <version>1.1</version>
       <exclusions>
         <exclusion>
           <artifactId>*</artifactId>
@@ -508,9 +497,9 @@
       </exclusions>
     </dependency>
     <dependency>
-      <groupId>net.shibboleth.utilities</groupId>
-      <artifactId>java-support</artifactId>
-      <version>8.4.0</version>
+      <groupId>org.apache.activemq</groupId>
+      <artifactId>activemq-broker</artifactId>
+      <version>6.1.0</version>
       <exclusions>
         <exclusion>
           <artifactId>*</artifactId>
@@ -519,9 +508,9 @@
       </exclusions>
     </dependency>
     <dependency>
-      <groupId>org.apache.activemq.protobuf</groupId>
-      <artifactId>activemq-protobuf</artifactId>
-      <version>1.1</version>
+      <groupId>org.apache.activemq</groupId>
+      <artifactId>activemq-client</artifactId>
+      <version>6.1.0</version>
       <exclusions>
         <exclusion>
           <artifactId>*</artifactId>
@@ -531,8 +520,8 @@
     </dependency>
     <dependency>
       <groupId>org.apache.activemq</groupId>
-      <artifactId>activemq-client-jakarta</artifactId>
-      <version>5.18.3</version>
+      <artifactId>activemq-jdbc-store</artifactId>
+      <version>6.1.0</version>
       <exclusions>
         <exclusion>
           <artifactId>*</artifactId>
@@ -542,8 +531,30 @@
     </dependency>
     <dependency>
       <groupId>org.apache.activemq</groupId>
-      <artifactId>activemq-jdbc-store</artifactId>
-      <version>5.18.3</version>
+      <artifactId>activemq-kahadb-store</artifactId>
+      <version>6.1.0</version>
+      <exclusions>
+        <exclusion>
+          <artifactId>*</artifactId>
+          <groupId>*</groupId>
+        </exclusion>
+      </exclusions>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.activemq</groupId>
+      <artifactId>activemq-openwire-legacy</artifactId>
+      <version>6.1.0</version>
+      <exclusions>
+        <exclusion>
+          <artifactId>*</artifactId>
+          <groupId>*</groupId>
+        </exclusion>
+      </exclusions>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.activemq</groupId>
+      <artifactId>activemq-ra</artifactId>
+      <version>6.1.0</version>
       <exclusions>
         <exclusion>
           <artifactId>*</artifactId>
@@ -1300,39 +1311,6 @@
         </exclusion>
       </exclusions>
     </dependency>
-    <dependency>
-      <groupId>org.apache.tomee</groupId>
-      <artifactId>activemq-broker-shade</artifactId>
-      <version>10.0.0-M1-SNAPSHOT</version>
-      <exclusions>
-        <exclusion>
-          <artifactId>*</artifactId>
-          <groupId>*</groupId>
-        </exclusion>
-      </exclusions>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.tomee</groupId>
-      <artifactId>activemq-kahadb-store-shade</artifactId>
-      <version>10.0.0-M1-SNAPSHOT</version>
-      <exclusions>
-        <exclusion>
-          <artifactId>*</artifactId>
-          <groupId>*</groupId>
-        </exclusion>
-      </exclusions>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.tomee</groupId>
-      <artifactId>activemq-ra-shade</artifactId>
-      <version>10.0.0-M1-SNAPSHOT</version>
-      <exclusions>
-        <exclusion>
-          <artifactId>*</artifactId>
-          <groupId>*</groupId>
-        </exclusion>
-      </exclusions>
-    </dependency>
     <dependency>
       <groupId>org.apache.tomee</groupId>
       <artifactId>commons-dbcp2-shade</artifactId>
diff --git a/boms/tomee-plus/pom.xml b/boms/tomee-plus/pom.xml
index cf1c493345..fdb9897392 100644
--- a/boms/tomee-plus/pom.xml
+++ b/boms/tomee-plus/pom.xml
@@ -188,17 +188,6 @@
         </exclusion>
       </exclusions>
     </dependency>
-    <dependency>
-      <groupId>commons-net</groupId>
-      <artifactId>commons-net</artifactId>
-      <version>3.8.0</version>
-      <exclusions>
-        <exclusion>
-          <artifactId>*</artifactId>
-          <groupId>*</groupId>
-        </exclusion>
-      </exclusions>
-    </dependency>
     <dependency>
       <groupId>io.churchkey</groupId>
       <artifactId>churchkey</artifactId>
@@ -485,28 +474,6 @@
         </exclusion>
       </exclusions>
     </dependency>
-    <dependency>
-      <groupId>javax.activation</groupId>
-      <artifactId>javax.activation-api</artifactId>
-      <version>1.2.0</version>
-      <exclusions>
-        <exclusion>
-          <artifactId>*</artifactId>
-          <groupId>*</groupId>
-        </exclusion>
-      </exclusions>
-    </dependency>
-    <dependency>
-      <groupId>javax.xml.bind</groupId>
-      <artifactId>jaxb-api</artifactId>
-      <version>2.3.1</version>
-      <exclusions>
-        <exclusion>
-          <artifactId>*</artifactId>
-          <groupId>*</groupId>
-        </exclusion>
-      </exclusions>
-    </dependency>
     <dependency>
       <groupId>net.shibboleth.utilities</groupId>
       <artifactId>java-support</artifactId>
@@ -518,32 +485,10 @@
         </exclusion>
       </exclusions>
     </dependency>
-    <dependency>
-      <groupId>org.apache.activemq.protobuf</groupId>
-      <artifactId>activemq-protobuf</artifactId>
-      <version>1.1</version>
-      <exclusions>
-        <exclusion>
-          <artifactId>*</artifactId>
-          <groupId>*</groupId>
-        </exclusion>
-      </exclusions>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.activemq</groupId>
-      <artifactId>activemq-client-jakarta</artifactId>
-      <version>5.18.3</version>
-      <exclusions>
-        <exclusion>
-          <artifactId>*</artifactId>
-          <groupId>*</groupId>
-        </exclusion>
-      </exclusions>
-    </dependency>
     <dependency>
       <groupId>org.apache.activemq</groupId>
       <artifactId>activemq-jdbc-store</artifactId>
-      <version>5.18.3</version>
+      <version>6.1.0</version>
       <exclusions>
         <exclusion>
           <artifactId>*</artifactId>
@@ -1322,39 +1267,6 @@
         </exclusion>
       </exclusions>
     </dependency>
-    <dependency>
-      <groupId>org.apache.tomee</groupId>
-      <artifactId>activemq-broker-shade</artifactId>
-      <version>10.0.0-M1-SNAPSHOT</version>
-      <exclusions>
-        <exclusion>
-          <artifactId>*</artifactId>
-          <groupId>*</groupId>
-        </exclusion>
-      </exclusions>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.tomee</groupId>
-      <artifactId>activemq-kahadb-store-shade</artifactId>
-      <version>10.0.0-M1-SNAPSHOT</version>
-      <exclusions>
-        <exclusion>
-          <artifactId>*</artifactId>
-          <groupId>*</groupId>
-        </exclusion>
-      </exclusions>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.tomee</groupId>
-      <artifactId>activemq-ra-shade</artifactId>
-      <version>10.0.0-M1-SNAPSHOT</version>
-      <exclusions>
-        <exclusion>
-          <artifactId>*</artifactId>
-          <groupId>*</groupId>
-        </exclusion>
-      </exclusions>
-    </dependency>
     <dependency>
       <groupId>org.apache.tomee</groupId>
       <artifactId>commons-dbcp2-shade</artifactId>
@@ -2125,17 +2037,6 @@
         </exclusion>
       </exclusions>
     </dependency>
-    <dependency>
-      <groupId>org.fusesource.hawtbuf</groupId>
-      <artifactId>hawtbuf</artifactId>
-      <version>1.11</version>
-      <exclusions>
-        <exclusion>
-          <artifactId>*</artifactId>
-          <groupId>*</groupId>
-        </exclusion>
-      </exclusions>
-    </dependency>
     <dependency>
       <groupId>org.glassfish.jaxb</groupId>
       <artifactId>jaxb-core</artifactId>
diff --git a/container/openejb-core/pom.xml b/container/openejb-core/pom.xml
index 614ac4cc04..6e04f81a36 100644
--- a/container/openejb-core/pom.xml
+++ b/container/openejb-core/pom.xml
@@ -512,13 +512,13 @@
 
     <!-- ActiveMQ -->
     <dependency>
-      <groupId>${project.groupId}</groupId>
-      <artifactId>activemq-ra-shade</artifactId>
+      <groupId>org.apache.activemq</groupId>
+      <artifactId>activemq-ra</artifactId>
       <optional>true</optional>
     </dependency>
     <dependency>
-      <groupId>${project.groupId}</groupId>
-      <artifactId>activemq-broker-shade</artifactId>
+      <groupId>org.apache.activemq</groupId>
+      <artifactId>activemq-broker</artifactId>
       <optional>true</optional>
     </dependency>
     <dependency>
diff --git a/deps/activemq-broker-shade/pom.xml b/deps/activemq-broker-shade/pom.xml
deleted file mode 100644
index 6658239cbd..0000000000
--- a/deps/activemq-broker-shade/pom.xml
+++ /dev/null
@@ -1,125 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-
-    Licensed to the Apache Software Foundation (ASF) under one or more
-    contributor license agreements.  See the NOTICE file distributed with
-    this work for additional information regarding copyright ownership.
-    The ASF licenses this file to You under the Apache License, Version 2.0
-    (the "License"); you may not use this file except in compliance with
-    the License.  You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
--->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-  <parent>
-    <artifactId>deps</artifactId>
-    <groupId>org.apache.tomee</groupId>
-    <version>10.0.0-M1-SNAPSHOT</version>
-  </parent>
-  <modelVersion>4.0.0</modelVersion>
-
-  <artifactId>activemq-broker-shade</artifactId>
-  <name>TomEE :: Deps :: Apache ActiveMQ Broker shade</name>
-
-  <dependencies>
-    <dependency>
-      <groupId>org.apache.activemq</groupId>
-      <artifactId>activemq-broker</artifactId>
-      <version>${version.activemq}</version>
-      <exclusions>
-        <exclusion>
-          <groupId>org.apache.activemq</groupId>
-          <artifactId>activemq-client</artifactId>
-        </exclusion>
-      </exclusions>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.activemq</groupId>
-      <artifactId>activemq-client-jakarta</artifactId>
-    </dependency>
-  </dependencies>
-
-  <build>
-    <plugins>
-      <plugin>
-        <groupId>org.apache.maven.plugins</groupId>
-        <artifactId>maven-shade-plugin</artifactId>
-        <version>3.2.4</version>
-        <executions>
-          <execution>
-            <phase>package</phase>
-            <goals>
-              <goal>shade</goal>
-            </goals>
-            <configuration>
-              <createSourcesJar>true</createSourcesJar>
-              <useBaseVersion>true</useBaseVersion>
-              <createDependencyReducedPom>false</createDependencyReducedPom>
-              <artifactSet>
-                <includes>
-                  <include>org.apache.activemq:activemq-broker</include> <!-- only this dep to make sure we don't add other things -->
-                </includes>
-              </artifactSet>
-              <transformers>
-                <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer" />
-              </transformers>
-              <relocations>
-                <relocation>
-                  <pattern>javax.annotation</pattern>
-                  <shadedPattern>jakarta.annotation</shadedPattern>
-                  <excludes>
-                    <exclude>javax.annotation.processing.**</exclude>
-                  </excludes>
-                </relocation>
-                <relocation>
-                  <pattern>javax.jms</pattern>
-                  <shadedPattern>jakarta.jms</shadedPattern>
-                </relocation>
-              </relocations>
-            </configuration>
-          </execution>
-        </executions>
-      </plugin>
-      <plugin>
-        <!--
-        Purpose of build-helper-maven-plugin is to ensure that IntelliJ sees shaded classes.
-        When navigating over to java classes in importing modules, the shaded imported classes will
-        show as resolved instead of unknown.
-        The artifact specified below is created when this module is built but is also used to resolve classes in IntelliJ.
-        "phase" is set to "none" - with this setting, the artifact jar will not be uploaded to repo
-        when running standalone "mvn install" command.
-
-        build-helper-maven-plugin can be removed completely with no effect on the "mvn clean" and "mvn install",
-        which is handled by maven-shade-plugin.
-        -->
-        <groupId>org.codehaus.mojo</groupId>
-        <artifactId>build-helper-maven-plugin</artifactId>
-        <version>3.4.0</version>
-        <executions>
-          <execution>
-            <id>workaround-makeItVisibleOnIntellij</id>
-            <phase>none</phase>
-            <goals>
-              <goal>attach-artifact</goal>
-            </goals>
-            <configuration>
-              <artifacts>
-                <artifact>
-                  <file>${project.build.directory}/activemq-broker-shade-10.0.0-M1-SNAPSHOT.jar</file>
-                  <type>jar</type>
-                  <classifier>optional</classifier>
-                </artifact>
-              </artifacts>
-            </configuration>
-          </execution>
-        </executions>
-      </plugin>
-    </plugins>
-  </build>
-</project>
diff --git a/deps/activemq-kahadb-store-shade/pom.xml b/deps/activemq-kahadb-store-shade/pom.xml
deleted file mode 100644
index 4f5f3896fc..0000000000
--- a/deps/activemq-kahadb-store-shade/pom.xml
+++ /dev/null
@@ -1,131 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-
-    Licensed to the Apache Software Foundation (ASF) under one or more
-    contributor license agreements.  See the NOTICE file distributed with
-    this work for additional information regarding copyright ownership.
-    The ASF licenses this file to You under the Apache License, Version 2.0
-    (the "License"); you may not use this file except in compliance with
-    the License.  You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
--->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-  <parent>
-    <artifactId>deps</artifactId>
-    <groupId>org.apache.tomee</groupId>
-    <version>10.0.0-M1-SNAPSHOT</version>
-  </parent>
-  <modelVersion>4.0.0</modelVersion>
-
-  <artifactId>activemq-kahadb-store-shade</artifactId>
-  <name>TomEE :: Deps :: Apache ActiveMQ KahaDB Store shade</name>
-
-  <dependencies>
-    <dependency>
-      <groupId>org.apache.activemq</groupId>
-      <artifactId>activemq-kahadb-store</artifactId>
-      <version>${version.activemq}</version>
-      <exclusions>
-        <exclusion>
-          <groupId>org.apache.activemq</groupId>
-          <artifactId>activemq-broker</artifactId>
-        </exclusion>
-        <exclusion>
-          <groupId>org.apache.geronimo.specs</groupId>
-          <artifactId>*</artifactId>
-        </exclusion>
-      </exclusions>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.tomee</groupId>
-      <artifactId>activemq-broker-shade</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>commons-net</groupId>
-      <artifactId>commons-net</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.activemq.protobuf</groupId>
-      <artifactId>activemq-protobuf</artifactId>
-      <version>1.1</version>
-    </dependency>
-  </dependencies>
-
-  <build>
-    <plugins>
-      <plugin>
-        <groupId>org.apache.maven.plugins</groupId>
-        <artifactId>maven-shade-plugin</artifactId>
-        <version>3.2.4</version>
-        <executions>
-          <execution>
-            <phase>package</phase>
-            <goals>
-              <goal>shade</goal>
-            </goals>
-            <configuration>
-              <createSourcesJar>true</createSourcesJar>
-              <useBaseVersion>true</useBaseVersion>
-              <createDependencyReducedPom>false</createDependencyReducedPom>
-              <artifactSet>
-                <includes>
-                  <include>org.apache.activemq:activemq-kahadb-store</include> <!-- only this dep to make sure we don't add other things -->
-                </includes>
-              </artifactSet>
-              <transformers>
-                <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer" />
-              </transformers>
-              <relocations>
-                <relocation>
-                  <pattern>javax.jms</pattern>
-                  <shadedPattern>jakarta.jms</shadedPattern>
-                </relocation>
-              </relocations>
-            </configuration>
-          </execution>
-        </executions>
-      </plugin>
-      <plugin>
-        <!--
-        Purpose of build-helper-maven-plugin is to ensure that IntelliJ sees shaded classes.
-        When navigating over to java classes in importing modules, the shaded imported classes will
-        show as resolved instead of unknown.
-        The artifact specified below is created when this module is built but is also used to resolve classes in IntelliJ.
-        "phase" is set to "none" - with this setting, the artifact jar will not be uploaded to repo
-        when running standalone "mvn install" command.
-
-        build-helper-maven-plugin can be removed completely with no effect on the "mvn clean" and "mvn install",
-        which is handled by maven-shade-plugin.
-        -->
-        <groupId>org.codehaus.mojo</groupId>
-        <artifactId>build-helper-maven-plugin</artifactId>
-        <version>3.4.0</version>
-        <executions>
-          <execution>
-            <id>workaround-makeItVisibleOnIntellij</id>
-            <phase>none</phase>
-            <goals>
-              <goal>attach-artifact</goal>
-            </goals>
-            <configuration>
-              <artifacts>
-                <artifact>
-                  <file>${project.build.directory}/activemq-kahadb-store-shade-10.0.0-M1-SNAPSHOT.jar</file>
-                  <type>jar</type>
-                  <classifier>optional</classifier>
-                </artifact>
-              </artifacts>
-            </configuration>
-          </execution>
-        </executions>
-      </plugin>
-    </plugins>
-  </build>
-</project>
diff --git a/deps/activemq-ra-shade/pom.xml b/deps/activemq-ra-shade/pom.xml
deleted file mode 100644
index 3df5169d07..0000000000
--- a/deps/activemq-ra-shade/pom.xml
+++ /dev/null
@@ -1,134 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-
-    Licensed to the Apache Software Foundation (ASF) under one or more
-    contributor license agreements.  See the NOTICE file distributed with
-    this work for additional information regarding copyright ownership.
-    The ASF licenses this file to You under the Apache License, Version 2.0
-    (the "License"); you may not use this file except in compliance with
-    the License.  You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
--->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-  <parent>
-    <artifactId>deps</artifactId>
-    <groupId>org.apache.tomee</groupId>
-    <version>10.0.0-M1-SNAPSHOT</version>
-  </parent>
-  <modelVersion>4.0.0</modelVersion>
-
-  <artifactId>activemq-ra-shade</artifactId>
-  <name>TomEE :: Deps :: Apache ActiveMQ RA shade</name>
-
-  <dependencies>
-    <dependency>
-      <groupId>org.apache.activemq</groupId>
-      <artifactId>activemq-ra</artifactId>
-      <version>${version.activemq}</version>
-      <exclusions>
-        <exclusion>
-          <groupId>org.apache.activemq</groupId>
-          <artifactId>activemq-broker</artifactId>
-        </exclusion>
-        <exclusion>
-          <groupId>org.apache.activemq</groupId>
-          <artifactId>activemq-kahadb-store</artifactId>
-        </exclusion>
-        <exclusion>
-          <groupId>org.apache.geronimo.specs</groupId>
-          <artifactId>*</artifactId>
-        </exclusion>
-      </exclusions>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.tomee</groupId>
-      <artifactId>activemq-broker-shade</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.tomee</groupId>
-      <artifactId>activemq-kahadb-store-shade</artifactId>
-    </dependency>
-  </dependencies>
-
-  <build>
-    <plugins>
-      <plugin>
-        <groupId>org.apache.maven.plugins</groupId>
-        <artifactId>maven-shade-plugin</artifactId>
-        <version>3.2.4</version>
-        <executions>
-          <execution>
-            <phase>package</phase>
-            <goals>
-              <goal>shade</goal>
-            </goals>
-            <configuration>
-              <createSourcesJar>true</createSourcesJar>
-              <useBaseVersion>true</useBaseVersion>
-              <createDependencyReducedPom>false</createDependencyReducedPom>
-              <artifactSet>
-                <includes>
-                  <include>org.apache.activemq:activemq-ra</include> <!-- only this dep to make sure we don't add other things -->
-                </includes>
-              </artifactSet>
-              <transformers>
-                <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer" />
-              </transformers>
-              <relocations>
-                <relocation>
-                  <pattern>javax.jms</pattern>
-                  <shadedPattern>jakarta.jms</shadedPattern>
-                </relocation>
-                <relocation>
-                  <pattern>javax.resource</pattern>
-                  <shadedPattern>jakarta.resource</shadedPattern>
-                </relocation>
-              </relocations>
-            </configuration>
-          </execution>
-        </executions>
-      </plugin>
-      <plugin>
-        <!--
-        Purpose of build-helper-maven-plugin is to ensure that IntelliJ sees shaded classes.
-        When navigating over to java classes in importing modules, the shaded imported classes will
-        show as resolved instead of unknown.
-        The artifact specified below is created when this module is built but is also used to resolve classes in IntelliJ.
-        "phase" is set to "none" - with this setting, the artifact jar will not be uploaded to repo
-        when running standalone "mvn install" command.
-
-        build-helper-maven-plugin can be removed completely with no effect on the "mvn clean" and "mvn install",
-        which is handled by maven-shade-plugin.
-        -->
-        <groupId>org.codehaus.mojo</groupId>
-        <artifactId>build-helper-maven-plugin</artifactId>
-        <version>3.4.0</version>
-        <executions>
-          <execution>
-            <id>workaround-makeItVisibleOnIntellij</id>
-            <phase>none</phase>
-            <goals>
-              <goal>attach-artifact</goal>
-            </goals>
-            <configuration>
-              <artifacts>
-                <artifact>
-                  <file>${project.build.directory}/activemq-ra-shade-10.0.0-M1-SNAPSHOT.jar</file>
-                  <type>jar</type>
-                  <classifier>optional</classifier>
-                </artifact>
-              </artifacts>
-            </configuration>
-          </execution>
-        </executions>
-      </plugin>
-    </plugins>
-  </build>
-</project>
diff --git a/deps/commons-fileupload-shade/pom.xml b/deps/commons-fileupload-shade/pom.xml
deleted file mode 100644
index 768ebc9dbc..0000000000
--- a/deps/commons-fileupload-shade/pom.xml
+++ /dev/null
@@ -1,109 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-
-    Licensed to the Apache Software Foundation (ASF) under one or more
-    contributor license agreements.  See the NOTICE file distributed with
-    this work for additional information regarding copyright ownership.
-    The ASF licenses this file to You under the Apache License, Version 2.0
-    (the "License"); you may not use this file except in compliance with
-    the License.  You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
--->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-  <parent>
-    <artifactId>deps</artifactId>
-    <groupId>org.apache.tomee</groupId>
-    <version>10.0.0-M1-SNAPSHOT</version>
-  </parent>
-  <modelVersion>4.0.0</modelVersion>
-
-  <artifactId>commons-fileupload-shade</artifactId>
-  <name>TomEE :: Deps :: Apache Commons FileUpload shade</name>
-
-  <dependencies>
-    <dependency>
-      <groupId>commons-fileupload</groupId>
-      <artifactId>commons-fileupload</artifactId>
-      <version>${version.commons-fileupload}</version>
-    </dependency>
-  </dependencies>
-
-  <build>
-    <plugins>
-      <plugin>
-        <groupId>org.apache.maven.plugins</groupId>
-        <artifactId>maven-shade-plugin</artifactId>
-        <version>3.2.4</version>
-        <executions>
-          <execution>
-            <phase>package</phase>
-            <goals>
-              <goal>shade</goal>
-            </goals>
-            <configuration>
-              <createSourcesJar>true</createSourcesJar>
-              <useBaseVersion>true</useBaseVersion>
-              <createDependencyReducedPom>false</createDependencyReducedPom>
-              <artifactSet>
-                <includes>
-                  <include>commons-fileupload:commons-fileupload</include> <!-- only this dep to make sure we don't add other things -->
-                </includes>
-              </artifactSet>
-              <transformers>
-                <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer" />
-              </transformers>
-              <relocations>
-                <relocation>
-                  <pattern>javax.servlet</pattern>
-                  <shadedPattern>jakarta.servlet</shadedPattern>
-                </relocation>
-              </relocations>
-            </configuration>
-          </execution>
-        </executions>
-      </plugin>
-
-      <plugin>
-        <!--
-        Purpose of build-helper-maven-plugin is to ensure that IntelliJ sees shaded classes.
-        When navigating over to java classes in importing modules, the shaded imported classes will
-        show as resolved instead of unknown.
-        The artifact specified below is created when this module is built but is also used to resolve classes in IntelliJ.
-        "phase" is set to "none" - with this setting, the artifact jar will not be uploaded to repo
-        when running standalone "mvn install" command.
-
-        build-helper-maven-plugin can be removed completely with no effect on the "mvn clean" and "mvn install",
-        which is handled by maven-shade-plugin.
-        -->
-        <groupId>org.codehaus.mojo</groupId>
-        <artifactId>build-helper-maven-plugin</artifactId>
-        <version>3.4.0</version>
-        <executions>
-          <execution>
-            <id>workaround-makeItVisibleOnIntellij</id>
-            <phase>none</phase>
-            <goals>
-              <goal>attach-artifact</goal>
-            </goals>
-            <configuration>
-              <artifacts>
-                <artifact>
-                  <file>${project.build.directory}/commons-fileupload-shade-10.0.0-M1-SNAPSHOT.jar</file>
-                  <type>jar</type>
-                  <classifier>optional</classifier>
-                </artifact>
-              </artifacts>
-            </configuration>
-          </execution>
-        </executions>
-      </plugin>
-    </plugins>
-  </build>
-</project>
diff --git a/deps/pom.xml b/deps/pom.xml
index 1e5a3b56df..8cd1acd172 100644
--- a/deps/pom.xml
+++ b/deps/pom.xml
@@ -30,11 +30,7 @@
   <modules>
     <module>taglibs-shade</module>
     <module>sxc-shade</module>
-    <module>activemq-broker-shade</module>
-    <module>activemq-kahadb-store-shade</module>
-    <module>activemq-ra-shade</module>
     <module>commons-dbcp2-shade</module>
-    <module>commons-fileupload-shade</module>
     <module>servicemix-bcel-shade</module>
   </modules>
   <build>
diff --git a/examples/client-resource-lookup-preview/pom.xml b/examples/client-resource-lookup-preview/pom.xml
index 7d478f7e50..7f87d3a408 100644
--- a/examples/client-resource-lookup-preview/pom.xml
+++ b/examples/client-resource-lookup-preview/pom.xml
@@ -67,9 +67,9 @@
       <version>10.0.0-M1-SNAPSHOT</version>
     </dependency>
     <dependency>
-      <groupId>org.apache.tomee</groupId>
-      <artifactId>activemq-broker-shade</artifactId>
-      <version>${project.version}</version>
+      <groupId>org.apache.activemq</groupId>
+      <artifactId>activemq-broker</artifactId>
+      <version>6.1.0</version>
       <scope>runtime</scope>
     </dependency>
     <!-- test deps -->
diff --git a/itests/openejb-itests-client/pom.xml b/itests/openejb-itests-client/pom.xml
index acffb02920..c56f5d00b5 100644
--- a/itests/openejb-itests-client/pom.xml
+++ b/itests/openejb-itests-client/pom.xml
@@ -99,8 +99,8 @@
       <optional>true</optional>
     </dependency>
     <dependency>
-      <groupId>${project.groupId}</groupId>
-      <artifactId>activemq-ra-shade</artifactId>
+      <groupId>org.apache.activemq</groupId>
+      <artifactId>activemq-ra</artifactId>
     </dependency>
     <dependency>
       <groupId>junit</groupId>
diff --git a/pom.xml b/pom.xml
index 7163c56a2c..dfdf45b3e9 100644
--- a/pom.xml
+++ b/pom.xml
@@ -162,12 +162,14 @@
     <version.commons-collections>3.2.2</version.commons-collections>
     <version.commons-dbcp2>2.11.0</version.commons-dbcp2>
     <version.commons-discovery>0.5</version.commons-discovery>
-    <version.commons-fileupload>1.5</version.commons-fileupload>
     <version.commons-io>2.15.0</version.commons-io>
     <version.commons-jcs-cache>2.1</version.commons-jcs-cache>
     <version.commons-lang3>3.13.0</version.commons-lang3>
     <version.commons-net>3.8.0</version.commons-net>
     <version.commons-pool>2.12.0</version.commons-pool>
+    <version.commons-fileupload>2.0.0-M2</version.commons-fileupload>
+    <version.commons-fileupload-servlet>2.0.0-M1</version.commons-fileupload-servlet>
+
 
     <!-- Java SE version -->
     <maven.compiler.source>11</maven.compiler.source>
@@ -208,7 +210,7 @@
     <!-- com.sun -->
     <version.impl.saaj>2.0.1</version.impl.saaj>
     <!-- org.apache -->
-    <version.activemq>5.18.3</version.activemq>
+    <version.activemq>6.1.0</version.activemq>
     <!-- downgrade to avoid a henn egg issue with batchee -->
     <version.batchee>1.0.4</version.batchee>
     <version.bval>3.0.0</version.bval>
@@ -1410,15 +1412,9 @@
         </exclusions>
       </dependency>
       <dependency>
-        <groupId>${project.groupId}</groupId>
-        <artifactId>activemq-ra-shade</artifactId>
-        <version>${project.version}</version>
-        <exclusions>
-          <exclusion>
-            <groupId>org.apache.activemq</groupId>
-            <artifactId>activemq-ra</artifactId>
-          </exclusion>
-        </exclusions>
+        <groupId>org.apache.activemq</groupId>
+        <artifactId>activemq-ra</artifactId>
+        <version>${version.activemq}</version>
       </dependency>
       <dependency>
         <groupId>commons-net</groupId>
@@ -1427,34 +1423,13 @@
       </dependency>
       <dependency>
         <groupId>org.apache.activemq</groupId>
-        <artifactId>activemq-client-jakarta</artifactId>
+        <artifactId>activemq-client</artifactId>
         <version>${version.activemq}</version>
       </dependency>
       <dependency>
-        <groupId>${project.groupId}</groupId>
-        <artifactId>activemq-kahadb-store-shade</artifactId>
-        <version>${project.version}</version>
-        <exclusions>
-          <exclusion>
-            <groupId>org.apache.activemq</groupId>
-            <artifactId>activemq-kahadb-store</artifactId>
-          </exclusion>
-        </exclusions>
-      </dependency>
-      <dependency>
-        <groupId>${project.groupId}</groupId>
-        <artifactId>activemq-broker-shade</artifactId>
-        <version>${project.version}</version>
-        <exclusions>
-          <exclusion>
-            <groupId>org.apache.activemq</groupId>
-            <artifactId>activemq-broker</artifactId>
-          </exclusion>
-          <exclusion>
-            <groupId>jakarta.jms</groupId>
-            <artifactId>jakarta.jms-api</artifactId>
-          </exclusion>
-        </exclusions>
+        <groupId>org.apache.activemq</groupId>
+        <artifactId>activemq-broker</artifactId>
+        <version>${version.activemq}</version>
       </dependency>
       <dependency>
         <groupId>org.apache.activemq</groupId>
@@ -1781,9 +1756,14 @@
         <version>${version.commons-codec}</version>
       </dependency>
       <dependency>
-        <groupId>${project.groupId}</groupId>
-        <artifactId>commons-fileupload-shade</artifactId>
-        <version>${project.version}</version>
+        <groupId>org.apache.commons</groupId>
+        <artifactId>commons-fileupload2-jakarta</artifactId>
+        <version>${version.commons-fileupload-servlet}</version>
+      </dependency>
+      <dependency>
+        <groupId>org.apache.commons</groupId>
+        <artifactId>commons-fileupload2-core</artifactId>
+        <version>${version.commons-fileupload}</version>
       </dependency>
       <dependency>
         <groupId>regexp</groupId>
diff --git a/server/openejb-activemq/pom.xml b/server/openejb-activemq/pom.xml
index 1bb51eec08..0c785600d7 100644
--- a/server/openejb-activemq/pom.xml
+++ b/server/openejb-activemq/pom.xml
@@ -38,8 +38,8 @@
       <version>${project.version}</version>
     </dependency>
     <dependency>
-      <groupId>${project.groupId}</groupId>
-      <artifactId>activemq-ra-shade</artifactId>
+      <groupId>org.apache.activemq</groupId>
+      <artifactId>activemq-ra</artifactId>
     </dependency>
     <dependency>
       <groupId>junit</groupId>
diff --git a/server/openejb-http/pom.xml b/server/openejb-http/pom.xml
index 22827f2807..1fefa4294d 100644
--- a/server/openejb-http/pom.xml
+++ b/server/openejb-http/pom.xml
@@ -164,9 +164,13 @@
     </dependency>
 
     <dependency>
-      <groupId>${project.groupId}</groupId>
-      <artifactId>commons-fileupload-shade</artifactId>
-      <version>${project.version}</version>
+      <groupId>org.apache.commons</groupId>
+      <artifactId>commons-fileupload2-jakarta</artifactId>
+      <optional>true</optional>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.commons</groupId>
+      <artifactId>commons-fileupload2-core</artifactId>
       <optional>true</optional>
     </dependency>
   </dependencies>
diff --git a/server/openejb-http/src/main/java/org/apache/openejb/server/httpd/part/CommonsFileUploadPart.java b/server/openejb-http/src/main/java/org/apache/openejb/server/httpd/part/CommonsFileUploadPart.java
index 93ea7367c6..55336ca5d7 100644
--- a/server/openejb-http/src/main/java/org/apache/openejb/server/httpd/part/CommonsFileUploadPart.java
+++ b/server/openejb-http/src/main/java/org/apache/openejb/server/httpd/part/CommonsFileUploadPart.java
@@ -16,14 +16,16 @@
 */
 package org.apache.openejb.server.httpd.part;
 
-import org.apache.commons.fileupload.FileItem;
-import org.apache.commons.fileupload.disk.DiskFileItem;
 
 import jakarta.servlet.http.Part;
+import org.apache.commons.fileupload2.core.FileItem;
+import org.apache.commons.fileupload2.core.DiskFileItem;
+
 import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.UnsupportedEncodingException;
+import java.nio.charset.Charset;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Iterator;
@@ -100,14 +102,14 @@ public class CommonsFileUploadPart implements Part {
             file = new File(location, fileName);
         }
         try {
-            fileItem.write(file);
+            fileItem.write(file.toPath());
         } catch (Exception e) {
             throw new IOException(e);
         }
     }
 
-    public String getString(final String encoding) throws UnsupportedEncodingException {
-        return fileItem.getString(encoding);
+    public String getString(final String encoding) throws IOException {
+        return fileItem.getString(Charset.forName(encoding));
     }
 
     @Override
diff --git a/server/openejb-http/src/main/java/org/apache/openejb/server/httpd/part/CommonsFileUploadPartFactory.java b/server/openejb-http/src/main/java/org/apache/openejb/server/httpd/part/CommonsFileUploadPartFactory.java
index 6585f1518a..35abad6ed2 100644
--- a/server/openejb-http/src/main/java/org/apache/openejb/server/httpd/part/CommonsFileUploadPartFactory.java
+++ b/server/openejb-http/src/main/java/org/apache/openejb/server/httpd/part/CommonsFileUploadPartFactory.java
@@ -16,18 +16,18 @@
  */
 package org.apache.openejb.server.httpd.part;
 
-import org.apache.commons.fileupload.FileItem;
-import org.apache.commons.fileupload.FileUploadException;
-import org.apache.commons.fileupload.disk.DiskFileItemFactory;
-import org.apache.commons.fileupload.servlet.ServletFileUpload;
-import org.apache.commons.fileupload.servlet.ServletRequestContext;
+import org.apache.commons.fileupload2.core.FileItem;
+import org.apache.commons.fileupload2.core.FileUploadException;
+import org.apache.commons.fileupload2.core.DiskFileItemFactory;
+import org.apache.commons.fileupload2.jakarta.JakartaServletFileUpload;
+import org.apache.commons.fileupload2.jakarta.JakartaServletRequestContext;
 import org.apache.openejb.loader.SystemInstance;
 import org.apache.openejb.server.httpd.HttpRequestImpl;
 
 import jakarta.servlet.http.Part;
 import java.io.File;
 import java.io.IOException;
-import java.io.UnsupportedEncodingException;
+import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
@@ -62,15 +62,14 @@ public final class CommonsFileUploadPartFactory {
 
     public static Collection<Part> read(final HttpRequestImpl request) { // mainly for testing
         // Create a new file upload handler
-        final DiskFileItemFactory factory = new DiskFileItemFactory();
-        factory.setRepository(REPO);
+        final DiskFileItemFactory factory = DiskFileItemFactory.builder().setPath(REPO.toPath()).get();
 
-        final ServletFileUpload upload = new ServletFileUpload();
+        final JakartaServletFileUpload upload = new JakartaServletFileUpload();
         upload.setFileItemFactory(factory);
 
         final List<Part> parts = new ArrayList<>();
         try {
-            final List<FileItem> items = upload.parseRequest(new ServletRequestContext(request));
+            final List<FileItem> items = upload.parseRequest(new JakartaServletRequestContext(request));
             final String enc = request.getCharacterEncoding();
             for (final FileItem item : items) {
                 final CommonsFileUploadPart part = new CommonsFileUploadPart(item, null);
@@ -88,10 +87,10 @@ public final class CommonsFileUploadPartFactory {
                             }
                         }
                         value = part.getString(encoding);
-                    } catch (final UnsupportedEncodingException uee) {
+                    } catch (final IOException uee) {
                         try {
-                            value = part.getString("UTF-8");
-                        } catch (final UnsupportedEncodingException e) {
+                            value = part.getString(String.valueOf(StandardCharsets.UTF_8));
+                        } catch (final IOException e) {
                             // not possible
                         }
                     }
diff --git a/tck/cdi-embedded/pom.xml b/tck/cdi-embedded/pom.xml
index 94e33d59bf..b30717c7aa 100644
--- a/tck/cdi-embedded/pom.xml
+++ b/tck/cdi-embedded/pom.xml
@@ -230,13 +230,13 @@
     </dependency>
     <!-- ActiveMQ is optional in openejb-core (embedded needs openejb-core + all deps)-->
     <dependency>
-      <groupId>${project.groupId}</groupId>
-      <artifactId>activemq-ra-shade</artifactId>
+      <groupId>org.apache.activemq</groupId>
+      <artifactId>activemq-ra</artifactId>
       <scope>test</scope>
     </dependency>
     <dependency>
-      <groupId>${project.groupId}</groupId>
-      <artifactId>activemq-broker-shade</artifactId>
+      <groupId>org.apache.activemq</groupId>
+      <artifactId>activemq-broker</artifactId>
       <scope>test</scope>
     </dependency>
     <dependency>
diff --git a/tomee/tomee-microprofile/tomee-microprofile-webapp/src/main/assembly/war.xml b/tomee/tomee-microprofile/tomee-microprofile-webapp/src/main/assembly/war.xml
index 8a8feef5b1..981df2726e 100644
--- a/tomee/tomee-microprofile/tomee-microprofile-webapp/src/main/assembly/war.xml
+++ b/tomee/tomee-microprofile/tomee-microprofile-webapp/src/main/assembly/war.xml
@@ -87,11 +87,7 @@
         it picks up transitive dependencies from shaded libraries
         -->
         <!-- exclude shaded artifacts because they are under our own groupId -->
-        <exclude>org.apache.activemq:activemq-broker</exclude>
-        <exclude>org.apache.activemq:activemq-kahadb-store</exclude>
-        <exclude>org.apache.activemq:activemq-ra</exclude>
         <exclude>org.apache.commons.dbcp2:*</exclude>
-        <exclude>commons-fileupload:*</exclude>
         <exclude>org.metatype.sxc:*</exclude>
         <exclude>org.apache.taglibs:*</exclude>
 
diff --git a/tomee/tomee-plume-webapp/pom.xml b/tomee/tomee-plume-webapp/pom.xml
index a29d37b667..be2f412305 100644
--- a/tomee/tomee-plume-webapp/pom.xml
+++ b/tomee/tomee-plume-webapp/pom.xml
@@ -327,8 +327,8 @@
       </exclusions>
     </dependency>
     <dependency>
-      <groupId>${project.groupId}</groupId>
-      <artifactId>activemq-broker-shade</artifactId>
+      <groupId>org.apache.activemq</groupId>
+      <artifactId>activemq-broker</artifactId>
     </dependency>
     <dependency>
       <groupId>org.apache.activemq</groupId>
@@ -341,8 +341,8 @@
       </exclusions>
     </dependency>
     <dependency>
-      <groupId>${project.groupId}</groupId>
-      <artifactId>activemq-ra-shade</artifactId>
+      <groupId>org.apache.activemq</groupId>
+      <artifactId>activemq-ra</artifactId>
     </dependency>
     <dependency>
       <groupId>org.apache.batchee</groupId>
diff --git a/tomee/tomee-plume-webapp/src/main/assembly/war.xml b/tomee/tomee-plume-webapp/src/main/assembly/war.xml
index 9106bd3084..b67de69338 100644
--- a/tomee/tomee-plume-webapp/src/main/assembly/war.xml
+++ b/tomee/tomee-plume-webapp/src/main/assembly/war.xml
@@ -106,11 +106,7 @@
         it picks up transitive dependencies from shaded libraries
         -->
         <!-- exclude shaded artifacts because they are under our own groupId -->
-        <exclude>org.apache.activemq:activemq-broker</exclude>
-        <exclude>org.apache.activemq:activemq-kahadb-store</exclude>
-        <exclude>org.apache.activemq:activemq-ra</exclude>
         <exclude>org.apache.commons.dbcp2:*</exclude>
-        <exclude>commons-fileupload:*</exclude>
         <exclude>org.metatype.sxc:*</exclude>
         <exclude>org.apache.taglibs:*</exclude>
 
diff --git a/tomee/tomee-plus-webapp/pom.xml b/tomee/tomee-plus-webapp/pom.xml
index 40521678d9..9c7edaf722 100644
--- a/tomee/tomee-plus-webapp/pom.xml
+++ b/tomee/tomee-plus-webapp/pom.xml
@@ -327,8 +327,8 @@
       </exclusions>
     </dependency>
     <dependency>
-      <groupId>${project.groupId}</groupId>
-      <artifactId>activemq-broker-shade</artifactId>
+      <groupId>org.apache.activemq</groupId>
+      <artifactId>activemq-broker</artifactId>
     </dependency>
     <dependency>
       <groupId>org.apache.activemq</groupId>
@@ -341,8 +341,8 @@
       </exclusions>
     </dependency>
     <dependency>
-      <groupId>${project.groupId}</groupId>
-      <artifactId>activemq-ra-shade</artifactId>
+      <groupId>org.apache.activemq</groupId>
+      <artifactId>activemq-ra</artifactId>
     </dependency>
     <dependency>
       <groupId>org.apache.batchee</groupId>
diff --git a/tomee/tomee-plus-webapp/src/main/assembly/war.xml b/tomee/tomee-plus-webapp/src/main/assembly/war.xml
index 40ae4fe9cb..86dbfbd4ec 100644
--- a/tomee/tomee-plus-webapp/src/main/assembly/war.xml
+++ b/tomee/tomee-plus-webapp/src/main/assembly/war.xml
@@ -100,11 +100,7 @@
         it picks up transitive dependencies from shaded libraries
         -->
         <!-- exclude shaded artifacts because they are under our own groupId -->
-        <exclude>org.apache.activemq:activemq-broker</exclude>
-        <exclude>org.apache.activemq:activemq-kahadb-store</exclude>
-        <exclude>org.apache.activemq:activemq-ra</exclude>
         <exclude>org.apache.commons.dbcp2:*</exclude>
-        <exclude>commons-fileupload:*</exclude>
         <exclude>org.metatype.sxc:*</exclude>
         <exclude>org.apache.taglibs:*</exclude>
 
diff --git a/tomee/tomee-webapp/src/main/assembly/war.xml b/tomee/tomee-webapp/src/main/assembly/war.xml
index 2ddf1e4df9..c4e8936e17 100644
--- a/tomee/tomee-webapp/src/main/assembly/war.xml
+++ b/tomee/tomee-webapp/src/main/assembly/war.xml
@@ -110,11 +110,7 @@
         it picks up transitive dependencies from shaded libraries
         -->
         <!-- exclude shaded artifacts because they are under our own groupId -->
-        <exclude>org.apache.activemq:activemq-broker</exclude>
-        <exclude>org.apache.activemq:activemq-kahadb-store</exclude>
-        <exclude>org.apache.activemq:activemq-ra</exclude>
         <exclude>org.apache.commons.dbcp2:*</exclude>
-        <exclude>commons-fileupload:*</exclude>
         <exclude>org.metatype.sxc:*</exclude>
         <exclude>org.apache.taglibs:*</exclude>
 


(tomee) 02/02: Tomcat 10.1.20 (and drop patched DefaultServlet as the changes should already be in Tomcat itself)

Posted by rz...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rzo1 pushed a commit to branch amq6
in repository https://gitbox.apache.org/repos/asf/tomee.git

commit 7326aedf7d571ba793ed7c7368b6fffbae438583
Author: Richard Zowalla <rz...@apache.org>
AuthorDate: Sun Mar 31 10:18:59 2024 +0200

    Tomcat 10.1.20 (and drop patched DefaultServlet as the changes should already be in Tomcat itself)
---
 pom.xml                                            |    2 +-
 .../apache/catalina/servlets/DefaultServlet.java   | 3054 --------------------
 2 files changed, 1 insertion(+), 3055 deletions(-)

diff --git a/pom.xml b/pom.xml
index dfdf45b3e9..00f87a6e56 100644
--- a/pom.xml
+++ b/pom.xml
@@ -206,7 +206,7 @@
     <version.geronimo-mail_2.1_spec>1.0.0-M1</version.geronimo-mail_2.1_spec>
 
     <!-- Jakarta EE Impl. -->
-    <tomcat.version>10.1.19</tomcat.version>
+    <tomcat.version>10.1.20</tomcat.version>
     <!-- com.sun -->
     <version.impl.saaj>2.0.1</version.impl.saaj>
     <!-- org.apache -->
diff --git a/tomee/apache-tomee/src/patch/java/org/apache/catalina/servlets/DefaultServlet.java b/tomee/apache-tomee/src/patch/java/org/apache/catalina/servlets/DefaultServlet.java
deleted file mode 100644
index 697e559e79..0000000000
--- a/tomee/apache-tomee/src/patch/java/org/apache/catalina/servlets/DefaultServlet.java
+++ /dev/null
@@ -1,3054 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.catalina.servlets;
-
-import java.io.BufferedInputStream;
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.OutputStreamWriter;
-import java.io.PrintWriter;
-import java.io.RandomAccessFile;
-import java.io.Reader;
-import java.io.Serializable;
-import java.io.StringReader;
-import java.io.StringWriter;
-import java.io.UnsupportedEncodingException;
-import java.nio.charset.Charset;
-import java.nio.charset.StandardCharsets;
-import java.security.AccessController;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.Enumeration;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Locale;
-
-import jakarta.servlet.DispatcherType;
-import jakarta.servlet.RequestDispatcher;
-import jakarta.servlet.ServletContext;
-import jakarta.servlet.ServletException;
-import jakarta.servlet.ServletOutputStream;
-import jakarta.servlet.ServletResponse;
-import jakarta.servlet.ServletResponseWrapper;
-import jakarta.servlet.UnavailableException;
-import jakarta.servlet.http.HttpServlet;
-import jakarta.servlet.http.HttpServletRequest;
-import jakarta.servlet.http.HttpServletResponse;
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.transform.Source;
-import javax.xml.transform.Transformer;
-import javax.xml.transform.TransformerException;
-import javax.xml.transform.TransformerFactory;
-import javax.xml.transform.dom.DOMSource;
-import javax.xml.transform.stream.StreamResult;
-import javax.xml.transform.stream.StreamSource;
-
-import org.apache.catalina.Context;
-import org.apache.catalina.Globals;
-import org.apache.catalina.WebResource;
-import org.apache.catalina.WebResourceRoot;
-import org.apache.catalina.connector.RequestFacade;
-import org.apache.catalina.connector.ResponseFacade;
-import org.apache.catalina.util.IOTools;
-import org.apache.catalina.util.ServerInfo;
-import org.apache.catalina.util.URLEncoder;
-import org.apache.catalina.webresources.CachedResource;
-import org.apache.tomcat.util.buf.B2CConverter;
-import org.apache.tomcat.util.http.ResponseUtil;
-import org.apache.tomcat.util.http.parser.ContentRange;
-import org.apache.tomcat.util.http.parser.EntityTag;
-import org.apache.tomcat.util.http.parser.Ranges;
-import org.apache.tomcat.util.res.StringManager;
-import org.apache.tomcat.util.security.Escape;
-import org.apache.tomcat.util.security.PrivilegedGetTccl;
-import org.apache.tomcat.util.security.PrivilegedSetTccl;
-import org.w3c.dom.Document;
-import org.xml.sax.InputSource;
-import org.xml.sax.SAXException;
-import org.xml.sax.ext.EntityResolver2;
-
-
-/**
- * <p>The default resource-serving servlet for most web applications,
- * used to serve static resources such as HTML pages and images.
- * </p>
- * <p>
- * This servlet is intended to be mapped to <em>/</em> e.g.:
- * </p>
- * <pre>
- *   &lt;servlet-mapping&gt;
- *       &lt;servlet-name&gt;default&lt;/servlet-name&gt;
- *       &lt;url-pattern&gt;/&lt;/url-pattern&gt;
- *   &lt;/servlet-mapping&gt;
- * </pre>
- * <p>It can be mapped to sub-paths, however in all cases resources are served
- * from the web application resource root using the full path from the root
- * of the web application context.
- * <br>e.g. given a web application structure:
- *</p>
- * <pre>
- * /context
- *   /images
- *     tomcat2.jpg
- *   /static
- *     /images
- *       tomcat.jpg
- * </pre>
- * <p>
- * ... and a servlet mapping that maps only <code>/static/*</code> to the default servlet:
- * </p>
- * <pre>
- *   &lt;servlet-mapping&gt;
- *       &lt;servlet-name&gt;default&lt;/servlet-name&gt;
- *       &lt;url-pattern&gt;/static/*&lt;/url-pattern&gt;
- *   &lt;/servlet-mapping&gt;
- * </pre>
- * <p>
- * Then a request to <code>/context/static/images/tomcat.jpg</code> will succeed
- * while a request to <code>/context/images/tomcat2.jpg</code> will fail.
- * </p>
- * @author Craig R. McClanahan
- * @author Remy Maucherat
- */
-public class DefaultServlet extends HttpServlet {
-
-    private static final long serialVersionUID = 1L;
-
-    /**
-     * The string manager for this package.
-     */
-    protected static final StringManager sm = StringManager.getManager(DefaultServlet.class);
-
-    private static final DocumentBuilderFactory factory;
-
-    private static final SecureEntityResolver secureEntityResolver;
-
-    /**
-     * Full range marker.
-     */
-    protected static final ArrayList<Range> FULL = new ArrayList<>();
-
-    private static final Range IGNORE = new Range();
-
-    /**
-     * MIME multipart separation string
-     */
-    protected static final String mimeSeparation = "CATALINA_MIME_BOUNDARY";
-
-    /**
-     * Size of file transfer buffer in bytes.
-     */
-    protected static final int BUFFER_SIZE = 4096;
-
-
-    // ----------------------------------------------------- Static Initializer
-
-    static {
-        if (Globals.IS_SECURITY_ENABLED) {
-            factory = DocumentBuilderFactory.newInstance();
-            factory.setNamespaceAware(true);
-            factory.setValidating(false);
-            secureEntityResolver = new SecureEntityResolver();
-        } else {
-            factory = null;
-            secureEntityResolver = null;
-        }
-    }
-
-
-    // ----------------------------------------------------- Instance Variables
-
-    /**
-     * The debugging detail level for this servlet.
-     */
-    protected int debug = 0;
-
-    /**
-     * The input buffer size to use when serving resources.
-     */
-    protected int input = 2048;
-
-    /**
-     * Should we generate directory listings?
-     */
-    protected boolean listings = false;
-
-    /**
-     * Read only flag. By default, it's set to true.
-     */
-    protected boolean readOnly = true;
-
-    /**
-     * List of compression formats to serve and their preference order.
-     */
-    protected CompressionFormat[] compressionFormats;
-
-    /**
-     * The output buffer size to use when serving resources.
-     */
-    protected int output = 2048;
-
-    /**
-     * Allow customized directory listing per directory.
-     */
-    protected String localXsltFile = null;
-
-    /**
-     * Allow customized directory listing per context.
-     */
-    protected String contextXsltFile = null;
-
-    /**
-     * Allow customized directory listing per instance.
-     */
-    protected String globalXsltFile = null;
-
-    /**
-     * Allow a readme file to be included.
-     */
-    protected String readmeFile = null;
-
-    /**
-     * The complete set of web application resources
-     */
-    protected transient WebResourceRoot resources = null;
-
-    /**
-     * File encoding to be used when reading static files. If none is specified
-     * the platform default is used.
-     */
-    protected String fileEncoding = null;
-    private transient Charset fileEncodingCharset = null;
-
-    /**
-     * If a file has a BOM, should that be used in preference to fileEncoding?
-     *
-     * - true  - BoM is stripped if present and any BoM found used to determine
-     *            the encoding used to read the resource. This is the default.
-     *
-     * - false - BoM is stripped and resource is read using the configured file
-     *            encoding (which will be the platform default if not explicitly
-     *            configured)
-     *
-     * - path-through - as current false but does not strip the BoM from the output
-     */
-    private String useBomIfPresent = "true";
-
-    /**
-     * Minimum size for sendfile usage in bytes.
-     */
-    protected int sendfileSize = 48 * 1024;
-
-    /**
-     * Should the Accept-Ranges: bytes header be send with static resources?
-     */
-    protected boolean useAcceptRanges = true;
-
-    /**
-     * Flag to determine if server information is presented.
-     */
-    protected boolean showServerInfo = true;
-
-    /**
-     * Flag to determine if resources should be sorted.
-     */
-    protected boolean sortListings = false;
-
-    /**
-     * The sorting manager for sorting files and directories.
-     */
-    protected transient SortManager sortManager;
-
-    /**
-     * Flag that indicates whether partial PUTs are permitted.
-     */
-    private boolean allowPartialPut = true;
-
-
-    // --------------------------------------------------------- Public Methods
-
-    /**
-     * Finalize this servlet.
-     */
-    @Override
-    public void destroy() {
-        // NOOP
-    }
-
-
-    /**
-     * Initialize this servlet.
-     */
-    @Override
-    public void init() throws ServletException {
-
-        if (getServletConfig().getInitParameter("debug") != null) {
-            debug = Integer.parseInt(getServletConfig().getInitParameter("debug"));
-        }
-
-        if (getServletConfig().getInitParameter("input") != null) {
-            input = Integer.parseInt(getServletConfig().getInitParameter("input"));
-        }
-
-        if (getServletConfig().getInitParameter("output") != null) {
-            output = Integer.parseInt(getServletConfig().getInitParameter("output"));
-        }
-
-        listings = Boolean.parseBoolean(getServletConfig().getInitParameter("listings"));
-
-        if (getServletConfig().getInitParameter("readonly") != null) {
-            readOnly = Boolean.parseBoolean(getServletConfig().getInitParameter("readonly"));
-        }
-
-        compressionFormats = parseCompressionFormats(
-            getServletConfig().getInitParameter("precompressed"),
-            getServletConfig().getInitParameter("gzip"));
-
-        if (getServletConfig().getInitParameter("sendfileSize") != null) {
-            sendfileSize = Integer.parseInt(getServletConfig().getInitParameter("sendfileSize")) * 1024;
-        }
-
-        fileEncoding = getServletConfig().getInitParameter("fileEncoding");
-        if (fileEncoding == null) {
-            fileEncodingCharset = Charset.defaultCharset();
-            fileEncoding = fileEncodingCharset.name();
-        } else {
-            try {
-                fileEncodingCharset = B2CConverter.getCharset(fileEncoding);
-            } catch (UnsupportedEncodingException e) {
-                throw new ServletException(e);
-            }
-        }
-
-        final String useBomIfPresentConfig = getServletConfig().getInitParameter("useBomIfPresent");
-        if (useBomIfPresentConfig != null) {
-            if (!Arrays.asList("true", "false", "pass-through").contains(useBomIfPresentConfig)) {
-                if (debug > 0) {
-                    log("DefaultServlet.init:  unsupported value " + useBomIfPresentConfig + " for useBomIfPresent." +
-                        " One of 'true', 'false', 'pass-through' is expected. Using 'true' by default.");
-                }
-            }
-            useBomIfPresent = useBomIfPresentConfig;
-        }
-
-        globalXsltFile = getServletConfig().getInitParameter("globalXsltFile");
-        contextXsltFile = getServletConfig().getInitParameter("contextXsltFile");
-        localXsltFile = getServletConfig().getInitParameter("localXsltFile");
-        readmeFile = getServletConfig().getInitParameter("readmeFile");
-
-        if (getServletConfig().getInitParameter("useAcceptRanges") != null) {
-            useAcceptRanges = Boolean.parseBoolean(getServletConfig().getInitParameter("useAcceptRanges"));
-        }
-
-        // Sanity check on the specified buffer sizes
-        if (input < 256) {
-            input = 256;
-        }
-        if (output < 256) {
-            output = 256;
-        }
-
-        if (debug > 0) {
-            log("DefaultServlet.init:  input buffer size=" + input +
-                ", output buffer size=" + output);
-        }
-
-        // Load the web resources
-        resources = (WebResourceRoot) getServletContext().getAttribute(Globals.RESOURCES_ATTR);
-
-        if (resources == null) {
-            throw new UnavailableException(sm.getString("defaultServlet.noResources"));
-        }
-
-        if (getServletConfig().getInitParameter("showServerInfo") != null) {
-            showServerInfo = Boolean.parseBoolean(getServletConfig().getInitParameter("showServerInfo"));
-        }
-
-        if (getServletConfig().getInitParameter("sortListings") != null) {
-            sortListings = Boolean.parseBoolean(getServletConfig().getInitParameter("sortListings"));
-
-            if(sortListings) {
-                boolean sortDirectoriesFirst;
-                if (getServletConfig().getInitParameter("sortDirectoriesFirst") != null) {
-                    sortDirectoriesFirst = Boolean.parseBoolean(getServletConfig().getInitParameter("sortDirectoriesFirst"));
-                } else {
-                    sortDirectoriesFirst = false;
-                }
-
-                sortManager = new SortManager(sortDirectoriesFirst);
-            }
-        }
-
-        if (getServletConfig().getInitParameter("allowPartialPut") != null) {
-            allowPartialPut = Boolean.parseBoolean(getServletConfig().getInitParameter("allowPartialPut"));
-        }
-    }
-
-    private CompressionFormat[] parseCompressionFormats(String precompressed, String gzip) {
-        List<CompressionFormat> ret = new ArrayList<>();
-        if (precompressed != null && precompressed.indexOf('=') > 0) {
-            for (String pair : precompressed.split(",")) {
-                String[] setting = pair.split("=");
-                String encoding = setting[0];
-                String extension = setting[1];
-                ret.add(new CompressionFormat(extension, encoding));
-            }
-        } else if (precompressed != null) {
-            if (Boolean.parseBoolean(precompressed)) {
-                ret.add(new CompressionFormat(".br", "br"));
-                ret.add(new CompressionFormat(".gz", "gzip"));
-            }
-        } else if (Boolean.parseBoolean(gzip)) {
-            // gzip handling is for backwards compatibility with Tomcat 8.x
-            ret.add(new CompressionFormat(".gz", "gzip"));
-        }
-        return ret.toArray(new CompressionFormat[0]);
-    }
-
-
-    // ------------------------------------------------------ Protected Methods
-
-
-    /**
-     * Return the relative path associated with this servlet.
-     *
-     * @param request The servlet request we are processing
-     * @return the relative path
-     */
-    protected String getRelativePath(HttpServletRequest request) {
-        return getRelativePath(request, false);
-    }
-
-    protected String getRelativePath(HttpServletRequest request, boolean allowEmptyPath) {
-        // IMPORTANT: DefaultServlet can be mapped to '/' or '/path/*' but always
-        // serves resources from the web app root with context rooted paths.
-        // i.e. it cannot be used to mount the web app root under a sub-path
-        // This method must construct a complete context rooted path, although
-        // subclasses can change this behaviour.
-
-        String servletPath;
-        String pathInfo;
-
-        if (request.getAttribute(RequestDispatcher.INCLUDE_REQUEST_URI) != null) {
-            // For includes, get the info from the attributes
-            pathInfo = (String) request.getAttribute(RequestDispatcher.INCLUDE_PATH_INFO);
-            servletPath = (String) request.getAttribute(RequestDispatcher.INCLUDE_SERVLET_PATH);
-        } else {
-            pathInfo = request.getPathInfo();
-            servletPath = request.getServletPath();
-        }
-
-        StringBuilder result = new StringBuilder();
-        if (servletPath.length() > 0) {
-            result.append(servletPath);
-        }
-        if (pathInfo != null) {
-            result.append(pathInfo);
-        }
-        if (result.length() == 0 && !allowEmptyPath) {
-            result.append('/');
-        }
-
-        return result.toString();
-    }
-
-
-    /**
-     * Determines the appropriate path to prepend resources with
-     * when generating directory listings. Depending on the behaviour of
-     * {@link #getRelativePath(HttpServletRequest)} this will change.
-     * @param request the request to determine the path for
-     * @return the prefix to apply to all resources in the listing.
-     */
-    protected String getPathPrefix(final HttpServletRequest request) {
-        return request.getContextPath();
-    }
-
-
-    @Override
-    protected void service(HttpServletRequest req, HttpServletResponse resp)
-        throws ServletException, IOException {
-
-        if (req.getDispatcherType() == DispatcherType.ERROR) {
-            doGet(req, resp);
-        } else {
-            super.service(req, resp);
-        }
-    }
-
-
-    /**
-     * Process a GET request for the specified resource.
-     *
-     * @param request The servlet request we are processing
-     * @param response The servlet response we are creating
-     *
-     * @exception IOException if an input/output error occurs
-     * @exception ServletException if a servlet-specified error occurs
-     */
-    @Override
-    protected void doGet(HttpServletRequest request,
-                         HttpServletResponse response)
-        throws IOException, ServletException {
-
-        // Serve the requested resource, including the data content
-        serveResource(request, response, true, fileEncoding);
-
-    }
-
-
-    /**
-     * Process a HEAD request for the specified resource.
-     *
-     * @param request The servlet request we are processing
-     * @param response The servlet response we are creating
-     *
-     * @exception IOException if an input/output error occurs
-     * @exception ServletException if a servlet-specified error occurs
-     */
-    @Override
-    protected void doHead(HttpServletRequest request, HttpServletResponse response)
-        throws IOException, ServletException {
-        // Serve the requested resource, without the data content unless we are
-        // being included since in that case the content needs to be provided so
-        // the correct content length is reported for the including resource
-        boolean serveContent = DispatcherType.INCLUDE.equals(request.getDispatcherType());
-        serveResource(request, response, serveContent, fileEncoding);
-    }
-
-
-    /**
-     * Override default implementation to ensure that TRACE is correctly
-     * handled.
-     *
-     * @param req   the {@link HttpServletRequest} object that
-     *                  contains the request the client made of
-     *                  the servlet
-     *
-     * @param resp  the {@link HttpServletResponse} object that
-     *                  contains the response the servlet returns
-     *                  to the client
-     *
-     * @exception IOException   if an input or output error occurs
-     *                              while the servlet is handling the
-     *                              OPTIONS request
-     *
-     * @exception ServletException  if the request for the
-     *                                  OPTIONS cannot be handled
-     */
-    @Override
-    protected void doOptions(HttpServletRequest req, HttpServletResponse resp)
-        throws ServletException, IOException {
-
-        resp.setHeader("Allow", determineMethodsAllowed(req));
-    }
-
-
-    protected String determineMethodsAllowed(HttpServletRequest req) {
-        StringBuilder allow = new StringBuilder();
-
-        // Start with methods that are always allowed
-        allow.append("OPTIONS, GET, HEAD, POST");
-
-        // PUT and DELETE depend on readonly
-        if (!readOnly) {
-            allow.append(", PUT, DELETE");
-        }
-
-        // Trace - assume disabled unless we can prove otherwise
-        if (req instanceof RequestFacade &&
-            ((RequestFacade) req).getAllowTrace()) {
-            allow.append(", TRACE");
-        }
-
-        return allow.toString();
-    }
-
-
-    protected void sendNotAllowed(HttpServletRequest req, HttpServletResponse resp)
-        throws IOException {
-        resp.addHeader("Allow", determineMethodsAllowed(req));
-        resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
-    }
-
-
-    /**
-     * Process a POST request for the specified resource.
-     *
-     * @param request The servlet request we are processing
-     * @param response The servlet response we are creating
-     *
-     * @exception IOException if an input/output error occurs
-     * @exception ServletException if a servlet-specified error occurs
-     */
-    @Override
-    protected void doPost(HttpServletRequest request,
-                          HttpServletResponse response)
-        throws IOException, ServletException {
-        doGet(request, response);
-    }
-
-
-    /**
-     * Process a PUT request for the specified resource.
-     *
-     * @param req The servlet request we are processing
-     * @param resp The servlet response we are creating
-     *
-     * @exception IOException if an input/output error occurs
-     * @exception ServletException if a servlet-specified error occurs
-     */
-    @Override
-    protected void doPut(HttpServletRequest req, HttpServletResponse resp)
-        throws ServletException, IOException {
-
-        if (readOnly) {
-            sendNotAllowed(req, resp);
-            return;
-        }
-
-        String path = getRelativePath(req);
-
-        WebResource resource = resources.getResource(path);
-
-        Range range = parseContentRange(req, resp);
-
-        if (range == null) {
-            // Processing error. parseContentRange() set the error code
-            return;
-        }
-
-        InputStream resourceInputStream = null;
-
-        try {
-            // Append data specified in ranges to existing content for this
-            // resource - create a temp. file on the local filesystem to
-            // perform this operation
-            // Assume just one range is specified for now
-            if (range == IGNORE) {
-                resourceInputStream = req.getInputStream();
-            } else {
-                File contentFile = executePartialPut(req, range, path);
-                resourceInputStream = new FileInputStream(contentFile);
-            }
-
-            if (resources.write(path, resourceInputStream, true)) {
-                if (resource.exists()) {
-                    resp.setStatus(HttpServletResponse.SC_NO_CONTENT);
-                } else {
-                    resp.setStatus(HttpServletResponse.SC_CREATED);
-                }
-            } else {
-                resp.sendError(HttpServletResponse.SC_CONFLICT);
-            }
-        } finally {
-            if (resourceInputStream != null) {
-                try {
-                    resourceInputStream.close();
-                } catch (IOException ioe) {
-                    // Ignore
-                }
-            }
-        }
-    }
-
-
-    /**
-     * Handle a partial PUT.  New content specified in request is appended to
-     * existing content in oldRevisionContent (if present). This code does
-     * not support simultaneous partial updates to the same resource.
-     * @param req The Servlet request
-     * @param range The range that will be written
-     * @param path The path
-     * @return the associated file object
-     * @throws IOException an IO error occurred
-     */
-    protected File executePartialPut(HttpServletRequest req, Range range,
-                                     String path)
-        throws IOException {
-
-        // Append data specified in ranges to existing content for this
-        // resource - create a temp. file on the local filesystem to
-        // perform this operation
-        File tempDir = (File) getServletContext().getAttribute
-            (ServletContext.TEMPDIR);
-        // Convert all '/' characters to '.' in resourcePath
-        String convertedResourcePath = path.replace('/', '.');
-        File contentFile = new File(tempDir, convertedResourcePath);
-        if (contentFile.createNewFile()) {
-            // Clean up contentFile when Tomcat is terminated
-            contentFile.deleteOnExit();
-        }
-
-        try (RandomAccessFile randAccessContentFile =
-                 new RandomAccessFile(contentFile, "rw")) {
-
-            WebResource oldResource = resources.getResource(path);
-
-            // Copy data in oldRevisionContent to contentFile
-            if (oldResource.isFile()) {
-                try (BufferedInputStream bufOldRevStream =
-                         new BufferedInputStream(oldResource.getInputStream(),
-                                                 BUFFER_SIZE)) {
-
-                    int numBytesRead;
-                    byte[] copyBuffer = new byte[BUFFER_SIZE];
-                    while ((numBytesRead = bufOldRevStream.read(copyBuffer)) != -1) {
-                        randAccessContentFile.write(copyBuffer, 0, numBytesRead);
-                    }
-
-                }
-            }
-
-            randAccessContentFile.setLength(range.length);
-
-            // Append data in request input stream to contentFile
-            randAccessContentFile.seek(range.start);
-            int numBytesRead;
-            byte[] transferBuffer = new byte[BUFFER_SIZE];
-            try (BufferedInputStream requestBufInStream =
-                     new BufferedInputStream(req.getInputStream(), BUFFER_SIZE)) {
-                while ((numBytesRead = requestBufInStream.read(transferBuffer)) != -1) {
-                    randAccessContentFile.write(transferBuffer, 0, numBytesRead);
-                }
-            }
-        }
-
-        return contentFile;
-    }
-
-
-    /**
-     * Process a DELETE request for the specified resource.
-     *
-     * @param req The servlet request we are processing
-     * @param resp The servlet response we are creating
-     *
-     * @exception IOException if an input/output error occurs
-     * @exception ServletException if a servlet-specified error occurs
-     */
-    @Override
-    protected void doDelete(HttpServletRequest req, HttpServletResponse resp)
-        throws ServletException, IOException {
-
-        if (readOnly) {
-            sendNotAllowed(req, resp);
-            return;
-        }
-
-        String path = getRelativePath(req);
-
-        WebResource resource = resources.getResource(path);
-
-        if (resource.exists()) {
-            if (resource.delete()) {
-                resp.setStatus(HttpServletResponse.SC_NO_CONTENT);
-            } else {
-                resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
-            }
-        } else {
-            resp.sendError(HttpServletResponse.SC_NOT_FOUND);
-        }
-
-    }
-
-
-    /**
-     * Check if the conditions specified in the optional If headers are
-     * satisfied.
-     *
-     * @param request   The servlet request we are processing
-     * @param response  The servlet response we are creating
-     * @param resource  The resource
-     * @return <code>true</code> if the resource meets all the specified
-     *  conditions, and <code>false</code> if any of the conditions is not
-     *  satisfied, in which case request processing is stopped
-     * @throws IOException an IO error occurred
-     */
-    protected boolean checkIfHeaders(HttpServletRequest request,
-                                     HttpServletResponse response,
-                                     WebResource resource)
-        throws IOException {
-
-        return checkIfMatch(request, response, resource)
-               && checkIfModifiedSince(request, response, resource)
-               && checkIfNoneMatch(request, response, resource)
-               && checkIfUnmodifiedSince(request, response, resource);
-
-    }
-
-
-    /**
-     * URL rewriter.
-     *
-     * @param path Path which has to be rewritten
-     * @return the rewritten path
-     */
-    protected String rewriteUrl(String path) {
-        return URLEncoder.DEFAULT.encode(path, StandardCharsets.UTF_8);
-    }
-
-
-    /**
-     * Serve the specified resource, optionally including the data content.
-     *
-     * @param request       The servlet request we are processing
-     * @param response      The servlet response we are creating
-     * @param content       Should the content be included?
-     * @param inputEncoding The encoding to use if it is necessary to access the
-     *                      source as characters rather than as bytes
-     *
-     * @exception IOException if an input/output error occurs
-     * @exception ServletException if a servlet-specified error occurs
-     */
-    protected void serveResource(HttpServletRequest request,
-                                 HttpServletResponse response,
-                                 boolean content,
-                                 String inputEncoding)
-        throws IOException, ServletException {
-
-        boolean serveContent = content;
-
-        // Identify the requested resource path
-        String path = getRelativePath(request, true);
-
-        if (debug > 0) {
-            if (serveContent)
-                log("DefaultServlet.serveResource:  Serving resource '" +
-                    path + "' headers and data");
-            else
-                log("DefaultServlet.serveResource:  Serving resource '" +
-                    path + "' headers only");
-        }
-
-        if (path.length() == 0) {
-            // Context root redirect
-            doDirectoryRedirect(request, response);
-            return;
-        }
-
-        WebResource resource = resources.getResource(path);
-        boolean isError = DispatcherType.ERROR == request.getDispatcherType();
-
-        if (!resource.exists()) {
-            // Check if we're included so we can return the appropriate
-            // missing resource name in the error
-            String requestUri = (String) request.getAttribute(
-                RequestDispatcher.INCLUDE_REQUEST_URI);
-            if (requestUri == null) {
-                requestUri = request.getRequestURI();
-            } else {
-                // We're included
-                // SRV.9.3 says we must throw a FNFE
-                throw new FileNotFoundException(sm.getString(
-                    "defaultServlet.missingResource", requestUri));
-            }
-
-            if (isError) {
-                response.sendError(((Integer) request.getAttribute(
-                    RequestDispatcher.ERROR_STATUS_CODE)).intValue());
-            } else {
-                response.sendError(HttpServletResponse.SC_NOT_FOUND,
-                                   sm.getString("defaultServlet.missingResource", requestUri));
-            }
-            return;
-        }
-
-        if (!resource.canRead()) {
-            // Check if we're included so we can return the appropriate
-            // missing resource name in the error
-            String requestUri = (String) request.getAttribute(
-                RequestDispatcher.INCLUDE_REQUEST_URI);
-            if (requestUri == null) {
-                requestUri = request.getRequestURI();
-            } else {
-                // We're included
-                // Spec doesn't say what to do in this case but a FNFE seems
-                // reasonable
-                throw new FileNotFoundException(sm.getString(
-                    "defaultServlet.missingResource", requestUri));
-            }
-
-            if (isError) {
-                response.sendError(((Integer) request.getAttribute(
-                    RequestDispatcher.ERROR_STATUS_CODE)).intValue());
-            } else {
-                response.sendError(HttpServletResponse.SC_FORBIDDEN, requestUri);
-            }
-            return;
-        }
-
-        boolean included = false;
-        // Check if the conditions specified in the optional If headers are
-        // satisfied.
-        if (resource.isFile()) {
-            // Checking If headers
-            included = (request.getAttribute(
-                RequestDispatcher.INCLUDE_CONTEXT_PATH) != null);
-            if (!included && !isError && !checkIfHeaders(request, response, resource)) {
-                return;
-            }
-        }
-
-        // Find content type.
-        String contentType = resource.getMimeType();
-        if (contentType == null) {
-            contentType = getServletContext().getMimeType(resource.getName());
-            resource.setMimeType(contentType);
-        }
-
-        // These need to reflect the original resource, not the potentially
-        // precompressed version of the resource so get them now if they are going to
-        // be needed later
-        String eTag = null;
-        String lastModifiedHttp = null;
-        if (resource.isFile() && !isError) {
-            eTag = generateETag(resource);
-            lastModifiedHttp = resource.getLastModifiedHttp();
-        }
-
-
-        // Serve a precompressed version of the file if present
-        boolean usingPrecompressedVersion = false;
-        if (compressionFormats.length > 0 && !included && resource.isFile() &&
-            !pathEndsWithCompressedExtension(path)) {
-            List<PrecompressedResource> precompressedResources =
-                getAvailablePrecompressedResources(path);
-            if (!precompressedResources.isEmpty()) {
-                ResponseUtil.addVaryFieldName(response, "accept-encoding");
-                PrecompressedResource bestResource =
-                    getBestPrecompressedResource(request, precompressedResources);
-                if (bestResource != null) {
-                    response.addHeader("Content-Encoding", bestResource.format.encoding);
-                    resource = bestResource.resource;
-                    usingPrecompressedVersion = true;
-                }
-            }
-        }
-
-        ArrayList<Range> ranges = FULL;
-        long contentLength = -1L;
-
-        if (resource.isDirectory()) {
-            if (!path.endsWith("/")) {
-                doDirectoryRedirect(request, response);
-                return;
-            }
-
-            // Skip directory listings if we have been configured to
-            // suppress them
-            if (!listings) {
-                response.sendError(HttpServletResponse.SC_NOT_FOUND,
-                                   sm.getString("defaultServlet.missingResource", request.getRequestURI()));
-                return;
-            }
-            contentType = "text/html;charset=UTF-8";
-        } else {
-            if (!isError) {
-                if (useAcceptRanges) {
-                    // Accept ranges header
-                    response.setHeader("Accept-Ranges", "bytes");
-                }
-
-                // Parse range specifier
-                ranges = parseRange(request, response, resource);
-                if (ranges == null) {
-                    return;
-                }
-
-                // ETag header
-                response.setHeader("ETag", eTag);
-
-                // Last-Modified header
-                response.setHeader("Last-Modified", lastModifiedHttp);
-            }
-
-            // Get content length
-            contentLength = resource.getContentLength();
-            // Special case for zero length files, which would cause a
-            // (silent) ISE when setting the output buffer size
-            if (contentLength == 0L) {
-                serveContent = false;
-            }
-        }
-
-        ServletOutputStream ostream = null;
-        PrintWriter writer = null;
-
-        if (serveContent) {
-            // Trying to retrieve the servlet output stream
-            try {
-                ostream = response.getOutputStream();
-            } catch (IllegalStateException e) {
-                // If it fails, we try to get a Writer instead if we're
-                // trying to serve a text file
-                if (!usingPrecompressedVersion && isText(contentType)) {
-                    writer = response.getWriter();
-                    // Cannot reliably serve partial content with a Writer
-                    ranges = FULL;
-                } else {
-                    throw e;
-                }
-            }
-        }
-
-        // Check to see if a Filter, Valve or wrapper has written some content.
-        // If it has, disable range requests and setting of a content length
-        // since neither can be done reliably.
-        ServletResponse r = response;
-        long contentWritten = 0;
-        while (r instanceof ServletResponseWrapper) {
-            r = ((ServletResponseWrapper) r).getResponse();
-        }
-        if (r instanceof ResponseFacade) {
-            contentWritten = ((ResponseFacade) r).getContentWritten();
-        }
-        if (contentWritten > 0) {
-            ranges = FULL;
-        }
-
-        String outputEncoding = response.getCharacterEncoding();
-        Charset charset = B2CConverter.getCharset(outputEncoding);
-        boolean conversionRequired;
-        /*
-         * The test below deliberately uses != to compare two Strings. This is
-         * because the code is looking to see if the default character encoding
-         * has been returned because no explicit character encoding has been
-         * defined. There is no clean way of doing this via the Servlet API. It
-         * would be possible to add a Tomcat specific API but that would require
-         * quite a bit of code to get to the Tomcat specific request object that
-         * may have been wrapped. The != test is a (slightly hacky) quick way of
-         * doing this.
-         */
-        boolean outputEncodingSpecified =
-            outputEncoding != org.apache.coyote.Constants.DEFAULT_BODY_CHARSET.name() &&
-            outputEncoding != resources.getContext().getResponseCharacterEncoding();
-        if (!usingPrecompressedVersion && isText(contentType) && outputEncodingSpecified &&
-            !charset.equals(fileEncodingCharset)) {
-            conversionRequired = true;
-            // Conversion often results fewer/more/different bytes.
-            // That does not play nicely with range requests.
-            ranges = FULL;
-        } else {
-            conversionRequired = false;
-        }
-
-        if (resource.isDirectory() || isError || ranges == FULL ) {
-            // Set the appropriate output headers
-            if (contentType != null) {
-                if (debug > 0)
-                    log("DefaultServlet.serveFile:  contentType='" +
-                        contentType + "'");
-                // Don't override a previously set content type
-                if (response.getContentType() == null) {
-                    response.setContentType(contentType);
-                }
-            }
-            if (resource.isFile() && contentLength >= 0 &&
-                (!serveContent || ostream != null)) {
-                if (debug > 0)
-                    log("DefaultServlet.serveFile:  contentLength=" +
-                        contentLength);
-                // Don't set a content length if something else has already
-                // written to the response or if conversion will be taking place
-                if (contentWritten == 0 && !conversionRequired) {
-                    response.setContentLengthLong(contentLength);
-                }
-            }
-
-            if (serveContent) {
-                try {
-                    response.setBufferSize(output);
-                } catch (IllegalStateException e) {
-                    // Silent catch
-                }
-                InputStream renderResult = null;
-                if (ostream == null) {
-                    // Output via a writer so can't use sendfile or write
-                    // content directly.
-                    if (resource.isDirectory()) {
-                        renderResult = render(request, getPathPrefix(request), resource, inputEncoding);
-                    } else {
-                        renderResult = resource.getInputStream();
-                        if (included) {
-                            // Need to make sure any BOM is removed
-                            if (!renderResult.markSupported()) {
-                                renderResult = new BufferedInputStream(renderResult);
-                            }
-                            Charset bomCharset = processBom(renderResult, isStripBOM());
-                            if (bomCharset != null && "true".equals(useBomIfPresent)) {
-                                inputEncoding = bomCharset.name();
-                            }
-                        }
-                    }
-                    copy(renderResult, writer, inputEncoding);
-                } else {
-                    // Output is via an OutputStream
-                    if (resource.isDirectory()) {
-                        renderResult = render(request, getPathPrefix(request), resource, inputEncoding);
-                    } else {
-                        // Output is content of resource
-                        // Check to see if conversion is required
-                        if (conversionRequired || included) {
-                            // When including a file, we need to check for a BOM
-                            // to determine if a conversion is required, so we
-                            // might as well always convert
-                            InputStream source = resource.getInputStream();
-                            if (!source.markSupported()) {
-                                source = new BufferedInputStream(source);
-                            }
-                            Charset bomCharset = processBom(source, isStripBOM());
-                            if (bomCharset != null && "true".equals(useBomIfPresent)) {
-                                inputEncoding = bomCharset.name();
-                            }
-                            // Following test also ensures included resources
-                            // are converted if an explicit output encoding was
-                            // specified
-                            if (outputEncodingSpecified) {
-                                OutputStreamWriter osw = new OutputStreamWriter(ostream, charset);
-                                PrintWriter pw = new PrintWriter(osw);
-                                copy(source, pw, inputEncoding);
-                                pw.flush();
-                            } else {
-                                // Just included but no conversion
-                                renderResult = source;
-                            }
-                        } else {
-                            if (!checkSendfile(request, response, resource, contentLength, null)) {
-                                // sendfile not possible so check if resource
-                                // content is available directly via
-                                // CachedResource. Do not want to call
-                                // getContent() on other resource
-                                // implementations as that could trigger loading
-                                // the contents of a very large file into memory
-                                byte[] resourceBody = null;
-                                if (resource instanceof CachedResource) {
-                                    resourceBody = resource.getContent();
-                                }
-                                if (resourceBody == null) {
-                                    // Resource content not directly available,
-                                    // use InputStream
-                                    renderResult = resource.getInputStream();
-                                } else {
-                                    // Use the resource content directly
-                                    ostream.write(resourceBody);
-                                }
-                            }
-                        }
-                    }
-                    // If a stream was configured, it needs to be copied to
-                    // the output (this method closes the stream)
-                    if (renderResult != null) {
-                        copy(renderResult, ostream);
-                    }
-                }
-            }
-
-        } else {
-
-            if ((ranges == null) || (ranges.isEmpty()))
-                return;
-
-            // Partial content response.
-
-            response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
-
-            if (ranges.size() == 1) {
-
-                Range range = ranges.get(0);
-                response.addHeader("Content-Range", "bytes "
-                                   + range.start
-                                   + "-" + range.end + "/"
-                                   + range.length);
-                long length = range.end - range.start + 1;
-                response.setContentLengthLong(length);
-
-                if (contentType != null) {
-                    if (debug > 0)
-                        log("DefaultServlet.serveFile:  contentType='" +
-                            contentType + "'");
-                    response.setContentType(contentType);
-                }
-
-                if (serveContent) {
-                    try {
-                        response.setBufferSize(output);
-                    } catch (IllegalStateException e) {
-                        // Silent catch
-                    }
-                    if (ostream != null) {
-                        if (!checkSendfile(request, response, resource,
-                                range.end - range.start + 1, range))
-                            copy(resource, ostream, range);
-                    } else {
-                        // we should not get here
-                        throw new IllegalStateException();
-                    }
-                }
-            } else {
-                response.setContentType("multipart/byteranges; boundary="
-                                        + mimeSeparation);
-                if (serveContent) {
-                    try {
-                        response.setBufferSize(output);
-                    } catch (IllegalStateException e) {
-                        // Silent catch
-                    }
-                    if (ostream != null) {
-                        copy(resource, ostream, ranges.iterator(), contentType);
-                    } else {
-                        // we should not get here
-                        throw new IllegalStateException();
-                    }
-                }
-            }
-        }
-    }
-
-    /*
-     * useBomIfPresent can take 3 values (see init): true, false and pass-through
-     *
-     * When later is used, then not only we'll ignore the BOM and use the configured encoding
-     * but we'll also leave the BOM in the output
-     */
-    private boolean isStripBOM() {
-        return !"pass-through".equals(useBomIfPresent);
-    }
-
-    /*
-     * Code borrowed heavily from Jasper's EncodingDetector
-     */
-    private static Charset processBom(final InputStream is, final boolean stripBOM) throws IOException {
-        // Java supported character sets do not use BOMs longer than 4 bytes
-        byte[] bom = new byte[4];
-        is.mark(bom.length);
-
-        int count = is.read(bom);
-
-        // BOMs are at least 2 bytes
-        if (count < 2) {
-            skip(is, 0, stripBOM);
-            return null;
-        }
-
-        // Look for two byte BOMs
-        int b0 = bom[0] & 0xFF;
-        int b1 = bom[1] & 0xFF;
-        if (b0 == 0xFE && b1 == 0xFF) {
-            skip(is, 2, stripBOM);
-            return StandardCharsets.UTF_16BE;
-        }
-        // Delay the UTF_16LE check if there are more that 2 bytes since it
-        // overlaps with UTF-32LE.
-        if (count == 2 && b0 == 0xFF && b1 == 0xFE) {
-            skip(is, 2, stripBOM);
-            return StandardCharsets.UTF_16LE;
-        }
-
-        // Remaining BOMs are at least 3 bytes
-        if (count < 3) {
-            skip(is, 0, stripBOM);
-            return null;
-        }
-
-        // UTF-8 is only 3-byte BOM
-        int b2 = bom[2] & 0xFF;
-        if (b0 == 0xEF && b1 == 0xBB && b2 == 0xBF) {
-            skip(is, 3, stripBOM);
-            return StandardCharsets.UTF_8;
-        }
-
-        if (count < 4) {
-            skip(is, 0, stripBOM);
-            return null;
-        }
-
-        // Look for 4-byte BOMs
-        int b3 = bom[3] & 0xFF;
-        if (b0 == 0x00 && b1 == 0x00 && b2 == 0xFE && b3 == 0xFF) {
-            return Charset.forName("UTF-32BE");
-        }
-        if (b0 == 0xFF && b1 == 0xFE && b2 == 0x00 && b3 == 0x00) {
-            return Charset.forName("UTF-32LE");
-        }
-
-        // Now we can check for UTF16-LE. There is an assumption here that we
-        // won't see a UTF16-LE file with a BOM where the first real data is
-        // 0x00 0x00
-        if (b0 == 0xFF && b1 == 0xFE) {
-            skip(is, 2, stripBOM);
-            return StandardCharsets.UTF_16LE;
-        }
-
-        skip(is, 0, stripBOM);
-        return null;
-    }
-
-
-    private static void skip(final InputStream is, int skip, final boolean stripBOM) throws IOException {
-        is.reset();
-        while (stripBOM && skip-- > 0) {
-            is.read();
-        }
-    }
-
-
-    private static boolean isText(String contentType) {
-        return  contentType == null || contentType.startsWith("text") ||
-                contentType.endsWith("xml") || contentType.contains("/javascript");
-    }
-
-
-    private boolean pathEndsWithCompressedExtension(String path) {
-        for (CompressionFormat format : compressionFormats) {
-            if (path.endsWith(format.extension)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    private List<PrecompressedResource> getAvailablePrecompressedResources(String path) {
-        List<PrecompressedResource> ret = new ArrayList<>(compressionFormats.length);
-        for (CompressionFormat format : compressionFormats) {
-            WebResource precompressedResource = resources.getResource(path + format.extension);
-            if (precompressedResource.exists() && precompressedResource.isFile()) {
-                ret.add(new PrecompressedResource(precompressedResource, format));
-            }
-        }
-        return ret;
-    }
-
-    /**
-     * Match the client preferred encoding formats to the available precompressed resources.
-     *
-     * @param request   The servlet request we are processing
-     * @param precompressedResources   List of available precompressed resources.
-     * @return The best matching precompressed resource or null if no match was found.
-     */
-    private PrecompressedResource getBestPrecompressedResource(HttpServletRequest request,
-                                                               List<PrecompressedResource> precompressedResources) {
-        Enumeration<String> headers = request.getHeaders("Accept-Encoding");
-        PrecompressedResource bestResource = null;
-        double bestResourceQuality = 0;
-        int bestResourcePreference = Integer.MAX_VALUE;
-        while (headers.hasMoreElements()) {
-            String header = headers.nextElement();
-            for (String preference : header.split(",")) {
-                double quality = 1;
-                int qualityIdx = preference.indexOf(';');
-                if (qualityIdx > 0) {
-                    int equalsIdx = preference.indexOf('=', qualityIdx + 1);
-                    if (equalsIdx == -1) {
-                        continue;
-                    }
-                    quality = Double.parseDouble(preference.substring(equalsIdx + 1).trim());
-                }
-                if (quality >= bestResourceQuality) {
-                    String encoding = preference;
-                    if (qualityIdx > 0) {
-                        encoding = encoding.substring(0, qualityIdx);
-                    }
-                    encoding = encoding.trim();
-                    if ("identity".equals(encoding)) {
-                        bestResource = null;
-                        bestResourceQuality = quality;
-                        bestResourcePreference = Integer.MAX_VALUE;
-                        continue;
-                    }
-                    if ("*".equals(encoding)) {
-                        bestResource = precompressedResources.get(0);
-                        bestResourceQuality = quality;
-                        bestResourcePreference = 0;
-                        continue;
-                    }
-                    for (int i = 0; i < precompressedResources.size(); ++i) {
-                        PrecompressedResource resource = precompressedResources.get(i);
-                        if (encoding.equals(resource.format.encoding)) {
-                            if (quality > bestResourceQuality || i < bestResourcePreference) {
-                                bestResource = resource;
-                                bestResourceQuality = quality;
-                                bestResourcePreference = i;
-                            }
-                            break;
-                        }
-                    }
-                }
-            }
-        }
-        return bestResource;
-    }
-
-    private void doDirectoryRedirect(HttpServletRequest request, HttpServletResponse response)
-        throws IOException {
-        StringBuilder location = new StringBuilder(request.getRequestURI());
-        location.append('/');
-        if (request.getQueryString() != null) {
-            location.append('?');
-            location.append(request.getQueryString());
-        }
-        // Avoid protocol relative redirects
-        while (location.length() > 1 && location.charAt(1) == '/') {
-            location.deleteCharAt(0);
-        }
-        response.sendRedirect(response.encodeRedirectURL(location.toString()));
-    }
-
-    /**
-     * Parse the content-range header.
-     *
-     * @param request The servlet request we are processing
-     * @param response The servlet response we are creating
-     * @return the partial content-range, {@code null} if the content-range
-     *         header was invalid or {@code #IGNORE} if there is no header to
-     *         process
-     * @throws IOException an IO error occurred
-     */
-    protected Range parseContentRange(HttpServletRequest request,
-                                             HttpServletResponse response)
-        throws IOException {
-
-        // Retrieving the content-range header (if any is specified
-        String contentRangeHeader = request.getHeader("Content-Range");
-
-        if (contentRangeHeader == null) {
-            return IGNORE;
-        }
-
-        if (!allowPartialPut) {
-            response.sendError(HttpServletResponse.SC_BAD_REQUEST);
-            return null;
-        }
-
-        ContentRange contentRange = ContentRange.parse(new StringReader(contentRangeHeader));
-
-        if (contentRange == null) {
-            response.sendError(HttpServletResponse.SC_BAD_REQUEST);
-            return null;
-        }
-
-
-        // bytes is the only range unit supported
-        if (!contentRange.getUnits().equals("bytes")) {
-            response.sendError(HttpServletResponse.SC_BAD_REQUEST);
-            return null;
-        }
-
-        // TODO: Remove the internal representation and use Ranges
-        // Convert to internal representation
-        Range range = new Range();
-        range.start = contentRange.getStart();
-        range.end = contentRange.getEnd();
-        range.length = contentRange.getLength();
-
-        if (!range.validate()) {
-            response.sendError(HttpServletResponse.SC_BAD_REQUEST);
-            return null;
-        }
-
-        return range;
-    }
-
-
-    /**
-     * Parse the range header.
-     *
-     * @param request   The servlet request we are processing
-     * @param response  The servlet response we are creating
-     * @param resource  The resource
-     * @return a list of ranges, {@code null} if the range header was invalid or
-     *         {@code #FULL} if the Range header should be ignored.
-     * @throws IOException an IO error occurred
-     */
-    protected ArrayList<Range> parseRange(HttpServletRequest request,
-                                HttpServletResponse response,
-                                WebResource resource) throws IOException {
-
-        // Range headers are only valid on GET requests. That implies they are
-        // also valid on HEAD requests. This method is only called by doGet()
-        // and doHead() so no need to check the request method.
-
-        // Checking If-Range
-        String headerValue = request.getHeader("If-Range");
-
-        if (headerValue != null) {
-
-            long headerValueTime = (-1L);
-            try {
-                headerValueTime = request.getDateHeader("If-Range");
-            } catch (IllegalArgumentException e) {
-                // Ignore
-            }
-
-            String eTag = generateETag(resource);
-            long lastModified = resource.getLastModified();
-
-            if (headerValueTime == (-1L)) {
-                // If the ETag the client gave does not match the entity
-                // etag, then the entire entity is returned.
-                if (!eTag.equals(headerValue.trim())) {
-                    return FULL;
-                }
-            } else {
-                // If the timestamp of the entity the client got differs from
-                // the last modification date of the entity, the entire entity
-                // is returned.
-                if (Math.abs(lastModified - headerValueTime) > 1000) {
-                    return FULL;
-                }
-            }
-        }
-
-        long fileLength = resource.getContentLength();
-
-        if (fileLength == 0) {
-            // Range header makes no sense for a zero length resource. Tomcat
-            // therefore opts to ignore it.
-            return FULL;
-        }
-
-        // Retrieving the range header (if any is specified
-        String rangeHeader = request.getHeader("Range");
-
-        if (rangeHeader == null) {
-            // No Range header is the same as ignoring any Range header
-            return FULL;
-        }
-
-        Ranges ranges = Ranges.parse(new StringReader(rangeHeader));
-
-        if (ranges == null) {
-            // The Range header is present but not formatted correctly.
-            // Could argue for a 400 response but 416 is more specific.
-            // There is also the option to ignore the (invalid) Range header.
-            // RFC7233#4.4 notes that many servers do ignore the Range header in
-            // these circumstances but Tomcat has always returned a 416.
-            response.addHeader("Content-Range", "bytes */" + fileLength);
-            response.sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE);
-            return null;
-        }
-
-        // bytes is the only range unit supported (and I don't see the point
-        // of adding new ones).
-        if (!ranges.getUnits().equals("bytes")) {
-            // RFC7233#3.1 Servers must ignore range units they don't understand
-            return FULL;
-        }
-
-        // TODO: Remove the internal representation and use Ranges
-        // Convert to internal representation
-        ArrayList<Range> result = new ArrayList<>();
-
-        for (Ranges.Entry entry : ranges.getEntries()) {
-            Range currentRange = new Range();
-            if (entry.getStart() == -1) {
-                currentRange.start = fileLength - entry.getEnd();
-                if (currentRange.start < 0) {
-                    currentRange.start = 0;
-                }
-                currentRange.end = fileLength - 1;
-            } else if (entry.getEnd() == -1) {
-                currentRange.start = entry.getStart();
-                currentRange.end = fileLength - 1;
-            } else {
-                currentRange.start = entry.getStart();
-                currentRange.end = entry.getEnd();
-            }
-            currentRange.length = fileLength;
-
-            if (!currentRange.validate()) {
-                response.addHeader("Content-Range", "bytes */" + fileLength);
-                response.sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE);
-                return null;
-            }
-
-            result.add(currentRange);
-        }
-
-        return result;
-    }
-
-
-    /**
-     * Decide which way to render. HTML or XML.
-     *
-     * @param contextPath The path
-     * @param resource    The resource
-     * @param encoding    The encoding to use to process the readme (if any)
-     *
-     * @return the input stream with the rendered output
-     *
-     * @throws IOException an IO error occurred
-     * @throws ServletException rendering error
-     *
-     * @deprecated Use {@link #render(HttpServletRequest, String, WebResource, String)} instead
-     */
-    @Deprecated
-    protected InputStream render(String contextPath, WebResource resource, String encoding)
-        throws IOException, ServletException {
-
-        return render(null, contextPath, resource, encoding);
-    }
-
-    /**
-     * Decide which way to render. HTML or XML.
-     *
-     * @param request     The HttpServletRequest being served
-     * @param contextPath The path
-     * @param resource    The resource
-     * @param encoding    The encoding to use to process the readme (if any)
-     *
-     * @return the input stream with the rendered output
-     *
-     * @throws IOException an IO error occurred
-     * @throws ServletException rendering error
-     */
-    protected InputStream render(HttpServletRequest request, String contextPath, WebResource resource, String encoding)
-        throws IOException, ServletException {
-
-        Source xsltSource = findXsltSource(resource);
-
-        if (xsltSource == null) {
-            return renderHtml(request, contextPath, resource, encoding);
-        }
-        return renderXml(request, contextPath, resource, xsltSource, encoding);
-    }
-
-
-    /**
-     * Return an InputStream to an XML representation of the contents this
-     * directory.
-     *
-     * @param contextPath Context path to which our internal paths are relative
-     * @param resource    The associated resource
-     * @param xsltSource  The XSL stylesheet
-     * @param encoding    The encoding to use to process the readme (if any)
-     *
-     * @return the XML data
-     *
-     * @throws IOException an IO error occurred
-     * @throws ServletException rendering error
-     * @deprecated Unused. Will be removed in Tomcat 10
-     * @deprecated Use {@link #render(HttpServletRequest, String, WebResource, String)} instead
-     */
-    @Deprecated
-    protected InputStream renderXml(String contextPath, WebResource resource, Source xsltSource,
-            String encoding)
-        throws ServletException, IOException
-    {
-        return renderXml(null, contextPath, resource, xsltSource, encoding);
-    }
-
-    /**
-     * Return an InputStream to an XML representation of the contents this
-     * directory.
-     *
-     * @param request     The HttpServletRequest being served
-     * @param contextPath Context path to which our internal paths are relative
-     * @param resource    The associated resource
-     * @param xsltSource  The XSL stylesheet
-     * @param encoding    The encoding to use to process the readme (if any)
-     *
-     * @return the XML data
-     *
-     * @throws IOException an IO error occurred
-     * @throws ServletException rendering error
-     */
-    protected InputStream renderXml(HttpServletRequest request, String contextPath, WebResource resource, Source xsltSource,
-                                    String encoding)
-        throws IOException, ServletException {
-
-        StringBuilder sb = new StringBuilder();
-
-        sb.append("<?xml version=\"1.0\"?>");
-        sb.append("<listing ");
-        sb.append(" contextPath='");
-        sb.append(contextPath);
-        sb.append('\'');
-        sb.append(" directory='");
-        sb.append(resource.getName());
-        sb.append("' ");
-        sb.append(" hasParent='").append(!resource.getName().equals("/"));
-        sb.append("'>");
-
-        sb.append("<entries>");
-
-        String[] entries = resources.list(resource.getWebappPath());
-
-        // rewriteUrl(contextPath) is expensive. cache result for later reuse
-        String rewrittenContextPath =  rewriteUrl(contextPath);
-        String directoryWebappPath = resource.getWebappPath();
-
-        for (String entry : entries) {
-
-            if (entry.equalsIgnoreCase("WEB-INF") ||
-                entry.equalsIgnoreCase("META-INF") ||
-                entry.equalsIgnoreCase(localXsltFile))
-                continue;
-
-            if ((directoryWebappPath + entry).equals(contextXsltFile))
-                continue;
-
-            WebResource childResource =
-                resources.getResource(directoryWebappPath + entry);
-            if (!childResource.exists()) {
-                continue;
-            }
-
-            sb.append("<entry");
-            sb.append(" type='")
-              .append(childResource.isDirectory()?"dir":"file")
-              .append('\'');
-            sb.append(" urlPath='")
-              .append(rewrittenContextPath)
-              .append(rewriteUrl(directoryWebappPath + entry))
-              .append(childResource.isDirectory()?"/":"")
-              .append('\'');
-            if (childResource.isFile()) {
-                sb.append(" size='")
-                  .append(renderSize(childResource.getContentLength()))
-                  .append('\'');
-            }
-            sb.append(" date='")
-              .append(childResource.getLastModifiedHttp())
-              .append('\'');
-
-            sb.append('>');
-            sb.append(Escape.htmlElementContent(entry));
-            if (childResource.isDirectory())
-                sb.append('/');
-            sb.append("</entry>");
-        }
-        sb.append("</entries>");
-
-        String readme = getReadme(resource, encoding);
-
-        if (readme!=null) {
-            sb.append("<readme><![CDATA[");
-            sb.append(readme);
-            sb.append("]]></readme>");
-        }
-
-        sb.append("</listing>");
-
-        // Prevent possible memory leak. Ensure Transformer and
-        // TransformerFactory are not loaded from the web application.
-        ClassLoader original;
-        if (Globals.IS_SECURITY_ENABLED) {
-            PrivilegedGetTccl pa = new PrivilegedGetTccl();
-            original = AccessController.doPrivileged(pa);
-        } else {
-            original = Thread.currentThread().getContextClassLoader();
-        }
-        try {
-            if (Globals.IS_SECURITY_ENABLED) {
-                PrivilegedSetTccl pa =
-                    new PrivilegedSetTccl(DefaultServlet.class.getClassLoader());
-                AccessController.doPrivileged(pa);
-            } else {
-                Thread.currentThread().setContextClassLoader(
-                    DefaultServlet.class.getClassLoader());
-            }
-
-            TransformerFactory tFactory = TransformerFactory.newInstance();
-            Source xmlSource = new StreamSource(new StringReader(sb.toString()));
-            Transformer transformer = tFactory.newTransformer(xsltSource);
-
-            ByteArrayOutputStream stream = new ByteArrayOutputStream();
-            OutputStreamWriter osWriter = new OutputStreamWriter(stream, StandardCharsets.UTF_8);
-            StreamResult out = new StreamResult(osWriter);
-            transformer.transform(xmlSource, out);
-            osWriter.flush();
-            return new ByteArrayInputStream(stream.toByteArray());
-        } catch (TransformerException e) {
-            throw new ServletException(sm.getString("defaultServlet.xslError"), e);
-        } finally {
-            if (Globals.IS_SECURITY_ENABLED) {
-                PrivilegedSetTccl pa = new PrivilegedSetTccl(original);
-                AccessController.doPrivileged(pa);
-            } else {
-                Thread.currentThread().setContextClassLoader(original);
-            }
-        }
-    }
-
-    /**
-     * Return an InputStream to an HTML representation of the contents of this
-     * directory.
-     *
-     * @param contextPath Context path to which our internal paths are relative
-     * @param resource    The associated resource
-     * @param encoding    The encoding to use to process the readme (if any)
-     *
-     * @return the HTML data
-     *
-     * @throws IOException an IO error occurred
-     *
-     * @deprecated Unused. Will be removed in Tomcat 10
-     * @deprecated Use {@link #renderHtml(HttpServletRequest, String, WebResource, String)} instead
-     */
-    @Deprecated
-    protected InputStream renderHtml(String contextPath, WebResource resource, String encoding)
-        throws IOException {
-        return renderHtml(null, contextPath, resource, encoding);
-    }
-
-    /**
-     * Return an InputStream to an HTML representation of the contents of this
-     * directory.
-     *
-     * @param request     The HttpServletRequest being served
-     * @param contextPath Context path to which our internal paths are relative
-     * @param resource    The associated resource
-     * @param encoding    The encoding to use to process the readme (if any)
-     *
-     * @return the HTML data
-     *
-     * @throws IOException an IO error occurred
-     */
-    protected InputStream renderHtml(HttpServletRequest request, String contextPath, WebResource resource, String encoding)
-        throws IOException {
-
-        // Prepare a writer to a buffered area
-        ByteArrayOutputStream stream = new ByteArrayOutputStream();
-        OutputStreamWriter osWriter = new OutputStreamWriter(stream, StandardCharsets.UTF_8);
-        PrintWriter writer = new PrintWriter(osWriter);
-
-        StringBuilder sb = new StringBuilder();
-
-        String directoryWebappPath = resource.getWebappPath();
-        WebResource[] entries = resources.listResources(directoryWebappPath);
-
-        // rewriteUrl(contextPath) is expensive. cache result for later reuse
-        String rewrittenContextPath =  rewriteUrl(contextPath);
-
-        // Render the page header
-        sb.append("<!doctype html><html>\r\n");
-        /* TODO Activate this as soon as we use smClient with the request locales
-        sb.append("<!doctype html><html lang=\"");
-        sb.append(smClient.getLocale().getLanguage()).append("\">\r\n");
-        */
-        sb.append("<head>\r\n");
-        sb.append("<title>");
-        sb.append(sm.getString("directory.title", directoryWebappPath));
-        sb.append("</title>\r\n");
-        sb.append("<style>");
-        sb.append(org.apache.catalina.util.TomcatCSS.TOMCAT_CSS);
-        sb.append("</style> ");
-        sb.append("</head>\r\n");
-        sb.append("<body>");
-        sb.append("<h1>");
-        sb.append(sm.getString("directory.title", directoryWebappPath));
-
-        // Render the link to our parent (if required)
-        String parentDirectory = directoryWebappPath;
-        if (parentDirectory.endsWith("/")) {
-            parentDirectory =
-                parentDirectory.substring(0, parentDirectory.length() - 1);
-        }
-        int slash = parentDirectory.lastIndexOf('/');
-        if (slash >= 0) {
-            String parent = directoryWebappPath.substring(0, slash);
-            sb.append(" - <a href=\"");
-            sb.append(rewrittenContextPath);
-            if (parent.equals(""))
-                parent = "/";
-            sb.append(rewriteUrl(parent));
-            if (!parent.endsWith("/"))
-                sb.append('/');
-            sb.append("\">");
-            sb.append("<b>");
-            sb.append(sm.getString("directory.parent", parent));
-            sb.append("</b>");
-            sb.append("</a>");
-        }
-
-        sb.append("</h1>");
-        sb.append("<hr class=\"line\">");
-
-        sb.append("<table width=\"100%\" cellspacing=\"0\"" +
-                  " cellpadding=\"5\" align=\"center\">\r\n");
-
-        SortManager.Order order;
-        if(sortListings && null != request)
-            order = sortManager.getOrder(request.getQueryString());
-        else
-            order = null;
-        // Render the column headings
-        sb.append("<tr>\r\n");
-        sb.append("<td align=\"left\"><font size=\"+1\"><strong>");
-        if(sortListings && null != request) {
-            sb.append("<a href=\"?C=N;O=");
-            sb.append(getOrderChar(order, 'N'));
-            sb.append("\">");
-            sb.append(sm.getString("directory.filename"));
-            sb.append("</a>");
-        } else {
-            sb.append(sm.getString("directory.filename"));
-        }
-        sb.append("</strong></font></td>\r\n");
-        sb.append("<td align=\"center\"><font size=\"+1\"><strong>");
-        if(sortListings && null != request) {
-            sb.append("<a href=\"?C=S;O=");
-            sb.append(getOrderChar(order, 'S'));
-            sb.append("\">");
-            sb.append(sm.getString("directory.size"));
-            sb.append("</a>");
-        } else {
-            sb.append(sm.getString("directory.size"));
-        }
-        sb.append("</strong></font></td>\r\n");
-        sb.append("<td align=\"right\"><font size=\"+1\"><strong>");
-        if(sortListings && null != request) {
-            sb.append("<a href=\"?C=M;O=");
-            sb.append(getOrderChar(order, 'M'));
-            sb.append("\">");
-            sb.append(sm.getString("directory.lastModified"));
-            sb.append("</a>");
-        } else {
-            sb.append(sm.getString("directory.lastModified"));
-        }
-        sb.append("</strong></font></td>\r\n");
-        sb.append("</tr>");
-
-        if(null != sortManager && null != request) {
-            sortManager.sort(entries, request.getQueryString());
-        }
-
-        boolean shade = false;
-        for (WebResource childResource : entries) {
-            String filename = childResource.getName();
-            if (filename.equalsIgnoreCase("WEB-INF") ||
-                filename.equalsIgnoreCase("META-INF"))
-                continue;
-
-            if (!childResource.exists()) {
-                continue;
-            }
-
-            sb.append("<tr");
-            if (shade)
-                sb.append(" bgcolor=\"#eeeeee\"");
-            sb.append(">\r\n");
-            shade = !shade;
-
-            sb.append("<td align=\"left\">&nbsp;&nbsp;\r\n");
-            sb.append("<a href=\"");
-            sb.append(rewrittenContextPath);
-            sb.append(rewriteUrl(childResource.getWebappPath()));
-            if (childResource.isDirectory())
-                sb.append('/');
-            sb.append("\"><tt>");
-            sb.append(Escape.htmlElementContent(filename));
-            if (childResource.isDirectory())
-                sb.append('/');
-            sb.append("</tt></a></td>\r\n");
-
-            sb.append("<td align=\"right\"><tt>");
-            if (childResource.isDirectory())
-                sb.append("&nbsp;");
-            else
-                sb.append(renderSize(childResource.getContentLength()));
-            sb.append("</tt></td>\r\n");
-
-            sb.append("<td align=\"right\"><tt>");
-            sb.append(childResource.getLastModifiedHttp());
-            sb.append("</tt></td>\r\n");
-
-            sb.append("</tr>\r\n");
-        }
-
-        // Render the page footer
-        sb.append("</table>\r\n");
-
-        sb.append("<hr class=\"line\">");
-
-        String readme = getReadme(resource, encoding);
-        if (readme!=null) {
-            sb.append(readme);
-            sb.append("<hr class=\"line\">");
-        }
-
-        if (showServerInfo) {
-            sb.append("<h3>").append(ServerInfo.getServerInfo()).append("</h3>");
-        }
-        sb.append("</body>\r\n");
-        sb.append("</html>\r\n");
-
-        // Return an input stream to the underlying bytes
-        writer.write(sb.toString());
-        writer.flush();
-        return new ByteArrayInputStream(stream.toByteArray());
-
-    }
-
-
-    /**
-     * Render the specified file size (in bytes).
-     *
-     * @param size File size (in bytes)
-     * @return the formatted size
-     */
-    protected String renderSize(long size) {
-
-        long leftSide = size / 1024;
-        long rightSide = (size % 1024) / 103;   // Makes 1 digit
-        if ((leftSide == 0) && (rightSide == 0) && (size > 0))
-            rightSide = 1;
-
-        return ("" + leftSide + "." + rightSide + " kb");
-
-    }
-
-
-    /**
-     * Get the readme file as a string.
-     * @param directory The directory to search
-     * @param encoding The readme encoding
-     * @return the readme for the specified directory
-     */
-    protected String getReadme(WebResource directory, String encoding) {
-
-        if (readmeFile != null) {
-            WebResource resource = resources.getResource(
-                directory.getWebappPath() + readmeFile);
-            if (resource.isFile()) {
-                StringWriter buffer = new StringWriter();
-                InputStreamReader reader = null;
-                try (InputStream is = resource.getInputStream()){
-                    if (encoding != null) {
-                        reader = new InputStreamReader(is, encoding);
-                    } else {
-                        reader = new InputStreamReader(is);
-                    }
-                    copyRange(reader, new PrintWriter(buffer));
-                } catch (IOException e) {
-                    log(sm.getString("defaultServlet.readerCloseFailed"), e);
-                } finally {
-                    if (reader != null) {
-                        try {
-                            reader.close();
-                        } catch (IOException e) {
-                        }
-                    }
-                }
-                return buffer.toString();
-            } else {
-                if (debug > 10)
-                    log("readme '" + readmeFile + "' not found");
-
-                return null;
-            }
-        }
-
-        return null;
-    }
-
-
-    /**
-     * Return a Source for the xsl template (if possible).
-     * @param directory The directory to search
-     * @return the source for the specified directory
-     * @throws IOException an IO error occurred
-     */
-    protected Source findXsltSource(WebResource directory)
-        throws IOException {
-
-        if (localXsltFile != null) {
-            WebResource resource = resources.getResource(
-                directory.getWebappPath() + localXsltFile);
-            if (resource.isFile()) {
-                InputStream is = resource.getInputStream();
-                if (is != null) {
-                    if (Globals.IS_SECURITY_ENABLED) {
-                        return secureXslt(is);
-                    } else {
-                        return new StreamSource(is);
-                    }
-                }
-            }
-            if (debug > 10) {
-                log("localXsltFile '" + localXsltFile + "' not found");
-            }
-        }
-
-        if (contextXsltFile != null) {
-            InputStream is =
-                getServletContext().getResourceAsStream(contextXsltFile);
-            if (is != null) {
-                if (Globals.IS_SECURITY_ENABLED) {
-                    return secureXslt(is);
-                } else {
-                    return new StreamSource(is);
-                }
-            }
-
-            if (debug > 10)
-                log("contextXsltFile '" + contextXsltFile + "' not found");
-        }
-
-        /*  Open and read in file in one fell swoop to reduce chance
-         *  chance of leaving handle open.
-         */
-        if (globalXsltFile != null) {
-            File f = validateGlobalXsltFile();
-            if (f != null) {
-                long globalXsltFileSize = f.length();
-                if (globalXsltFileSize > Integer.MAX_VALUE) {
-                    log("globalXsltFile [" + f.getAbsolutePath() + "] is too big to buffer");
-                } else {
-                    try (FileInputStream fis = new FileInputStream(f)){
-                        byte b[] = new byte[(int)f.length()];
-                        IOTools.readFully(fis, b);
-                        return new StreamSource(new ByteArrayInputStream(b));
-                    }
-                }
-            }
-        }
-
-        return null;
-    }
-
-
-    private File validateGlobalXsltFile() {
-        Context context = resources.getContext();
-
-        File baseConf = new File(context.getCatalinaBase(), "conf");
-        File result = validateGlobalXsltFile(baseConf);
-        if (result == null) {
-            File homeConf = new File(context.getCatalinaHome(), "conf");
-            if (!baseConf.equals(homeConf)) {
-                result = validateGlobalXsltFile(homeConf);
-            }
-        }
-
-        return result;
-    }
-
-
-    private File validateGlobalXsltFile(File base) {
-        File candidate = new File(globalXsltFile);
-        if (!candidate.isAbsolute()) {
-            candidate = new File(base, globalXsltFile);
-        }
-
-        if (!candidate.isFile()) {
-            return null;
-        }
-
-        // First check that the resulting path is under the provided base
-        try {
-            if (!candidate.getCanonicalFile().toPath().startsWith(base.getCanonicalFile().toPath())) {
-                return null;
-            }
-        } catch (IOException ioe) {
-            return null;
-        }
-
-        // Next check that an .xsl or .xslt file has been specified
-        String nameLower = candidate.getName().toLowerCase(Locale.ENGLISH);
-        if (!nameLower.endsWith(".xslt") && !nameLower.endsWith(".xsl")) {
-            return null;
-        }
-
-        return candidate;
-    }
-
-
-    private Source secureXslt(InputStream is) {
-        // Need to filter out any external entities
-        Source result = null;
-        try {
-            DocumentBuilder builder = factory.newDocumentBuilder();
-            builder.setEntityResolver(secureEntityResolver);
-            Document document = builder.parse(is);
-            result = new DOMSource(document);
-        } catch (ParserConfigurationException | SAXException | IOException e) {
-            if (debug > 0) {
-                log(e.getMessage(), e);
-            }
-        } finally {
-            if (is != null) {
-                try {
-                    is.close();
-                } catch (IOException e) {
-                    // Ignore
-                }
-            }
-        }
-        return result;
-    }
-
-
-    // -------------------------------------------------------- protected Methods
-
-    /**
-     * Check if sendfile can be used.
-     * @param request The Servlet request
-     * @param response The Servlet response
-     * @param resource The resource
-     * @param length The length which will be written (will be used only if
-     *  range is null)
-     * @param range The range that will be written
-     * @return <code>true</code> if sendfile should be used (writing is then
-     *  delegated to the endpoint)
-     */
-    protected boolean checkSendfile(HttpServletRequest request,
-                                    HttpServletResponse response,
-                                    WebResource resource,
-                                  long length, Range range) {
-        String canonicalPath;
-        if (sendfileSize > 0
-            && length > sendfileSize
-            && (Boolean.TRUE.equals(request.getAttribute(Globals.SENDFILE_SUPPORTED_ATTR)))
-            && (request.getClass().getName().equals("org.apache.catalina.connector.RequestFacade"))
-            && (response.getClass().getName().equals("org.apache.catalina.connector.ResponseFacade"))
-            && resource.isFile()
-            && ((canonicalPath = resource.getCanonicalPath()) != null)
-        ) {
-            request.setAttribute(Globals.SENDFILE_FILENAME_ATTR, canonicalPath);
-            if (range == null) {
-                request.setAttribute(Globals.SENDFILE_FILE_START_ATTR, Long.valueOf(0L));
-                request.setAttribute(Globals.SENDFILE_FILE_END_ATTR, Long.valueOf(length));
-            } else {
-                request.setAttribute(Globals.SENDFILE_FILE_START_ATTR, Long.valueOf(range.start));
-                request.setAttribute(Globals.SENDFILE_FILE_END_ATTR, Long.valueOf(range.end + 1));
-            }
-            return true;
-        }
-        return false;
-    }
-
-
-    /**
-     * Check if the if-match condition is satisfied.
-     *
-     * @param request   The servlet request we are processing
-     * @param response  The servlet response we are creating
-     * @param resource  The resource
-     * @return <code>true</code> if the resource meets the specified condition,
-     *  and <code>false</code> if the condition is not satisfied, in which case
-     *  request processing is stopped
-     * @throws IOException an IO error occurred
-     */
-    protected boolean checkIfMatch(HttpServletRequest request, HttpServletResponse response, WebResource resource)
-        throws IOException {
-
-        String headerValue = request.getHeader("If-Match");
-        if (headerValue != null) {
-
-            boolean conditionSatisfied;
-
-            if (!headerValue.equals("*")) {
-                String resourceETag = generateETag(resource);
-                if (resourceETag == null) {
-                    conditionSatisfied = false;
-                } else {
-                    // RFC 7232 requires strong comparison for If-Match headers
-                    Boolean matched = EntityTag.compareEntityTag(new StringReader(headerValue), false, resourceETag);
-                    if (matched == null) {
-                        if (debug > 10) {
-                            log("DefaultServlet.checkIfMatch:  Invalid header value [" + headerValue + "]");
-                        }
-                        response.sendError(HttpServletResponse.SC_BAD_REQUEST);
-                        return false;
-                    }
-                    conditionSatisfied = matched.booleanValue();
-                }
-            } else {
-                conditionSatisfied = true;
-            }
-
-            if (!conditionSatisfied) {
-                response.sendError(HttpServletResponse.SC_PRECONDITION_FAILED);
-                return false;
-            }
-        }
-        return true;
-    }
-
-
-    /**
-     * Check if the if-modified-since condition is satisfied.
-     *
-     * @param request   The servlet request we are processing
-     * @param response  The servlet response we are creating
-     * @param resource  The resource
-     * @return <code>true</code> if the resource meets the specified condition,
-     *  and <code>false</code> if the condition is not satisfied, in which case
-     *  request processing is stopped
-     */
-    protected boolean checkIfModifiedSince(HttpServletRequest request,
-                                           HttpServletResponse response, WebResource resource) {
-        try {
-            long headerValue = request.getDateHeader("If-Modified-Since");
-            long lastModified = resource.getLastModified();
-            if (headerValue != -1) {
-
-                // If an If-None-Match header has been specified, if modified since
-                // is ignored.
-                if ((request.getHeader("If-None-Match") == null)
-                    && (lastModified < headerValue + 1000)) {
-                    // The entity has not been modified since the date
-                    // specified by the client. This is not an error case.
-                    response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
-                    response.setHeader("ETag", generateETag(resource));
-
-                    return false;
-                }
-            }
-        } catch (IllegalArgumentException illegalArgument) {
-            return true;
-        }
-        return true;
-    }
-
-
-    /**
-     * Check if the if-none-match condition is satisfied.
-     *
-     * @param request   The servlet request we are processing
-     * @param response  The servlet response we are creating
-     * @param resource  The resource
-     * @return <code>true</code> if the resource meets the specified condition,
-     *  and <code>false</code> if the condition is not satisfied, in which case
-     *  request processing is stopped
-     * @throws IOException an IO error occurred
-     */
-    protected boolean checkIfNoneMatch(HttpServletRequest request, HttpServletResponse response, WebResource resource)
-        throws IOException {
-
-        String headerValue = request.getHeader("If-None-Match");
-        if (headerValue != null) {
-
-            boolean conditionSatisfied;
-
-            String resourceETag = generateETag(resource);
-            if (!headerValue.equals("*")) {
-                if (resourceETag == null) {
-                    conditionSatisfied = false;
-                } else {
-                    // RFC 7232 requires weak comparison for If-None-Match headers
-                    Boolean matched = EntityTag.compareEntityTag(new StringReader(headerValue), true, resourceETag);
-                    if (matched == null) {
-                        if (debug > 10) {
-                            log("DefaultServlet.checkIfNoneMatch:  Invalid header value [" + headerValue + "]");
-                        }
-                        response.sendError(HttpServletResponse.SC_BAD_REQUEST);
-                        return false;
-                    }
-                    conditionSatisfied = matched.booleanValue();
-                }
-            } else {
-                conditionSatisfied = true;
-            }
-
-            if (conditionSatisfied) {
-                // For GET and HEAD, we should respond with
-                // 304 Not Modified.
-                // For every other method, 412 Precondition Failed is sent
-                // back.
-                if ("GET".equals(request.getMethod()) || "HEAD".equals(request.getMethod())) {
-                    response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
-                    response.setHeader("ETag", resourceETag);
-                } else {
-                    response.sendError(HttpServletResponse.SC_PRECONDITION_FAILED);
-                }
-                return false;
-            }
-        }
-        return true;
-    }
-
-
-    /**
-     * Check if the if-unmodified-since condition is satisfied.
-     *
-     * @param request   The servlet request we are processing
-     * @param response  The servlet response we are creating
-     * @param resource  The resource
-     * @return <code>true</code> if the resource meets the specified condition,
-     *  and <code>false</code> if the condition is not satisfied, in which case
-     *  request processing is stopped
-     * @throws IOException an IO error occurred
-     */
-    protected boolean checkIfUnmodifiedSince(HttpServletRequest request,
-                                             HttpServletResponse response, WebResource resource)
-        throws IOException {
-        try {
-            long lastModified = resource.getLastModified();
-            long headerValue = request.getDateHeader("If-Unmodified-Since");
-            if (headerValue != -1) {
-                if ( lastModified >= (headerValue + 1000)) {
-                    // The entity has not been modified since the date
-                    // specified by the client. This is not an error case.
-                    response.sendError(HttpServletResponse.SC_PRECONDITION_FAILED);
-                    return false;
-                }
-            }
-        } catch(IllegalArgumentException illegalArgument) {
-            return true;
-        }
-        return true;
-    }
-
-
-    /**
-     * Provides the entity tag (the ETag header) for the given resource.
-     * Intended to be over-ridden by custom DefaultServlet implementations that
-     * wish to use an alternative format for the entity tag.
-     *
-     * @param resource  The resource for which an entity tag is required.
-     *
-     * @return The result of calling {@link WebResource#getETag()} on the given
-     *         resource
-     */
-    protected String generateETag(WebResource resource) {
-        return resource.getETag();
-    }
-
-
-    /**
-     * Copy the contents of the specified input stream to the specified
-     * output stream, and ensure that both streams are closed before returning
-     * (even in the face of an exception).
-     *
-     * @param is        The input stream to read the source resource from
-     * @param ostream   The output stream to write to
-     *
-     * @exception IOException if an input/output error occurs
-     */
-    protected void copy(InputStream is, ServletOutputStream ostream) throws IOException {
-
-        IOException exception = null;
-        InputStream istream = new BufferedInputStream(is, input);
-
-        // Copy the input stream to the output stream
-        exception = copyRange(istream, ostream);
-
-        // Clean up the input stream
-        istream.close();
-
-        // Rethrow any exception that has occurred
-        if (exception != null)
-            throw exception;
-    }
-
-
-    /**
-     * Copy the contents of the specified input stream to the specified
-     * output stream, and ensure that both streams are closed before returning
-     * (even in the face of an exception).
-     *
-     * @param is        The input stream to read the source resource from
-     * @param writer    The writer to write to
-     * @param encoding  The encoding to use when reading the source input stream
-     *
-     * @exception IOException if an input/output error occurs
-     */
-    protected void copy(InputStream is, PrintWriter writer, String encoding) throws IOException {
-        IOException exception = null;
-
-        Reader reader;
-        if (encoding == null) {
-            reader = new InputStreamReader(is);
-        } else {
-            reader = new InputStreamReader(is, encoding);
-        }
-
-        // Copy the input stream to the output stream
-        exception = copyRange(reader, writer);
-
-        // Clean up the reader
-        reader.close();
-
-        // Rethrow any exception that has occurred
-        if (exception != null) {
-            throw exception;
-        }
-    }
-
-
-    /**
-     * Copy the contents of the specified input stream to the specified
-     * output stream, and ensure that both streams are closed before returning
-     * (even in the face of an exception).
-     *
-     * @param resource  The source resource
-     * @param ostream   The output stream to write to
-     * @param range     Range the client wanted to retrieve
-     * @exception IOException if an input/output error occurs
-     */
-    protected void copy(WebResource resource, ServletOutputStream ostream,
-                      Range range)
-        throws IOException {
-
-        IOException exception = null;
-
-        InputStream resourceInputStream = resource.getInputStream();
-        InputStream istream =
-            new BufferedInputStream(resourceInputStream, input);
-        exception = copyRange(istream, ostream, range.start, range.end);
-
-        // Clean up the input stream
-        istream.close();
-
-        // Rethrow any exception that has occurred
-        if (exception != null)
-            throw exception;
-
-    }
-
-
-    /**
-     * Copy the contents of the specified input stream to the specified
-     * output stream, and ensure that both streams are closed before returning
-     * (even in the face of an exception).
-     *
-     * @param resource      The source resource
-     * @param ostream       The output stream to write to
-     * @param ranges        Enumeration of the ranges the client wanted to
-     *                          retrieve
-     * @param contentType   Content type of the resource
-     * @exception IOException if an input/output error occurs
-     */
-    protected void copy(WebResource resource, ServletOutputStream ostream,
-                      Iterator<Range> ranges, String contentType)
-        throws IOException {
-
-        IOException exception = null;
-
-        while ( (exception == null) && (ranges.hasNext()) ) {
-
-            InputStream resourceInputStream = resource.getInputStream();
-            try (InputStream istream = new BufferedInputStream(resourceInputStream, input)) {
-
-                Range currentRange = ranges.next();
-
-                // Writing MIME header.
-                ostream.println();
-                ostream.println("--" + mimeSeparation);
-                if (contentType != null)
-                    ostream.println("Content-Type: " + contentType);
-                ostream.println("Content-Range: bytes " + currentRange.start
-                               + "-" + currentRange.end + "/"
-                               + currentRange.length);
-                ostream.println();
-
-                // Printing content
-                exception = copyRange(istream, ostream, currentRange.start,
-                                      currentRange.end);
-            }
-        }
-
-        ostream.println();
-        ostream.print("--" + mimeSeparation + "--");
-
-        // Rethrow any exception that has occurred
-        if (exception != null)
-            throw exception;
-
-    }
-
-
-    /**
-     * Copy the contents of the specified input stream to the specified
-     * output stream, and ensure that both streams are closed before returning
-     * (even in the face of an exception).
-     *
-     * @param istream The input stream to read from
-     * @param ostream The output stream to write to
-     * @return Exception which occurred during processing
-     */
-    protected IOException copyRange(InputStream istream,
-                                    ServletOutputStream ostream) {
-
-        // Copy the input stream to the output stream
-        IOException exception = null;
-        byte buffer[] = new byte[input];
-        int len = buffer.length;
-        while (true) {
-            try {
-                len = istream.read(buffer);
-                if (len == -1)
-                    break;
-                ostream.write(buffer, 0, len);
-            } catch (IOException e) {
-                exception = e;
-                len = -1;
-                break;
-            }
-        }
-        return exception;
-
-    }
-
-
-    /**
-     * Copy the contents of the specified input stream to the specified
-     * output stream, and ensure that both streams are closed before returning
-     * (even in the face of an exception).
-     *
-     * @param reader The reader to read from
-     * @param writer The writer to write to
-     * @return Exception which occurred during processing
-     */
-    protected IOException copyRange(Reader reader, PrintWriter writer) {
-
-        // Copy the input stream to the output stream
-        IOException exception = null;
-        char buffer[] = new char[input];
-        int len = buffer.length;
-        while (true) {
-            try {
-                len = reader.read(buffer);
-                if (len == -1)
-                    break;
-                writer.write(buffer, 0, len);
-            } catch (IOException e) {
-                exception = e;
-                len = -1;
-                break;
-            }
-        }
-        return exception;
-
-    }
-
-
-    /**
-     * Copy the contents of the specified input stream to the specified
-     * output stream, and ensure that both streams are closed before returning
-     * (even in the face of an exception).
-     *
-     * @param istream The input stream to read from
-     * @param ostream The output stream to write to
-     * @param start Start of the range which will be copied
-     * @param end End of the range which will be copied
-     * @return Exception which occurred during processing
-     */
-    protected IOException copyRange(InputStream istream,
-                                    ServletOutputStream ostream,
-                                    long start, long end) {
-
-        if (debug > 10)
-            log("Serving bytes:" + start + "-" + end);
-
-        long skipped = 0;
-        try {
-            skipped = istream.skip(start);
-        } catch (IOException e) {
-            return e;
-        }
-        if (skipped < start) {
-            return new IOException(sm.getString("defaultServlet.skipfail",
-                                                Long.valueOf(skipped), Long.valueOf(start)));
-        }
-
-        IOException exception = null;
-        long bytesToRead = end - start + 1;
-
-        byte buffer[] = new byte[input];
-        int len = buffer.length;
-        while ( (bytesToRead > 0) && (len >= buffer.length)) {
-            try {
-                len = istream.read(buffer);
-                if (bytesToRead >= len) {
-                    ostream.write(buffer, 0, len);
-                    bytesToRead -= len;
-                } else {
-                    ostream.write(buffer, 0, (int) bytesToRead);
-                    bytesToRead = 0;
-                }
-            } catch (IOException e) {
-                exception = e;
-                len = -1;
-            }
-            if (len < buffer.length)
-                break;
-        }
-
-        return exception;
-
-    }
-
-
-    protected static class Range {
-
-        public long start;
-        public long end;
-        public long length;
-
-        /**
-         * Validate range.
-         *
-         * @return true if the range is valid, otherwise false
-         */
-        public boolean validate() {
-            if (end >= length)
-                end = length - 1;
-            return (start >= 0) && (end >= 0) && (start <= end) && (length > 0);
-        }
-    }
-
-    protected static class CompressionFormat implements Serializable {
-        private static final long serialVersionUID = 1L;
-        public final String extension;
-        public final String encoding;
-
-        public CompressionFormat(String extension, String encoding) {
-            this.extension = extension;
-            this.encoding = encoding;
-        }
-    }
-
-    private static class PrecompressedResource {
-        public final WebResource resource;
-        public final CompressionFormat format;
-
-        private PrecompressedResource(WebResource resource, CompressionFormat format) {
-            this.resource = resource;
-            this.format = format;
-        }
-    }
-
-    /**
-     * This is secure in the sense that any attempt to use an external entity
-     * will trigger an exception.
-     */
-    private static class SecureEntityResolver implements EntityResolver2  {
-
-        @Override
-        public InputSource resolveEntity(String publicId, String systemId)
-            throws SAXException, IOException {
-            throw new SAXException(sm.getString("defaultServlet.blockExternalEntity",
-                                                publicId, systemId));
-        }
-
-        @Override
-        public InputSource getExternalSubset(String name, String baseURI)
-            throws SAXException, IOException {
-            throw new SAXException(sm.getString("defaultServlet.blockExternalSubset",
-                                                name, baseURI));
-        }
-
-        @Override
-        public InputSource resolveEntity(String name, String publicId,
-                                         String baseURI, String systemId) throws SAXException,
-                                                                                 IOException {
-            throw new SAXException(sm.getString("defaultServlet.blockExternalEntity2",
-                                                name, publicId, baseURI, systemId));
-        }
-    }
-
-    /**
-     * Gets the ordering character to be used for a particular column.
-     *
-     * @param order  The order that is currently being applied
-     * @param column The column that will be rendered.
-     *
-     * @return Either 'A' or 'D', to indicate "ascending" or "descending" sort
-     *         order.
-     */
-    private char getOrderChar(SortManager.Order order, char column) {
-        if(column == order.column) {
-            if(order.ascending) {
-                return 'D';
-            } else {
-                return 'A';
-            }
-        } else {
-            return 'D';
-        }
-    }
-
-    /**
-     * A class encapsulating the sorting of resources.
-     */
-    private static class SortManager
-    {
-        /**
-         * The default sort.
-         */
-        protected Comparator<WebResource> defaultResourceComparator;
-
-        /**
-         * Comparator to use when sorting resources by name.
-         */
-        protected Comparator<WebResource> resourceNameComparator;
-
-        /**
-         * Comparator to use when sorting files by name, ascending (reverse).
-         */
-        protected Comparator<WebResource> resourceNameComparatorAsc;
-
-        /**
-         * Comparator to use when sorting resources by size.
-         */
-        protected Comparator<WebResource> resourceSizeComparator;
-
-        /**
-         * Comparator to use when sorting files by size, ascending (reverse).
-         */
-        protected Comparator<WebResource> resourceSizeComparatorAsc;
-
-        /**
-         * Comparator to use when sorting resources by last-modified date.
-         */
-        protected Comparator<WebResource> resourceLastModifiedComparator;
-
-        /**
-         * Comparator to use when sorting files by last-modified date, ascending (reverse).
-         */
-        protected Comparator<WebResource> resourceLastModifiedComparatorAsc;
-
-        public SortManager(boolean directoriesFirst) {
-            resourceNameComparator = new ResourceNameComparator();
-            resourceNameComparatorAsc = Collections.reverseOrder(resourceNameComparator);
-            resourceSizeComparator = new ResourceSizeComparator(resourceNameComparator);
-            resourceSizeComparatorAsc = Collections.reverseOrder(resourceSizeComparator);
-            resourceLastModifiedComparator = new ResourceLastModifiedDateComparator(resourceNameComparator);
-            resourceLastModifiedComparatorAsc = Collections.reverseOrder(resourceLastModifiedComparator);
-
-            if(directoriesFirst) {
-                resourceNameComparator = new DirsFirstComparator(resourceNameComparator);
-                resourceNameComparatorAsc = new DirsFirstComparator(resourceNameComparatorAsc);
-                resourceSizeComparator = new DirsFirstComparator(resourceSizeComparator);
-                resourceSizeComparatorAsc = new DirsFirstComparator(resourceSizeComparatorAsc);
-                resourceLastModifiedComparator = new DirsFirstComparator(resourceLastModifiedComparator);
-                resourceLastModifiedComparatorAsc = new DirsFirstComparator(resourceLastModifiedComparatorAsc);
-            }
-
-            defaultResourceComparator = resourceNameComparator;
-        }
-
-        /**
-         * Sorts an array of resources according to an ordering string.
-         *
-         * @param resources The array to sort.
-         * @param order     The ordering string.
-         *
-         * @see #getOrder(String)
-         */
-        public void sort(WebResource[] resources, String order) {
-            Comparator<WebResource> comparator = getComparator(order);
-
-            if(null != comparator)
-                Arrays.sort(resources, comparator);
-        }
-
-        public Comparator<WebResource> getComparator(String order) {
-            return getComparator(getOrder(order));
-        }
-
-        public Comparator<WebResource> getComparator(Order order) {
-            if(null == order)
-                return defaultResourceComparator;
-
-            if('N' == order.column) {
-                if(order.ascending) {
-                    return resourceNameComparatorAsc;
-                } else {
-                    return resourceNameComparator;
-                }
-            }
-
-            if('S' == order.column) {
-                if(order.ascending) {
-                    return resourceSizeComparatorAsc;
-                } else {
-                    return resourceSizeComparator;
-                }
-            }
-
-            if('M' == order.column) {
-                if(order.ascending) {
-                    return resourceLastModifiedComparatorAsc;
-                } else {
-                    return resourceLastModifiedComparator;
-                }
-            }
-
-            return defaultResourceComparator;
-        }
-
-        /**
-         * Gets the Order to apply given an ordering-string. This
-         * ordering-string matches a subset of the ordering-strings
-         * supported by
-         * <a href="https://httpd.apache.org/docs/2.4/mod/mod_autoindex.html#query">Apache httpd</a>.
-         *
-         * @param order The ordering-string provided by the client.
-         *
-         * @return An Order specifying the column and ascending/descending to
-         *         be applied to resources.
-         */
-        public Order getOrder(String order) {
-            if(null == order || 0 == order.trim().length())
-                return Order.DEFAULT;
-
-            String[] options = order.split(";");
-
-            if(0 == options.length)
-                return Order.DEFAULT;
-
-            char column = '\0';
-            boolean ascending = false;
-
-            for(String option : options) {
-                option = option.trim();
-
-                if(2 < option.length()) {
-                    char opt = option.charAt(0);
-                    if('C' == opt)
-                        column = option.charAt(2);
-                    else if('O' == opt)
-                        ascending = ('A' == option.charAt(2));
-                }
-            }
-
-            if('N' == column) {
-                if(ascending) {
-                    return Order.NAME_ASC;
-                } else {
-                    return Order.NAME;
-                }
-            }
-
-            if('S' == column) {
-                if(ascending) {
-                    return Order.SIZE_ASC;
-                } else {
-                    return Order.SIZE;
-                }
-            }
-
-            if('M' == column) {
-                if(ascending) {
-                    return Order.LAST_MODIFIED_ASC;
-                } else {
-                    return Order.LAST_MODIFIED;
-                }
-            }
-
-            return Order.DEFAULT;
-        }
-
-        public static class Order {
-            final char column;
-            final boolean ascending;
-
-            public Order(char column, boolean ascending) {
-                this.column = column;
-                this.ascending = ascending;
-            }
-
-            public static final Order NAME = new Order('N', false);
-            public static final Order NAME_ASC = new Order('N', true);
-            public static final Order SIZE = new Order('S', false);
-            public static final Order SIZE_ASC = new Order('S', true);
-            public static final Order LAST_MODIFIED = new Order('M', false);
-            public static final Order LAST_MODIFIED_ASC = new Order('M', true);
-
-            public static final Order DEFAULT = NAME;
-        }
-    }
-
-    private static class DirsFirstComparator
-        implements Comparator<WebResource>
-    {
-        private final Comparator<WebResource> base;
-
-        public DirsFirstComparator(Comparator<WebResource> core) {
-            this.base = core;
-        }
-
-        @Override
-        public int compare(WebResource r1, WebResource r2) {
-            if(r1.isDirectory()) {
-                if(r2.isDirectory()) {
-                    return base.compare(r1, r2);
-                } else {
-                    return -1; // r1, directory, first
-                }
-            } else if(r2.isDirectory()) {
-                return 1; // r2, directory, first
-            } else {
-                return base.compare(r1, r2);
-            }
-        }
-    }
-
-    private static class ResourceNameComparator
-        implements Comparator<WebResource>
-    {
-        @Override
-        public int compare(WebResource r1, WebResource r2) {
-            return r1.getName().compareTo(r2.getName());
-        }
-    }
-
-    private static class ResourceSizeComparator
-        implements Comparator<WebResource>
-    {
-        private Comparator<WebResource> base;
-
-        public ResourceSizeComparator(Comparator<WebResource> base) {
-            this.base = base;
-        }
-
-        @Override
-        public int compare(WebResource r1, WebResource r2) {
-            int c = Long.compare(r1.getContentLength(), r2.getContentLength());
-
-            if(0 == c)
-                return base.compare(r1, r2);
-            else
-                return c;
-        }
-    }
-
-    private static class ResourceLastModifiedDateComparator
-        implements Comparator<WebResource>
-    {
-        private Comparator<WebResource> base;
-
-        public ResourceLastModifiedDateComparator(Comparator<WebResource> base) {
-            this.base = base;
-        }
-
-        @Override
-        public int compare(WebResource r1, WebResource r2) {
-            int c = Long.compare(r1.getLastModified(), r2.getLastModified());
-
-            if(0 == c)
-                return base.compare(r1, r2);
-            else
-                return c;
-        }
-    }
-}