jackrabbit-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Roland Porath" <rol...@exari.com>
Subject properties with XML-Values; patch
Date Wed, 13 Feb 2008 06:41:23 GMT
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 {@link
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 {@link
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;
	}
}






Mime
View raw message