From remm@locus.apache.org Mon Aug 7 02:30:14 2000 Return-Path: Mailing-List: contact tomcat-dev-help@jakarta.apache.org; run by ezmlm Delivered-To: mailing list tomcat-dev@jakarta.apache.org Received: (qmail 56481 invoked by uid 500); 7 Aug 2000 02:30:14 -0000 Delivered-To: apmail-jakarta-tomcat-cvs@apache.org Received: (qmail 56477 invoked by uid 1135); 7 Aug 2000 02:30:14 -0000 Date: 7 Aug 2000 02:30:14 -0000 Message-ID: <20000807023014.56476.qmail@locus.apache.org> From: remm@locus.apache.org To: jakarta-tomcat-cvs@apache.org Subject: cvs commit: jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/servlets DefaultServlet.java WebdavServlet.java remm 00/08/06 19:30:14 Modified: proposals/catalina/src/share/org/apache/tomcat/servlets DefaultServlet.java WebdavServlet.java Log: - Lock checking when deleting resources and collections - Fixes for path related problems, both in the DAV servlet and in the default servlet - COPY destination header is properly resolved - Error reports for COPY and DELETE - Still no PROPPATCH support, but the code from Slide will be easy to adapt. However, since the Resources don't handle metadata (and won't for the forseeable future, since it would be hard to implement on a lot of repositories), it would be mostly useless. Revision Changes Path 1.21 +43 -35 jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/servlets/DefaultServlet.java Index: DefaultServlet.java =================================================================== RCS file: /home/cvs/jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/servlets/DefaultServlet.java,v retrieving revision 1.20 retrieving revision 1.21 diff -u -r1.20 -r1.21 --- DefaultServlet.java 2000/08/06 04:54:46 1.20 +++ DefaultServlet.java 2000/08/07 02:30:13 1.21 @@ -1,7 +1,7 @@ /* - * $Header: /home/cvs/jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/servlets/DefaultServlet.java,v 1.20 2000/08/06 04:54:46 remm Exp $ - * $Revision: 1.20 $ - * $Date: 2000/08/06 04:54:46 $ + * $Header: /home/cvs/jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/servlets/DefaultServlet.java,v 1.21 2000/08/07 02:30:13 remm Exp $ + * $Revision: 1.21 $ + * $Date: 2000/08/07 02:30:13 $ * * ==================================================================== * @@ -108,7 +108,7 @@ * * @author Craig R. McClanahan * @author Remy Maucherat - * @version $Revision: 1.20 $ $Date: 2000/08/06 04:54:46 $ + * @version $Revision: 1.21 $ $Date: 2000/08/07 02:30:13 $ */ public class DefaultServlet @@ -276,6 +276,25 @@ /** + * Return the relative path associated with this servlet. + * + * @param request The servlet request we are processing + */ + protected String getRelativePath(HttpServletRequest request) { + + String result = request.getPathInfo(); + if (result == null) { + result = request.getServletPath(); + } + if ((result == null) || (result.equals(""))) { + result = "/"; + } + return result; + + } + + + /** * Process a GET request for the specified resource. * * @param request The servlet request we are processing @@ -348,9 +367,7 @@ return; } - String servletPath = req.getServletPath(); - if (servletPath == null) - servletPath = "/"; + String path = getRelativePath(req); // Looking for a Content-Range header if (req.getHeader("Content-Range") != null) { @@ -362,10 +379,9 @@ ApplicationContext context = (ApplicationContext) getServletContext(); Resources resources = context.getResources(); - boolean exists = resources.exists(servletPath); + boolean exists = resources.exists(path); - boolean result = resources.setResource(servletPath, - req.getInputStream()); + boolean result = resources.setResource(path, req.getInputStream()); if (result) { if (exists) { @@ -397,18 +413,16 @@ return; } - String servletPath = req.getServletPath(); - if (servletPath == null) - servletPath = "/"; + String path = getRelativePath(req); // Retrieve the Catalina context ApplicationContext context = (ApplicationContext) getServletContext(); Resources resources = context.getResources(); - boolean exists = resources.exists(servletPath); + boolean exists = resources.exists(path); if (exists) { - boolean result = resources.deleteResource(servletPath); + boolean result = resources.deleteResource(path); if (result) { resp.setStatus(HttpServletResponse.SC_NO_CONTENT); } else { @@ -911,27 +925,21 @@ throws IOException, ServletException { // Identify the requested resource path - String servletPath = request.getServletPath(); - if (servletPath == null) - servletPath = "/"; + String path = getRelativePath(request); if (debug > 0) { if (content) log("DefaultServlet.serveResource: Serving resource '" + - servletPath + "' headers and data"); + path + "' headers and data"); else log("DefaultServlet.serveResource: Serving resource '" + - servletPath + "' headers only"); - } - if (servletPath == null) { - response.sendError(HttpServletResponse.SC_BAD_REQUEST); - return; + path + "' headers only"); } // Exclude any resource in the /WEB-INF and /META-INF subdirectories // (the "toUpperCase()" avoids problems on Windows systems) - if (servletPath.toUpperCase().startsWith("/WEB-INF") || - servletPath.toUpperCase().startsWith("/META-INF")) { - response.sendError(HttpServletResponse.SC_NOT_FOUND, servletPath); + if (path.toUpperCase().startsWith("/WEB-INF") || + path.toUpperCase().startsWith("/META-INF")) { + response.sendError(HttpServletResponse.SC_NOT_FOUND, path); return; } @@ -941,12 +949,12 @@ // Convert the resource path to a URL URL resourceURL = null; try { - resourceURL = context.getResource(servletPath); + resourceURL = context.getResource(path); } catch (MalformedURLException e) { ; } if (resourceURL == null) { - response.sendError(HttpServletResponse.SC_NOT_FOUND, servletPath); + response.sendError(HttpServletResponse.SC_NOT_FOUND, path); return; } if (debug > 0) @@ -954,19 +962,18 @@ resourceURL.toString() + "'"); Resources resources = context.getResources(); - ResourceInfo resourceInfo = new ResourceInfo(servletPath, resources); + ResourceInfo resourceInfo = new ResourceInfo(path, resources); // If the resource is a collection (aka a directory), we check // the welcome files list. if (resourceInfo.collection) { - ResourceInfo welcomeFileInfo = checkWelcomeFiles(servletPath, - resources); + ResourceInfo welcomeFileInfo = checkWelcomeFiles(path, resources); if (welcomeFileInfo != null) { resourceInfo = welcomeFileInfo; } if ((welcomeFileInfo != null) && - (!servletPath.endsWith("/"))) { + (!path.endsWith("/"))) { response.sendRedirect(request.getRequestURI() + "/"); return; } @@ -974,7 +981,8 @@ } if (!resourceInfo.exists()) { - response.sendError(HttpServletResponse.SC_NOT_FOUND, servletPath); + response.sendError(HttpServletResponse.SC_NOT_FOUND, + resourceInfo.path); return; } @@ -991,7 +999,7 @@ // suppress them if (!listings) { response.sendError(HttpServletResponse.SC_NOT_FOUND, - servletPath); + resourceInfo.path); return; } contentType = "text/html"; 1.6 +227 -118 jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/servlets/WebdavServlet.java Index: WebdavServlet.java =================================================================== RCS file: /home/cvs/jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/servlets/WebdavServlet.java,v retrieving revision 1.5 retrieving revision 1.6 diff -u -r1.5 -r1.6 --- WebdavServlet.java 2000/08/06 04:54:50 1.5 +++ WebdavServlet.java 2000/08/07 02:30:13 1.6 @@ -1,7 +1,7 @@ /* - * $Header: /home/cvs/jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/servlets/WebdavServlet.java,v 1.5 2000/08/06 04:54:50 remm Exp $ - * $Revision: 1.5 $ - * $Date: 2000/08/06 04:54:50 $ + * $Header: /home/cvs/jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/servlets/WebdavServlet.java,v 1.6 2000/08/07 02:30:13 remm Exp $ + * $Revision: 1.6 $ + * $Date: 2000/08/07 02:30:13 $ * * ==================================================================== * @@ -120,7 +120,7 @@ * are handled by the DefaultServlet. * * @author Remy Maucherat - * @version $Revision: 1.5 $ $Date: 2000/08/06 04:54:50 $ + * @version $Revision: 1.6 $ $Date: 2000/08/07 02:30:13 $ */ public class WebdavServlet @@ -274,8 +274,8 @@ String method = req.getMethod(); - String servletPath = req.getServletPath(); - System.out.println("[" + method + "] " + servletPath); + String path = getRelativePath(req); + System.out.println("[" + method + "] " + path); if (method.equals(METHOD_PROPFIND)) { doPropfind(req, resp); @@ -330,9 +330,7 @@ protected void doOptions(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { - String servletPath = req.getServletPath(); - if (servletPath == null) - servletPath = "/"; + String path = getRelativePath(req); resp.addHeader("DAV", "1,2"); String methodsAllowed = null; @@ -342,7 +340,7 @@ Resources resources = context.getResources(); - if (!resources.exists(servletPath)) { + if (!resources.exists(path)) { methodsAllowed = "OPTIONS, MKCOL, PUT, LOCK"; resp.addHeader("Allow", methodsAllowed); return; @@ -350,7 +348,7 @@ methodsAllowed = "OPTIONS, GET, HEAD, POST, DELETE, TRACE, " + "PROPFIND, PROPPATCH, COPY, MOVE, LOCK, UNLOCK"; - if (!resources.isCollection(servletPath)) { + if (!resources.isCollection(path)) { methodsAllowed += ", PUT"; } @@ -370,9 +368,7 @@ return; } - String servletPath = req.getServletPath(); - if (servletPath == null) - servletPath = "/"; + String path = getRelativePath(req); // Properties which are to be displayed. Vector properties = null; @@ -460,8 +456,8 @@ Resources resources = context.getResources(); - if (!resources.exists(servletPath)) { - resp.sendError(HttpServletResponse.SC_NOT_FOUND, servletPath); + if (!resources.exists(path)) { + resp.sendError(HttpServletResponse.SC_NOT_FOUND, path); return; } @@ -474,12 +470,12 @@ XMLWriter.OPENING); if (depth == 0) { - parseProperties(resources, generatedXML, servletPath, type, + parseProperties(req, resources, generatedXML, path, type, properties); } else { // The stack always contains the object of the current level Stack stack = new Stack(); - stack.push(servletPath); + stack.push(path); // Stack of the objects one level below Stack stackBelow = new Stack(); @@ -487,7 +483,7 @@ while ((!stack.isEmpty()) && (depth >= 0)) { String currentPath = (String) stack.pop(); - parseProperties(resources, generatedXML, currentPath, type, + parseProperties(req, resources, generatedXML, currentPath, type, properties); if (resources.isCollection(currentPath)) { @@ -510,7 +506,7 @@ String lockNullPath = (String) lockNullResourcesList.nextElement(); parseLockNullProperties - (generatedXML, currentPath, type, + (req, generatedXML, currentPath, type, properties); } } @@ -574,9 +570,7 @@ return; } - String servletPath = req.getServletPath(); - if (servletPath == null) - servletPath = "/"; + String path = getRelativePath(req); // Retrieve the Catalina context ApplicationContext context = (ApplicationContext) getServletContext(); @@ -585,12 +579,12 @@ // Can't create a collection if a resource already exists at the given // path - if (resources.exists(servletPath)) { + if (resources.exists(path)) { resp.sendError(WebdavStatus.SC_METHOD_NOT_ALLOWED); return; } - boolean result = resources.createCollection(servletPath); + boolean result = resources.createCollection(path); if (!result) { resp.sendError(WebdavStatus.SC_CONFLICT, @@ -599,7 +593,7 @@ } else { resp.setStatus(WebdavStatus.SC_CREATED); // Removing any lock-null resource which would be present - lockNullResources.remove(servletPath); + lockNullResources.remove(path); } } @@ -645,12 +639,10 @@ super.doPut(req, resp); - String servletPath = req.getServletPath(); - if (servletPath == null) - servletPath = "/"; + String path = getRelativePath(req); // Removing any lock-null resource which would be present - lockNullResources.remove(servletPath); + lockNullResources.remove(path); } @@ -686,12 +678,10 @@ return; } - String servletPath = req.getServletPath(); - if (servletPath == null) - servletPath = "/"; + String path = getRelativePath(req); if (copyResource(req, resp)) { - deleteResource(servletPath, resp); + deleteResource(path, req, resp); } } @@ -893,11 +883,9 @@ } - String servletPath = req.getServletPath(); - if (servletPath == null) - servletPath = "/"; + String path = getRelativePath(req); - lock.path = servletPath; + lock.path = path; // Retrieve the Catalina context ApplicationContext context = (ApplicationContext) getServletContext(); @@ -917,8 +905,7 @@ String lockToken = md5Encoder.encode(md5Helper.digest(lockTokenStr.getBytes())); - if ( (resources.exists(servletPath)) && - (resources.isCollection(servletPath)) && + if ( (resources.exists(path)) && (resources.isCollection(path)) && (lock.depth == INFINITY) ) { // Locking a collection (and all its member resources) @@ -1090,7 +1077,7 @@ // Checking resource locks - LockInfo toRenew = (LockInfo) resourceLocks.get(servletPath); + LockInfo toRenew = (LockInfo) resourceLocks.get(path); Enumeration tokenList = null; if (lock != null) { @@ -1112,7 +1099,7 @@ Enumeration collectionLocksList = collectionLocks.elements(); while (collectionLocksList.hasMoreElements()) { toRenew = (LockInfo) collectionLocksList.nextElement(); - if (servletPath.equals(toRenew.path)) { + if (path.equals(toRenew.path)) { tokenList = toRenew.tokens.elements(); while (tokenList.hasMoreElements()) { @@ -1163,9 +1150,7 @@ return; } - String servletPath = req.getServletPath(); - if (servletPath == null) - servletPath = "/"; + String path = getRelativePath(req); String lockTokenHeader = req.getHeader("Lock-Token"); if (lockTokenHeader == null) @@ -1173,7 +1158,7 @@ // Checking resource locks - LockInfo lock = (LockInfo) resourceLocks.get(servletPath); + LockInfo lock = (LockInfo) resourceLocks.get(path); Enumeration tokenList = null; if (lock != null) { @@ -1188,9 +1173,9 @@ } if (lock.tokens.isEmpty()) { - resourceLocks.remove(servletPath); + resourceLocks.remove(path); // Removing any lock-null resource which would be present - lockNullResources.remove(servletPath); + lockNullResources.remove(path); } } @@ -1200,7 +1185,7 @@ Enumeration collectionLocksList = collectionLocks.elements(); while (collectionLocksList.hasMoreElements()) { lock = (LockInfo) collectionLocksList.nextElement(); - if (servletPath.equals(lock.path)) { + if (path.equals(lock.path)) { tokenList = lock.tokens.elements(); while (tokenList.hasMoreElements()) { @@ -1214,7 +1199,7 @@ if (lock.tokens.isEmpty()) { collectionLocks.removeElement(lock); // Removing any lock-null resource which would be present - lockNullResources.remove(servletPath); + lockNullResources.remove(path); } } @@ -1240,9 +1225,7 @@ */ private boolean isLocked(HttpServletRequest req) { - String servletPath = req.getServletPath(); - if (servletPath == null) - servletPath = "/"; + String path = getRelativePath(req); String ifHeader = req.getHeader("If"); if (ifHeader == null) @@ -1252,7 +1235,7 @@ if (lockTokenHeader == null) lockTokenHeader = ""; - return isLocked(servletPath, ifHeader + lockTokenHeader); + return isLocked(path, ifHeader + lockTokenHeader); } @@ -1331,7 +1314,6 @@ // Parsing destination header String destinationPath = req.getHeader("Destination"); - System.out.println("Dest path:" + destinationPath); if (destinationPath.startsWith("http://")) { destinationPath = destinationPath.substring("http://".length()); @@ -1341,7 +1323,6 @@ if ((hostName != null) && (destinationPath.startsWith(hostName))) { destinationPath = destinationPath.substring(hostName.length()); } - System.out.println("Dest path 2:" + destinationPath); if (destinationPath.startsWith(":")) { int firstSeparator = destinationPath.indexOf("/"); @@ -1351,23 +1332,27 @@ destinationPath = destinationPath.substring(firstSeparator); } } - System.out.println("Dest path 3:" + destinationPath); - /* - String servletPath = req.getServletPath(); - if ((servletPath != null) && - (destinationPath.startsWith(servletPath))) { - destinationPath = destinationPath - .substring(servletPath.length()); - } - System.out.println("Dest path 4:" + destinationPath); - */ - - String servletPath = req.getServletPath(); - if (servletPath == null) - servletPath = "/"; + String contextPath = req.getContextPath(); + if ((contextPath != null) && + (destinationPath.startsWith(contextPath))) { + destinationPath = destinationPath.substring(contextPath.length()); + } - if (destinationPath.equals(servletPath)) { + String pathInfo = req.getPathInfo(); + if (pathInfo != null) { + String servletPath = req.getServletPath(); + if ((servletPath != null) && + (destinationPath.startsWith(servletPath))) { + destinationPath = destinationPath + .substring(servletPath.length()); + } + } + System.out.println("Dest path :" + destinationPath); + + String path = getRelativePath(req); + + if (destinationPath.equals(path)) { resp.sendError(WebdavStatus.SC_FORBIDDEN); return false; } @@ -1396,7 +1381,7 @@ // Delete destination resource, if it exists if (resources.exists(destinationPath)) { - if (!deleteResource(destinationPath, resp)) { + if (!deleteResource(destinationPath, req, resp)) { return false; } else { resp.setStatus(WebdavStatus.SC_NO_CONTENT); @@ -1420,8 +1405,15 @@ Hashtable errorList = new Hashtable(); boolean result = copyResource(resources, errorList, - servletPath, destinationPath); + path, destinationPath); + if ((!result) || (!errorList.isEmpty())) { + + sendReport(req, resp, errorList); + return false; + + } + // Removing any lock-null resource which would be present at // the destination path lockNullResources.remove(destinationPath); @@ -1446,7 +1438,9 @@ if (resources.isCollection(source)) { if (!resources.createCollection(dest)) { - // Add the error to the list + errorList.put + (dest, + new Integer(WebdavStatus.SC_CONFLICT)); return false; } String[] members = resources.getCollectionMembers(source); @@ -1460,7 +1454,9 @@ InputStream is = resources.getResourceAsStream(source); if (!resources.setResource(dest, is)) { - // Add the error to the list + errorList.put + (source, + new Integer(WebdavStatus.SC_INTERNAL_SERVER_ERROR)); return false; } @@ -1482,16 +1478,9 @@ HttpServletResponse resp) throws ServletException, IOException { - String servletPath = req.getServletPath(); - if (servletPath == null) - servletPath = "/"; - - if (isLocked(req)) { - resp.sendError(WebdavStatus.SC_LOCKED); - return false; - } + String path = getRelativePath(req); - return deleteResource(servletPath, resp); + return deleteResource(path, req, resp); } @@ -1500,11 +1489,26 @@ * Delete a resource. * * @param path Path of the resource which is to be deleted + * @param req Servlet request * @param resp Servlet response */ - private boolean deleteResource(String path, HttpServletResponse resp) + private boolean deleteResource(String path, HttpServletRequest req, + HttpServletResponse resp) throws ServletException, IOException { + String ifHeader = req.getHeader("If"); + if (ifHeader == null) + ifHeader = ""; + + String lockTokenHeader = req.getHeader("Lock-Token"); + if (lockTokenHeader == null) + lockTokenHeader = ""; + + if (isLocked(path, ifHeader + lockTokenHeader)) { + resp.sendError(WebdavStatus.SC_LOCKED); + return false; + } + // Retrieve the Catalina context ApplicationContext context = (ApplicationContext) getServletContext(); @@ -1526,12 +1530,13 @@ Hashtable errorList = new Hashtable(); - deleteCollection(resources, path, errorList); + deleteCollection(req, resources, path, errorList); resources.deleteResource(path); if (!errorList.isEmpty()) { - // TODO : Display a status report if there was an error + sendReport(req, resp, errorList); + return false; } @@ -1544,6 +1549,119 @@ /** + * Deletes a collection. + * + * @param resources Resources implementation associated with the context + * @param path Path to the collection to be deleted + * @param errorList Contains the list of the errors which occured + */ + private void deleteCollection(HttpServletRequest req, Resources resources, + String path, Hashtable errorList) { + + String ifHeader = req.getHeader("If"); + if (ifHeader == null) + ifHeader = ""; + + String lockTokenHeader = req.getHeader("Lock-Token"); + if (lockTokenHeader == null) + lockTokenHeader = ""; + + String[] members = resources.getCollectionMembers(path); + + for (int i=0; i