Package org.apache.slide.webdav.method

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

/*
* $Header: /home/cvs/jakarta-slide/src/webdav/server/org/apache/slide/webdav/method/PropPatchMethod.java,v 1.20 2001/08/31 03:21:45 remm Exp $
* $Revision: 1.20 $
* $Date: 2001/08/31 03:21:45 $
*
* ====================================================================
*
* 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.slide.webdav.method;

import java.security.Principal;
import java.io.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.*;
import org.xml.sax.SAXException;

import org.apache.util.XMLPrinter;
import org.apache.util.DOMWriter;
import org.apache.util.WebdavStatus;
import org.apache.slide.authenticate.CredentialsToken;
import org.apache.slide.common.*;
import org.apache.slide.security.AccessDeniedException;
import org.apache.slide.webdav.*;
import org.apache.slide.structure.*;
import org.apache.slide.lock.*;
import org.apache.slide.content.*;

/**
* PROPPATCH method.
*
* @author <a href="mailto:remm@apache.org">Remy Maucherat</a>
*/
public class PropPatchMethod extends WebdavMethod {
   
   
    // -------------------------------------------------------------- Constants
   
   
    private static final int SET = 0;
    private static final int REMOVE = 1;
   
   
    // ----------------------------------------------------- Instance Variables
   
   
    /**
     * Properties to set. Vector of SlideProperty objects.
     */
    private Vector propertiesToSet;
   
    /**
     * Properties to remove. Vector of String.
     */
    private Vector propertiesToRemove;
   
   
    /**
     * DOM Writer.
     */
    private DOMWriter domWriter;
   
   
    /**
     * Resource which will have its properties updated.
     */
    private String resourcePath;
   
   
    // ----------------------------------------------------------- Constructors
   
   
    /**
     * PROPPATCH method constructor.
     *
     * @param token Namespace access token
     * @param req HTTP request
     * @param resp HTTP response
     */
    public PropPatchMethod(NamespaceAccessToken token, HttpServletRequest req,
                           HttpServletResponse resp,
                           WebdavServletConfig config) {
        super(token, req, resp, config);
        readRequestContent();
    }
   
   
    // ------------------------------------------------------ Protected Methods
   
   
    /**
     * Parse the request.
     *
     * @exception WebdavException Bad request
     */
    protected void parseRequest()
        throws WebdavException {
       
        resourcePath = requestUri;
        if (resourcePath == null) {
            resourcePath = "/";
        }
       
        propertiesToSet = new Vector();
       
        propertiesToRemove = new Vector();
       
        if (requestBody.length() != 0) {
            try {
                Node setNode = null;
                Node removeNode = null;
               
                Document document = parseRequestContent();
               
                // Get the root element of the document
                Element rootElement = document.getDocumentElement();
                NodeList childList = rootElement.getChildNodes();
               
                for (int i=0; i < childList.getLength(); i++) {
                    Node currentNode = childList.item(i);
                    switch (currentNode.getNodeType()) {
                        case Node.TEXT_NODE:
                            break;
                        case Node.ELEMENT_NODE:
                            if (currentNode.getNodeName().endsWith("set")) {
                                NodeList tempList =
                                    currentNode.getChildNodes();
                                for (int j=0; j < tempList.getLength(); j++) {
                                    switch (tempList.item(j).getNodeType()) {
                                        case Node.TEXT_NODE:
                                            break;
                                        case Node.ELEMENT_NODE:
                                            if (tempList.item(j).getNodeName()
                                                .endsWith("prop")) {
                                                parseSetNode(tempList.item(j));
                                            }
                                            break;
                                    }
                                }
                            }
                            if (currentNode.getNodeName().endsWith("remove")) {
                                NodeList tempList = currentNode.getChildNodes();
                                for (int j=0; j < tempList.getLength(); j++) {
                                    switch (tempList.item(j).getNodeType()) {
                                        case Node.TEXT_NODE:
                                            break;
                                        case Node.ELEMENT_NODE:
                                            if (tempList.item(j).getNodeName()
                                                .endsWith("prop")) {
                                                parseRemoveNode(tempList.item(j));
                                            }
                                            break;
                                    }
                                }
                            }
                            break;
                    }
                }
               
            } catch (SAXException e) {
                resp.setStatus(WebdavStatus.SC_BAD_REQUEST);
                throw new WebdavException(WebdavStatus.SC_BAD_REQUEST);
            } catch (ParserConfigurationException e) {
                System.err.println(e.getMessage());
                resp.setStatus(WebdavStatus.SC_INTERNAL_SERVER_ERROR);
                throw new WebdavException
                    (WebdavStatus.SC_INTERNAL_SERVER_ERROR);
            } catch (IOException e) {
                System.err.println(e.getMessage());
                e.printStackTrace();
                resp.setStatus(WebdavStatus.SC_INTERNAL_SERVER_ERROR);
                throw new WebdavException
                    (WebdavStatus.SC_INTERNAL_SERVER_ERROR);
            }
        } else {
            try {
                resp.sendError(WebdavStatus.SC_BAD_REQUEST,
                               WebdavStatus.getStatusText
                                   (WebdavStatus.SC_BAD_REQUEST));
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
       
    }
   
   
    /**
     * Execute the request.
     *
     * @exception WebdavException
     */
    protected void executeRequest()
        throws WebdavException {
       
        // Prevent dirty reads
        slideToken.setForceStoreEnlistment(true);
       
        try {
           
            NodeRevisionDescriptors revisionDescriptors =
                content.retrieve(slideToken, resourcePath);
            NodeRevisionDescriptor revisionDescriptor = null;
           
            try {
                revisionDescriptor =
                    content.retrieve(slideToken, revisionDescriptors);
            } catch (RevisionDescriptorNotFoundException ex) {
                revisionDescriptor = new NodeRevisionDescriptor(0);
                // TODO : Create the initial revision ?
            }
           
            // Modifying the properties
           
            Enumeration propertyList = null;
           
            propertyList = propertiesToSet.elements();
           
            while (propertyList.hasMoreElements()) {
               
                Property currentProperty =
                    (Property) propertyList.nextElement();
               
                if (checkProperty(currentProperty, SET)) {
                   
                    NodeProperty newProperty =
                        new NodeProperty(currentProperty.name,
                                         currentProperty.value,
                                         currentProperty.namespace);
                    revisionDescriptor.setProperty(newProperty);
                   
                }
            }
           
            propertyList = propertiesToRemove.elements();
           
            while (propertyList.hasMoreElements()) {
               
                Property currentProperty =
                    (Property) propertyList.nextElement();
               
                if (checkProperty(currentProperty, REMOVE)) {
                   
                    revisionDescriptor.removeProperty(currentProperty.name);
                   
                }
               
            }
           
            content.store(slideToken, resourcePath, revisionDescriptor, null);
           
            resp.setStatus(WebdavStatus.SC_MULTI_STATUS);
           
        } catch (Exception e) {
            resp.setStatus(getErrorCode(e))// special handling needed
            throw new WebdavException(WebdavStatus.SC_ACCEPTED, false); // abort the TA
        }
       
       
        // No serious errors. Printing the XML report.
        writeReport();
       
    }
   
       
       
       
    /**
     * Get return status based on exception type.
     */
    protected int getErrorCode(Exception ex) {
        try {
            throw ex;
        } catch (LinkedObjectNotFoundException e) {
            return WebdavStatus.SC_NOT_FOUND;
        } catch (Exception e) {
            return super.getErrorCode(e);
        }
    }


       
    // -------------------------------------------------------- Private Methods
   
   
    /**
     * Parse the set property node given.
     */
    private void parseSetNode(Node setNode) {
       
        NodeList childList = setNode.getChildNodes();
       
        for (int i=0; i < childList.getLength(); i++) {
            Node currentNode = childList.item(i);
            switch (currentNode.getNodeType()) {
                case Node.TEXT_NODE:
                    break;
                case Node.ELEMENT_NODE:
                   
                    Property propertyToSet = getProperty(currentNode);
                   
                    StringWriter writer = new StringWriter();
                    domWriter = new DOMWriter(writer, true);
                   
                    // Printing all child nodes using the DOM printer
                    NodeList childNodes = currentNode.getChildNodes();
                    Node childNode = childNodes.item(0);
                    int pos = 0;
                    while (childNode != null) {
                        domWriter.print(childNode);
                        childNode = childNodes.item(++pos);
                    }
                   
                    String nodeValue = writer.toString();
                    propertyToSet.value = nodeValue;
                   
                    propertiesToSet.addElement(propertyToSet);
                   
                    break;
            }
        }
    }
   
   
    /**
     * Parse the remove property node given.
     */
    private void parseRemoveNode(Node removeNode) {
       
        NodeList childList = removeNode.getChildNodes();
       
        for (int i=0; i < childList.getLength(); i++) {
            Node currentNode = childList.item(i);
            switch (currentNode.getNodeType()) {
                case Node.TEXT_NODE:
                    break;
                case Node.ELEMENT_NODE:
                   
                    Property propertyToRemove = getProperty(currentNode);
                   
                    propertiesToRemove.addElement(propertyToRemove);
                   
                    break;
            }
        }
    }
   
   
    /**
     * Parse the namespace info of a node name.
     *
     * @param node The DOM node to parse
     * @return The corresponding Property object
     */
    private Property getProperty(Node node) {
       
        Property property = new Property();
       
        property.name = node.getLocalName();
        property.namespace = node.getNamespaceURI();
        property.namespaceAbbrev = node.getPrefix();
       
        return property;
       
    }
   
   
    /**
     * Check if the property is a live property which should have its value
     * enforced by the server.
     *
     * @param property The property object
     * @param actionType Can be either SET or REMOVE
     */
    private boolean checkProperty(Property property, int actionType) {
       
        // Checking the standard DAV properties which can't be modified using
        // a propatch.
        if (
               (property.name.equalsIgnoreCase("creationdate")) ||
               (property.name.equalsIgnoreCase("getcontentlength")) ||
               (property.name.equalsIgnoreCase("getetag")) ||
               (property.name.equalsIgnoreCase("getlastmodified")) ||
               (property.name.equalsIgnoreCase("lockdiscovery"))
        ) {
            property.status = WebdavStatus.SC_CONFLICT;
            return false;
        }
       
        switch (actionType) {
           
            case SET:
               
                break;
               
            case REMOVE:
               
                break;
               
        }
       
        return true;
       
    }
   
   
    /**
     * Write the report.
     */
    private void writeReport()
        throws WebdavException {
       
        // Create multistatus object
        XMLPrinter generatedXML = new XMLPrinter();
       
        generatedXML.writeXMLHeader();
        generatedXML.writeElement("d", "DAV", "multistatus",
                                  XMLPrinter.OPENING);
       
        generatedXML.writeElement("d", null, "response", XMLPrinter.OPENING);
        generatedXML.writeProperty("d", null, "href",
                                   WebdavUtils.encodeURL(requestUri));
       
       
       
        // Parse the two properties list, and printout their status
        Enumeration propertyList = null;
       
        propertyList = propertiesToSet.elements();
       
        while(propertyList.hasMoreElements()) {
            Property property = (Property) propertyList.nextElement();
            generatedXML.writeElement("d", null, "propstat",
                                      XMLPrinter.OPENING);
            generatedXML.writeElement("d", null, "prop", XMLPrinter.OPENING);
            generatedXML.writeElement(property.namespaceAbbrev,
                                      property.namespace, property.name,
                                      XMLPrinter.NO_CONTENT);
            generatedXML.writeElement("d", null, "prop", XMLPrinter.CLOSING);
            generatedXML.writeProperty
                ("d", null, "status", "HTTP/1.1 " + property.status + " "
                     + WebdavStatus.getStatusText(property.status));
            generatedXML.writeElement("d", null, "propstat",
                                      XMLPrinter.CLOSING);
        }
       
        propertyList = propertiesToRemove.elements();
       
        while(propertyList.hasMoreElements()) {
            Property property = (Property) propertyList.nextElement();
            generatedXML.writeElement("d", null, "propstat",
                                      XMLPrinter.OPENING);
            generatedXML.writeElement("d", null, "prop", XMLPrinter.OPENING);
            generatedXML.writeElement(property.namespaceAbbrev,
                                      property.namespace, property.name,
                                      XMLPrinter.NO_CONTENT);
            generatedXML.writeElement("d", null, "prop", XMLPrinter.CLOSING);
            generatedXML.writeProperty
                ("d", null, "status", "HTTP/1.1 " + property.status + " "
                     + WebdavStatus.getStatusText(property.status));
            generatedXML.writeElement("d", null, "propstat",
                                      XMLPrinter.CLOSING);
        }
       
        generatedXML.writeElement("d", null, "response", XMLPrinter.CLOSING);
        generatedXML.writeElement("d", "multistatus", XMLPrinter.CLOSING);
       
        try {
            Writer writer = resp.getWriter();
            writer.write(generatedXML.toString());
            writer.flush();
        } catch (Exception e) {
            e.printStackTrace();
            throw new WebdavException(WebdavStatus.SC_INTERNAL_SERVER_ERROR);
        }
       
    }
   
   
    // --------------------------------------------------- Property Inner Class
   
   
    private class Property {
       
        public String name;
        public String value;
        public String namespace;
        public String namespaceAbbrev;
        public int status = WebdavStatus.SC_OK;
       
    }
   
   
   
    /**
     * Returns true
     */
    protected boolean methodNeedsTransactionSupport() {
        return true;
    }
   
   
   
   
}
TOP

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

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.