Package org.apache.slide.webdav.method

Source Code of org.apache.slide.webdav.method.LockMethod

/*
* $Header: /home/cvspublic/jakarta-slide/src/webdav/server/org/apache/slide/webdav/method/LockMethod.java,v 1.55.2.3 2004/03/23 13:32:08 ozeigermann Exp $
* $Revision: 1.55.2.3 $
* $Date: 2004/03/23 13:32:08 $
*
* ====================================================================
*
* Copyright 1999-2002 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

package org.apache.slide.webdav.method;

import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;
import java.util.Date;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import org.apache.slide.common.NamespaceAccessToken;
import org.apache.slide.common.NamespaceConfig;
import org.apache.slide.common.SlideException;
import org.apache.slide.content.NodeRevisionDescriptor;
import org.apache.slide.lock.NodeLock;
import org.apache.slide.lock.ObjectIsAlreadyLockedException;
import org.apache.slide.structure.ObjectNotFoundException;
import org.apache.slide.structure.SubjectNode;
import org.apache.slide.util.XMLValue;
import org.apache.slide.webdav.WebdavException;
import org.apache.slide.webdav.WebdavServletConfig;
import org.apache.slide.webdav.util.PropertyHelper;
import org.apache.slide.webdav.util.WebdavConstants;
import org.apache.util.WebdavStatus;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.output.XMLOutputter;

/**
* LOCK method.
*
* @author <a href="mailto:remm@apache.org">Remy Maucherat</a>
*/
public class LockMethod extends AbstractMultistatusResponseMethod
    implements WebdavConstants {
   
   
    // -------------------------------------------------------------- Constants
   
   
   
    /**
     * Create a new lock.
     */
    private static final int LOCK_CREATION = 0;
   
   
    /**
     * Refresh lock.
     */
    private static final int LOCK_REFRESH = 1;
   
    /**
     * Maximum and default timeout.
     */
    private static final int MAX_TIMEOUT = Integer.MAX_VALUE;
    private static final int DEFAULT_TIMEOUT = MAX_TIMEOUT;
   
    /**
     * The default owner if not explicitely specified by the request.
     */
    public static final String DEFAULT_LOCK_OWNER = "";
   
    // ----------------------------------------------------- Instance Variables
   
   
    /**
     * Depth.
     */
    private int depth;
   
   
    /**
     * Type of the LOCK method.
     */
    private int lockType;
   
   
    /**
     * Lock duration.
     */
    private int lockDuration = DEFAULT_TIMEOUT;
   
   
    /**
     * DAV Namespace support.
     */
    private boolean davNative;
   
   
    /**
     * Lock scope.
     */
    private String lockInfo_lockScope;
   
   
    /**
     * Lock type.
     */
    private String lockInfo_lockType;
   
   
    /**
     * Lock owner.
     */
    private String lockInfo_lockOwner;
   
   
    /**
     * Lock subject.
     */
    private String lockInfo_lockSubject;
   
    /**
     * The PropertyHelper used by this instance.
     */
    protected PropertyHelper propertyHelper = null;
       
   
    // ----------------------------------------------------------- Constructors
   
   
    /**
     * Constructor.
     *
     * @param token     the token for accessing the namespace
     * @param config    configuration of the WebDAV servlet
     */
    public LockMethod(NamespaceAccessToken token, WebdavServletConfig config) {
        super(token, config);
    }
   
   
    // ------------------------------------------------------ Protected Methods
   
   
    /**
     * Parse request.
     *
     * @exception WebdavException Does not happen
     */
    protected void parseRequest()
        throws WebdavException {
       
        propertyHelper = PropertyHelper.getPropertyHelper(slideToken, token, getConfig());
        //        readRequestContent();
       
       
        // Loads the associated object from the store.
        lockInfo_lockSubject = requestUri;
        if (lockInfo_lockSubject == null) {
            lockInfo_lockSubject = "/";
        }
       
        depth = requestHeaders.getDepth(INFINITY);
        if (depth != 0 && depth != INFINITY) {
            int sc = WebdavStatus.SC_PRECONDITION_FAILED;
            sendError( sc, "Invalid header Depth: "+depth );
            throw new WebdavException( sc );
        }
       
        lockDuration = requestHeaders.getTimeout(MAX_TIMEOUT);
       
        if (req.getContentLength() > 0) {
            parseLockInfo();
        }
        else {
            lockType = LOCK_REFRESH;
        }
       
    }
   
    /**
     * Parses the <code>&lt;lockinfo&gt;</code> request content document.
     *
     * @throws     WebdavException  if parsing the request failed or if
     *                              the request is not valid.
     */
    private void parseLockInfo() throws WebdavException {
       
        lockType = LOCK_CREATION;
       
        try {
            Element lockScopeElement = null;
            Element lockTypeElement = null;
            Element lockOwnerElement = null;
            Iterator childrenIterator = parseRequestContent(E_LOCKINFO).getChildren().iterator();
            Element currentElement = null;
            while (childrenIterator.hasNext()) {
                currentElement = (Element)childrenIterator.next();
                if (E_LOCKSCOPE.equals(currentElement.getName())) {
                    lockScopeElement = currentElement;
                }
                else if (E_LOCKTYPE.equals(currentElement.getName())) {
                    lockTypeElement = currentElement;
                }
                else if (E_OWNER.equals(currentElement.getName())) {
                    lockOwnerElement = currentElement;
                }
            }
           
            parseLockScope(lockScopeElement);
            parseLockType(lockTypeElement);
            parseOwner(lockOwnerElement);
        }
        catch (JDOMException e) {
            int statusCode = WebdavStatus.SC_BAD_REQUEST;
            sendError( statusCode, e );
            throw new WebdavException( statusCode );
        }
        catch (IOException e) {
            int statusCode = WebdavStatus.SC_INTERNAL_SERVER_ERROR;
            sendError( statusCode, e );
            throw new WebdavException( statusCode );
        }
    }
   
    /**
     * Parses the <code>&lt;lockscope&gt;</code> part of the request content
     * document.
     *
     * @param      lockScopeElement  the <code>&lt;lockscope&gt;</code> to parse.
     *
     * @throws     JDOMException  if parsing the request failed or if
     *                           the request is not valid.
     */
    private void parseLockScope(Element lockScopeElement) throws JDOMException {
       
        if (lockScopeElement == null) {
            throw new JDOMException("Expected <"+E_LOCKSCOPE+"> element");
        }
       
        List children = lockScopeElement.getChildren();
        if (children.size() != 1) {
            throw new JDOMException("<"+E_LOCKSCOPE+"> must have exactly one child element");
        }
       
        lockInfo_lockScope = ((Element)children.get(0)).getName();
    }
   
    /**
     * Parses the <code>&lt;locktype&gt;</code> part of the request content
     * document.
     *
     * @param      lockTypeElement  the <code>&lt;locktype&gt;</code> to parse.
     *
     * @throws     JDOMException  if parsing the request failed or if
     *                           the request is not valid.
     */
    private void parseLockType(Element lockTypeElement) throws JDOMException {
       
        if (lockTypeElement == null) {
            throw new JDOMException("Expected <"+E_LOCKTYPE+"> element");
        }
       
        List children = lockTypeElement.getChildren();
        if (children.size() != 1) {
            throw new JDOMException("<"+E_LOCKTYPE+"> must have exactly one child element");
        }
       
        lockInfo_lockType = ((Element)children.get(0)).getName();
    }
   
    /**
     * Parses the <code>&lt;owner&gt;</code> part of the request content
     * document.
     *
     * @param      ownerElement  the <code>&lt;owner&gt;</code> to parse.
     *
     * @throws     JDOMException  if parsing the request failed or if
     *                           the request is not valid.
     */
    private void parseOwner(Element ownerElement) throws JDOMException {
       
        if (ownerElement == null) {
            lockInfo_lockOwner = DEFAULT_LOCK_OWNER;
            return;
            //          throw new JDOMException("Expected <"+E_OWNER+"> element");
        }
       
        StringWriter stringWriter = new StringWriter();
        XMLOutputter xmlOutputter = new XMLOutputter();
        try {
            xmlOutputter.outputElementContent(ownerElement, stringWriter);
        }
        catch (IOException e) {
            // this should not happen since we do no "real" I/O but
            // only print to a PrintWriter
            e.printStackTrace();
        }
        lockInfo_lockOwner = stringWriter.toString();
       
        if (lockInfo_lockOwner.length() == 0) {
            lockInfo_lockOwner = DEFAULT_LOCK_OWNER;
            //          throw new JDOMException("<"+E_OWNER+"> element must not be empty");
        }
    }
   
   
    /**
     * Execute request.
     *
     * @exception WebdavException Unrecoverable error while renewing lock
     */
    protected void executeRequest()
        throws WebdavException {
       
        // Prevent dirty reads
        slideToken.setForceStoreEnlistment(true);
       
       
        SubjectNode toLockSubject = null;
        boolean isCollection = isCollection(lockInfo_lockSubject);
        boolean inheritance = false;
        Date lockDate = null;
       
        switch (lockType) {
           
            case LOCK_CREATION:
               
                try {
                   
                    NamespaceConfig namespaceConfig = token.getNamespaceConfig();
                   
                    try {
                        toLockSubject = (SubjectNode) structure
                            .retrieve(slideToken, lockInfo_lockSubject);
                    } catch (ObjectNotFoundException ex) {
                       
                        // Creating a lock null resource
                        toLockSubject = new SubjectNode();
                       
                        // Creating new subject
                        structure.create(slideToken, toLockSubject,
                                         lockInfo_lockSubject);
                       
                        NodeRevisionDescriptor revisionDescriptor =
                            new NodeRevisionDescriptor(0);
                       
                        // Resource type
                        XMLValue lockNull =
                            new XMLValue(new Element(E_LOCKNULL, DNSP));
                        revisionDescriptor.setResourceType(lockNull.toString());
                       
                        // Creating the revision descriptor
                        content.create(slideToken, lockInfo_lockSubject,
                                       revisionDescriptor, null);
                    }
                   
                    NodeLock lockToken = null;
                   
                    inheritance = (depth != 0);
                    boolean exclusive =
                        !(lockInfo_lockScope.equals(E_SHARED));
                   
                    if (lockDate == null)
                        lockDate = new Date((new Date()).getTime()
                                                + ((long)lockDuration * 1000L));
                   
                    lockToken =
                        new NodeLock(toLockSubject, (SubjectNode)security.getPrincipal(slideToken),
                                     namespaceConfig.getCreateObjectAction(),
                                     lockDate, inheritance, exclusive, lockInfo_lockOwner);
                    lock.lock(slideToken, lockToken);
                   
                    // Set the lock-token header
                    // [RFC 2518, 9.5] " The Lock-Token response header is used
                    // with the LOCK method to indicate the lock token created as
                    // a result of a successful LOCK request to create a new
                    // lock."
                    resp.setHeader("Lock-Token",
                                   "<"+S_LOCK_TOKEN+lockToken.getLockId()+">");
                   
                    resp.setStatus(WebdavStatus.SC_OK);
                   
                    // The lock token on which the DAV module will have the info
                   
                    showLockDiscoveryInfo(lockToken);
                   
                } catch (ObjectIsAlreadyLockedException e) {
                    if (inheritance && generateMultiStatusResponse(isCollection, e, requestUri)) {
                        // error is on the resource which we attempted to lock
                        String errorMessage = generateErrorMessage(e);
                        // Write it on the servlet writer
                        resp.setContentType(TEXT_XML_UTF_8);
                        resp.setStatus(WebdavStatus.SC_MULTI_STATUS);
                        try {
                            resp.getWriter().write(errorMessage);
                        } catch(IOException ex) {
                            // Critical error ... Servlet container is dead or something
                            int statusCode = WebdavStatus.SC_INTERNAL_SERVER_ERROR;
                            sendError( statusCode, e );
                            throw new WebdavException( statusCode );
                        }
                    } else {
                        // Returning 207 on non-collection requests is generally
                        // considered bad. So let's not do it, since this way
                        // makes clients generally behave better.
                        resp.setStatus(WebdavStatus.SC_LOCKED);
                    }
                    //
                    // make sure the transaction is aborted
                    // throw any WebDAV exception to indicate the transaction wants to be aborted
                    //
                    throw new WebdavException(WebdavStatus.SC_ACCEPTED, false);
                } catch (Exception e) {
                    int statusCode = getErrorCode( e );
                    sendError( statusCode, e );
                    throw new WebdavException( statusCode );
                }
               
                break;
               
            case LOCK_REFRESH:
               
                try {
                   
                    Enumeration lockTokens =
                        lock.enumerateLocks(slideToken, lockInfo_lockSubject, false);
                   
                    NodeLock currentLockToken = null;
                    Date newExpirationDate =
                        new Date((new Date()).getTime() + ((long)lockDuration * 1000L));
                    while (lockTokens.hasMoreElements()) {
                        currentLockToken = (NodeLock) lockTokens.nextElement();
                        lock.renew(slideToken, currentLockToken,
                                   newExpirationDate);
                    }
                   
                    showLockDiscoveryInfo(currentLockToken);
                   
                } catch (SlideException e) {
                    int statusCode = WebdavStatus.SC_PRECONDITION_FAILED;
                    sendError( statusCode, e );
                    throw new WebdavException( statusCode );
                }
               
                break;
               
        }
       
    }
   
   
   
   
   
    /**
     * Get return status based on exception type.
     */
    protected int getErrorCode(Exception ex) {
        try {
            throw ex;
        } catch (ObjectNotFoundException e) {
            return WebdavStatus.SC_PRECONDITION_FAILED;
        } catch (Exception e) {
            return super.getErrorCode(e);
        }
    }
   
   
    /**
     * Show lockdiscovery info.
     *
     * @exception WebdavException Something is wrong with the servlet container
     */
    protected void showLockDiscoveryInfo(NodeLock token)
        throws WebdavException {
       
        // Generating XML response
        org.jdom.Element prop = new org.jdom.Element(E_PROP, DNSP);
        org.jdom.Element lockdiscovery = new org.jdom.Element(E_LOCKDISCOVERY, DNSP);
        prop.addContent(lockdiscovery);
        XMLValue xmlValue = propertyHelper.computeLockDiscovery(token,
                                                                req.getServletPath(),
                                                                req.getContextPath());
        Iterator iterator = xmlValue.iterator();
        while (iterator.hasNext()) {
            lockdiscovery.addContent((org.jdom.Element)iterator.next());
        }
       
        try {
            //System.out.println("Query result");
            //System.out.println(generatedXML.toString());
            resp.setContentType(TEXT_XML_UTF_8);
            Writer writer = resp.getWriter();
            new org.jdom.output.XMLOutputter(XML_REPONSE_INDENT, true).output(new org.jdom.Document(prop), writer);
            writer.flush();
        } catch (Exception e) {
            int statusCode = WebdavStatus.SC_INTERNAL_SERVER_ERROR;
            sendError( statusCode, e );
            throw new WebdavException( statusCode );
        }
       
       
    }
   
   
    /**
     * Returns true
     */
    protected boolean methodNeedsTransactionSupport() {
        return true;
    }
   
   
}

TOP

Related Classes of org.apache.slide.webdav.method.LockMethod

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.