webdavservlet.java
来自「RESIN 3.2 最新源码」· Java 代码 · 共 1,536 行 · 第 1/3 页
JAVA
1,536 行
/* * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved * * This file is part of Resin(R) Open Source * * Each copy or derived work must preserve the copyright notice and this * notice unmodified. * * Resin Open Source is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Resin Open Source is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty * of NON-INFRINGEMENT. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License * along with Resin Open Source; if not, write to the * Free SoftwareFoundation, Inc. * 59 Temple Place, Suite 330 * Boston, MA 02111-1307 USA * * @author Scott Ferguson */package com.caucho.servlets.webdav;import com.caucho.log.Log;import com.caucho.server.webapp.Application;import com.caucho.util.CharBuffer;import com.caucho.util.HTTPUtil;import com.caucho.util.QDate;import com.caucho.vfs.Path;import com.caucho.vfs.ReadStream;import com.caucho.vfs.Vfs;import com.caucho.vfs.WriteStream;import com.caucho.xml.XmlParser;import org.xml.sax.Attributes;import org.xml.sax.SAXException;import javax.naming.Context;import javax.naming.InitialContext;import javax.servlet.GenericServlet;import javax.servlet.ServletContext;import javax.servlet.ServletException;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.util.ArrayList;import java.util.Collections;import java.util.HashMap;import java.util.Iterator;import java.util.logging.Level;import java.util.logging.Logger;/** * Serves the WebDAV protocol. The underlying AbstractPath controls * the actual files served and modified. The default AbstractPath * just uses getRealPath from the current ServletContext. * * <p>More sophisticated users can customize AbstractPath to provide their * own WebDAV view for their objects, much like the Linux /proc * filesystem provides a view to Linux kernel modules. * * <pre> * <resource-ref res-ref-name='resin/webdav'> * <class-name>test.foo.MyDataSource</class-name> * <init-param my-foo='bar'/> * </resource-ref> * * <servlet-mapping url-pattern='/webdav/*' * servlet-name='com.caucho.http.webdav.WebDavServlet'> * <init-param enable='write'/> * <init-param path-source='resin/webdav'/> * </servlet-mapping> * </pre> */public class WebDavServlet extends GenericServlet { private static final Logger log = Log.open(WebDavServlet.class); private QDate _calendar = new QDate(); private boolean _enable = false; private boolean _enableWrite = false; private boolean _addCrLf = false; private String _user; private String _role; private boolean _needsSecure; private AbstractPath _path; private String _root; /** * Sets the enable value. */ public void setEnable(String enable) { if (enable == null || enable.equals("")) return; else if (enable.equals("read")) _enable = true; else if (enable.equals("write") || enable.equals("all") || enable.equals("yes") || enable.equals("true")) { _enable = true; _enableWrite = true; } } /** * Sets the allowed role. */ public void setRole(String role) { _role = role; } /** * Sets the allowed user. */ public void setUser(String user) { _user = user; } /** * Set true for securted. */ public void setSecure(boolean needsSecure) { _needsSecure = needsSecure; } /** * Sets the path. */ public void setPathSource(AbstractPath path) { _path = path; } /** * Sets the root. */ public void setRoot(String root) { _root = root; } /** * Sets true if should add cr/lf */ public void setCrLf(boolean addCrLf) { _addCrLf = addCrLf; } public void init() throws ServletException { String enable = getInitParameter("enable"); if (enable != null) setEnable(enable); String role = getInitParameter("role"); if (role != null) setRole(role); if (_role == null) _role = "webdav"; else if (_role.equals("*")) _role = null; String user = getInitParameter("user"); if (user != null) setUser(user); String secure = getInitParameter("secure"); if (secure == null) { } else if ("false".equalsIgnoreCase(secure) || "no".equalsIgnoreCase(secure)) _needsSecure = false; else _needsSecure = true; String pathSource = getInitParameter("path-source"); try { if (pathSource != null) { Context env = (Context) new InitialContext().lookup("java:comp/env"); _path = (AbstractPath) env.lookup(pathSource); } } catch (Exception e) { log.log(Level.FINE, e.toString(), e); } try { if (pathSource != null && _path == null) { _path = (AbstractPath) new InitialContext().lookup(pathSource); } } catch (Exception e) { throw new ServletException(e); } String root = getInitParameter("root"); if (_path != null) { } else if (_root != null) { Path pwd = ((Application) getServletContext()).getAppDir(); _path = new FilePath(pwd.lookup(_root)); } else if (root != null) { Path pwd = ((Application) getServletContext()).getAppDir(); _path = new FilePath(pwd.lookup(root)); } else _path = new ApplicationPath(); } /** * Service the webdav request. */ public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException { HttpServletRequest req = (HttpServletRequest) request; HttpServletResponse res = (HttpServletResponse) response; if (! _enable) { res.sendError(res.SC_FORBIDDEN); return; } if (_needsSecure && ! req.isSecure()) { res.sendError(res.SC_FORBIDDEN); return; } if (_role != null && ! req.isUserInRole(_role)) { res.sendError(res.SC_FORBIDDEN); return; } if (_user != null) { java.security.Principal principal = req.getUserPrincipal(); if (principal == null) { res.sendError(res.SC_FORBIDDEN); return; } if (! principal.getName().equals(_user)) { res.sendError(res.SC_FORBIDDEN); return; } } ServletContext app = getServletContext(); String requestURI = req.getRequestURI(); String pathInfo = req.getPathInfo(); String depthString = req.getHeader("Depth"); int depth = Integer.MAX_VALUE; OutputStream os = res.getOutputStream(); WriteStream out = Vfs.openWrite(os); out.setEncoding("UTF-8"); if (_addCrLf) out.setNewlineString("\r\n"); try { if ("0".equals(depthString)) depth = 0; else if ("1".equals(depthString)) depth = 1; if (req.getMethod().equals("OPTIONS")) { res.setHeader("DAV", "1"); res.setHeader("MS-Author-Via", "DAV"); if (_enableWrite) res.setHeader("Allow", "OPTIONS, PROPFIND, GET, HEAD, PUT, MKCOL, DELETE, COPY, MOVE, PROPPATCH"); else if (_enable) res.setHeader("Allow", "OPTIONS, PROPFIND, GET, HEAD"); } else if (req.getMethod().equals("PROPFIND")) { handlePropfind(req, res, out, depth); } else if (req.getMethod().equals("GET") || req.getMethod().equals("HEAD")) { handleGet(req, res, out); } else if (req.getMethod().equals("PUT") && _enableWrite) { handlePut(req, res, out); } else if (req.getMethod().equals("MKCOL") && _enableWrite) { handleMkcol(req, res, out); } else if (req.getMethod().equals("DELETE") && _enableWrite) { handleDelete(req, res, out); } else if (req.getMethod().equals("COPY") && _enableWrite) { handleCopy(req, res, out, depth); } else if (req.getMethod().equals("MOVE") && _enableWrite) { handleMove(req, res, out); } else if (req.getMethod().equals("PROPPATCH") && _enableWrite) { handleProppatch(req, res, out, depth); } else if (! _enableWrite && "PUT".equals(req.getMethod()) || "MKCOL".equals(req.getMethod()) || "DELETE".equals(req.getMethod()) || "COPY".equals(req.getMethod()) || "MOVE".equals(req.getMethod()) || "PROPPATCH".equals(req.getMethod())) { res.sendError(res.SC_FORBIDDEN); } else { res.sendError(res.SC_NOT_IMPLEMENTED, "Method not implemented"); } } finally { out.close(); } } private void handlePropfind(HttpServletRequest req, HttpServletResponse res, WriteStream out, int depth) throws ServletException, IOException { InputStream is = req.getInputStream(); PropfindHandler handler = new PropfindHandler(); XmlParser parser = new XmlParser(); parser.setContentHandler(handler); try { parser.parse(is); } catch (SAXException e) { sendError(res, out, res.SC_BAD_REQUEST, "Bad Request for PROPFIND", String.valueOf(e)); return; } Application app = (Application) getServletContext(); Path appDir = app.getAppDir(); String pathInfo = req.getPathInfo(); String uriPwd = app.getContextPath() + req.getServletPath(); if (pathInfo == null) pathInfo = "/"; else uriPwd = uriPwd + pathInfo; if (_path.isDirectory(pathInfo, req, app) && ! uriPwd.endsWith("/")) uriPwd = uriPwd + "/"; ServletContext rootApp = app.getContext("/"); ArrayList<AttributeName> properties = handler.getProperties(); boolean isPropname = handler.isPropname(); if (properties.size() == 0) addAllProperties(properties, pathInfo, req, app); startMultistatus(res, out); printPathProperties(out, req, app, uriPwd, pathInfo, properties, isPropname, depth); out.println("</D:multistatus>"); } /** * Proppatch sets properties. This implementation does not allow * any property setting. */ private void handleProppatch(HttpServletRequest req, HttpServletResponse res, WriteStream out, int depth) throws ServletException, IOException { InputStream is = req.getInputStream(); ProppatchHandler handler = new ProppatchHandler(); XmlParser parser = new XmlParser(); parser.setContentHandler(handler); try { parser.parse(is); } catch (SAXException e) { sendError(res, out, res.SC_BAD_REQUEST, "Bad Request for PROPPATCH", "Bad Request: " + e); return; } Application app = (Application) getServletContext(); Path appDir = app.getAppDir(); String pathInfo = req.getPathInfo(); String uriPwd = app.getContextPath() + req.getServletPath(); if (pathInfo == null) pathInfo = "/"; else uriPwd = uriPwd + pathInfo; if (_path.isDirectory(pathInfo, req, app) && ! uriPwd.endsWith("/")) uriPwd = uriPwd + "/"; ArrayList forbidden = new ArrayList(); startMultistatus(res, out); out.println("<D:response>"); out.println("<D:href>" + escapeXml(uriPwd) + "</D:href>"); ArrayList properties = new ArrayList(); ArrayList<ProppatchCommand> commands = handler.getCommands(); for (int i = 0; i < commands.size(); i++) { ProppatchCommand command = commands.get(i); int code = command.getCode(); AttributeName name = command.getName(); String value = command.getValue(); int status; out.println("<D:propstat><D:prop><" + name.getName() + " xmlns:" + name.getPrefix() + "=\"" + name.getNamespace() + "\"/>"); if (code == ProppatchCommand.SET) { _path.setAttribute(name, value, pathInfo, req, app); out.println("<D:status>HTTP/1.1 200 OK</D:status>"); } else if (code == ProppatchCommand.REMOVE) { _path.removeAttribute(name, pathInfo, req, app); out.println("<D:status>HTTP/1.1 200 OK</D:status>"); } else out.println("<D:status>HTTP/1.1 424 Failed</D:status>"); out.println("</D:prop></D:propstat>"); } out.println("</D:response>"); out.println("</D:multistatus>"); } private void handlePut(HttpServletRequest req, HttpServletResponse res, WriteStream out) throws ServletException, IOException { ServletContext app = getServletContext(); String pathInfo = req.getPathInfo(); if (pathInfo == null) pathInfo = "/"; if (! _path.isDirectory(getParent(pathInfo), req, app)) { sendError(res, out, 409, "Conflict", "PUT requires a parent collection"); return; } else if (! _path.exists(pathInfo, req, app)) res.setStatus(201, "Created"); else res.setStatus(204, "No Content"); OutputStream os; try { os = _path.openWrite(pathInfo, req, app); } catch (IOException e) { log.log(Level.FINE, e.toString(), e); sendError(res, out, 403, "Forbidden", "PUT forbidden"); return; } WriteStream ws = Vfs.openWrite(os); Path path =ws.getPath(); try { InputStream is = req.getInputStream(); ws.writeStream(is); } finally { ws.close(); } } /** * Creates a directory. */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?