jackrabbit-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ang...@apache.org
Subject svn commit: r596721 - in /jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav: DavConstants.java server/ server/AbstractWebdavServlet.java
Date Tue, 20 Nov 2007 15:45:36 GMT
Author: angela
Date: Tue Nov 20 07:45:35 2007
New Revision: 596721

URL: http://svn.apache.org/viewvc?rev=596721&view=rev
Log:
JCR-1210 WebDAV: pack AbstractWebdavServlet with the jackrabbit-webdav project

Added:
    jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/server/
    jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/server/AbstractWebdavServlet.java
  (with props)
Modified:
    jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavConstants.java

Modified: jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavConstants.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavConstants.java?rev=596721&r1=596720&r2=596721&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavConstants.java
(original)
+++ jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavConstants.java
Tue Nov 20 07:45:35 2007
@@ -34,7 +34,7 @@
      */
     public static final Namespace NAMESPACE = Namespace.getNamespace("D", "DAV:");
 
-    //---< Headers (Names and Value Constants) >--------------------------------
+    //--------------------------------< Headers (Names and Value Constants) >---
     public static final String HEADER_DAV = "DAV";
     public static final String HEADER_DESTINATION = "Destination";
     public static final String HEADER_IF = "If";
@@ -102,7 +102,7 @@
     public static final String XML_WRITE = "write";
     public static final String XML_OWNER = "owner";
 
-    //---< Property Names >-----------------------------------------------------
+    //-----------------------------------------------------< Property Names >---
     /*
      * Webdav property names as defined by RFC 2518<br>
      * Note: Microsoft webdav clients as well as Webdrive request additional
@@ -122,12 +122,17 @@
     public static final String PROPERTY_SOURCE = "source";
     public static final String PROPERTY_SUPPORTEDLOCK = "supportedlock";
 
-    //---< PropFind Constants >-------------------------------------------------
+    //-------------------------------------------------< PropFind Constants >---
     public static final int PROPFIND_BY_PROPERTY = 0;
     public static final int PROPFIND_ALL_PROP = 1;
     public static final int PROPFIND_PROPERTY_NAMES = 2;
 
-    //---< Date Format Constants >----------------------------------------------
+    //----------------------------------------------< Date Format Constants >---
+    /**
+     * Marker for undefined modification or creation time.
+     */
+    public static long UNDEFINED_TIME = -1;
+
     /**
      * modificationDate date format per RFC 1123
      */

Added: jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/server/AbstractWebdavServlet.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/server/AbstractWebdavServlet.java?rev=596721&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/server/AbstractWebdavServlet.java
(added)
+++ jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/server/AbstractWebdavServlet.java
Tue Nov 20 07:45:35 2007
@@ -0,0 +1,1168 @@
+/*
+ * $Id$
+ *
+ * Copyright 1997-2005 Day Management AG
+ * Barfuesserplatz 6, 4001 Basel, Switzerland
+ * All Rights Reserved.
+ *
+ * This software is the confidential and proprietary information of
+ * Day Management AG, ("Confidential Information"). You shall not
+ * disclose such Confidential Information and shall use it only in
+ * accordance with the terms of the license agreement you entered into
+ * with Day.
+ */
+package org.apache.jackrabbit.webdav.server;
+
+import org.apache.jackrabbit.webdav.DavCompliance;
+import org.apache.jackrabbit.webdav.DavConstants;
+import org.apache.jackrabbit.webdav.DavException;
+import org.apache.jackrabbit.webdav.DavLocatorFactory;
+import org.apache.jackrabbit.webdav.DavMethods;
+import org.apache.jackrabbit.webdav.DavResource;
+import org.apache.jackrabbit.webdav.DavResourceFactory;
+import org.apache.jackrabbit.webdav.DavServletRequest;
+import org.apache.jackrabbit.webdav.DavServletResponse;
+import org.apache.jackrabbit.webdav.DavSessionProvider;
+import org.apache.jackrabbit.webdav.MultiStatus;
+import org.apache.jackrabbit.webdav.MultiStatusResponse;
+import org.apache.jackrabbit.webdav.WebdavRequest;
+import org.apache.jackrabbit.webdav.WebdavRequestImpl;
+import org.apache.jackrabbit.webdav.WebdavResponse;
+import org.apache.jackrabbit.webdav.WebdavResponseImpl;
+import org.apache.jackrabbit.webdav.io.InputContext;
+import org.apache.jackrabbit.webdav.io.InputContextImpl;
+import org.apache.jackrabbit.webdav.io.OutputContext;
+import org.apache.jackrabbit.webdav.io.OutputContextImpl;
+import org.apache.jackrabbit.webdav.lock.ActiveLock;
+import org.apache.jackrabbit.webdav.lock.LockInfo;
+import org.apache.jackrabbit.webdav.observation.EventDiscovery;
+import org.apache.jackrabbit.webdav.observation.ObservationResource;
+import org.apache.jackrabbit.webdav.observation.Subscription;
+import org.apache.jackrabbit.webdav.observation.SubscriptionInfo;
+import org.apache.jackrabbit.webdav.ordering.OrderPatch;
+import org.apache.jackrabbit.webdav.ordering.OrderingResource;
+import org.apache.jackrabbit.webdav.property.DavProperty;
+import org.apache.jackrabbit.webdav.property.DavPropertyName;
+import org.apache.jackrabbit.webdav.property.DavPropertyNameSet;
+import org.apache.jackrabbit.webdav.search.SearchConstants;
+import org.apache.jackrabbit.webdav.search.SearchInfo;
+import org.apache.jackrabbit.webdav.search.SearchResource;
+import org.apache.jackrabbit.webdav.security.AclProperty;
+import org.apache.jackrabbit.webdav.security.AclResource;
+import org.apache.jackrabbit.webdav.transaction.TransactionInfo;
+import org.apache.jackrabbit.webdav.transaction.TransactionResource;
+import org.apache.jackrabbit.webdav.version.ActivityResource;
+import org.apache.jackrabbit.webdav.version.DeltaVConstants;
+import org.apache.jackrabbit.webdav.version.DeltaVResource;
+import org.apache.jackrabbit.webdav.version.LabelInfo;
+import org.apache.jackrabbit.webdav.version.MergeInfo;
+import org.apache.jackrabbit.webdav.version.OptionsInfo;
+import org.apache.jackrabbit.webdav.version.OptionsResponse;
+import org.apache.jackrabbit.webdav.version.UpdateInfo;
+import org.apache.jackrabbit.webdav.version.VersionControlledResource;
+import org.apache.jackrabbit.webdav.version.VersionResource;
+import org.apache.jackrabbit.webdav.version.VersionableResource;
+import org.apache.jackrabbit.webdav.version.report.Report;
+import org.apache.jackrabbit.webdav.version.report.ReportInfo;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.w3c.dom.Document;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+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.List;
+
+/**
+ * <code>AbstractWebdavServlet</code>
+ * <p/>
+ */
+abstract public class AbstractWebdavServlet extends HttpServlet implements DavConstants {
+
+    // todo respect Position header
+    /**
+     * default logger
+     */
+    private static Logger log = LoggerFactory.getLogger(AbstractWebdavServlet.class);
+
+    /**
+     * Default value for the 'WWW-Authenticate' header, that is set, if request
+     * results in a {@link DavServletResponse#SC_UNAUTHORIZED 401 (Unauthorized)}
+     * error.
+     *
+     * @see #getAuthenticateHeaderValue()
+     */
+    public static final String DEFAULT_AUTHENTICATE_HEADER = "Basic realm=\"Jackrabbit Webdav
Server\"";
+
+    /**
+     * Checks if the precondition for this request and resource is valid.
+     *
+     * @param request
+     * @param resource
+     * @return
+     */
+    abstract protected boolean isPreconditionValid(WebdavRequest request, DavResource resource);
+
+    /**
+     * Returns the <code>DavSessionProvider</code>.
+     *
+     * @return the session provider
+     */
+    abstract public DavSessionProvider getDavSessionProvider();
+
+    /**
+     * Returns the <code>DavSessionProvider</code>.
+     *
+     * @param davSessionProvider
+     */
+    abstract public void setDavSessionProvider(DavSessionProvider davSessionProvider);
+
+    /**
+     * Returns the <code>DavLocatorFactory</code>.
+     *
+     * @return the locator factory
+     */
+    abstract public DavLocatorFactory getLocatorFactory();
+
+    /**
+     * Sets the <code>DavLocatorFactory</code>.
+     *
+     * @param locatorFactory
+     */
+    abstract public void setLocatorFactory(DavLocatorFactory locatorFactory);
+
+    /**
+     * Returns the <code>DavResourceFactory</code>.
+     *
+     * @return the resource factory
+     */
+    abstract public DavResourceFactory getResourceFactory();
+
+    /**
+     * Sets the <code>DavResourceFactory</code>.
+     *
+     * @param resourceFactory
+     */
+    abstract public void setResourceFactory(DavResourceFactory resourceFactory);
+
+    /**
+     * Returns the value of the 'WWW-Authenticate' header, that is returned in
+     * case of 401 error.
+     *
+     * @return value of the 'WWW-Authenticate' header
+     */
+    abstract public String getAuthenticateHeaderValue();
+
+    /**
+     * Service the given request.
+     *
+     * @param request
+     * @param response
+     * @throws ServletException
+     * @throws IOException
+     */
+    protected void service(HttpServletRequest request, HttpServletResponse response)
+            throws ServletException, IOException {
+
+        WebdavRequest webdavRequest = new WebdavRequestImpl(request, getLocatorFactory());
+        // DeltaV requires 'Cache-Control' header for all methods except 'VERSION-CONTROL'
and 'REPORT'.
+        int methodCode = DavMethods.getMethodCode(request.getMethod());
+        boolean noCache = DavMethods.isDeltaVMethod(webdavRequest) && !(DavMethods.DAV_VERSION_CONTROL
== methodCode || DavMethods.DAV_REPORT == methodCode);
+        WebdavResponse webdavResponse = new WebdavResponseImpl(response, noCache);
+        try {
+            // make sure there is a authenticated user
+            if (!getDavSessionProvider().attachSession(webdavRequest)) {
+                return;
+            }
+
+            // check matching if=header for lock-token relevant operations
+            DavResource resource = getResourceFactory().createResource(webdavRequest.getRequestLocator(),
webdavRequest, webdavResponse);
+            if (!isPreconditionValid(webdavRequest, resource)) {
+                webdavResponse.sendError(DavServletResponse.SC_PRECONDITION_FAILED);
+                return;
+            }
+            if (!execute(webdavRequest, webdavResponse, methodCode, resource)) {
+                super.service(request, response);
+            }
+
+        } catch (DavException e) {
+            if (e.getErrorCode() == HttpServletResponse.SC_UNAUTHORIZED) {
+                webdavResponse.setHeader("WWW-Authenticate", getAuthenticateHeaderValue());
+                webdavResponse.sendError(e.getErrorCode(), e.getStatusPhrase());
+            } else {
+                webdavResponse.sendError(e);
+            }
+        } finally {
+            getDavSessionProvider().releaseSession(webdavRequest);
+        }
+    }
+
+    /**
+     * Executes the respective method in the given webdav context
+     *
+     * @param request
+     * @param response
+     * @param method
+     * @param resource
+     * @throws ServletException
+     * @throws IOException
+     * @throws DavException
+     */
+    protected boolean execute(WebdavRequest request, WebdavResponse response,
+                              int method, DavResource resource)
+            throws ServletException, IOException, DavException {
+
+        switch (method) {
+            case DavMethods.DAV_GET:
+                doGet(request, response, resource);
+                break;
+            case DavMethods.DAV_HEAD:
+                doHead(request, response, resource);
+                break;
+            case DavMethods.DAV_PROPFIND:
+                doPropFind(request, response, resource);
+                break;
+            case DavMethods.DAV_PROPPATCH:
+                doPropPatch(request, response, resource);
+                break;
+            case DavMethods.DAV_POST:
+                doPost(request, response, resource);
+                break;
+            case DavMethods.DAV_PUT:
+                doPut(request, response, resource);
+                break;
+            case DavMethods.DAV_DELETE:
+                doDelete(request, response, resource);
+                break;
+            case DavMethods.DAV_COPY:
+                doCopy(request, response, resource);
+                break;
+            case DavMethods.DAV_MOVE:
+                doMove(request, response, resource);
+                break;
+            case DavMethods.DAV_MKCOL:
+                doMkCol(request, response, resource);
+                break;
+            case DavMethods.DAV_OPTIONS:
+                doOptions(request, response, resource);
+                break;
+            case DavMethods.DAV_LOCK:
+                doLock(request, response, resource);
+                break;
+            case DavMethods.DAV_UNLOCK:
+                doUnlock(request, response, resource);
+                break;
+            case DavMethods.DAV_ORDERPATCH:
+                doOrderPatch(request, response, resource);
+                break;
+            case DavMethods.DAV_SUBSCRIBE:
+                doSubscribe(request, response, resource);
+                break;
+            case DavMethods.DAV_UNSUBSCRIBE:
+                doUnsubscribe(request, response, resource);
+                break;
+            case DavMethods.DAV_POLL:
+                doPoll(request, response, resource);
+                break;
+            case DavMethods.DAV_SEARCH:
+                doSearch(request, response, resource);
+                break;
+            case DavMethods.DAV_VERSION_CONTROL:
+                doVersionControl(request, response, resource);
+                break;
+            case DavMethods.DAV_LABEL:
+                doLabel(request, response, resource);
+                break;
+            case DavMethods.DAV_REPORT:
+                doReport(request, response, resource);
+                break;
+            case DavMethods.DAV_CHECKIN:
+                doCheckin(request, response, resource);
+                break;
+            case DavMethods.DAV_CHECKOUT:
+                doCheckout(request, response, resource);
+                break;
+            case DavMethods.DAV_UNCHECKOUT:
+                doUncheckout(request, response, resource);
+                break;
+            case DavMethods.DAV_MERGE:
+                doMerge(request, response, resource);
+                break;
+            case DavMethods.DAV_UPDATE:
+                doUpdate(request, response, resource);
+                break;
+            case DavMethods.DAV_MKWORKSPACE:
+                doMkWorkspace(request, response, resource);
+                break;
+            case DavMethods.DAV_MKACTIVITY:
+                doMkActivity(request, response, resource);
+                break;
+            case DavMethods.DAV_BASELINE_CONTROL:
+                doBaselineControl(request, response, resource);
+                break;
+            case DavMethods.DAV_ACL:
+                doAcl(request, response, resource);
+                break;
+            default:
+                // any other method
+                return false;
+        }
+        return true;
+    }
+
+    /**
+     * The OPTION method
+     *
+     * @param request
+     * @param response
+     * @param resource
+     */
+    protected void doOptions(WebdavRequest request, WebdavResponse response,
+                             DavResource resource) throws IOException, DavException {
+        response.addHeader(DavConstants.HEADER_DAV, resource.getComplianceClass());
+        response.addHeader("Allow", resource.getSupportedMethods());
+        response.addHeader("MS-Author-Via", DavConstants.HEADER_DAV);
+        if (resource instanceof SearchResource) {
+            String[] langs = ((SearchResource) resource).getQueryGrammerSet().getQueryLanguages();
+            for (int i = 0; i < langs.length; i++) {
+                response.addHeader(SearchConstants.HEADER_DASL, "<" + langs[i] + ">");
+            }
+        }
+        // with DeltaV the OPTIONS request may contain a Xml body.
+        OptionsResponse oR = null;
+        OptionsInfo oInfo = request.getOptionsInfo();
+        if (oInfo != null && resource instanceof DeltaVResource) {
+            oR = ((DeltaVResource) resource).getOptionResponse(oInfo);
+        }
+        if (oR == null) {
+            response.setStatus(DavServletResponse.SC_OK);
+        } else {
+            response.sendXmlResponse(oR, DavServletResponse.SC_OK);
+        }
+    }
+
+    /**
+     * The HEAD method
+     *
+     * @param request
+     * @param response
+     * @param resource
+     * @throws IOException
+     */
+    protected void doHead(WebdavRequest request, WebdavResponse response,
+                          DavResource resource) throws IOException {
+        spoolResource(request, response, resource, false);
+    }
+
+    /**
+     * The GET method
+     *
+     * @param request
+     * @param response
+     * @param resource
+     * @throws IOException
+     */
+    protected void doGet(WebdavRequest request, WebdavResponse response,
+                         DavResource resource) throws IOException {
+        spoolResource(request, response, resource, true);
+    }
+
+    /**
+     * @param request
+     * @param response
+     * @param resource
+     * @param sendContent
+     * @throws IOException
+     */
+    private void spoolResource(WebdavRequest request, WebdavResponse response,
+                               DavResource resource, boolean sendContent)
+            throws IOException {
+
+        if (!resource.exists()) {
+            response.sendError(HttpServletResponse.SC_NOT_FOUND);
+            return;
+        }
+
+        long modSince = request.getDateHeader("If-Modified-Since");
+        if (modSince > UNDEFINED_TIME) {
+            long modTime = resource.getModificationTime();
+            // test if resource has been modified. note that formatted modification
+            // time lost the milli-second precision
+            if (modTime != UNDEFINED_TIME && (modTime / 1000 * 1000) <= modSince)
{
+                // resource has not been modified since the time indicated in the
+                // 'If-Modified-Since' header.
+                response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
+                return;
+            }
+        }
+
+        // spool resource properties and ev. resource content.
+        OutputStream out = (sendContent) ? response.getOutputStream() : null;
+        resource.spool(getOutputContext(response, out));
+        response.flushBuffer();
+    }
+
+    /**
+     * The PROPFIND method
+     *
+     * @param request
+     * @param response
+     * @param resource
+     * @throws IOException
+     */
+    protected void doPropFind(WebdavRequest request, WebdavResponse response,
+                              DavResource resource) throws IOException, DavException {
+
+        if (!resource.exists()) {
+            response.sendError(DavServletResponse.SC_NOT_FOUND);
+            return;
+        }
+
+        int depth = request.getDepth(DEPTH_INFINITY);
+        DavPropertyNameSet requestProperties = request.getPropFindProperties();
+        int propfindType = request.getPropFindType();
+
+        MultiStatus mstatus = new MultiStatus();
+        mstatus.addResourceProperties(resource, requestProperties, propfindType, depth);
+        response.sendMultiStatus(mstatus);
+    }
+
+    /**
+     * The PROPPATCH method
+     *
+     * @param request
+     * @param response
+     * @param resource
+     * @throws IOException
+     */
+    protected void doPropPatch(WebdavRequest request, WebdavResponse response,
+                               DavResource resource)
+            throws IOException, DavException {
+
+        List changeList = request.getPropPatchChangeList();
+        if (changeList.isEmpty()) {
+            response.sendError(DavServletResponse.SC_BAD_REQUEST);
+            return;
+        }
+
+        MultiStatus ms = new MultiStatus();
+        MultiStatusResponse msr = resource.alterProperties(changeList);
+        ms.addResponse(msr);
+        response.sendMultiStatus(ms);
+    }
+
+    /**
+     * The POST method. Delegate to PUT
+     *
+     * @param request
+     * @param response
+     * @param resource
+     * @throws IOException
+     * @throws DavException
+     */
+    protected void doPost(WebdavRequest request, WebdavResponse response,
+                          DavResource resource) throws IOException, DavException {
+        doPut(request, response, resource);
+    }
+
+    /**
+     * The PUT method
+     *
+     * @param request
+     * @param response
+     * @param resource
+     * @throws IOException
+     * @throws DavException
+     */
+    protected void doPut(WebdavRequest request, WebdavResponse response,
+                         DavResource resource) throws IOException, DavException {
+
+        DavResource parentResource = resource.getCollection();
+        if (parentResource == null || !parentResource.exists()) {
+            // parent does not exist
+            response.sendError(DavServletResponse.SC_CONFLICT);
+            return;
+        }
+
+        int status;
+        // test if resource already exists
+        if (resource.exists()) {
+            status = DavServletResponse.SC_NO_CONTENT;
+        } else {
+            status = DavServletResponse.SC_CREATED;
+        }
+
+        parentResource.addMember(resource, getInputContext(request, request.getInputStream()));
+        response.setStatus(status);
+    }
+
+    /**
+     * The MKCOL method
+     *
+     * @param request
+     * @param response
+     * @param resource
+     * @throws IOException
+     * @throws DavException
+     */
+    protected void doMkCol(WebdavRequest request, WebdavResponse response,
+                           DavResource resource) throws IOException, DavException {
+
+        DavResource parentResource = resource.getCollection();
+        if (parentResource == null || !parentResource.exists() || !parentResource.isCollection())
{
+            // parent does not exist or is not a collection
+            response.sendError(DavServletResponse.SC_CONFLICT);
+            return;
+        }
+        // shortcut: mkcol is only allowed on deleted/non-existing resources
+        if (resource.exists()) {
+            response.sendError(DavServletResponse.SC_METHOD_NOT_ALLOWED);
+        }
+
+        if (request.getContentLength() > 0 || request.getHeader("Transfer-Encoding") !=
null) {
+            parentResource.addMember(resource, getInputContext(request, request.getInputStream()));
+        } else {
+            parentResource.addMember(resource, getInputContext(request, null));
+        }
+        response.setStatus(DavServletResponse.SC_CREATED);
+    }
+
+    /**
+     * The DELETE method
+     *
+     * @param request
+     * @param response
+     * @param resource
+     * @throws IOException
+     * @throws DavException
+     */
+    protected void doDelete(WebdavRequest request, WebdavResponse response,
+                            DavResource resource) throws IOException, DavException {
+        DavResource parent = resource.getCollection();
+        if (parent != null) {
+            parent.removeMember(resource);
+            response.setStatus(DavServletResponse.SC_NO_CONTENT);
+        } else {
+            response.sendError(DavServletResponse.SC_FORBIDDEN, "Cannot remove the root resource.");
+        }
+    }
+
+    /**
+     * The COPY method
+     *
+     * @param request
+     * @param response
+     * @param resource
+     * @throws IOException
+     * @throws DavException
+     */
+    protected void doCopy(WebdavRequest request, WebdavResponse response,
+                          DavResource resource) throws IOException, DavException {
+
+        // only depth 0 and infinity is allowed
+        int depth = request.getDepth(DEPTH_INFINITY);
+        if (!(depth == DEPTH_0 || depth == DEPTH_INFINITY)) {
+            response.sendError(DavServletResponse.SC_BAD_REQUEST);
+            return;
+        }
+
+        DavResource destResource = getResourceFactory().createResource(request.getDestinationLocator(),
request, response);
+        int status = validateDestination(destResource, request);
+        if (status > DavServletResponse.SC_NO_CONTENT) {
+            response.sendError(status);
+            return;
+        }
+
+        resource.copy(destResource, depth == DEPTH_0);
+        response.setStatus(status);
+    }
+
+    /**
+     * The MOVE method
+     *
+     * @param request
+     * @param response
+     * @param resource
+     * @throws IOException
+     * @throws DavException
+     */
+    protected void doMove(WebdavRequest request, WebdavResponse response,
+                          DavResource resource) throws IOException, DavException {
+
+        DavResource destResource = getResourceFactory().createResource(request.getDestinationLocator(),
request, response);
+        int status = validateDestination(destResource, request);
+        if (status > DavServletResponse.SC_NO_CONTENT) {
+            response.sendError(status);
+            return;
+        }
+
+        resource.move(destResource);
+        response.setStatus(status);
+    }
+
+    /**
+     * Validate the given destination resource and return the proper status
+     * code: Any return value greater/equal than {@link DavServletResponse#SC_NO_CONTENT}
+     * indicates an error.
+     *
+     * @param destResource destination resource to be validated.
+     * @param request
+     * @return status code indicating whether the destination is valid.
+     */
+    private int validateDestination(DavResource destResource, WebdavRequest request)
+            throws DavException {
+
+        String destHeader = request.getHeader(HEADER_DESTINATION);
+        if (destHeader == null || "".equals(destHeader)) {
+            return DavServletResponse.SC_BAD_REQUEST;
+        }
+        if (destResource.getLocator().equals(request.getRequestLocator())) {
+            return DavServletResponse.SC_FORBIDDEN;
+        }
+
+        int status;
+        if (destResource.exists()) {
+            if (request.isOverwrite()) {
+                // matching if-header required for existing resources
+                if (!request.matchesIfHeader(destResource)) {
+                    return DavServletResponse.SC_PRECONDITION_FAILED;
+                } else {
+                    // overwrite existing resource
+                    destResource.getCollection().removeMember(destResource);
+                    status = DavServletResponse.SC_NO_CONTENT;
+                }
+            } else {
+                // cannot copy/move to an existing item, if overwrite is not forced
+                return DavServletResponse.SC_PRECONDITION_FAILED;
+            }
+        } else {
+            // destination does not exist >> copy/move can be performed
+            status = DavServletResponse.SC_CREATED;
+        }
+        return status;
+    }
+
+    /**
+     * The LOCK method
+     *
+     * @param request
+     * @param response
+     * @param resource
+     * @throws IOException
+     * @throws DavException
+     */
+    protected void doLock(WebdavRequest request, WebdavResponse response,
+                          DavResource resource) throws IOException, DavException {
+
+        LockInfo lockInfo = request.getLockInfo();
+        if (lockInfo.isRefreshLock()) {
+            // refresh any matching existing locks
+            ActiveLock[] activeLocks = resource.getLocks();
+            List lList = new ArrayList();
+            for (int i = 0; i < activeLocks.length; i++) {
+                // adjust lockinfo with type/scope retrieved from the lock.
+                lockInfo.setType(activeLocks[i].getType());
+                lockInfo.setScope(activeLocks[i].getScope());
+
+                DavProperty etagProp = resource.getProperty(DavPropertyName.GETETAG);
+                String etag = etagProp != null ? String.valueOf(etagProp.getValue()) : "";
+                if (request.matchesIfHeader(resource.getHref(), activeLocks[i].getToken(),
etag)) {
+                    lList.add(resource.refreshLock(lockInfo, activeLocks[i].getToken()));
+                }
+            }
+            if (lList.isEmpty()) {
+                throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED);
+            }
+            ActiveLock[] refreshedLocks = (ActiveLock[]) lList.toArray(new ActiveLock[lList.size()]);
+            response.sendRefreshLockResponse(refreshedLocks);
+        } else {
+            // create a new lock
+            ActiveLock lock = resource.lock(lockInfo);
+            response.sendLockResponse(lock);
+        }
+    }
+
+    /**
+     * The UNLOCK method
+     *
+     * @param request
+     * @param response
+     * @param resource
+     * @throws DavException
+     */
+    protected void doUnlock(WebdavRequest request, WebdavResponse response,
+                            DavResource resource) throws DavException {
+        // get lock token from header
+        String lockToken = request.getLockToken();
+        TransactionInfo tInfo = request.getTransactionInfo();
+        if (tInfo != null) {
+            ((TransactionResource) resource).unlock(lockToken, tInfo);
+        } else {
+            resource.unlock(lockToken);
+        }
+        response.setStatus(DavServletResponse.SC_NO_CONTENT);
+    }
+
+    /**
+     * The ORDERPATCH method
+     *
+     * @param request
+     * @param response
+     * @param resource
+     * @throws IOException
+     * @throws DavException
+     */
+    protected void doOrderPatch(WebdavRequest request,
+                                WebdavResponse response,
+                                DavResource resource)
+            throws IOException, DavException {
+
+        if (!(resource instanceof OrderingResource)) {
+            response.sendError(DavServletResponse.SC_METHOD_NOT_ALLOWED);
+            return;
+        }
+
+        OrderPatch op = request.getOrderPatch();
+        if (op == null) {
+            response.sendError(DavServletResponse.SC_BAD_REQUEST);
+            return;
+        }
+        // perform reordering of internal members
+        ((OrderingResource) resource).orderMembers(op);
+        response.setStatus(DavServletResponse.SC_OK);
+    }
+
+    /**
+     * The SUBSCRIBE method
+     *
+     * @param request
+     * @param response
+     * @param resource
+     * @throws IOException
+     * @throws DavException
+     */
+    protected void doSubscribe(WebdavRequest request,
+                               WebdavResponse response,
+                               DavResource resource)
+            throws IOException, DavException {
+
+        if (!(resource instanceof ObservationResource)) {
+            response.sendError(DavServletResponse.SC_METHOD_NOT_ALLOWED);
+            return;
+        }
+
+        SubscriptionInfo info = request.getSubscriptionInfo();
+        if (info == null) {
+            response.sendError(DavServletResponse.SC_UNSUPPORTED_MEDIA_TYPE);
+            return;
+        }
+        Subscription subs = ((ObservationResource) resource).subscribe(info, request.getSubscriptionId());
+        response.sendSubscriptionResponse(subs);
+    }
+
+    /**
+     * The UNSUBSCRIBE method
+     *
+     * @param request
+     * @param response
+     * @param resource
+     * @throws IOException
+     * @throws DavException
+     */
+    protected void doUnsubscribe(WebdavRequest request,
+                                 WebdavResponse response,
+                                 DavResource resource)
+            throws IOException, DavException {
+
+        if (!(resource instanceof ObservationResource)) {
+            response.sendError(DavServletResponse.SC_METHOD_NOT_ALLOWED);
+            return;
+        }
+        ((ObservationResource) resource).unsubscribe(request.getSubscriptionId());
+        response.setStatus(DavServletResponse.SC_NO_CONTENT);
+    }
+
+    /**
+     * The POLL method
+     *
+     * @param request
+     * @param response
+     * @param resource
+     * @throws IOException
+     * @throws DavException
+     */
+    protected void doPoll(WebdavRequest request,
+                          WebdavResponse response,
+                          DavResource resource)
+            throws IOException, DavException {
+
+        if (!(resource instanceof ObservationResource)) {
+            response.sendError(DavServletResponse.SC_METHOD_NOT_ALLOWED);
+            return;
+        }
+        EventDiscovery ed = ((ObservationResource) resource).poll(
+                request.getSubscriptionId(), request.getPollTimeout());
+        response.sendPollResponse(ed);
+    }
+
+    /**
+     * The VERSION-CONTROL method
+     *
+     * @param request
+     * @param response
+     * @param resource
+     * @throws DavException
+     * @throws IOException
+     */
+    protected void doVersionControl(WebdavRequest request, WebdavResponse response,
+                                    DavResource resource)
+            throws DavException, IOException {
+        if (!(resource instanceof VersionableResource)) {
+            response.sendError(DavServletResponse.SC_METHOD_NOT_ALLOWED);
+            return;
+        }
+        ((VersionableResource) resource).addVersionControl();
+    }
+
+    /**
+     * The LABEL method
+     *
+     * @param request
+     * @param response
+     * @param resource
+     * @throws DavException
+     * @throws IOException
+     */
+    protected void doLabel(WebdavRequest request, WebdavResponse response,
+                           DavResource resource)
+            throws DavException, IOException {
+
+        LabelInfo labelInfo = request.getLabelInfo();
+        if (resource instanceof VersionResource) {
+            ((VersionResource) resource).label(labelInfo);
+        } else if (resource instanceof VersionControlledResource) {
+            ((VersionControlledResource) resource).label(labelInfo);
+        } else {
+            // any other resource type that does not support a LABEL request
+            response.sendError(DavServletResponse.SC_METHOD_NOT_ALLOWED);
+        }
+    }
+
+    /**
+     * The REPORT method
+     *
+     * @param request
+     * @param response
+     * @param resource
+     * @throws DavException
+     * @throws IOException
+     */
+    protected void doReport(WebdavRequest request, WebdavResponse response,
+                            DavResource resource)
+            throws DavException, IOException {
+        ReportInfo info = request.getReportInfo();
+        Report report;
+        if (resource instanceof DeltaVResource) {
+            report = ((DeltaVResource) resource).getReport(info);
+        } else if (resource instanceof AclResource) {
+            report = ((AclResource) resource).getReport(info);
+        } else {
+            response.sendError(DavServletResponse.SC_METHOD_NOT_ALLOWED);
+            return;
+        }
+
+        int statusCode = (report.isMultiStatusReport()) ? DavServletResponse.SC_MULTI_STATUS
: DavServletResponse.SC_OK;
+        response.sendXmlResponse(report, statusCode);
+    }
+
+    /**
+     * The CHECKIN method
+     *
+     * @param request
+     * @param response
+     * @param resource
+     * @throws DavException
+     * @throws IOException
+     */
+    protected void doCheckin(WebdavRequest request, WebdavResponse response,
+                             DavResource resource)
+            throws DavException, IOException {
+
+        if (!(resource instanceof VersionControlledResource)) {
+            response.sendError(DavServletResponse.SC_METHOD_NOT_ALLOWED);
+            return;
+        }
+        String versionHref = ((VersionControlledResource) resource).checkin();
+        response.setHeader(DeltaVConstants.HEADER_LOCATION, versionHref);
+        response.setStatus(DavServletResponse.SC_CREATED);
+    }
+
+    /**
+     * The CHECKOUT method
+     *
+     * @param request
+     * @param response
+     * @param resource
+     * @throws DavException
+     * @throws IOException
+     */
+    protected void doCheckout(WebdavRequest request, WebdavResponse response,
+                              DavResource resource)
+            throws DavException, IOException {
+        if (!(resource instanceof VersionControlledResource)) {
+            response.sendError(DavServletResponse.SC_METHOD_NOT_ALLOWED);
+            return;
+        }
+        ((VersionControlledResource) resource).checkout();
+    }
+
+    /**
+     * The UNCHECKOUT method
+     *
+     * @param request
+     * @param response
+     * @param resource
+     * @throws DavException
+     * @throws IOException
+     */
+    protected void doUncheckout(WebdavRequest request, WebdavResponse response,
+                                DavResource resource)
+            throws DavException, IOException {
+        if (!(resource instanceof VersionControlledResource)) {
+            response.sendError(DavServletResponse.SC_METHOD_NOT_ALLOWED);
+            return;
+        }
+        ((VersionControlledResource) resource).uncheckout();
+    }
+
+    /**
+     * The MERGE method
+     *
+     * @param request
+     * @param response
+     * @param resource
+     * @throws DavException
+     * @throws IOException
+     */
+    protected void doMerge(WebdavRequest request, WebdavResponse response,
+                           DavResource resource) throws DavException, IOException {
+
+        if (!(resource instanceof VersionControlledResource)) {
+            response.sendError(DavServletResponse.SC_METHOD_NOT_ALLOWED);
+            return;
+        }
+        MergeInfo info = request.getMergeInfo();
+        MultiStatus ms = ((VersionControlledResource) resource).merge(info);
+        response.sendMultiStatus(ms);
+    }
+
+    /**
+     * The UPDATE method
+     *
+     * @param request
+     * @param response
+     * @param resource
+     * @throws DavException
+     * @throws IOException
+     */
+    protected void doUpdate(WebdavRequest request, WebdavResponse response,
+                            DavResource resource) throws DavException, IOException {
+
+        if (!(resource instanceof VersionControlledResource)) {
+            response.sendError(DavServletResponse.SC_METHOD_NOT_ALLOWED);
+            return;
+        }
+        UpdateInfo info = request.getUpdateInfo();
+        MultiStatus ms = ((VersionControlledResource) resource).update(info);
+        response.sendMultiStatus(ms);
+    }
+
+    /**
+     * The MKWORKSPACE method
+     *
+     * @param request
+     * @param response
+     * @param resource
+     * @throws DavException
+     * @throws IOException
+     */
+    protected void doMkWorkspace(WebdavRequest request, WebdavResponse response,
+                                 DavResource resource) throws DavException, IOException {
+        if (resource.exists()) {
+            AbstractWebdavServlet.log.warn("Cannot create a new workspace. Resource already
exists.");
+            response.sendError(DavServletResponse.SC_FORBIDDEN);
+            return;
+        }
+
+        DavResource parentResource = resource.getCollection();
+        if (parentResource == null || !parentResource.exists() || !parentResource.isCollection())
{
+            // parent does not exist or is not a collection
+            response.sendError(DavServletResponse.SC_CONFLICT);
+            return;
+        }
+        if (!(parentResource instanceof DeltaVResource)) {
+            response.sendError(DavServletResponse.SC_METHOD_NOT_ALLOWED);
+            return;
+        }
+        ((DeltaVResource) parentResource).addWorkspace(resource);
+        response.setStatus(DavServletResponse.SC_CREATED);
+    }
+
+    /**
+     * The MKACTIVITY method
+     *
+     * @param request
+     * @param response
+     * @param resource
+     * @throws DavException
+     * @throws IOException
+     */
+    protected void doMkActivity(WebdavRequest request, WebdavResponse response,
+                                DavResource resource) throws DavException, IOException {
+        if (resource.exists()) {
+            AbstractWebdavServlet.log.warn("Unable to create activity: A resource already
exists at the request-URL " + request.getRequestURL());
+            response.sendError(DavServletResponse.SC_FORBIDDEN);
+            return;
+        }
+
+        DavResource parentResource = resource.getCollection();
+        if (parentResource == null || !parentResource.exists() || !parentResource.isCollection())
{
+            // parent does not exist or is not a collection
+            response.sendError(DavServletResponse.SC_CONFLICT);
+            return;
+        }
+        // TODO: improve. see http://issues.apache.org/jira/browse/JCR-394
+        if (parentResource.getComplianceClass().indexOf(DavCompliance.ACTIVITY) < 0) {
+            response.sendError(DavServletResponse.SC_METHOD_NOT_ALLOWED);
+            return;
+        }
+
+        if (!(resource instanceof ActivityResource)) {
+            AbstractWebdavServlet.log.error("Unable to create activity: ActivityResource
expected");
+            response.sendError(DavServletResponse.SC_INTERNAL_SERVER_ERROR);
+            return;
+        }
+
+        // try to add the new activity resource
+        parentResource.addMember(resource, getInputContext(request, request.getInputStream()));
+
+        // Note: mandatory cache control header has already been set upon response creation.
+        response.setStatus(DavServletResponse.SC_CREATED);
+    }
+
+    /**
+     * The BASELINECONTROL method
+     *
+     * @param request
+     * @param response
+     * @param resource
+     * @throws DavException
+     * @throws IOException
+     */
+    protected void doBaselineControl(WebdavRequest request, WebdavResponse response,
+                                     DavResource resource)
+        throws DavException, IOException {
+
+        if (!resource.exists()) {
+            AbstractWebdavServlet.log.warn("Unable to add baseline control. Resource does
not exist " + resource.getHref());
+            response.sendError(DavServletResponse.SC_NOT_FOUND);
+            return;
+        }
+        // TODO: improve. see http://issues.apache.org/jira/browse/JCR-394
+        if (!(resource instanceof VersionControlledResource) || !resource.isCollection())
{
+            AbstractWebdavServlet.log.warn("BaselineControl is not supported by resource
" + resource.getHref());
+            response.sendError(DavServletResponse.SC_METHOD_NOT_ALLOWED);
+            return;
+        }
+
+        // TODO : missing method on VersionControlledResource
+        throw new DavException(DavServletResponse.SC_NOT_IMPLEMENTED);
+        /*
+        ((VersionControlledResource) resource).addBaselineControl(request.getRequestDocument());
+        // Note: mandatory cache control header has already been set upon response creation.
+        response.setStatus(DavServletResponse.SC_OK);
+        */
+    }
+
+    /**
+     * The SEARCH method
+     *
+     * @param request
+     * @param response
+     * @param resource
+     * @throws DavException
+     * @throws IOException
+     */
+    protected void doSearch(WebdavRequest request, WebdavResponse response,
+                            DavResource resource) throws DavException, IOException {
+
+        if (!(resource instanceof SearchResource)) {
+            response.sendError(DavServletResponse.SC_METHOD_NOT_ALLOWED);
+            return;
+        }
+        Document doc = request.getRequestDocument();
+        if (doc != null) {
+            SearchInfo sR = SearchInfo.createFromXml(doc.getDocumentElement());
+            response.sendMultiStatus(((SearchResource) resource).search(sR));
+        } else {
+            // request without request body is valid if requested resource
+            // is a 'query' resource.
+            response.sendMultiStatus(((SearchResource) resource).search(null));
+        }
+    }
+
+    /**
+     * The ACL method
+     *
+     * @param request
+     * @param response
+     * @param resource
+     * @throws DavException
+     * @throws IOException
+     */
+    protected void doAcl(WebdavRequest request, WebdavResponse response,
+                         DavResource resource) throws DavException, IOException {
+        if (!(resource instanceof AclResource)) {
+            response.sendError(DavServletResponse.SC_METHOD_NOT_ALLOWED);
+            return;
+        }
+        Document doc = request.getRequestDocument();
+        if (doc == null) {
+            throw new DavException(DavServletResponse.SC_BAD_REQUEST, "ACL request requires
a DAV:acl body.");
+        }
+        AclProperty acl = AclProperty.createFromXml(doc.getDocumentElement());
+        ((AclResource)resource).alterAcl(acl);
+    }
+
+    /**
+     * Return a new <code>InputContext</code> used for adding resource members
+     *
+     * @param request
+     * @param in
+     * @return
+     * @see #spoolResource(WebdavRequest, WebdavResponse, DavResource, boolean)
+     */
+    protected InputContext getInputContext(DavServletRequest request, InputStream in) {
+        return new InputContextImpl(request, in);
+    }
+
+    /**
+     * Return a new <code>OutputContext</code> used for spooling resource properties
and
+     * the resource content
+     *
+     * @param response
+     * @param out
+     * @return
+     * @see #doPut(WebdavRequest, WebdavResponse, DavResource)
+     * @see #doPost(WebdavRequest, WebdavResponse, DavResource)
+     * @see #doMkCol(WebdavRequest, WebdavResponse, DavResource)
+     */
+    protected OutputContext getOutputContext(DavServletResponse response, OutputStream out)
{
+        return new OutputContextImpl(response, out);
+    }
+}

Propchange: jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/server/AbstractWebdavServlet.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/server/AbstractWebdavServlet.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision url



Mime
View raw message