Package org.apache.xindice.webadmin.webdav.components

Source Code of org.apache.xindice.webadmin.webdav.components.Propfind

/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements.  See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.
*
* $Id: Propfind.java 551440 2007-06-28 04:26:07Z vgritsenko $
*/

package org.apache.xindice.webadmin.webdav.components;

import java.io.IOException;
import java.util.Set;
import java.util.HashMap;
import java.util.Iterator;
import java.util.ArrayList;
import java.util.HashSet;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletResponse;

import org.apache.xindice.core.Collection;
import org.apache.xindice.core.DBException;
import org.apache.xindice.core.Database;
import org.apache.xindice.core.data.Entry;
import org.apache.xindice.webadmin.webdav.components.props.CreationDate;
import org.apache.xindice.webadmin.webdav.components.props.DAVProperty;
import org.apache.xindice.webadmin.webdav.components.props.LastModified;
import org.apache.xindice.webadmin.webdav.components.props.DisplayName;
import org.apache.xindice.webadmin.webdav.components.props.ResourceType;
import org.apache.xindice.webadmin.webdav.components.props.ContentType;
import org.apache.xindice.webadmin.webdav.WebdavStatus;
import org.apache.xindice.webadmin.webdav.DAVRequest;
import org.apache.xindice.webadmin.webdav.DAVResponse;
import org.apache.xindice.webadmin.PartialResponse;
import org.apache.xindice.webadmin.Location;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

/**
* This class implements the Propfind command for WebDAV operations on
* Xindice. <br>
* <br>
* PROPFIND command requests properties defined for resources or collections.
* Request can have a body that contians XML document. It is possible
* to request particular property values, all property values, or a
* list of the names of the resource's properties. A client may choose not
* to submit a request body. An empty PROPFIND request body is treated as a
* request for the names and values of all properties.<br>
* <br>
* A client may submit a Depth header with a value of "0", "1", or "infinity"
* with a PROPFIND on a collection. By default, the PROPFIND method without a
* Depth header acts as if a "Depth: infinity" header was included.<br>
* <br>
* The default operation status code is 207 (Multi-Status).
*
* @author <a href="mailto:jmetzner@apache.org">Jan Metzner</a>
* @author <a href="mailto:gianugo@apache.org">Gianugo Rabellino</a>
* @version $Revision: 551440 $, $Date: 2007-06-28 00:26:07 -0400 (Thu, 28 Jun 2007) $
*/
public class Propfind implements DAVComponent {

    public static final int FIND_BY_PROPERTY = 1;
    public static final int FIND_PROPERTY_NAMES = 2;
    public static final int FIND_ALL_PROP = 3;

    private static final HashMap PROPS_MAP = new HashMap();
    static {
        DAVProperty[] props = {
                new CreationDate(),
                new LastModified(),
                new DisplayName(),
                new ResourceType(),
                new ContentType()
        };

        for (int i = 0; i < props.length; i++) {
            PROPS_MAP.put(props[i].getName(), props[i]);
        }
    }

    private static final Log log = LogFactory.getLog(Propfind.class);

    public void execute(DAVRequest req, DAVResponse res, Location target) throws ServletException, IOException {
        if (!target.isRoot() && target.getCollection() == null) {
            res.setStatus(HttpServletResponse.SC_NOT_FOUND);
            return;
        }

        try {
            process(req, res, target.getCollection(), target.getName());
        } catch (DBException e) {
            log.error(e);
            throw new ServletException(e);
        }
    }

    private void process(DAVRequest req, DAVResponse res, Collection col, String name)
    throws DBException, IOException {
        res.setProtocol(req.getProtocol());
        Document requestDoc = req.getRequestDoc();
        int type = getPropFindType(requestDoc);

        Set requestedProps = null;
        if (type == FIND_BY_PROPERTY) {
            requestedProps = getRequestPropertyNames(requestDoc);
        }

        String contextPath = req.getContextPath();
        if (name == null) {
            int depth = req.getDepth();
            String requestPath = req.getPath();

            if (requestPath == null || requestPath.equals("/")) { // root
                col = null;
            }

            HashMap values = getProperties(col, null, requestedProps, type);
            addPropfindResponse(res, getLocation(contextPath, col), values);

            if (depth != 0) {
                processChildren(res, contextPath, col, requestedProps, type, depth);
            }

        } else {
            Entry entry = col.getEntry(name);
            if (entry == null) {
                res.setStatus(HttpServletResponse.SC_NOT_FOUND);
            } else {
                HashMap values = getProperties(col, entry, requestedProps, type);
                addPropfindResponse(res, getLocation(contextPath, col, name), values);
            }
        }

        res.closeMultistatusResponse();
    }

    private void processChildren(DAVResponse res, String contextPath, Collection col, Set requestedProps, int type, int depth)
    throws DBException, IOException {
        String[] children;
        if (col == null) {
            children = Database.listDatabases();
        } else {
            children = col.listCollections();
        }

        if (depth != 0) {
            // child resources
            if (col != null) {
                String[] childResources = col.listDocuments();
                for (int i = 0; i < childResources.length; i++) {
                    HashMap values = getProperties(col, col.getEntry(childResources[i]), requestedProps, type);
                    addPropfindResponse(res, getLocation(contextPath, col, childResources[i]), values);
                }
            }

            // child collections
            for (int i = 0; i < children.length; i++) {
                Collection childCol = col != null ?
                        col.getCollection(children[i]) :
                        Database.getDatabase(children[i]);

                HashMap values = getProperties(childCol, null, requestedProps, type);
                addPropfindResponse(res, getLocation(contextPath, childCol), values);
                processChildren(res, contextPath, childCol, requestedProps, type, depth - 1 );
            }
        }
    }

    private HashMap getProperties(Collection col, Entry entry, Set requestedProps, int type) {
        HashMap values = null;
        switch (type) {
            case FIND_PROPERTY_NAMES:
                values = getPropertyNames(col, entry);
                break;
            case FIND_ALL_PROP:
                values = getAllPropertiesValues(col, entry);
                break;
            case FIND_BY_PROPERTY:
                values = getPropertiesValues(col, entry, requestedProps);
                break;
        }

        return values;
    }

    private HashMap getPropertyNames(Collection col, Entry entry) {
        ArrayList values = new ArrayList();

        for (Iterator i = PROPS_MAP.keySet().iterator(); i.hasNext(); ) {
            String property = (String) i.next();

            if (getProperty(col, entry, property) != null) {
                values.add(new PartialResponse.Content(property));
            }
        }

        HashMap status = new HashMap();
        status.put(new Integer(WebdavStatus.SC_OK), values);
        return status;
    }

    private HashMap getPropertiesValues(Collection col, Entry entry, Set requestProps) {
        ArrayList values = new ArrayList();
        ArrayList notFound = new ArrayList();

        for (Iterator i = requestProps.iterator(); i.hasNext(); ) {
            String requestProp = (String) i.next();
            if (PROPS_MAP.containsKey(requestProp)) { // supported property

                PartialResponse.Content part = getProperty(col, entry, requestProp);

                if (part != null) {
                    values.add(part);
                } else {
                    notFound.add(new PartialResponse.Content(requestProp));
                }
            } else { // requested property not supported
                notFound.add(new PartialResponse.Content(requestProp));
            }
        }

        HashMap status = new HashMap();
        status.put(new Integer(WebdavStatus.SC_OK), values);
        status.put(new Integer(WebdavStatus.SC_NOT_FOUND), notFound);
        return status;
    }

    private HashMap getAllPropertiesValues(Collection col, Entry entry) {
        ArrayList values = new ArrayList();

        Set props = PROPS_MAP.keySet();
        for (Iterator i = props.iterator(); i.hasNext(); ) {
            String requestProp = (String) i.next();

            PartialResponse.Content part = getProperty(col, entry, requestProp);

            if (part != null) {
                values.add(part);
            }
        }

        HashMap status = new HashMap();
        status.put(new Integer(WebdavStatus.SC_OK), values);
        return status;
    }

    private PartialResponse.Content getProperty(Collection col, Entry entry, String propName) {
        DAVProperty prop = (DAVProperty) PROPS_MAP.get(propName);

        PartialResponse.Content part;
        if (entry != null) {
            part = prop.getProperty(entry);
        } else if (col != null) {
            part = prop.getProperty(col);
        } else {
            part = prop.getRootProperty();
        }

        return part;
    }

    private Set getRequestPropertyNames(Document doc) {
        NodeList nodes = doc.getDocumentElement().getElementsByTagNameNS("DAV:", "prop");

        HashSet properties = new HashSet();
        NodeList childList = nodes.item(0).getChildNodes();
        for (int i = 0; i < childList.getLength(); i++) {
            Node currentNode = childList.item(i);
            if (currentNode.getNodeType() == Node.ELEMENT_NODE && currentNode.getNamespaceURI().equals("DAV:")) {
                properties.add(currentNode.getLocalName());
            }
        }
        if (log.isDebugEnabled()) {
            log.debug("Requested properties: " + properties.toString());
        }

        return properties;
    }

    private int getPropFindType(Document doc) {
        if (doc == null) {
            return FIND_ALL_PROP;
        }

        int type = FIND_ALL_PROP;
        Node propfind = doc.getDocumentElement();
        if (propfind != null && isNodeNamed(propfind, "propfind")) {
            NodeList childList = propfind.getChildNodes();

            for (int i = 0; i < childList.getLength(); i++) {
                Node currentNode = childList.item(i);
                if (currentNode.getNodeType() == Node.ELEMENT_NODE) {
                    if (isNodeNamed(currentNode, "prop")) {
                        type = FIND_BY_PROPERTY;
                        break;
                    } else if (isNodeNamed(currentNode, "propname")) {
                        type = FIND_PROPERTY_NAMES;
                        break;
                    } else if (isNodeNamed(currentNode, "allprop")) {
                        type = FIND_ALL_PROP;
                        break;
                    }
                }
            }
        }

        return type;
    }

    private boolean isNodeNamed(Node node, String name) {
        return node.getNamespaceURI().equals("DAV:") && node.getLocalName().equals(name);
    }

    private String getLocation(String context, Collection col) {
        return context + (col != null ? col.getCanonicalName() : "") + "/";
    }

    private String getLocation(String context, Collection col, String resource) {
        return context + col.getCanonicalDocumentName(resource);
    }

    public void addPropfindResponse(DAVResponse res, String location, HashMap statusList) throws IOException {
        PartialResponse response = new PartialResponse(location);

        for (Iterator i = statusList.keySet().iterator(); i.hasNext(); ) {
            Integer status = (Integer) i.next();
            ArrayList props = (ArrayList) statusList.get(status);

            if (props != null && props.size() > 0) {
                PartialResponse.Content prop = new PartialResponse.Content("prop");
                for (Iterator j = props.iterator(); j.hasNext(); ) {
                    prop.addChild((PartialResponse.Content) j.next());
                }

                PartialResponse.Content stat = new PartialResponse.Content("status");
                stat.setValue(res.getProtocol() + " " + status + " " + WebdavStatus.getStatusText(status.intValue()));

                PartialResponse.Content propstat = new PartialResponse.Content("propstat");
                propstat.addChild(prop);
                propstat.addChild(stat);

                response.addContent(propstat);
            }
        }

        res.sendMultiStatusResponse(response);
    }
}
TOP

Related Classes of org.apache.xindice.webadmin.webdav.components.Propfind

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.