Hm,

the code contains some ugly parts, I have to say.

I'm not sure how exactly this is supposed to work, because JCR doesn't have an XML property type. Are you trying to map this to child nodes, or are you trying to persist this as a JCR string property?

BR, Julian



Angela Schreiber wrote:
hi roland

are you sure, it's not simply a bug in the dav-library?

assuming your client sends a valid and well-formed
PROPPATCH body, i'd say that it should simply work
without you having to create patches. and if it doesn't
there might something wrong in the library.

that's what i would prefer to know first.
am i missing something?
angela

Roland Porath wrote:
I started a discussion about properties with xml-values on users.
Seems I got a patch to do just that.
Just thought I'd send it to the dev list. Maybe somebody finds it
interesting, maybe somebody finds a flaw in the code or the basic
assumptions.

Seems like there were two separate problems:
1. when trying to set the property WebdavRequestImpl.parsePropPatchRequest
did not recognise a property value as being xml
To patch that without having to patch the jars I created my own servlet that
instatiates my new implementation of WebdavRequest. (ExariWebdavRequest)

2. on propget the html encoding in the serialisation did some damage to my beloved xml. (especially < and > turned into something scary, you know the
problem)
The fix was to create my own WebdavProperty implementation
(ExariWebdavProperty)

I apologise for the somewhat jingoistic terminology.

There's one snag however. Like I said I tried to keep the patch self
contained but currently I need to patch DavResourceImp.setProperty to
instantiate my property type instead of the default one. Any ideas how that
could be done better?

Can you find anything that might cause trouble in my code? All my tests seem to work fine but I can see my old mate Confirmation Bias lurking somewhere
in the corner.

Here comes the code.

Feedback and questions are more than welcome

Cheers

Roland

CUT HERE +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

/*
 * 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.
 */
package org.apache.jackrabbit.webdav.property;

import java.io.IOException;
import java.io.StringReader;
import java.util.List;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.FactoryConfigurationError;
import javax.xml.parsers.ParserConfigurationException;

import org.apache.jackrabbit.webdav.xml.DomUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

/**
 * <code>DefaultDavProperty</code>...
 */
public class ExariWebdavProperty extends AbstractDavProperty {

    private static Logger log =
LoggerFactory.getLogger(ExariWebdavProperty.class);
        protected Node node = null;

    /**
     * the value of the property
     */
    private final Object value;

    protected boolean isXML;

    /**
     * instantiate a Property from a Node
     * if this ctor is called we know that it is a property containing
xml
     * @param node
     */
    private ExariWebdavProperty(Node node)
    {
        this(DavPropertyName.createFromXml((Element)node),
node.getNodeValue(), false);
        this.node = node;         this.isXML = true;
    }
   /**
     * Creates a new WebDAV property with the given
<code>DavPropertyName</code>
* and value. If the property is meant to be protected the 'isProtected'
     * flag must be set to true.
     *
     * @param name the name of the property
     * @param value the value of the property
     * @param isProtected A value of true, defines this property to be
protected.
     * It will not be returned in a [EMAIL PROTECTED]
org.apache.jackrabbit.webdav.DavConstants#PROPFIND_ALL_PROP DAV:allprop}
* PROPFIND request and cannot be set/removed with a PROPPATCH request.
     */
private ExariWebdavProperty(DavPropertyName name, Object value, boolean
isProtected)     {
        super(name, isProtected);
        this.value = value;
    }

    /**
     * Creates a new non- protected WebDAV property with the given
     * <code>DavPropertyName</code> and value.
     *
     * @param name the name of the property
     * @param value the value of the property
     */
    public ExariWebdavProperty(DavPropertyName name, Object value)     {
        this(name, value, false);
        try
        {
            Document doc =
DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
            node = DomUtil.createElement(doc, name.getName(), null);
Node valueNode = DocumentBuilderFactory.newInstance().newDocumentBuilder().
                    parse(new InputSource(new
StringReader((String) value))).getFirstChild();
            node.appendChild(doc.importNode(valueNode, true));
            isXML = true;
        }         catch (SAXException e)
        {
            //this is quite ugly; we're using  the exception to
determine if the content is xml
            //the exeption produces consoleoutput
            isXML= false;
        }         catch (IOException e)
        {
            e.printStackTrace();
        }         catch (ParserConfigurationException e)
        {
            e.printStackTrace();
        }         catch (FactoryConfigurationError e)
        {

            e.printStackTrace();
        }
        if (log.isDebugEnabled()) log.debug("created: name=" +
name.getName() + ", value=" + value + ", isXML=" + isXML);
    }

    /**
     * from AbstractDavProperty
     * @return the value of this property
     */
    public Object getValue()     {
        return value;
    }

    /**
* Create a new <code>DefaultDavProperty</code> instance from the given
Xml
     * element. Name and namespace of the element are building the [EMAIL 
PROTECTED]
DavPropertyName},
* while the element's content forms the property value. The following
logic
     * is applied:
     * <pre>
     * - empty Element           -&gt; <code>null</code> value
     * - single Text content     -&gt; <code>String</code> value
     * - single non-Text content -&gt; Element.getContent(0) is used as
value
     * - other: List obtained from Element.getContent() is used as value
     * </pre>
     *
     * @param propertyElement
     * @return
     */
public static ExariWebdavProperty createFromXml(Element propertyElement)

    {
        if (propertyElement == null)         {
            throw new IllegalArgumentException("Cannot create a new
DavProperty from a 'null' element.");
        }
        DavPropertyName name =
DavPropertyName.createFromXml(propertyElement);
        Object value;
        if (!DomUtil.hasContent(propertyElement)) {
            value = null;
        }  else {
            List c = DomUtil.getContent(propertyElement);
            value = getXmlPropertyValue((Node)c.get(0));
        }
        return new ExariWebdavProperty(name, value, false);
    }
        private static Object getXmlPropertyValue(Node node)
    {
        if (node.getNodeName().equals("#text"))
        {
            return node.getNodeValue();
        }
        else
        {
            return new ExariWebdavProperty(node);
        }
    }
public Element toXml(Document document)
    {
        if (isXML)
        {
            return (Element) document.importNode(node, true);
        }
        else
        {
            Element property =
document.createElement(getName().getName());
            Text propValue =
document.createTextNode((String)value);
            property.appendChild(propValue);
            return property;
        }
    }
public String toString()
    {
        return toXMLString(node);
    }
private String toXMLString(Node node)
    {
        String result =  "";
        NodeList kids = node.getChildNodes();
        if (node.getNodeName().equals("#text"))
        {
            result = result + node.getNodeValue();
        }
        else
        {
            result = result + "<" + node.getNodeName() + ">";
            for (int kidCount=0; kidCount<kids.getLength();
kidCount++)
            {
                result = result +
toXMLString(kids.item(kidCount));
            }
            result = result + "</" + node.getNodeName() + ">";
        }
        return result;
    }
}








Reply via email to