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> * &lt;resource-ref res-ref-name='resin/webdav'> *   &lt;class-name>test.foo.MyDataSource&lt;/class-name> *   &lt;init-param my-foo='bar'/> * &lt;/resource-ref> * * &lt;servlet-mapping url-pattern='/webdav/*' *                  servlet-name='com.caucho.http.webdav.WebDavServlet'> *   &lt;init-param enable='write'/> *   &lt;init-param path-source='resin/webdav'/> * &lt;/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 + -
显示快捷键?