Package org.apache.webdav.lib.methods

Source Code of org.apache.webdav.lib.methods.LockMethod

/*
* $Header: /home/cvs/jakarta-slide/src/webdav/client/src/org/apache/webdav/lib/methods/LockMethod.java,v 1.25 2001/08/30 04:54:02 remm Exp $
* $Revision: 1.25 $
* $Date: 2001/08/30 04:54:02 $
*
* ====================================================================
*
* The Apache Software License, Version 1.1
*
* Copyright (c) 1999 The Apache Software Foundation.  All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
*    notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
*    notice, this list of conditions and the following disclaimer in
*    the documentation and/or other materials provided with the
*    distribution.
*
* 3. The end-user documentation included with the redistribution, if
*    any, must include the following acknowlegement:
*       "This product includes software developed by the
*        Apache Software Foundation (http://www.apache.org/)."
*    Alternately, this acknowlegement may appear in the software itself,
*    if and wherever such third-party acknowlegements normally appear.
*
* 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
*    Foundation" must not be used to endorse or promote products derived
*    from this software without prior written permission. For written
*    permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache"
*    nor may "Apache" appear in their names without prior written
*    permission of the Apache Group.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation.  For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
* [Additional notices, if required by prior licensing conditions]
*
*/
package org.apache.webdav.lib.methods;

import java.io.InputStream;
import java.io.IOException;
import java.io.StringWriter;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.FactoryConfigurationError;
import javax.xml.parsers.ParserConfigurationException;

import org.apache.commons.httpclient.State;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpStatus;

import org.apache.webdav.lib.WebdavState;
import org.apache.webdav.lib.properties.LockEntryProperty;

import org.apache.util.DOMUtils;
import org.apache.util.DOMWriter;

import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.DOMException;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;

import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

/**
* Web resources can be locked to ensure that only one user is updating
* the resource at a time.  Locking helps to prevent the "lost update" problem.
* There are two types of lock currently defined by the WebDAV specification:
* exclusive locks and shared locks.
*
* <p>   Per the specification, a lock indicates that someone is updating the
* resource, (hence the lock is a "write lock"), although the specification
* notes that the the syntax is extensible, and permits the eventual creation
* of locking for other access types.
*
* <h3>Shared and Exclusive Locks</h3>
*
* <p>   The most basic form of lock is an <em>exclusive lock</em>. This is a
* lock where the access right in question is only granted to a single client.
* The need for this arbitration results from a desire to avoid having to merge
* results.  However, there are times when the goal of a lock is not to exclude
* others from exercising an access right but rather to provide a mechanism for
* principals to indicate that they intend to exercise their access rights.
* <em>Shared locks</em> are provided for this case. A shared lock allows
* multiple clients to receive a lock. Hence any user with appropriate
* access can get the lock.
*
* <p>   With shared locks there are two trust sets that affect a resource.
* The first trust set is created by access permissions.  Principals who are
* trusted, for example, may have permission to write to the resource.  Among
* those who have access permission to write to the resource, the set of
* principals who have taken out a shared lock also must trust each other,
* creating a (typically) smaller trust set within the access permission write
* set.
*
* <h3>Lock Compatibility</h3>
*
* <p>   The following table indicates what happens if a new lock request
* is sent to a resource that is already locked: </p>
*
* <table border="1">
* <!-- ------------------------------------------------------------------- -->
* <tr><th>             </th><th colspan="2">     Lock Request       </th></tr>
* <tr><th>Current Lock </th><th>Exclusive Lock </th><th>Shared Lock </th></tr>
* <!-- ------------------------------------------------------------------- -->
* <tr><td>None         </td><td>Success        </td><td>Sucess      </td></tr>
* <tr><td>Shared       </td><td>Failure        </td><td>Sucess      </td></tr>
* <tr><td>Exclusive    </td><td>Failure        </td><td>Failure     </td></tr>
* <!-- ------------------------------------------------------------------- -->
* </table>
*
* @author <a href="mailto:remm@apache.org">Remy Maucherat</a>
* @author <a href="mailto:bcholmes@interlog.org">B.C. Holmes</a>
*/
public class LockMethod
    extends XMLResponseMethodBase implements DepthSupport {


    // -------------------------------------------------------------- Constants


    public static final short SCOPE_EXCLUSIVE =
        LockEntryProperty.SCOPE_EXCLUSIVE;
    public static final short SCOPE_SHARED = LockEntryProperty.SCOPE_SHARED;

    public static final short TYPE_WRITE = LockEntryProperty.TYPE_WRITE;

    public static final long TIMEOUT_INFINITY = Long.MAX_VALUE;


    // ----------------------------------------------------- Instance Variables


    /**
     * The scope of lock we're requesting.  The default scope is
     * SCOPE_EXCLUSIVE.
     */
    private short scope = SCOPE_EXCLUSIVE;


    /**
     * The type of lock we're requesting.  The default type is TYPE_WRITE.
     */
    private short type = TYPE_WRITE;


    /**
     * Depth.
     */
    private int depth = DEPTH_INFINITY;


    /**
     * Opaque token of the lock we're trying to refresh.
     */
    private String refreshOpaqueToken = null;


    /**
     * Lock timeout.
     */
    private long timeout = TIMEOUT_INFINITY;


    /**
     * Lock owner.
     */
    private String owner = null;


    /**
     * Lock token.
     */
    private String lockToken = null;


    // ----------------------------------------------------------- Constructors


    /**
     * Method constructor.
     */
    public LockMethod() {
        name = "LOCK";
    }


    /**
     * Method constructor.
     */
    public LockMethod(String path) {
        super(path);
        name = "LOCK";
    }


    /**
     * Method constructor.
     */
    public LockMethod(String path, String refreshOpaqueToken, long timeout) {
        this(path);
        this.refreshOpaqueToken = refreshOpaqueToken;
        setTimeout(timeout);
    }


    /**
     * Method constructor.
     */
    public LockMethod(String path, String owner, short scope, long timeout) {
        this(path);
        setOwner(owner);
        setScope(scope);
        setTimeout(timeout);
    }


    // ------------------------------------------------------------- Properties

       
       
       
    /**
     * Set header. handle the special case of Depth and Time
     *
     * @param headerName Header name
     * @param headerValue Header value
     */
    public void setHeader(String headerName, String headerValue) {
        if (headerName.equalsIgnoreCase("Depth")){
            int depth = -1;
            if (headerValue.equals("0")){
                depth = DEPTH_0;
            }
            if (headerValue.equals("1")){
                depth = DEPTH_1;
            }
            else if (headerValue.equalsIgnoreCase("infinity")){
                depth = DEPTH_INFINITY;
            }
            setDepth(depth);
        }
        else if(headerName.equalsIgnoreCase("Timeout")){
            if (headerValue.startsWith("Second-"))
                headerValue = headerValue.substring("Second-".length());
            try {
                setTimeout(Long.parseLong(headerValue));
            } catch (NumberFormatException e) {
            }
        }
        else if(headerName.equalsIgnoreCase("Owner")){
            setOwner(headerValue);
        }
        else{
            super.setHeader(headerName, headerValue);
        }
    }



    /**
     * Depth setter.
     *
     * @param depth New depth value
     */
    public void setDepth(int depth) {
        checkNotUsed();
        if (depth != DEPTH_0 && depth != DEPTH_INFINITY) {
            throw new IllegalArgumentException
            ("invalid depth value for lock method " + depth);
        }
        this.depth = depth;
    }


    /**
     * Depth getter.
     *
     * @return int depth value
     */
    public int getDepth() {
        return depth;
    }


    public String getLockToken() {
        checkUsed();
        return this.lockToken;
    }



    public boolean isRefresh() {
        return !((this.refreshOpaqueToken == null ) ||
                 (this.refreshOpaqueToken.equals("")));
    }


    public short getScope() {
        return this.scope;
    }


    /**
     * Sets the owner of the lock.  This method provides only "basic" owner
     * information.  Thus, <code>setOwner("Jezebel Lipshitz")</code> will
     * produce an <code>owner</code> element in the request document like this:
     *
     * <pre>
     *   &lt;D:owner&gt;Jezebel Lipshitz&lt;/D:owner&gt;
     * </pre>
     *
     * <p>  Examples in the Webdav specification suggest that one can use
     * e-mail addresses, home page URLs, or other information; this
     * implementation doesn't handle any of that.
     */
    public void setOwner(String owner) {
        checkNotUsed();
        this.owner = owner;
    }


    public void setScope(short scope) {
        checkNotUsed();
        if (scope != SCOPE_SHARED && scope != SCOPE_EXCLUSIVE) {
            throw new IllegalArgumentException("invalid scope value");
        }
        this.scope = scope;
    }


    public long getTimeout() {
        return this.timeout;
    }


    public void setTimeout(long timeout) {
        checkNotUsed();
        if (timeout < 0) {
            throw new IllegalArgumentException("invalid timeout value: " +
                                                   timeout);
        }
        this.timeout = timeout;
    }


    // --------------------------------------------------- WebdavMethod Methods


    public void recycle() {
        super.recycle();
        this.refreshOpaqueToken = null;
        this.depth = DEPTH_INFINITY;
        this.type = TYPE_WRITE;
        this.scope = SCOPE_EXCLUSIVE;
        this.timeout = TIMEOUT_INFINITY;
    }


    /**
     * Generate additional headers needed by the request.
     *
     * @param host the host
     * @param state State token
     */
    public void generateHeaders(String host, State state) {

        super.generateHeaders(host, state);

        switch (depth) {
            case DEPTH_0:
                super.setHeader("Depth", "0");
                break;
            case DEPTH_INFINITY:
                super.setHeader("Depth", "infinity");
                break;
            default:
        }

        if (timeout == TIMEOUT_INFINITY) {
            super.setHeader("Timeout", "Infinity, Second-" + TIMEOUT_INFINITY);
        } else {
            super.setHeader("Timeout", "Second-" + timeout);
        }

        if (isRefresh()) {
            super.setHeader("If", "(<" + refreshOpaqueToken + ">)");
        }

        super.setHeader("Content-Type", "text/xml; charset=utf-8");

    }


    /**
     * Generate the query body.
     *
     * @return String query
     */
    public String generateQuery() {

        if (query != null) return query;

        if (!isRefresh()) {

            if (this.owner == null || this.owner.equals("")) {
                throw new IllegalStateException
                    ("The owner property has not been set");
            }

            try {

                DocumentBuilderFactory factory =
                    DocumentBuilderFactory.newInstance();
                DocumentBuilder builder = factory.newDocumentBuilder();
                Document document = builder.newDocument();

                Element lockinfo = document.createElement("DAV:lockinfo");
                document.appendChild(lockinfo);
                lockinfo.setAttribute("xmlns:DAV", "DAV:");

                Element lockscope = document.createElement("DAV:lockscope");
                lockinfo.appendChild(lockscope);

                if (this.scope == SCOPE_EXCLUSIVE) {
                    Element exclusive =
                        document.createElement("DAV:exclusive");
                    lockscope.appendChild(exclusive);
                } else {
                    Element shared = document.createElement("DAV:shared");
                    lockscope.appendChild(shared);
                }

                Element locktype = document.createElement("DAV:locktype");
                lockinfo.appendChild(locktype);

                Element write = document.createElement("DAV:write");
                locktype.appendChild(write);

                Element owner = document.createElement("DAV:owner");
                lockinfo.appendChild(owner);

                Text text = document.createTextNode(this.owner);
                owner.appendChild(text);

                StringWriter stringWriter = new StringWriter();
                DOMWriter domWriter = new DOMWriter(stringWriter, false);
                domWriter.print(document);

                query = stringWriter.getBuffer().toString();

            } catch (DOMException e) {
            } catch (ParserConfigurationException e) {
            }

        }

        return query;

    }


    /**
     * Parse response.
     *
     * @param input Input stream
     */
    public void parseResponse(InputStream input)
        throws IOException, HttpException {
        int status = getStatusCode();
//      if (status == HttpStatus.SC_OK ||
//          status == HttpStatus.SC_MULTI_STATUS ||
//          status == HttpStatus.SC_CONFLICT) {
        if (status == HttpStatus.SC_OK ||
            status == HttpStatus.SC_MULTI_STATUS ) {

            parseXMLResponse(input);

            if ( (status == HttpStatus.SC_OK) &&
                    (this.state instanceof WebdavState)) {
                String prefix = DOMUtils.findDavPrefix(
                    getResponseDocument());
                NodeList list = getResponseDocument().getDocumentElement()
                    .getElementsByTagName(prefix + "locktoken");

                if (list.getLength() == 1) {
                    Element locktoken = (Element) list.item(0);
                    NodeList list2 = locktoken.getElementsByTagName(
                        prefix + "href");
                    if (list2.getLength() == 1) {
                        this.lockToken = DOMUtils.getTextValue(list2.item(0));
                        ((WebdavState) this.state).addLock
                            (getPath(), this.lockToken);
                    }
                }
            }
        }
    }
}

TOP

Related Classes of org.apache.webdav.lib.methods.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.