org.osaf.caldav4j.methods.PropFindMethod.java Source code

Java tutorial

Introduction

Here is the source code for org.osaf.caldav4j.methods.PropFindMethod.java

Source

/*
 * Copyright 2006 Open Source Applications 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.osaf.caldav4j.methods;

import static org.osaf.caldav4j.CalDAVConstants.NS_CALDAV;
import static org.osaf.caldav4j.CalDAVConstants.NS_DAV;

import java.util.Enumeration;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
import java.util.Vector;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.webdav.lib.Ace;
import org.apache.webdav.lib.Property;
import org.apache.webdav.lib.properties.AclProperty;
import org.apache.webdav.lib.properties.PropertyFactory;
import org.apache.webdav.lib.util.DOMUtils;
import org.apache.webdav.lib.util.QName;
import org.apache.webdav.lib.util.WebdavStatus;
import org.osaf.caldav4j.CalDAVConstants;
import org.osaf.caldav4j.exceptions.CalDAV4JException;
import org.osaf.caldav4j.exceptions.DOMValidationException;
import org.osaf.caldav4j.model.response.CalDAVResponse;
import org.osaf.caldav4j.model.response.TicketDiscoveryProperty;
import org.osaf.caldav4j.util.CaldavStatus;
import org.osaf.caldav4j.util.XMLUtils;
import org.osaf.caldav4j.xml.OutputsDOM;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

/**
 * This method is overwritten in order to register the ticketdiscovery element
 * with the PropertyFactory.
 * 
 * @author EdBindl
 * 
 */
public class PropFindMethod extends org.apache.webdav.lib.methods.PropFindMethod {
    private static final Log log = LogFactory.getLog(PropFindMethod.class);
    private OutputsDOM propFindRequest;

    /**
     * Registers the TicketDiscoveryProperty with the PropertyFactory
     */
    static {
        try {
            PropertyFactory.register(CalDAVConstants.NS_XYTHOS, CalDAVConstants.ELEM_TICKETDISCOVERY,
                    TicketDiscoveryProperty.class);
        } catch (Exception e) {
            throw new RuntimeException("Could not register TicketDiscoveryProperty!", e);
        }
    }

    public PropFindMethod() {
        super();
    }

    public PropFindMethod(String path, Enumeration propertyNames) {
        super(path, propertyNames);
    }

    //    
    //    private parseResponseProperties(String urlPath) {
    //       Enumeration<Property> myEnum = getResponseProperties(urlPath);
    //       
    //       while (getResponseProperties(urlPath).hasMoreElements()) {
    //          BaseProperty e =  (BaseProperty) myEnum.nextElement();
    //            String[] types={"acl","calendar-description","displayname"};
    //            for (int i=0 ; i<types.length ; i++) {
    //               if (! types[i].equals(e.getName()))
    //                  continue;
    //               
    //               switch (i) {
    //            case 0:
    //               aclProperty = (AclProperty) e;
    //               
    //               break;
    //
    //            default:
    //               break;
    //            }
    //            }
    //
    //          
    //       }
    //    }
    /**
     * Returns an enumeration of <code>Property</code> objects.
     */
    //    public Enumeration<Property> getResponseProperties(String urlPath) {
    //       checkUsed();
    //
    //       Response response = (Response) getResponseHashtable().get(urlPath);
    //       if (response == null){
    //          response = (Response) getResponseHashtable().get(stripHost(urlPath));
    //       }
    //       if (response != null) {
    //          return  response.getProperties();
    //       } else {
    //          return  (new Vector()).elements();
    //       }
    //    }

    public void setPropFindRequest(OutputsDOM myprop) {
        this.propFindRequest = myprop;
    }

    /**
     * Generates a request body from the calendar query.
     */
    protected String generateRequestBody() {
        Document doc = null;
        try {
            doc = propFindRequest.createNewDocument(XMLUtils.getDOMImplementation());
        } catch (DOMValidationException domve) {
            log.error("Error trying to create DOM from CalDAVPropfindRequest: ", domve);
            throw new RuntimeException(domve);
        }
        return XMLUtils.toPrettyXML(doc);
    }

    //
    // recycle reportmethods
    //
    private Hashtable<String, CalDAVResponse> responseHashtable = null;
    private static Map<QName, Error> errorMap = null;
    private Error error = null;

    public enum ErrorType {
        PRECONDITION, POSTCONDITON
    }

    /**
     * Precondtions and Postconditions
     * @author bobbyrullo
     *
     */
    public enum Error {
        SUPPORTED_CALENDAR_DATA(ErrorType.PRECONDITION, NS_CALDAV, "supported-calendar-data"), VALID_FILTER(
                ErrorType.PRECONDITION, NS_CALDAV, "valid-filter"), NUMBER_OF_MATCHES_WITHIN_LIMITS(
                        ErrorType.POSTCONDITON, NS_DAV, "number-of-matches-within-limits");

        private final ErrorType errorType;
        private final String namespaceURI;
        private final String elementName;

        Error(ErrorType errorType, String namespaceURI, String elementName) {
            this.errorType = errorType;
            this.namespaceURI = namespaceURI;
            this.elementName = elementName;
        }

        public ErrorType errorType() {
            return errorType;
        }

        public String namespaceURI() {
            return namespaceURI;
        }

        public String elementName() {
            return elementName;
        }

    }

    static {
        errorMap = new HashMap<QName, Error>();
        for (Error error : Error.values()) {
            errorMap.put(new QName(error.namespaceURI(), error.elementName()), error);
        }
    }

    public static final String ELEMENT_ERROR = "error";

    /**
     * Return an enumeration containing the responses.
     *
     * @return An enumeration containing objects implementing the
     * ResponseEntity interface
     */
    public Enumeration<CalDAVResponse> getResponses() {
        return getResponseHashtable().elements();
    }

    public Error getError() {
        return error;
    }

    /**
     * return the AclProperty relative to a given url
     * @author rpolli
     * @param urlPath
     * @return AclProperty xml response or null if missing
     */
    public AclProperty getAcl(String urlPath) {
        return (AclProperty) getWebDavProperty(urlPath, CalDAVConstants.QNAME_ACL);
    }

    public Ace[] getAces(String urlPath) throws CalDAV4JException {
        int status = -1;
        AclProperty acls = (AclProperty) getWebDavProperty(urlPath, CalDAVConstants.QNAME_ACL);
        if (acls != null) {
            status = acls.getStatusCode();
            switch (status) {
            case CaldavStatus.SC_OK:
                return acls.getAces();
            default:
                break;
            }
        }
        throw new CalDAV4JException("Error gettinh ACLs. PROPFIND status is: " + status);
    }

    public String getCalendarDescription(String urlPath) {
        Property p = getWebDavProperty(urlPath, CalDAVConstants.QNAME_CALENDAR_DESCRIPTION);
        if (p != null) {
            return p.getPropertyAsString();
        } else {
            return "";
        }
    }

    public String getDisplayName(String urlPath) {
        Property p = getWebDavProperty(urlPath, CalDAVConstants.QNAME_DISPLAYNAME);
        if (p != null) {
            return p.getPropertyAsString();
        } else {
            return "";
        }
    }

    /**
     * 
     * @param caldavProperty can be CaldavConstants.QNAME_XXXXX
     * @return
     * 
     * TODO check equivalent URIs (eg. duplicate|trailing "/")
     */
    private Property getWebDavProperty(String urlPath, QName property) {
        CalDAVResponse response = getResponseHashtable().get(urlPath);
        if (response != null) {
            return response.getProperty(property);
        } else {
            response = getResponseHashtable().get(urlPath + "/");
        }
        if (response != null) {
            return response.getProperty(property);
        } else {
            log.warn("Can't find object at: " + urlPath);
            return null;
        }

    }

    protected Hashtable<String, CalDAVResponse> getResponseHashtable() {
        checkUsed();
        if (responseHashtable == null) {
            initHashtable();
        }
        return responseHashtable;
    }

    protected Vector<String> getResponseURLs() {
        checkUsed();
        if (responseHashtable == null) {
            initHashtable();
        }
        return responseURLs;
    }

    /**
     * A lot of this code had to be copied from the parent XMLResponseMethodBase, since it's 
     * initHashtable doesn't allow for new types of Responses.
     * 
     * Of course, the same mistake is being made here, so it is a TODO to fix that
     *
     */
    @SuppressWarnings("unchecked")
    private void initHashtable() {
        responseHashtable = new Hashtable<String, CalDAVResponse>();
        responseURLs = new Vector<String>();
        // Also accept OK sent by buggy servers in reply to a PROPFIND
        // or REPORT (Xythos, Catacomb, ...?).
        int statusCode = getStatusCode();
        if (statusCode == WebdavStatus.SC_MULTI_STATUS) {

            Document rdoc = getResponseDocument();

            NodeList list = null;
            if (rdoc != null) {
                Element multistatus = getResponseDocument().getDocumentElement();
                list = multistatus.getChildNodes();
            }

            if (list != null) {
                for (int i = 0; i < list.getLength(); i++) {
                    try {
                        Element child = (Element) list.item(i);
                        String name = DOMUtils.getElementLocalName(child);
                        String namespace = DOMUtils.getElementNamespaceURI(child);
                        if (Response.TAG_NAME.equals(name) && "DAV:".equals(namespace)) {
                            CalDAVResponse response = new CalDAVResponse(child);
                            String href = response.getHref();
                            responseHashtable.put(href, response);
                            responseURLs.add(href);
                        }
                    } catch (ClassCastException e) {
                    }
                }
            }
        } else if (statusCode == WebdavStatus.SC_CONFLICT || statusCode == WebdavStatus.SC_FORBIDDEN) {
            Document rdoc = getResponseDocument();
            Element errorElement = rdoc.getDocumentElement();

            // first make sure that the element is actually an error.
            if (!errorElement.getNamespaceURI().equals(NS_DAV)
                    || !errorElement.getLocalName().equals(ELEMENT_ERROR)) {
                Node condition = errorElement.getChildNodes().item(0);
                error = errorMap.get(new QName(condition.getNamespaceURI(), condition.getLocalName()));
            }
        }
    }

}