All Downloads are FREE. Search and download functionalities are using the official Maven repository.

nl.info.webdav.WebDavServletBean Maven / Gradle / Ivy

There is a newer version: 1.2.73
Show newest version
package nl.info.webdav;

import java.io.IOException;
import java.security.Principal;
import java.util.Enumeration;
import java.util.HashMap;

import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import nl.info.webdav.exceptions.UnauthenticatedException;
import nl.info.webdav.locking.ResourceLocks;
import nl.info.webdav.methods.DoCopy;
import nl.info.webdav.methods.DoDelete;
import nl.info.webdav.methods.DoGet;
import nl.info.webdav.methods.DoHead;
import nl.info.webdav.methods.DoLock;
import nl.info.webdav.methods.DoMkcol;
import nl.info.webdav.methods.DoMove;
import nl.info.webdav.methods.DoNotImplemented;
import nl.info.webdav.methods.DoOptions;
import nl.info.webdav.methods.DoPropfind;
import nl.info.webdav.methods.DoProppatch;
import nl.info.webdav.methods.DoPut;
import nl.info.webdav.methods.DoUnlock;

public class WebDavServletBean extends HttpServlet {
    private static final org.slf4j.Logger LOG = org.slf4j.LoggerFactory.getLogger(WebDavServletBean.class);

    private static final boolean READ_ONLY = false;
    private final HashMap _methodMap = new HashMap<>();
    protected ResourceLocks _resLocks;
    protected IWebdavStore _store;

    public WebDavServletBean() {
        _resLocks = new ResourceLocks();
    }

    public void init(
            IWebdavStore store,
            String dftIndexFile,
            String insteadOf404,
            int noContentLengthHeaders,
            boolean lazyFolderCreationOnPut
    ) {
        _store = store;
        IMimeTyper mimeTyper = (transaction, path) -> {
            String retVal = _store.getStoredObject(transaction, path).getMimeType();
            if (retVal == null) {
                retVal = getServletContext().getMimeType(path);
            }
            return retVal;
        };

        register("GET", new DoGet(store, dftIndexFile, insteadOf404, _resLocks,
                mimeTyper, noContentLengthHeaders));
        register("HEAD", new DoHead(store, dftIndexFile, insteadOf404,
                _resLocks, mimeTyper, noContentLengthHeaders));
        DoDelete doDelete = (DoDelete) register("DELETE", new DoDelete(store,
                _resLocks, READ_ONLY));
        DoCopy doCopy = (DoCopy) register("COPY", new DoCopy(store, _resLocks,
                doDelete, READ_ONLY));
        register("LOCK", new DoLock(store, _resLocks, READ_ONLY));
        register("UNLOCK", new DoUnlock(store, _resLocks, READ_ONLY));
        register("MOVE", new DoMove(_resLocks, doDelete, doCopy, READ_ONLY));
        register("MKCOL", new DoMkcol(store, _resLocks, READ_ONLY));
        register("OPTIONS", new DoOptions(store, _resLocks));
        register("PUT", new DoPut(store, _resLocks, READ_ONLY,
                lazyFolderCreationOnPut));
        register("PROPFIND", new DoPropfind(store, _resLocks, mimeTyper));
        register("PROPPATCH", new DoProppatch(store, _resLocks, READ_ONLY));
        register("*NO*IMPL*", new DoNotImplemented(READ_ONLY));
    }

    @Override
    public void destroy() {
        if (_store != null)
            _store.destroy();
        super.destroy();
    }

    protected IMethodExecutor register(String methodName, IMethodExecutor method) {
        _methodMap.put(methodName, method);
        return method;
    }

    /**
     * Handles the special WebDAV methods.
     */
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String methodName = req.getMethod();
        ITransaction transaction = null;
        boolean needRollback = false;

        if (LOG.isTraceEnabled())
            debugRequest(methodName, req);

        try {
            Principal userPrincipal = getUserPrincipal(req);
            transaction = _store.begin(userPrincipal);
            needRollback = true;
            _store.checkAuthentication(transaction);
            resp.setStatus(WebdavStatus.SC_OK);

            try {
                IMethodExecutor methodExecutor = _methodMap
                        .get(methodName);
                if (methodExecutor == null) {
                    methodExecutor = _methodMap
                            .get("*NO*IMPL*");
                }
                methodExecutor.execute(transaction, req, resp);
                _store.commit(transaction);

                // Clear input stream if available otherwise later access
                // include current input. This occurs if the client
                // sends a request with body to a resource that does not exist.
                if (req.getContentLength() != 0 && !req.getInputStream().isFinished()) {
                    LOG.trace("Skipping over unconsumed data from the input stream.");
                    int bytesAvailable;
                    while ((bytesAvailable = req.getInputStream().available()) > 0) {
                        long bytesSkipped = req.getInputStream().skip(bytesAvailable);
                        LOG.trace("Skipped over {} bytes from the input stream.", bytesSkipped);
                    }
                }
                needRollback = false;
            } catch (IOException ioException) {
                LOG.error("Error occurred during handling of WebDAV method. Rolling back transaction.", ioException);
                if (!resp.isCommitted())
                    resp.sendError(WebdavStatus.SC_INTERNAL_SERVER_ERROR);
                _store.rollback(transaction);
                throw new ServletException(ioException);
            }
        } catch (UnauthenticatedException exception) {
            if (!resp.isCommitted())
                resp.sendError(WebdavStatus.SC_FORBIDDEN);
        } catch (Exception exception) {
            LOG.error("Error occurred during handling of WebDAV method. Rolling back transaction.", exception);
            throw new ServletException(exception);
        } finally {
            if (needRollback)
                _store.rollback(transaction);
        }
    }

    /**
     * Method that permit to customize the way
     * user information are extracted from the request, default use JAAS
     * 
     * @param req the request
     * @return the principal
     */
    protected Principal getUserPrincipal(HttpServletRequest req) {
        return req.getUserPrincipal();
    }

    private void debugRequest(String methodName, HttpServletRequest req) {
        LOG.trace("-----------");
        LOG.trace("WebdavServlet\n request: methodName = {}", methodName);
        LOG.trace("time: {}", System.currentTimeMillis());
        LOG.trace("path: {}", req.getRequestURI());
        LOG.trace("-----------");
        Enumeration e = req.getHeaderNames();
        while (e.hasMoreElements()) {
            String s = (String) e.nextElement();
            LOG.trace("header: {} {}", s, req.getHeader(s));
        }
        e = req.getAttributeNames();
        while (e.hasMoreElements()) {
            String s = (String) e.nextElement();
            LOG.trace("attribute: {} {}", s, req.getAttribute(s));
        }
        e = req.getParameterNames();
        while (e.hasMoreElements()) {
            String s = (String) e.nextElement();
            LOG.trace("parameter: {} {}", s, req.getParameter(s));
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy