Package org.apache.webdav.lib.methods

Source Code of org.apache.webdav.lib.methods.XMLResponseMethodBase$OptionsResponse

/*
* $Header: /home/cvs/jakarta-slide/webdavclient/clientlib/src/java/org/apache/webdav/lib/methods/XMLResponseMethodBase.java,v 1.2.2.3 2004/04/09 15:45:47 ib Exp $
* $Revision: 1.2.2.3 $
* $Date: 2004/04/09 15:45:47 $
*
* ====================================================================
*
* 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.webdav.lib.methods;

import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.apache.commons.httpclient.HttpConnection;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpState;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.util.DOMUtils;
import org.apache.util.DOMWriter;
import org.apache.util.WebdavStatus;
import org.apache.webdav.lib.BaseProperty;
import org.apache.webdav.lib.Property;
import org.apache.webdav.lib.ResponseEntity;
import org.apache.webdav.lib.properties.AclProperty;
import org.apache.webdav.lib.properties.CurrentUserPrivilegeSetProperty;
import org.apache.webdav.lib.properties.GetLastModifiedProperty;
import org.apache.webdav.lib.properties.LockDiscoveryProperty;
import org.apache.webdav.lib.properties.OwnerProperty;
import org.apache.webdav.lib.properties.PrincipalCollectionSetProperty;
import org.apache.webdav.lib.properties.ResourceTypeProperty;
import org.apache.webdav.lib.properties.SupportedLockProperty;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;

/**
* Utility class for XML response parsing.
*
* @author B.C. Holmes
* @author Remy Maucherat
* @author Dirk Verbeeck
*/
public abstract class XMLResponseMethodBase
    extends HttpRequestBodyMethodBase {

    //static private final Log log = LogSource.getInstance(XMLResponseMethodBase.class.getName());

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


    /**
     * Method constructor.
     */
    public XMLResponseMethodBase() {
        super();
    }


    /**
     * Method constructor.
     *
     * @param uri the URI to request
     */
    public XMLResponseMethodBase(String uri) {
        super(uri);
    }


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


    /**
     * Response document.
     */
    private Document responseDocument = null;


    /**
     * Document builder.
     */
    protected DocumentBuilder builder = null;


    /**
     * Hashtable of response nodes
     */
    private Hashtable responseHashtable = null;

    /**
     * Vector of response nodes, to keep track of insertion order
     * FIXME: the above Hashtable and this Vector should be ported
     * to plain Collections
     */
    protected Vector responseURLs = null;


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


    /**
     * Response document getter.
     *
     * @return Document response document
     */
    public Document getResponseDocument() {
        return this.responseDocument;
    }


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

    /*protected HttpState getState() {
        return state;
    }*/


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

    /**
     * Debug property setter.
     *
     * @param int Debug
     */
/*
    public void setDebug(int debug) {
        super.setDebug(debug);
        log.setLevel(debug);
    }
*/


    /**
     * Reset the State of the class to its initial state, so that it can be
     * used again.
     */
    public void recycle() {
        super.recycle();
        responseHashtable = null;
        responseURLs = null;
    }

    protected void readResponseBody(HttpState state, HttpConnection conn)
    throws IOException, HttpException {

        super.readResponseBody(state, conn);
        InputStream inStream = getResponseBodyAsStream();
        if (inStream != null) {
            parseResponse(inStream, state, conn);
            inStream.close();
        }
    }

    /**
     * Return the length (in bytes) of my request body, suitable for use in a
     * <tt>Content-Length</tt> header.
     *
     * <p>
     * Return <tt>-1</tt> when the content-length is unknown.
     * </p>
     *
     * <p>
     * This implementation returns <tt>0</tt>, indicating that the request has
     * no body.
     * </p>
     *
     * @return <tt>0</tt>, indicating that the request has no body.
     */
    protected int getRequestContentLength() {
        if (!isRequestContentAlreadySet()) {
            String contents = generateRequestBody();
            // be nice - allow overriding functions to return null or empty
            // strings for no content.
            if (contents == null)
                contents = "";

            setRequestBody(contents);
        }

        return super.getRequestContentLength();
    }

    /**
     * DAV requests that contain a body must override this function to
     * generate that body.
     *
     * <p>The default behavior simply returns an empty body.</p>
     */
    protected String generateRequestBody() {
        return "";
    }

    /**
     * Write the request body to the given {@link HttpConnection}.
     *
     * <p>
     * This implementation writes any computed body and returns <tt>true</tt>.
     * </p>
     *
     * @param state the client state
     * @param conn the connection to write to
     *
     * @return <tt>true</tt>
     * @throws IOException when i/o errors occur reading the response
     * @throws HttpException when a protocol error occurs or state is invalid
     */
    protected boolean writeRequestBody(HttpState state, HttpConnection conn)
            throws IOException, HttpException {

        if (getRequestContentLength() > 0) {
            return super.writeRequestBody(state, conn);
        }
        return true;
    }

    /**
     * Parse response.
     *
     * @param input Input stream
     */
    public void parseResponse(InputStream input, HttpState state, HttpConnection conn)
        throws IOException, HttpException {
        // Also accept OK sent by buggy servers in reply to a PROPFIND or
        // REPORT (Xythos, Catacomb, ...?).
        if (getStatusCode() == WebdavStatus.SC_MULTI_STATUS
            || (this instanceof PropFindMethod || this instanceof ReportMethod)
                && getStatusCode() == HttpStatus.SC_OK) {
            try {
                parseXMLResponse(input);
            } catch (IOException e) {
                // FIX ME:  provide a way to deliver non xml data
            }
        }
    }


    protected void parseXMLResponse(InputStream input)
        throws IOException, HttpException {

        if (builder == null) {
            try {
                DocumentBuilderFactory factory =
                    DocumentBuilderFactory.newInstance();
                factory.setNamespaceAware(true);
                builder = factory.newDocumentBuilder();
            } catch (ParserConfigurationException e) {
                throw new HttpException
                    ("XML Parser Configuration error: " + e.getMessage());
            }
        }

        try {

            responseDocument = builder.parse(new InputSource(input));

        } catch (Exception e) {
            throw new IOException
                ("XML parsing error; response stream is not valid XML: "
                 + e.getMessage());
        }


        // init the response table to display the responses during debugging
        /*if (debug > 10) {
            //if (log.isDebugEnabled()) {
            initResponseHashtable();
        }*/

    }


    protected Hashtable getResponseHashtable() {
        checkUsed();
        if (responseHashtable == null) {
            initResponseHashtable();
        }
        return responseHashtable;
    }

    protected Vector getResponseURLs() {
        checkUsed();
        if (responseHashtable == null) {
            initResponseHashtable();
        }
        return responseURLs;
    }

    private synchronized void initResponseHashtable() {
        if (responseHashtable == null) {

            responseHashtable = new Hashtable();
            responseURLs = new Vector();
            int status = getStatusLine().getStatusCode();

            // Also accept OK sent by buggy servers in reply to a PROPFIND
            // or REPORT (Xythos, Catacomb, ...?).
            if (status == WebdavStatus.SC_MULTI_STATUS
                || (this instanceof PropFindMethod
                    || this instanceof ReportMethod)
                    && status == HttpStatus.SC_OK) {

                Element multistatus =
                    getResponseDocument().getDocumentElement();
                NodeList 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)) {
                                Response response =
                                    new ResponseWithinMultistatus(child);
                                responseHashtable.put(response.getHref(),
                                                      response);
                                responseURLs.add(response.getHref());
                                /*if (debug>10)
                                    System.out.println(response); */
                                //log.debug(response);
                            }
                        } catch (ClassCastException e) {
                        }
                    }
                }
            } else if (responseDocument != null) {
                Response response = new SingleResponse(responseDocument,
                    getPath(), status);
                responseHashtable.put(response.getHref(), response);
                responseURLs.add(response.getHref());
                /*if (debug>10)
                    System.out.println(response); */
                //log.debug(response);
            }
        }
    }


    /**
     * This method creates a property implementation from an element.
     * It treats known properties (i.e., the DAV properties) specially.
     * These properties are instantiated as an implementation from the
     * <code>org.apache.webdav.lib.properties</code> package.
     */
    protected static Property convertElementToProperty(
        Response response, Element element) {

        Property property = null;
        String namespace = DOMUtils.getElementNamespaceURI(element);

        // handle DAV properties specially
        if (namespace != null && namespace.equals("DAV:")) {

            String localName = DOMUtils.getElementLocalName(element);

            if (ResourceTypeProperty.TAG_NAME.equals(localName)) {
                property = new ResourceTypeProperty(response, element);
            } else if (GetLastModifiedProperty.TAG_NAME.equals(localName)) {
                property = new GetLastModifiedProperty(response, element);
            } else if (CurrentUserPrivilegeSetProperty.TAG_NAME.equals
                       (localName)) {
                property =
                    new CurrentUserPrivilegeSetProperty(response, element);
            } else if (LockDiscoveryProperty.TAG_NAME.equals(localName)) {
                property = new LockDiscoveryProperty(response, element);
            } else if (SupportedLockProperty.TAG_NAME.equals(localName)) {
                property = new SupportedLockProperty(response, element);
            } else if (AclProperty.TAG_NAME.equals(localName)) {
                property = new AclProperty(response, element);
            } else if (PrincipalCollectionSetProperty.TAG_NAME.equals(localName)) {
                property = new PrincipalCollectionSetProperty(response, element);
            } else if (OwnerProperty.TAG_NAME.equals(localName)) {
                property = new OwnerProperty(response, element);
            }
        }

        if (property == null) {
            property = new BaseProperty(response, element);
        }

        return property;
    }


    // ---------------------------------------------------------- Inner Classes


    /**
     * An abstract class that models a DAV:response.
     */
    public abstract class Response implements ResponseEntity {

        protected Node node = null;

        Response(Node node) {
            this.node = node;
        }

        public static final String TAG_NAME = "response";
        public abstract int getStatusCode();
        public abstract String getHref();

        public Enumeration getHistories(){
            Vector result = new Vector();
            return result.elements();
        }
        public Enumeration getWorkspaces(){
            Vector result = new Vector();
            return result.elements();
        }
        public Enumeration getProperties() {
            NodeList list =
                DOMUtils.getElementsByTagNameNS(node, "prop", "DAV:");
            Vector vector = new Vector();
            for (int i = 0; list != null && i < list.getLength(); i++ ) {
                Element element = (Element) list.item(i);
                NodeList children = element.getChildNodes();
                for (int j = 0; children != null && j < children.getLength();
                     j++) {
                    try {
                        Element child = (Element) children.item(j);
                        vector.addElement(XMLResponseMethodBase.
                            convertElementToProperty(this, child));
                    } catch (ClassCastException e) {
                    }
                }
            }
            return vector.elements();
        }

        public String toString () {
            StringWriter tmp = new StringWriter();
            DOMWriter domWriter = new DOMWriter(tmp, true);
            domWriter.print(node);
            return tmp.getBuffer().toString();
        }
    }


    /**
     * A class that models the DAV:response element within a multistatus.
     */
    class ResponseWithinMultistatus extends Response {

        public ResponseWithinMultistatus(Element element) {
            super(element);
        }

        public int getStatusCode() {
            // The status element for the response can be inside the propstat element
            // or directly inside the response element.

            //  <multistatus xmlns=\DAV:\>
            //    <response>
            //      <href>/slide/files/</href>
            //      <propstat>
            //        <prop><displayname>files</displayname></prop>
            //        <status>HTTP/1.1 200 OK</status>
            //      </propstat>
            //    </response>
            //  </multistatus>
            Element propstat = getFirstElement("DAV:", "propstat");
            if (propstat != null ) {
                Element status = DOMUtils.getFirstElement(propstat,"DAV:", "status");
                if (status != null) {
                    return DOMUtils.parseStatus(DOMUtils.getTextValue(status));
                }
            }

            //  <multistatus xmlns=\DAV:\>
            //    <response>
            //      <href>/slide/files/</href>
            //      <href>/slide/files/a</href>
            //      <status>HTTP/1.1 200 OK</status>
            //    </response>
            //  </multistatus>
            Element status = getFirstElement("DAV:", "status");
            if (status != null) {
                return DOMUtils.parseStatus(DOMUtils.getTextValue(status));
            }

            return -1;
        }

        public String getHref() {
            Element href = getFirstElement("DAV:", "href");
            if (href != null) {
                return DOMUtils.getTextValue(href);
            } else {
                return "";
            }

        }

        protected Element getFirstElement(String namespace, String name) {
            return DOMUtils.getFirstElement(this.node, namespace, name);
        }
    }

    class SingleResponse extends Response {

        private int statusCode = -1;
        private String href = null;

        SingleResponse(Document document, String href, int statusCode) {
            super(document);
            this.statusCode = statusCode;
            this.href = href;
        }

        public int getStatusCode() {
            return this.statusCode;
        }

        public String getHref() {
            return this.href;
        }
    }

        class OptionsResponse extends SingleResponse{

            OptionsResponse(Document document, String href, int statusCode) {
                super(document, href, statusCode);

            }


            public Enumeration getWorkspaces(){


                Node root = responseDocument.cloneNode(true).getFirstChild();
                //System.out.println("Rootnode ws: "+ root.getNodeName());

                String sPrefix = root.getPrefix();
                Vector result = new Vector();

                Node child = root.getFirstChild();
                while (child!=null && !child.getNodeName().equalsIgnoreCase(sPrefix+":workspace-collection-set")){
                    child = child.getNextSibling();
                }

                if (child!=null && child.getNodeName().equalsIgnoreCase(sPrefix+":workspace-collection-set")){
                    child = child.getFirstChild();
                    while (child!=null){
                        result.add(child.getFirstChild().getNodeValue());
                        child = child.getNextSibling();
                    }
                }

                return result.elements();
            }

            public Enumeration getHistories(){
                Node root = responseDocument.cloneNode(true).getFirstChild();
                //System.out.println("Rootnode vh : " + root.getNodeName());

                String sPrefix = root.getPrefix();
                Vector result = new Vector();

                //System.out.println("Prefix : " + sPrefix);

                Node child = root.getFirstChild();
                while (child!=null && !child.getNodeName().equalsIgnoreCase(sPrefix+":version-history-collection-set")){
                    child = child.getNextSibling();
                }

                if (child!=null && child.getNodeName().equalsIgnoreCase(sPrefix+":version-history-collection-set")){
                    child = child.getFirstChild();
                    while (child!=null){
                        result.add(child.getFirstChild().getNodeValue());
                        child = child.getNextSibling();
                    }
                }

                return result.elements();
            }

        }
        protected void setDocument(Document doc){
            responseDocument = doc;
        }
        protected void setResponseHashtable(Hashtable h){
            responseHashtable = h;
        }
}

TOP

Related Classes of org.apache.webdav.lib.methods.XMLResponseMethodBase$OptionsResponse

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.