Index: src/main/java/org/apache/catalina/servlets/DefaultServlet.java =================================================================== --- src/main/java/org/apache/catalina/servlets/DefaultServlet.java (revision 46674) +++ src/main/java/org/apache/catalina/servlets/DefaultServlet.java (revision ) @@ -59,7 +59,6 @@ package org.apache.catalina.servlets; import java.io.BufferedInputStream; -import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; @@ -750,147 +749,12 @@ path + "' headers only"); } - CacheEntry cacheEntry = null; - ProxyDirContext proxyDirContext = resources; - if (alternateDocBases == null - || alternateDocBases.size() == 0) { - cacheEntry = proxyDirContext.lookupCache(path); - } else { - AlternateDocBase match = AlternateDocBase.findMatch( - path, alternateDocBases); - if (match != null) { - cacheEntry = ((ProxyDirContext) match.getResources()).lookupCache(path); - } else { - // None of the url patterns for alternate docbases matched - cacheEntry = proxyDirContext.lookupCache(path); - } - } + CacheEntry cacheEntry = lookupCacheEntry(path); - if (!cacheEntry.exists) { - // Try looking up resource in - // WEB-INF/lib/[*.jar]/META-INF/resources - ClassLoader cl = Thread.currentThread().getContextClassLoader(); - String metaInfResPath = Globals.META_INF_RESOURCES + path; - if (cl instanceof WebappClassLoader) { - WebappClassLoader wcl = (WebappClassLoader)cl; - final URL resourceUrl = wcl.getResourceFromJars(metaInfResPath); - if (resourceUrl != null) { - // XXX Remove dependency on WebappClassLoader - ConcurrentHashMap resourceEntries = - wcl.getResourceEntries(); - ResourceEntry resourceEntry = resourceEntries.get(metaInfResPath); - if (resourceEntry != null) { - // create a CacheEntry to continue the processing - cacheEntry = new CacheEntry(); - try { - URI resourceUri = resourceUrl.toURI(); - if ("file".equals(resourceUri.getScheme()) && - (new File(resourceUri)).isDirectory()) { - if (!path.endsWith("/")) { - response.sendRedirect( - response.encodeRedirectUrl( - request.getContextPath() + path + "/")); + if (hasValidationErrors(request, response, path, cacheEntry)) { - return; - } + return; + } - FileDirContext fileDirContext = new FileDirContext(); - String base = resourceUrl.getPath(); - int index = base.lastIndexOf(path); - if (index != -1) { - base = base.substring(0, index); - } - fileDirContext.setDocBase(base); - proxyDirContext = new ProxyDirContext( - new Hashtable(), fileDirContext); - - cacheEntry.context = proxyDirContext; - } else { - cacheEntry.resource = new Resource() { - public InputStream streamContent() throws IOException { - return resourceUrl.openStream(); - } - }; - } - } catch(Exception ex) { - throw new IOException(ex); - } - - cacheEntry.name = path; - cacheEntry.attributes = new ResourceAttributes(); - cacheEntry.exists = true; - } - } - } - } - - if (!cacheEntry.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); - /* IASRI 4878272 - if (requestUri == null) { - requestUri = request.getRequestURI(); - } else { - */ - if (requestUri != null) { - /* - * We're included, and the response.sendError() below is going - * to be ignored by the including resource (see SRV.8.3, - * "The Include Method"). - * Therefore, the only way we can let the including resource - * know about the missing resource is by throwing an - * exception - */ - throw new FileNotFoundException(requestUri); - } - - /* IASRI 4878272 - response.sendError(HttpServletResponse.SC_NOT_FOUND, - requestUri); - */ - // BEGIN IASRI 4878272 - response.sendError(HttpServletResponse.SC_NOT_FOUND); - // END IASRI 4878272 - return; - } - - // If the resource is not a collection, and the resource path - // ends with "/" or "\", return NOT FOUND - if (cacheEntry.context == null) { - if (path.endsWith("/") || (path.endsWith("\\"))) { - /* IASRI 4878272 - // 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(); - } - response.sendError(HttpServletResponse.SC_NOT_FOUND, - requestUri); - */ - // BEGIN IASRI 4878272 - response.sendError(HttpServletResponse.SC_NOT_FOUND); - // END IASRI 4878272 - return; - } - } - - // Check if the conditions specified in the optional If headers are - // satisfied. - if (cacheEntry.context == null) { - - // Checking If headers - boolean included = - (request.getAttribute(RequestDispatcher.INCLUDE_CONTEXT_PATH) != null); - if (!included - && !checkIfHeaders(request, response, cacheEntry.attributes)) { - return; - } - - } - // Find content type. String contentType = cacheEntry.attributes.getMimeType(); if (contentType == null) { @@ -903,18 +767,6 @@ if (cacheEntry.context != null) { - // Skip directory listings if we have been configured to - // suppress them - if (!listings) { - /* IASRI 4878272 - response.sendError(HttpServletResponse.SC_NOT_FOUND, - request.getRequestURI()); - */ - // BEGIN IASRI 4878272 - response.sendError(HttpServletResponse.SC_NOT_FOUND); - // END IASRI 4878272 - return; - } contentType = "text/html;charset=UTF-8"; } else { @@ -995,12 +847,20 @@ if (content) { // Serve the directory browser - renderResult = - render(request.getContextPath(), cacheEntry, proxyDirContext); + try { + ProxyDirContext context = new ProxyDirContext( + new Hashtable(), cacheEntry.context); + renderResult = render(request.getContextPath(), cacheEntry, context); + } catch (Exception e) { + throw new IOException(e); - } + } + + - } + } + } + // Copy the input stream to our output stream (if requested) if (content) { try { @@ -1087,8 +947,188 @@ } + /** + * Look up the resource identified by path and return a CacheEntry for it + * @param path the path to look up + * @return a CacheEntry representing the content of the path + * @throws IOException an IOException occurred + */ + private CacheEntry lookupCacheEntry(String path) throws IOException { + CacheEntry cacheEntry = null; + ProxyDirContext proxyDirContext = resources; + if (alternateDocBases == null + || alternateDocBases.size() == 0) { + cacheEntry = proxyDirContext.lookupCache(path); + } else { + AlternateDocBase match = AlternateDocBase.findMatch( + path, alternateDocBases); + if (match != null) { + cacheEntry = ((ProxyDirContext) match.getResources()).lookupCache(path); + } else { + // None of the url patterns for alternate docbases matched + cacheEntry = proxyDirContext.lookupCache(path); + } + } + if (!cacheEntry.exists) { + // Try looking up resource in + // WEB-INF/lib/[*.jar]/META-INF/resources + ClassLoader cl = Thread.currentThread().getContextClassLoader(); + String metaInfResPath = Globals.META_INF_RESOURCES + path; + if (cl instanceof WebappClassLoader) { + WebappClassLoader wcl = (WebappClassLoader)cl; + final URL resourceUrl = wcl.getResourceFromJars(metaInfResPath); + if (resourceUrl != null) { + // XXX Remove dependency on WebappClassLoader + ConcurrentHashMap resourceEntries = + wcl.getResourceEntries(); + ResourceEntry resourceEntry = resourceEntries.get(metaInfResPath); + if (resourceEntry != null) { + // create a CacheEntry to continue the processing + cacheEntry = new CacheEntry(); + try { + URI resourceUri = resourceUrl.toURI(); + if ("file".equals(resourceUri.getScheme()) && + (new File(resourceUri)).isDirectory()) { + + FileDirContext fileDirContext = new FileDirContext(); + String base = resourceUrl.getPath(); + int index = base.lastIndexOf(path); + if (index != -1) { + base = base.substring(0, index); + } + fileDirContext.setDocBase(base); + cacheEntry.context = fileDirContext; + + } else { + cacheEntry.resource = new Resource() { + public InputStream streamContent() throws IOException { + return resourceUrl.openStream(); + } + }; + } + } catch(Exception ex) { + throw new IOException(ex); + } + + cacheEntry.name = path; + cacheEntry.attributes = new ResourceAttributes(); + cacheEntry.exists = true; + } + } + } + } + return cacheEntry; + } + /** + * Checks the CacheEntry served for the given path for errors + * @param request the request being processed + * @param response the response + * @param path the path being served + * @param cacheEntry the CacheEntry for the given path + * @return true if there are any errors, false otherwise + * @throws IOException if an IOException occurs + */ + private boolean hasValidationErrors(HttpServletRequest request, HttpServletResponse response, String path, CacheEntry cacheEntry) throws IOException { + if (!cacheEntry.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); + /* IASRI 4878272 + if (requestUri == null) { + requestUri = request.getRequestURI(); + } else { + */ + if (requestUri != null) { + /* + * We're included, and the response.sendError() below is going + * to be ignored by the including resource (see SRV.8.3, + * "The Include Method"). + * Therefore, the only way we can let the including resource + * know about the missing resource is by throwing an + * exception + */ + throw new FileNotFoundException(requestUri); + } + + /* IASRI 4878272 + response.sendError(HttpServletResponse.SC_NOT_FOUND, + requestUri); + */ + // BEGIN IASRI 4878272 + response.sendError(HttpServletResponse.SC_NOT_FOUND); + // END IASRI 4878272 + return true; + } + + // If the resource is a collection, but the path does not end with "/", redirect with appended "/" + if(cacheEntry.context != null) { + if (!path.endsWith("/")) { + response.sendRedirect( + response.encodeRedirectUrl( + request.getContextPath() + path + "/")); + return true; + } + } + + // If the resource is not a collection, and the resource path + // ends with "/" or "\", return NOT FOUND + if (cacheEntry.context == null) { + if (path.endsWith("/") || (path.endsWith("\\"))) { + /* IASRI 4878272 + // 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(); + } + response.sendError(HttpServletResponse.SC_NOT_FOUND, + requestUri); + */ + // BEGIN IASRI 4878272 + response.sendError(HttpServletResponse.SC_NOT_FOUND); + // END IASRI 4878272 + return true; + } + } + + // Check if the conditions specified in the optional If headers are + // satisfied. + if (cacheEntry.context == null) { + + // Checking If headers + boolean included = + (request.getAttribute(RequestDispatcher.INCLUDE_CONTEXT_PATH) != null); + if (!included + && !checkIfHeaders(request, response, cacheEntry.attributes)) { + return true; + } + + } + + if (cacheEntry.context != null) { + + // Skip directory listings if we have been configured to + // suppress them + if (!listings) { + /* IASRI 4878272 + response.sendError(HttpServletResponse.SC_NOT_FOUND, + request.getRequestURI()); + */ + // BEGIN IASRI 4878272 + response.sendError(HttpServletResponse.SC_NOT_FOUND); + // END IASRI 4878272 + return true; + } + } + return false; + } + + + /** * Parse the content-range header. * * @param request The servlet request we are processing