Apply patch to DefaultServlet to support JSTL TCK
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
index e0b6711..160cefd 100644
--- 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
@@ -316,8 +316,8 @@
}
compressionFormats = parseCompressionFormats(
- getServletConfig().getInitParameter("precompressed"),
- getServletConfig().getInitParameter("gzip"));
+ getServletConfig().getInitParameter("precompressed"),
+ getServletConfig().getInitParameter("gzip"));
if (getServletConfig().getInitParameter("sendfileSize") != null) {
sendfileSize = Integer.parseInt(getServletConfig().getInitParameter("sendfileSize")) * 1024;
@@ -475,7 +475,7 @@
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp)
- throws ServletException, IOException {
+ throws ServletException, IOException {
if (req.getDispatcherType() == DispatcherType.ERROR) {
doGet(req, resp);
@@ -516,7 +516,7 @@
*/
@Override
protected void doHead(HttpServletRequest request, HttpServletResponse response)
- throws IOException, ServletException {
+ 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
@@ -565,7 +565,7 @@
// Trace - assume disabled unless we can prove otherwise
if (req instanceof RequestFacade &&
- ((RequestFacade) req).getAllowTrace()) {
+ ((RequestFacade) req).getAllowTrace()) {
allow.append(", TRACE");
}
@@ -574,7 +574,7 @@
protected void sendNotAllowed(HttpServletRequest req, HttpServletResponse resp)
- throws IOException {
+ throws IOException {
resp.addHeader("Allow", determineMethodsAllowed(req));
resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
}
@@ -689,15 +689,15 @@
}
try (RandomAccessFile randAccessContentFile =
- new RandomAccessFile(contentFile, "rw")) {
+ 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)) {
+ new BufferedInputStream(oldResource.getInputStream(),
+ BUFFER_SIZE)) {
int numBytesRead;
byte[] copyBuffer = new byte[BUFFER_SIZE];
@@ -715,7 +715,7 @@
int numBytesRead;
byte[] transferBuffer = new byte[BUFFER_SIZE];
try (BufferedInputStream requestBufInStream =
- new BufferedInputStream(req.getInputStream(), BUFFER_SIZE)) {
+ new BufferedInputStream(req.getInputStream(), BUFFER_SIZE)) {
while ((numBytesRead = requestBufInStream.read(transferBuffer)) != -1) {
randAccessContentFile.write(transferBuffer, 0, numBytesRead);
}
@@ -779,9 +779,9 @@
throws IOException {
return checkIfMatch(request, response, resource)
- && checkIfModifiedSince(request, response, resource)
- && checkIfNoneMatch(request, response, resource)
- && checkIfUnmodifiedSince(request, response, resource);
+ && checkIfModifiedSince(request, response, resource)
+ && checkIfNoneMatch(request, response, resource)
+ && checkIfUnmodifiedSince(request, response, resource);
}
@@ -842,22 +842,22 @@
// 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);
+ 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));
+ "defaultServlet.missingResource", requestUri));
}
if (isError) {
response.sendError(((Integer) request.getAttribute(
- RequestDispatcher.ERROR_STATUS_CODE)).intValue());
+ RequestDispatcher.ERROR_STATUS_CODE)).intValue());
} else {
response.sendError(HttpServletResponse.SC_NOT_FOUND,
- sm.getString("defaultServlet.missingResource", requestUri));
+ sm.getString("defaultServlet.missingResource", requestUri));
}
return;
}
@@ -866,7 +866,7 @@
// 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);
+ RequestDispatcher.INCLUDE_REQUEST_URI);
if (requestUri == null) {
requestUri = request.getRequestURI();
} else {
@@ -874,12 +874,12 @@
// Spec doesn't say what to do in this case but a FNFE seems
// reasonable
throw new FileNotFoundException(sm.getString(
- "defaultServlet.missingResource", requestUri));
+ "defaultServlet.missingResource", requestUri));
}
if (isError) {
response.sendError(((Integer) request.getAttribute(
- RequestDispatcher.ERROR_STATUS_CODE)).intValue());
+ RequestDispatcher.ERROR_STATUS_CODE)).intValue());
} else {
response.sendError(HttpServletResponse.SC_FORBIDDEN, requestUri);
}
@@ -892,7 +892,7 @@
if (resource.isFile()) {
// Checking If headers
included = (request.getAttribute(
- RequestDispatcher.INCLUDE_CONTEXT_PATH) != null);
+ RequestDispatcher.INCLUDE_CONTEXT_PATH) != null);
if (!included && !isError && !checkIfHeaders(request, response, resource)) {
return;
}
@@ -919,13 +919,13 @@
// Serve a precompressed version of the file if present
boolean usingPrecompressedVersion = false;
if (compressionFormats.length > 0 && !included && resource.isFile() &&
- !pathEndsWithCompressedExtension(path)) {
+ !pathEndsWithCompressedExtension(path)) {
List<PrecompressedResource> precompressedResources =
- getAvailablePrecompressedResources(path);
+ getAvailablePrecompressedResources(path);
if (!precompressedResources.isEmpty()) {
ResponseUtil.addVaryFieldName(response, "accept-encoding");
PrecompressedResource bestResource =
- getBestPrecompressedResource(request, precompressedResources);
+ getBestPrecompressedResource(request, precompressedResources);
if (bestResource != null) {
response.addHeader("Content-Encoding", bestResource.format.encoding);
resource = bestResource.resource;
@@ -947,7 +947,7 @@
// suppress them
if (!listings) {
response.sendError(HttpServletResponse.SC_NOT_FOUND,
- sm.getString("defaultServlet.missingResource", request.getRequestURI()));
+ sm.getString("defaultServlet.missingResource", request.getRequestURI()));
return;
}
contentType = "text/html;charset=UTF-8";
@@ -1029,10 +1029,10 @@
* doing this.
*/
boolean outputEncodingSpecified =
- outputEncoding != org.apache.coyote.Constants.DEFAULT_BODY_CHARSET.name() &&
- outputEncoding != resources.getContext().getResponseCharacterEncoding();
+ outputEncoding != org.apache.coyote.Constants.DEFAULT_BODY_CHARSET.name() &&
+ outputEncoding != resources.getContext().getResponseCharacterEncoding();
if (!usingPrecompressedVersion && isText(contentType) && outputEncodingSpecified &&
- !charset.equals(fileEncodingCharset)) {
+ !charset.equals(fileEncodingCharset)) {
conversionRequired = true;
// Conversion often results fewer/more/different bytes.
// That does not play nicely with range requests.
@@ -1053,7 +1053,7 @@
}
}
if (resource.isFile() && contentLength >= 0 &&
- (!serveContent || ostream != null)) {
+ (!serveContent || ostream != null)) {
if (debug > 0)
log("DefaultServlet.serveFile: contentLength=" +
contentLength);
@@ -1213,11 +1213,20 @@
}
}
+ /*
+ * 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(InputStream is) throws IOException {
+ 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);
@@ -1226,7 +1235,7 @@
// BOMs are at least 2 bytes
if (count < 2) {
- skip(is, 0);
+ skip(is, 0, stripBOM);
return null;
}
@@ -1234,31 +1243,31 @@
int b0 = bom[0] & 0xFF;
int b1 = bom[1] & 0xFF;
if (b0 == 0xFE && b1 == 0xFF) {
- skip(is, 2);
+ 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);
+ skip(is, 2, stripBOM);
return StandardCharsets.UTF_16LE;
}
// Remaining BOMs are at least 3 bytes
if (count < 3) {
- skip(is, 0);
+ 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);
+ skip(is, 3, stripBOM);
return StandardCharsets.UTF_8;
}
if (count < 4) {
- skip(is, 0);
+ skip(is, 0, stripBOM);
return null;
}
@@ -1275,18 +1284,18 @@
// 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);
+ skip(is, 2, stripBOM);
return StandardCharsets.UTF_16LE;
}
- skip(is, 0);
+ skip(is, 0, stripBOM);
return null;
}
- private static void skip(InputStream is, int skip) throws IOException {
+ private static void skip(final InputStream is, int skip, final boolean stripBOM) throws IOException {
is.reset();
- while (skip-- > 0) {
+ while (stripBOM && skip-- > 0) {
is.read();
}
}
@@ -1326,7 +1335,7 @@
* @return The best matching precompressed resource or null if no match was found.
*/
private PrecompressedResource getBestPrecompressedResource(HttpServletRequest request,
- List<PrecompressedResource> precompressedResources) {
+ List<PrecompressedResource> precompressedResources) {
Enumeration<String> headers = request.getHeaders("Accept-Encoding");
PrecompressedResource bestResource = null;
double bestResourceQuality = 0;
@@ -1379,7 +1388,7 @@
}
private void doDirectoryRedirect(HttpServletRequest request, HttpServletResponse response)
- throws IOException {
+ throws IOException {
StringBuilder location = new StringBuilder(request.getRequestURI());
location.append('/');
if (request.getQueryString() != null) {
@@ -1404,7 +1413,7 @@
* @throws IOException an IO error occurred
*/
protected Range parseContentRange(HttpServletRequest request,
- HttpServletResponse response)
+ HttpServletResponse response)
throws IOException {
// Retrieving the content-range header (if any is specified
@@ -1460,8 +1469,8 @@
* @throws IOException an IO error occurred
*/
protected ArrayList<Range> parseRange(HttpServletRequest request,
- HttpServletResponse response,
- WebResource resource) throws IOException {
+ 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()
@@ -1654,7 +1663,7 @@
* @throws ServletException rendering error
*/
protected InputStream renderXml(HttpServletRequest request, String contextPath, WebResource resource, Source xsltSource,
- String encoding)
+ String encoding)
throws IOException, ServletException {
StringBuilder sb = new StringBuilder();
@@ -1681,15 +1690,15 @@
for (String entry : entries) {
if (entry.equalsIgnoreCase("WEB-INF") ||
- entry.equalsIgnoreCase("META-INF") ||
- entry.equalsIgnoreCase(localXsltFile))
+ entry.equalsIgnoreCase("META-INF") ||
+ entry.equalsIgnoreCase(localXsltFile))
continue;
if ((directoryWebappPath + entry).equals(contextXsltFile))
continue;
WebResource childResource =
- resources.getResource(directoryWebappPath + entry);
+ resources.getResource(directoryWebappPath + entry);
if (!childResource.exists()) {
continue;
}
@@ -1742,11 +1751,11 @@
try {
if (Globals.IS_SECURITY_ENABLED) {
PrivilegedSetTccl pa =
- new PrivilegedSetTccl(DefaultServlet.class.getClassLoader());
+ new PrivilegedSetTccl(DefaultServlet.class.getClassLoader());
AccessController.doPrivileged(pa);
} else {
Thread.currentThread().setContextClassLoader(
- DefaultServlet.class.getClassLoader());
+ DefaultServlet.class.getClassLoader());
}
TransformerFactory tFactory = TransformerFactory.newInstance();
@@ -1866,7 +1875,7 @@
sb.append("<hr class=\"line\">");
sb.append("<table width=\"100%\" cellspacing=\"0\"" +
- " cellpadding=\"5\" align=\"center\">\r\n");
+ " cellpadding=\"5\" align=\"center\">\r\n");
SortManager.Order order;
if(sortListings && null != request)
@@ -2010,7 +2019,7 @@
if (readmeFile != null) {
WebResource resource = resources.getResource(
- directory.getWebappPath() + readmeFile);
+ directory.getWebappPath() + readmeFile);
if (resource.isFile()) {
StringWriter buffer = new StringWriter();
InputStreamReader reader = null;
@@ -2055,7 +2064,7 @@
if (localXsltFile != null) {
WebResource resource = resources.getResource(
- directory.getWebappPath() + localXsltFile);
+ directory.getWebappPath() + localXsltFile);
if (resource.isFile()) {
InputStream is = resource.getInputStream();
if (is != null) {
@@ -2193,8 +2202,8 @@
* delegated to the endpoint)
*/
protected boolean checkSendfile(HttpServletRequest request,
- HttpServletResponse response,
- WebResource resource,
+ HttpServletResponse response,
+ WebResource resource,
long length, Range range) {
String canonicalPath;
if (sendfileSize > 0
@@ -2204,7 +2213,7 @@
&& (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));
@@ -2231,7 +2240,7 @@
* @throws IOException an IO error occurred
*/
protected boolean checkIfMatch(HttpServletRequest request, HttpServletResponse response, WebResource resource)
- throws IOException {
+ throws IOException {
String headerValue = request.getHeader("If-Match");
if (headerValue != null) {
@@ -2278,7 +2287,7 @@
* request processing is stopped
*/
protected boolean checkIfModifiedSince(HttpServletRequest request,
- HttpServletResponse response, WebResource resource) {
+ HttpServletResponse response, WebResource resource) {
try {
long headerValue = request.getDateHeader("If-Modified-Since");
long lastModified = resource.getLastModified();
@@ -2315,7 +2324,7 @@
* @throws IOException an IO error occurred
*/
protected boolean checkIfNoneMatch(HttpServletRequest request, HttpServletResponse response, WebResource resource)
- throws IOException {
+ throws IOException {
String headerValue = request.getHeader("If-None-Match");
if (headerValue != null) {
@@ -2372,8 +2381,8 @@
* @throws IOException an IO error occurred
*/
protected boolean checkIfUnmodifiedSince(HttpServletRequest request,
- HttpServletResponse response, WebResource resource)
- throws IOException {
+ HttpServletResponse response, WebResource resource)
+ throws IOException {
try {
long lastModified = resource.getLastModified();
long headerValue = request.getDateHeader("If-Unmodified-Since");
@@ -2560,7 +2569,7 @@
* @return Exception which occurred during processing
*/
protected IOException copyRange(InputStream istream,
- ServletOutputStream ostream) {
+ ServletOutputStream ostream) {
// Copy the input stream to the output stream
IOException exception = null;
@@ -2627,8 +2636,8 @@
* @return Exception which occurred during processing
*/
protected IOException copyRange(InputStream istream,
- ServletOutputStream ostream,
- long start, long end) {
+ ServletOutputStream ostream,
+ long start, long end) {
if (debug > 10)
log("Serving bytes:" + start + "-" + end);
@@ -2641,7 +2650,7 @@
}
if (skipped < start) {
return new IOException(sm.getString("defaultServlet.skipfail",
- Long.valueOf(skipped), Long.valueOf(start)));
+ Long.valueOf(skipped), Long.valueOf(start)));
}
IOException exception = null;
@@ -2719,24 +2728,24 @@
@Override
public InputSource resolveEntity(String publicId, String systemId)
- throws SAXException, IOException {
+ throws SAXException, IOException {
throw new SAXException(sm.getString("defaultServlet.blockExternalEntity",
- publicId, systemId));
+ publicId, systemId));
}
@Override
public InputSource getExternalSubset(String name, String baseURI)
- throws SAXException, IOException {
+ throws SAXException, IOException {
throw new SAXException(sm.getString("defaultServlet.blockExternalSubset",
- name, baseURI));
+ name, baseURI));
}
@Override
public InputSource resolveEntity(String name, String publicId,
- String baseURI, String systemId) throws SAXException,
- IOException {
+ String baseURI, String systemId) throws SAXException,
+ IOException {
throw new SAXException(sm.getString("defaultServlet.blockExternalEntity2",
- name, publicId, baseURI, systemId));
+ name, publicId, baseURI, systemId));
}
}