Package org.apache.slide.webdav.method

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

/*
* $Header: /home/cvs/jakarta-slide/src/webdav/server/org/apache/slide/webdav/method/LabelMethod.java,v 1.21.2.1 2004/02/05 16:11:23 mholz Exp $
* $Revision: 1.21.2.1 $
* $Date: 2004/02/05 16:11:23 $
*
* ====================================================================
*
* 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.util.Enumeration;
import java.util.Iterator;

import org.apache.slide.common.NamespaceAccessToken;
import org.apache.slide.common.NestedSlideException;
import org.apache.slide.common.ServiceAccessException;
import org.apache.slide.common.SlideException;
import org.apache.slide.common.SlideToken;
import org.apache.slide.content.NodeProperty;
import org.apache.slide.content.NodeRevisionDescriptor;
import org.apache.slide.content.NodeRevisionDescriptors;
import org.apache.slide.structure.ObjectNode;
import org.apache.slide.util.XMLValue;
import org.apache.slide.webdav.WebdavException;
import org.apache.slide.webdav.WebdavServletConfig;
import org.apache.slide.webdav.util.DeltavConstants;
import org.apache.slide.webdav.util.LabeledRevisionNotFoundException;
import org.apache.slide.webdav.util.PreconditionViolationException;
import org.apache.slide.webdav.util.PropertyHelper;
import org.apache.slide.webdav.util.VersioningHelper;
import org.apache.slide.webdav.util.ViolatedPrecondition;
import org.apache.slide.webdav.util.WebdavUtils;
import org.apache.slide.webdav.util.resourcekind.AbstractResourceKind;
import org.apache.slide.webdav.util.resourcekind.CheckedInVersionControlled;
import org.apache.slide.webdav.util.resourcekind.ResourceKind;
import org.apache.slide.webdav.util.resourcekind.Version;
import org.apache.slide.webdav.util.resourcekind.VersionControlled;
import org.apache.util.WebdavStatus;
import org.jdom.Element;
import org.jdom.JDOMException;

/**
* LABEL method.
*
* @version $Revision: 1.21.2.1 $
*
* @author <a href="mailto:ralf.stuckert@softwareag.com">Ralf Stuckert</a>
*/
public class LabelMethod extends AbstractMultistatusResponseMethod implements DeltavConstants {
    /**
     ** String constant for <code>Label missing</code>.
     **/
    public static final String LABEL_MISSING = "Label missing";
   
    /**
     * String constant for <code>Request content &lt;label&gt; element must
     * contain either &lt;add&gt;, &lt;set&gt; or &lt;remove&gt;</code>.
     */
    public static final String LABEL_MUST_CONTAIN_EITHER_ADD_SET_OR_REMOVE =
        "Request content <label> element must contain either <" +
        E_ADD + ">, <" + E_SET + "> or <" + E_REMOVE + ">";
   
   
   
   
    /**
     * Resource to be written.
     */
    private String resourcePath;
   
    /**
     * Indicates if the resource to delete is a collection.
     */
    protected boolean isCollection = false;
   
    /**
     * The VersioningHelper used by this instance.
     */
    protected VersioningHelper versioningHelper = null;
   
    /**
     * Indicates which label operation to perform:
     * <code>add</code>, <code>set</code> or <code>remove</code>.
     */
    protected String operation = null;
   
    /**
     * The label to add/set/remove.
     */
    protected String label = null;
   
    /**
     * The value of the <code>Label</code> header
     */
    protected String labelHeader = null;
   
   
    // ----------------------------------------------------------- Constructors
   
   
    /**
     * Constructor.
     *
     * @param token     the token for accessing the namespace
     * @param config    configuration of the WebDAV servlet
     */
    public LabelMethod(NamespaceAccessToken token,
                       WebdavServletConfig config) {
        super(token, config);
    }
   
    /**
     * Parse WebDAV XML query.
     *
     * @throws WebdavException
     */
    protected void parseRequest() throws WebdavException {
        //        readRequestContent();
        versioningHelper = VersioningHelper.getVersioningHelper(slideToken,
                                                                token,
                                                                req,
                                                                resp,
                                                                config);
        resourcePath = requestUri;
        if (resourcePath == null) {
            resourcePath = "/";
        }
       
        labelHeader = WebdavUtils.fixTomcatHeader(requestHeaders.getLabel(), "UTF-8");
       
        try{
            Element root = parseRequestContent(DeltavConstants.E_LABEL);
            Element current = root.getChild(DeltavConstants.E_ADD, DNSP);
            Element operationElement = null;
            if (current != null) {
                operationElement = current;
            }
            current = root.getChild(DeltavConstants.E_SET, DNSP);
            if ( current != null) {
                if (operationElement != null) {
                    throw new JDOMException(LABEL_MUST_CONTAIN_EITHER_ADD_SET_OR_REMOVE);
                }
                operationElement = current;
            }
            current = root.getChild(DeltavConstants.E_REMOVE, DNSP);
            if ( current != null) {
                if (operationElement != null) {
                    throw new JDOMException(LABEL_MUST_CONTAIN_EITHER_ADD_SET_OR_REMOVE);
                }
                operationElement = current;
            }
            if (operationElement == null) {
                throw new JDOMException(LABEL_MUST_CONTAIN_EITHER_ADD_SET_OR_REMOVE);
            }
            operation = operationElement.getName();
           
            Element labelName = operationElement.getChild(DeltavConstants.E_LABEL_NAME, DNSP);
            if ( (labelName == null) ||
                    (labelName.getText() == null) ||
                    (labelName.getText().length() == 0) ) {
                throw new JDOMException(LABEL_MISSING);
            }
            label = labelName.getText();
        }
        catch (IOException  e){
            int statusCode = WebdavStatus.SC_INTERNAL_SERVER_ERROR;
            sendError( statusCode, e );
            throw new WebdavException( statusCode );
        }
        catch (JDOMException  e){
            int statusCode = WebdavStatus.SC_BAD_REQUEST;
            sendError( statusCode, e );
            throw new WebdavException( statusCode );
        }
    }
   
    /**
     * Execute the request.
     *
     * @throws WebdavException
     * @throws IOException
     */
    protected void executeRequest() throws WebdavException, IOException {
       
        // Prevent dirty reads
        slideToken.setForceStoreEnlistment(true);
       
        // check lock-null resources
        try {
            if (isLockNull(resourcePath)) {
                int statusCode = WebdavStatus.SC_NOT_FOUND;
                sendError( statusCode, "lock-null resource", new Object[]{resourcePath} );
                throw new WebdavException( statusCode );
            }
        }
        catch (ServiceAccessException e) {
            int statusCode = getErrorCode((Exception)e);
            sendError( statusCode, e );
            throw new WebdavException( statusCode );
        }
       
        isCollection = isCollection(resourcePath);
        try {
            labelResource(resourcePath);
        }
        catch (NestedSlideException nestedSlideException) {
            // If it's not a collection, we don't want to give a 207,
            // because it's silly, and it confuses many clients (such as
            // MS Web Folders).
            if (generateMultiStatusResponse(isCollection, nestedSlideException, requestUri)) {
                String errorMessage = generateErrorMessage(nestedSlideException);
                // Write it on the servlet writer
                resp.setStatus(WebdavStatus.SC_MULTI_STATUS);
                try {
                    resp.setContentType(TEXT_XML_UTF_8);
                    resp.getWriter().write(errorMessage);
                } catch(IOException ex) {
                    // Critical error ... Servlet container is dead or something
                    int statusCode = WebdavStatus.SC_INTERNAL_SERVER_ERROR;
                    sendError( statusCode, ex );
                    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.
                SlideException exception = (SlideException)nestedSlideException.enumerateExceptions().nextElement();
                if (exception instanceof PreconditionViolationException) {
                    try {
                        sendPreconditionViolation((PreconditionViolationException)exception);
                    } catch(IOException ex) {
                        // Critical error ... Servlet container is dead or something
                        int statusCode = WebdavStatus.SC_INTERNAL_SERVER_ERROR;
                        sendError( statusCode, ex );
                        throw new WebdavException( statusCode );
                    }
                }
                else {
                    int statusCode = getErrorCode( exception );
                    sendError( statusCode, exception );
                    throw new WebdavException( statusCode );
                }
            }
            //
            // 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);
        }
        finally {
            resp.setHeader(H_CACHE_CONTROL, NO_CACHE);
        }
    }
   
    /**
     * Labels the reource identified by the given <code>resourcePath</code>.
     * If the resource is a collection and a <code>Depth</code> header is specified
     * than the request is applied recursivly. If an attempt to label a resource
     * fails, the corresponding Exception is contained in the thrown
     * NestedSlideException.
     *
     * @param      resourcePath   the path of the resource to label.
     *
     * @throws     NestedSlideException, if an attempt to label a resource fails.
     */
    protected void labelResource(String resourcePath) throws NestedSlideException {
        NestedSlideException nestedSlideException = new NestedSlideException(null);
        try {
            labelResource(resourcePath, getDepth(), nestedSlideException);
        }
        catch (WebdavException e) {
            nestedSlideException.addException(e);
        }
        if ( ! nestedSlideException.isEmpty() ) {
            throw nestedSlideException;
        }
    }
   
    /**
     * Labels the reource identified by the given <code>resourcePath</code>.
     * If the resource is a collection and the <code>depth</code> > 0
     * than the request is applied recursivly. If an attempt to label a resource
     * fails, the corresponding Exception will be added to the given
     * <code>nestedSlideException</code>.
     *
     * @param      resourcePath          the path of the resource to label.
     * @param      depth                 the depth to use if the resource is a collection.
     * @param      nestedSlideException  the NestedSlideException to add all occurring
     *                                   Exceptions to.
     */
    protected void labelResource(String resourcePath, int depth, NestedSlideException nestedSlideException) {
       
        try {
           
            if ( ! isCollection(resourcePath) ) {
                ViolatedPrecondition violatedPrecondition = getPreconditionViolation(resourcePath);
                if (violatedPrecondition != null) {
                    throw new PreconditionViolationException(violatedPrecondition, resourcePath);
                }
               
                performLabelOperation(resourcePath);
            }
            else if (depth > 0) {
               
                // process children recursivly
                ObjectNode currentNode = structure.retrieve(slideToken, resourcePath);
                Enumeration childrenEnum = structure.getChildren(slideToken, currentNode);
                if (childrenEnum != null) {
                    while (childrenEnum.hasMoreElements()) {
                        labelResource(((ObjectNode)childrenEnum.nextElement()).getUri(), depth-1, nestedSlideException);
                    }
                }
            }
        }
        catch (SlideException e) {
            nestedSlideException.addException(e);
        }
        catch (JDOMException e) {
            nestedSlideException.addException(new SlideException(e.getMessage()));
        }
    }
   
    /**
     * Perform the LABEL operation means it either adds, sets or removes the label.
     *
     * @param      resourcePath  the resource to add/set/remove the label.
     *
     * @throws     JDOMException
     * @throws     SlideException
     */
    private void performLabelOperation(String resourcePath) throws JDOMException, SlideException {
       
        String labelHeader = WebdavUtils.fixTomcatHeader(requestHeaders.getLabel(), "UTF-8");
        String labeledResourceUri = getResourceUri(resourcePath, labelHeader);
        NodeRevisionDescriptors revisionDescriptors =
            content.retrieve( slideToken, labeledResourceUri);
        NodeRevisionDescriptor revisionDescriptor =
            content.retrieve( slideToken, revisionDescriptors);
        ResourceKind resourceKind = AbstractResourceKind.determineResourceKind(token, revisionDescriptors, revisionDescriptor);
        if (resourceKind instanceof Version) {
           
            if (DeltavConstants.E_REMOVE.equals(operation)) {
                PropertyHelper.removeElementFromProperty(revisionDescriptor,
                                                         P_LABEL_NAME_SET,
                                                         E_LABEL_NAME,
                                                         label);
                content.store(slideToken, revisionDescriptors.getUri(), revisionDescriptor, null);
            }
           
            if (DeltavConstants.E_SET.equals(operation)) {
                try {
                    NodeRevisionDescriptor alreadyLabeledDescriptor =
                        versioningHelper.retrieveLabeledRevision(revisionDescriptors.getUri(),
                                                                 label);
                    PropertyHelper.removeElementFromProperty(alreadyLabeledDescriptor,
                                                             P_LABEL_NAME_SET,
                                                             E_LABEL_NAME,
                                                             label);
                    content.store(slideToken, revisionDescriptors.getUri(), alreadyLabeledDescriptor, null);
                }
                catch (LabeledRevisionNotFoundException e) {
                    // there is no version with the given label so far,
                    // so we can perform the <set> operation without any preparation
                }
            }
           
            if (DeltavConstants.E_ADD.equals(operation) ||
                DeltavConstants.E_SET.equals(operation) ) {
                PropertyHelper.addElementToProperty(revisionDescriptor,
                                                    P_LABEL_NAME_SET,
                                                    E_LABEL_NAME,
                                                    label);
                content.store(slideToken, revisionDescriptors.getUri(), revisionDescriptor, null);
            }
        }
    }
   
    /**
     * Checks the (DeltaV) preconditions
     * <ul>
     * <li>&lt;DAV:must-be-checked-in&gt;</li>
     * <li>&lt;DAV:must-select-version-in-history&gt;</li>
     * <li>&lt;DAV:must-be-new-label&gt;</li>
     * <li>&lt;DAV:label-must-exist&gt;</li>
     * </ul>
     *
     * @param      resourcePath       the URI of the resource.
     *
     * @return     the precondition that has been violated (if any).
     *
     * @throws     SlideException
     */
    protected ViolatedPrecondition getPreconditionViolation(String resourcePath) throws SlideException {
        // use a non-blocking slide token.
        SlideToken stoken = readonlySlideToken();
       
        ViolatedPrecondition violatedPrecondition = null;
        NodeRevisionDescriptors revisionDescriptors =
            content.retrieve( stoken, resourcePath);
        NodeRevisionDescriptor revisionDescriptor =
            content.retrieve( stoken, revisionDescriptors);
        ResourceKind resourceKind = AbstractResourceKind.determineResourceKind(token, revisionDescriptors, revisionDescriptor);
       
        // check <DAV:must-be-checked-in>
        if ( (resourceKind instanceof VersionControlled) &&
            !(resourceKind instanceof CheckedInVersionControlled) ) {
            return new ViolatedPrecondition(DeltavConstants.C_MUST_BE_CHECKED_IN,
                                            WebdavStatus.SC_CONFLICT);
        }
       
        // check <DAV:must-select-version-in-history>
        if ( (resourceKind instanceof VersionControlled) &&
                (labelHeader != null) ) {
            try {
                versioningHelper.getLabeledResourceUri(resourcePath, labelHeader);
            }
            catch (LabeledRevisionNotFoundException e) {
                return new ViolatedPrecondition(DeltavConstants.C_MUST_SELECT_VERSION_IN_HISTORY,
                                                WebdavStatus.SC_CONFLICT);
            }
        }
       
        try {
            String slideResourceUri = getResourceUri(resourcePath, labelHeader);
            revisionDescriptors =
                content.retrieve( stoken, slideResourceUri);
            revisionDescriptor =
                content.retrieve( stoken, revisionDescriptors);
            resourceKind = AbstractResourceKind.determineResourceKind(token, revisionDescriptors, revisionDescriptor);
            if (resourceKind instanceof Version) {
               
                // check <DAV:label-must-exist>
                if (DeltavConstants.E_REMOVE.equals(operation)) {
                    if ( ! hasLabel(revisionDescriptor, label) ) {
                        return new ViolatedPrecondition(DeltavConstants.C_LABEL_MUST_EXIST,
                                                        WebdavStatus.SC_CONFLICT);
                    }
                }
               
                try {
                    versioningHelper.retrieveLabeledRevision(revisionDescriptors.getUri(), label);
                    // check <DAV:must-be-new-label>
                    if (DeltavConstants.E_ADD.equals(operation)) {
                        return new ViolatedPrecondition(DeltavConstants.C_MUST_BE_NEW_LABEL,
                                                        WebdavStatus.SC_CONFLICT);
                    }
                }
                catch (LabeledRevisionNotFoundException e) {}
            }
        }
        catch (LabeledRevisionNotFoundException e) {
            // check <DAV:label-must-exist>
            if (DeltavConstants.E_REMOVE.equals(operation)) {
                return new ViolatedPrecondition(DeltavConstants.C_LABEL_MUST_EXIST,
                                                WebdavStatus.SC_CONFLICT);
            }
        }
       
        return violatedPrecondition;
    }
   
   
    /**
     * Returns the value of the <code>Depth</code> header. If not specified,
     * <code>0</code> is used as default.
     *
     * @return     the value of the <code>Depth</code> header.
     */
    private int getDepth() throws WebdavException {
        return requestHeaders.getDepth(0);
    }
   
    /**
     * Returns <code>true</code> if the given <code>revisionDescriptor</code>
     * has a <code>&lt;label-name-set&gt;</code> property that contains a
     * <code>&lt;label-name&gt;</code> element with the given <code>label</code>.
     *
     * @param      revisionDescriptor  the NodeRevisionDescriptor to check.
     * @param      label               the label to look for.
     *
     * @return     <code>true</code>, if the label was found.
     */
    protected boolean hasLabel(NodeRevisionDescriptor revisionDescriptor, String label) {
       
        boolean containsLabel = false;
        NodeProperty labelNameSetProperty = revisionDescriptor.getProperty(DeltavConstants.P_LABEL_NAME_SET);
        if ( (labelNameSetProperty != null) && (labelNameSetProperty.getValue() != null) ) {
            try {
                XMLValue xmlValue = new XMLValue(labelNameSetProperty.getValue().toString());
                Iterator iterator = xmlValue.iterator();
                while ( !containsLabel && iterator.hasNext()) {
                    containsLabel = label.equals(((Element)iterator.next()).getText());
                }
            }
            catch (JDOMException e) {}
            catch (IllegalArgumentException e) {}
        }
       
        return containsLabel;
    }
   
    /**
     * Returns the Uri of the resource identified by the given <code>resourcePath</code>
     * and the given <code>label</code>. If the <code>label</code> is <code>null</code>
     * and the resource is a VCR, the associated VR is returned.
     *
     * @param      resourcePath  the path of the resource.
     * @param      label         the label (may be <code>null</code>).
     *
     * @return     the Uri of the resource identified by the given <code>resourcePath</code>
     *             and the given <code>label</code>.
     *
     * @throws     SlideException
     */
    protected String getResourceUri(String resourcePath, String label) throws SlideException {
       
        String labeledResourceUri = versioningHelper.getLabeledResourceUri(resourcePath,
                                                                           label);
        NodeRevisionDescriptors revisionDescriptors =
            content.retrieve( slideToken,labeledResourceUri);
        NodeRevisionDescriptor revisionDescriptor =
            content.retrieve( slideToken, revisionDescriptors);
        ResourceKind resourceKind = AbstractResourceKind.determineResourceKind(token, revisionDescriptors, revisionDescriptor);
        if (resourceKind instanceof VersionControlled) {
            labeledResourceUri = versioningHelper.getUriOfAssociatedVR(resourcePath);
        }
       
        return labeledResourceUri;
    }
   
}


TOP

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

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.