You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by an...@apache.org on 2008/08/20 15:15:04 UTC

svn commit: r687317 - in /jackrabbit/sandbox/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav: ExceptionConverter.java ItemInfoImpl.java PropertyInfoImpl.java RepositoryServiceImpl.java

Author: angela
Date: Wed Aug 20 06:15:03 2008
New Revision: 687317

URL: http://svn.apache.org/viewvc?rev=687317&view=rev
Log:
JCR-1300: spi2dav Improve performance for large binary properties

Modified:
    jackrabbit/sandbox/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/ExceptionConverter.java
    jackrabbit/sandbox/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/ItemInfoImpl.java
    jackrabbit/sandbox/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/PropertyInfoImpl.java
    jackrabbit/sandbox/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/RepositoryServiceImpl.java

Modified: jackrabbit/sandbox/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/ExceptionConverter.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/ExceptionConverter.java?rev=687317&r1=687316&r2=687317&view=diff
==============================================================================
--- jackrabbit/sandbox/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/ExceptionConverter.java (original)
+++ jackrabbit/sandbox/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/ExceptionConverter.java Wed Aug 20 06:15:03 2008
@@ -45,11 +45,11 @@
     // avoid instanciation
     private ExceptionConverter() {}
 
-    static RepositoryException generate(DavException davExc) throws RepositoryException {
+    public static RepositoryException generate(DavException davExc) throws RepositoryException {
         return generate(davExc, null);
     }
 
-    static RepositoryException generate(DavException davExc, DavMethod method) throws RepositoryException {
+    public static RepositoryException generate(DavException davExc, DavMethod method) throws RepositoryException {
         String msg = davExc.getMessage();
         if (davExc.hasErrorCondition()) {
             try {

Modified: jackrabbit/sandbox/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/ItemInfoImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/ItemInfoImpl.java?rev=687317&r1=687316&r2=687317&view=diff
==============================================================================
--- jackrabbit/sandbox/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/ItemInfoImpl.java (original)
+++ jackrabbit/sandbox/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/ItemInfoImpl.java Wed Aug 20 06:15:03 2008
@@ -17,7 +17,6 @@
 package org.apache.jackrabbit.spi2dav;
 
 import org.apache.jackrabbit.spi.ItemInfo;
-import org.apache.jackrabbit.spi.NodeId;
 import org.apache.jackrabbit.spi.Path;
 import org.apache.jackrabbit.webdav.property.DavPropertySet;
 import org.apache.jackrabbit.webdav.property.DavProperty;
@@ -38,13 +37,16 @@
 
     private final Path path;
 
-    public ItemInfoImpl(DavPropertySet propSet, NamePathResolver resolver)
+    ItemInfoImpl(Path path) {
+        this.path = path;
+    }
+
+    ItemInfoImpl(DavPropertySet propSet, NamePathResolver resolver)
             throws NameException, NamespaceException {
 
         DavProperty pathProp = propSet.get(ItemResourceConstants.JCR_PATH);
         String jcrPath = pathProp.getValue().toString();
         path = resolver.getQPath(jcrPath);
-
     }
 
     /**

Modified: jackrabbit/sandbox/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/PropertyInfoImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/PropertyInfoImpl.java?rev=687317&r1=687316&r2=687317&view=diff
==============================================================================
--- jackrabbit/sandbox/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/PropertyInfoImpl.java (original)
+++ jackrabbit/sandbox/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/PropertyInfoImpl.java Wed Aug 20 06:15:03 2008
@@ -16,6 +16,7 @@
  */
 package org.apache.jackrabbit.spi2dav;
 
+import org.apache.jackrabbit.spi.Path;
 import org.apache.jackrabbit.spi.PropertyId;
 import org.apache.jackrabbit.spi.PropertyInfo;
 import org.apache.jackrabbit.spi.QValue;
@@ -27,8 +28,6 @@
 import org.apache.jackrabbit.webdav.jcr.ItemResourceConstants;
 import org.apache.jackrabbit.webdav.jcr.property.ValuesProperty;
 import org.apache.jackrabbit.webdav.property.DavPropertySet;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 import javax.jcr.PropertyType;
 import javax.jcr.RepositoryException;
@@ -41,14 +40,21 @@
  */
 public class PropertyInfoImpl extends ItemInfoImpl implements PropertyInfo {
 
-    private static Logger log = LoggerFactory.getLogger(PropertyInfoImpl.class);
-
     private final PropertyId id;
 
     private int type;
     private boolean isMultiValued;
     private QValue[] values;
 
+    public PropertyInfoImpl(PropertyId id, Path path, int type,
+                            boolean isMultiValued, QValue[] values) {
+        super(path);
+        this.id = id;
+        this.type = type;
+        this.isMultiValued = isMultiValued;
+        this.values = values;
+    }
+
     public PropertyInfoImpl(PropertyId id, DavPropertySet propSet,
                             NamePathResolver resolver, ValueFactory valueFactory,
                             QValueFactory qValueFactory)

Modified: jackrabbit/sandbox/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/RepositoryServiceImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/RepositoryServiceImpl.java?rev=687317&r1=687316&r2=687317&view=diff
==============================================================================
--- jackrabbit/sandbox/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/RepositoryServiceImpl.java (original)
+++ jackrabbit/sandbox/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/RepositoryServiceImpl.java Wed Aug 20 06:15:03 2008
@@ -24,19 +24,10 @@
 import org.apache.commons.httpclient.URI;
 import org.apache.commons.httpclient.URIException;
 import org.apache.commons.httpclient.auth.AuthScope;
+import org.apache.commons.httpclient.methods.GetMethod;
 import org.apache.commons.httpclient.methods.InputStreamRequestEntity;
-import org.apache.commons.httpclient.params.HttpConnectionManagerParams;
-import org.apache.jackrabbit.spi.commons.conversion.IllegalNameException;
-import org.apache.jackrabbit.spi.commons.conversion.MalformedPathException;
-import org.apache.jackrabbit.spi.commons.conversion.NameException;
-import org.apache.jackrabbit.spi.commons.conversion.NamePathResolver;
-import org.apache.jackrabbit.spi.commons.conversion.NameResolver;
-import org.apache.jackrabbit.spi.commons.conversion.ParsingNameResolver;
-import org.apache.jackrabbit.spi.commons.conversion.ParsingPathResolver;
-import org.apache.jackrabbit.spi.commons.conversion.PathResolver;
-import org.apache.jackrabbit.spi.commons.name.NameConstants;
-import org.apache.jackrabbit.spi.commons.namespace.AbstractNamespaceResolver;
-import org.apache.jackrabbit.spi.commons.namespace.NamespaceResolver;
+import org.apache.commons.httpclient.methods.RequestEntity;
+import org.apache.commons.httpclient.methods.StringRequestEntity;
 import org.apache.jackrabbit.spi.Batch;
 import org.apache.jackrabbit.spi.ChildInfo;
 import org.apache.jackrabbit.spi.Event;
@@ -66,10 +57,22 @@
 import org.apache.jackrabbit.spi.commons.ChildInfoImpl;
 import org.apache.jackrabbit.spi.commons.EventBundleImpl;
 import org.apache.jackrabbit.spi.commons.EventFilterImpl;
-import org.apache.jackrabbit.util.Text;
-import org.apache.jackrabbit.uuid.UUID;
+import org.apache.jackrabbit.spi.commons.conversion.IllegalNameException;
+import org.apache.jackrabbit.spi.commons.conversion.MalformedPathException;
+import org.apache.jackrabbit.spi.commons.conversion.NameException;
+import org.apache.jackrabbit.spi.commons.conversion.NamePathResolver;
+import org.apache.jackrabbit.spi.commons.conversion.NameResolver;
+import org.apache.jackrabbit.spi.commons.conversion.ParsingNameResolver;
+import org.apache.jackrabbit.spi.commons.conversion.ParsingPathResolver;
+import org.apache.jackrabbit.spi.commons.conversion.PathResolver;
+import org.apache.jackrabbit.spi.commons.name.NameConstants;
+import org.apache.jackrabbit.spi.commons.namespace.AbstractNamespaceResolver;
+import org.apache.jackrabbit.spi.commons.namespace.NamespaceResolver;
+import org.apache.jackrabbit.spi.commons.value.QValueValue;
 import org.apache.jackrabbit.spi.commons.value.ValueFactoryQImpl;
 import org.apache.jackrabbit.spi.commons.value.ValueFormat;
+import org.apache.jackrabbit.util.Text;
+import org.apache.jackrabbit.uuid.UUID;
 import org.apache.jackrabbit.webdav.DavConstants;
 import org.apache.jackrabbit.webdav.DavException;
 import org.apache.jackrabbit.webdav.DavMethods;
@@ -102,6 +105,7 @@
 import org.apache.jackrabbit.webdav.header.CodedUrlHeader;
 import org.apache.jackrabbit.webdav.header.IfHeader;
 import org.apache.jackrabbit.webdav.jcr.ItemResourceConstants;
+import org.apache.jackrabbit.webdav.jcr.JcrValueType;
 import org.apache.jackrabbit.webdav.jcr.nodetype.NodeTypeConstants;
 import org.apache.jackrabbit.webdav.jcr.nodetype.NodeTypeProperty;
 import org.apache.jackrabbit.webdav.jcr.observation.SubscriptionImpl;
@@ -125,6 +129,7 @@
 import org.apache.jackrabbit.webdav.property.DavPropertyName;
 import org.apache.jackrabbit.webdav.property.DavPropertyNameSet;
 import org.apache.jackrabbit.webdav.property.DavPropertySet;
+import org.apache.jackrabbit.webdav.property.DefaultDavProperty;
 import org.apache.jackrabbit.webdav.property.HrefProperty;
 import org.apache.jackrabbit.webdav.search.SearchConstants;
 import org.apache.jackrabbit.webdav.search.SearchInfo;
@@ -146,6 +151,7 @@
 import org.slf4j.LoggerFactory;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
+import org.xml.sax.SAXException;
 
 import javax.jcr.AccessDeniedException;
 import javax.jcr.Credentials;
@@ -169,9 +175,11 @@
 import javax.jcr.nodetype.NoSuchNodeTypeException;
 import javax.jcr.query.InvalidQueryException;
 import javax.jcr.version.VersionException;
+import javax.xml.parsers.DocumentBuilder;
 import javax.xml.parsers.ParserConfigurationException;
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
@@ -255,11 +263,7 @@
         } catch (URIException e) {
             throw new RepositoryException(e);
         }
-
         connectionManager = new MultiThreadedHttpConnectionManager();
-        HttpConnectionManagerParams params = new HttpConnectionManagerParams();
-        params.setMaxConnectionsPerHost(hostConfig, 20);
-        connectionManager.setParams(params);
     }
 
     private static void checkSessionInfo(SessionInfo sessionInfo) throws RepositoryException {
@@ -342,7 +346,7 @@
         log.debug("Removed Client " + cl + " for SessionInfo " + sessionInfo);
     }
 
-    private String getItemUri(ItemId itemId, SessionInfo sessionInfo) throws RepositoryException {
+    protected String getItemUri(ItemId itemId, SessionInfo sessionInfo) throws RepositoryException {
         return uriResolver.getItemUri(itemId, sessionInfo.getWorkspaceName(), sessionInfo);
     }
 
@@ -800,7 +804,11 @@
         // currently: missing 'value/values' property PropertyInfo cannot be built
         // currently: missing prop-names with child-NodeInfo
         List l = new ArrayList();
-        l.add(getNodeInfo(sessionInfo, nodeId));
+        NodeInfo nInfo = getNodeInfo(sessionInfo, nodeId);
+        l.add(nInfo);
+        // at least add propertyInfos for the meta-props already known from the
+        // nodeInfo.
+        l.addAll(buildPropertyInfos(nInfo));
         return l.iterator();
     }
 
@@ -822,6 +830,41 @@
         return nInfo;
     }
 
+    private List buildPropertyInfos(NodeInfo nInfo) throws RepositoryException {
+        List l = new ArrayList(3);
+        NodeId nid = nInfo.getId();
+        Path nPath = nInfo.getPath();
+
+        if (nid.getPath() == null) {
+            PropertyId id = getIdFactory().createPropertyId(nid, NameConstants.JCR_UUID);
+            QValue[] vs = new QValue[] {getQValueFactory().create(nid.getUniqueID(), PropertyType.STRING)};
+            Path p = getPathFactory().create(nPath, NameConstants.JCR_UUID, true);
+            PropertyInfo pi = new PropertyInfoImpl(id, p, PropertyType.STRING, false, vs);
+            l.add(pi);
+        }
+
+        Name pName = NameConstants.JCR_PRIMARYTYPE;
+        QValue[] vs = new QValue[] {getQValueFactory().create(nInfo.getNodetype())};
+        PropertyInfo pi = new PropertyInfoImpl(getIdFactory().createPropertyId(nid, pName),
+                getPathFactory().create(nPath, pName, true), PropertyType.NAME, false, vs);
+        l.add(pi);
+
+        Name[] mixins = nInfo.getMixins();
+        if (mixins.length > 0) {
+            pName = NameConstants.JCR_MIXINTYPES;
+            vs = new QValue[mixins.length];
+            for (int i = 0; i < mixins.length; i++) {
+                vs[i] = getQValueFactory().create(mixins[i]);
+            }
+            pi = new PropertyInfoImpl(getIdFactory().createPropertyId(nid, pName),
+                    getPathFactory().create(nPath, pName, true), PropertyType.NAME,
+                    true, vs);
+            l.add(pi);
+        }
+
+        return l;
+    }
+
     /**
      * @see RepositoryService#getChildInfos(SessionInfo, NodeId)
      */
@@ -884,35 +927,55 @@
      * @see RepositoryService#getPropertyInfo(SessionInfo, PropertyId)
      */
     public PropertyInfo getPropertyInfo(SessionInfo sessionInfo, PropertyId propertyId) throws ItemNotFoundException, RepositoryException {
-        // set of Dav-properties to be retrieved
-        DavPropertyNameSet nameSet = new DavPropertyNameSet();
-        nameSet.add(ItemResourceConstants.JCR_PARENT);
-        nameSet.add(ItemResourceConstants.JCR_NAME);
-        nameSet.add(ItemResourceConstants.JCR_TYPE);
-        nameSet.add(ItemResourceConstants.JCR_VALUE);
-        nameSet.add(ItemResourceConstants.JCR_VALUES);
-        nameSet.add(ItemResourceConstants.JCR_PATH);
-        nameSet.add(DavPropertyName.RESOURCETYPE);
-
-        PropFindMethod method = null;
+        GetMethod method = null;
         try {
             String uri = getItemUri(propertyId, sessionInfo);
-            method = new PropFindMethod(uri, nameSet, DEPTH_0);
-            getClient(sessionInfo).executeMethod(method);
-            method.checkSuccess();
+            method = new GetMethod(uri);
+            HttpClient client = getClient(sessionInfo);
+            client.executeMethod(method);
 
-            MultiStatusResponse[] responses = method.getResponseBodyAsMultiStatus().getResponses();
-            if (responses.length < 1) {
-                throw new ItemNotFoundException("Unable to retrieve the property with id " + propertyId);
+            int status = method.getStatusCode();
+            if (status != DavServletResponse.SC_OK) {
+                throw ExceptionConverter.generate(new DavException(status, method.getStatusText()));
             }
 
-            DavPropertySet propSet = responses[0].getProperties(DavServletResponse.SC_OK);
-            NodeId parentId = getParentId(propSet, sessionInfo);
-            PropertyId id = uriResolver.buildPropertyId(parentId, responses[0], sessionInfo.getWorkspaceName(), getNamePathResolver(sessionInfo));
+            Path path = uriResolver.getQPath(uri, sessionInfo);
+
+            String ct = null;
+            Header hd = method.getResponseHeader(DavConstants.HEADER_CONTENT_TYPE);
+            if (hd != null) {
+                ct = hd.getValue();
+            }
+
+            boolean isMultiValued;
+            QValue[] values;
+            int type = JcrValueType.typeFromContentType(ct);
 
             NamePathResolver resolver = getNamePathResolver(sessionInfo);
-            PropertyInfo pInfo = new PropertyInfoImpl(id, propSet,
-                    resolver, valueFactory, getQValueFactory());
+            if (type != PropertyType.UNDEFINED) {
+                QValue v;
+                if (type == PropertyType.BINARY) {
+                    v = getQValueFactory().create(method.getResponseBodyAsStream());
+                } else {
+                    Value jcrValue = valueFactory.createValue(method.getResponseBodyAsString(), type);
+                    if (jcrValue instanceof QValueValue) {
+                        v = ((QValueValue) jcrValue).getQValue();
+                    } else {
+                        v = ValueFormat.getQValue(jcrValue, resolver, getQValueFactory());
+                    }
+                }
+                values = new QValue[] {v};
+                isMultiValued = false;
+            } else if (ct.startsWith("text/xml")) {
+                // jcr:values property spooled
+                values = getValues(method.getResponseBodyAsStream(), resolver);
+                type = (values.length > 0) ? values[0].getType() : loadType(uri, client);
+                isMultiValued = true;
+            } else {
+                throw new ItemNotFoundException("Unable to retrieve the property with id " + propertyId);
+            }
+
+            PropertyInfo pInfo = new PropertyInfoImpl(propertyId, path, type, isMultiValued, values);
             return pInfo;
         } catch (IOException e) {
             throw new RepositoryException(e);
@@ -927,6 +990,67 @@
         }
     }
 
+    private QValue[] getValues(InputStream response, NamePathResolver resolver) throws RepositoryException {
+        try {
+            DocumentBuilder db = DomUtil.BUILDER_FACTORY.newDocumentBuilder();
+            Document doc = db.parse(response);
+            Element prop = DomUtil.getChildElement(doc, ItemResourceConstants.JCR_VALUES.getName(), ItemResourceConstants.JCR_VALUES.getNamespace());
+            if (prop == null) {
+                // no jcr-values present in the response body -> apparently
+                // not representation of a jcr-property
+                throw new ItemNotFoundException();
+            } else {
+                DavProperty p = DefaultDavProperty.createFromXml(prop);
+                ValuesProperty vp = new ValuesProperty(p, PropertyType.STRING, valueFactory);
+
+                Value[] jcrVs = vp.getJcrValues();
+                QValue[] qvs = new QValue[jcrVs.length];
+                int type = (jcrVs.length > 0) ? jcrVs[0].getType() : PropertyType.STRING;
+
+                for (int i = 0; i < jcrVs.length; i++) {
+                    if (jcrVs[i] instanceof QValueValue) {
+                        qvs[i] = ((QValueValue) jcrVs[i]).getQValue();
+                    } else if (type == PropertyType.BINARY) {
+                        qvs[i] = qValueFactory.create(jcrVs[i].getStream());
+                    } else {
+                        qvs[i] = ValueFormat.getQValue(jcrVs[i], resolver, qValueFactory);
+                    }
+                }
+                return qvs;
+            }
+        } catch (Exception e) {
+            log.error("Internal Error: ", e);
+            throw new RepositoryException(e);
+        }
+    }
+
+    private int loadType(String propertyURI, HttpClient client) throws IOException, DavException, RepositoryException {
+        DavPropertyNameSet nameSet = new DavPropertyNameSet();
+        nameSet.add(ItemResourceConstants.JCR_TYPE);
+
+        DavMethodBase method = null;
+        try {
+            method = new PropFindMethod(propertyURI, nameSet, DavConstants.DEPTH_0);
+            client.executeMethod(method);
+            method.checkSuccess();
+
+            MultiStatusResponse[] responses = method.getResponseBodyAsMultiStatus().getResponses();
+            if (responses.length == 1) {
+                DavPropertySet props = responses[0].getProperties(DavServletResponse.SC_OK);
+                DavProperty type = props.get(ItemResourceConstants.JCR_TYPE);
+                if (type != null) {
+                    return PropertyType.valueFromName(type.getValue().toString());
+                } else {
+                    throw new RepositoryException("Internal error. Cannot retrieve property type at " + propertyURI);
+                }
+            } else {
+                throw new ItemNotFoundException("Internal error. Cannot retrieve property type at " + propertyURI);
+            }
+        } finally {
+            method.releaseConnection();
+        }
+    }
+
     /**
      * @see RepositoryService#createBatch(SessionInfo,ItemId)
      */
@@ -1989,9 +2113,12 @@
          */
         public void addProperty(NodeId parentId, Name propertyName, QValue value) throws ValueFormatException, VersionException, LockException, ConstraintViolationException, PathNotFoundException, ItemExistsException, AccessDeniedException, UnsupportedRepositoryOperationException, RepositoryException {
             checkConsumed();
-            Value jcrValue = ValueFormat.getJCRValue(value, resolver, valueFactory);
-            ValuesProperty vp = new ValuesProperty(jcrValue);
-            internalAddProperty(parentId, propertyName, vp);
+            String uri = getItemUri(parentId, propertyName, sessionInfo);
+
+            PutMethod method = new PutMethod(uri);
+            method.setRequestHeader(DavConstants.HEADER_CONTENT_TYPE, JcrValueType.contentTypeFromType(value.getType()));
+            method.setRequestEntity(getEntity(value));
+            methods.add(method);
         }
 
         /**
@@ -1999,22 +2126,19 @@
          */
         public void addProperty(NodeId parentId, Name propertyName, QValue[] values) throws ValueFormatException, VersionException, LockException, ConstraintViolationException, PathNotFoundException, ItemExistsException, AccessDeniedException, UnsupportedRepositoryOperationException, RepositoryException {
             checkConsumed();
-            Value[] jcrValues = new Value[values.length];
-            for (int i = 0; i < values.length; i++) {
-                jcrValues[i] = ValueFormat.getJCRValue(values[i], resolver, valueFactory);
-            }
-            ValuesProperty vp = new ValuesProperty(jcrValues);
-            internalAddProperty(parentId, propertyName, vp);
-        }
-
-        private void internalAddProperty(NodeId parentId, Name propertyName, ValuesProperty vp) throws ValueFormatException, VersionException, LockException, ConstraintViolationException, PathNotFoundException, ItemExistsException, AccessDeniedException, UnsupportedRepositoryOperationException, RepositoryException {
+            // TODO: avoid usage of the ValuesProperty. specially for binary props.
+            // TODO: replace by a multipart-POST
             try {
                 String uri = getItemUri(parentId, propertyName, sessionInfo);
+                Value[] jcrValues = new Value[values.length];
+                for (int i = 0; i < values.length; i++) {
+                    jcrValues[i] = ValueFormat.getJCRValue(values[i], resolver, valueFactory);
+                }
+                ValuesProperty vp = new ValuesProperty(jcrValues);
                 PutMethod method = new PutMethod(uri);
                 method.setRequestBody(vp);
 
                 methods.add(method);
-
             } catch (IOException e) {
                 throw new RepositoryException(e);
             }
@@ -2025,17 +2149,19 @@
          */
         public void setValue(PropertyId propertyId, QValue value) throws ValueFormatException, VersionException, LockException, ConstraintViolationException, AccessDeniedException, UnsupportedRepositoryOperationException, RepositoryException {
             checkConsumed();
-            DavPropertySet setProperties = new DavPropertySet();
             if (value == null) {
                 // setting property value to 'null' is identical to a removal
                 remove(propertyId);
             } else {
-                // qualified value must be converted to jcr value
-                Value jcrValue = ValueFormat.getJCRValue(value, resolver, valueFactory);
-                ValuesProperty vp = new ValuesProperty(jcrValue);
-                setProperties.add(vp);
+                RequestEntity ent = getEntity(value);
+                String uri = getItemUri(propertyId, sessionInfo);
+                // TODO: use PUT in order to avoid the ValuesProperty-PROPPATCH call.
+                // TODO: actually not quite correct for PROPPATCH assert that prop really exists.
+                PutMethod method = new PutMethod(uri);
+                method.setRequestHeader(DavConstants.HEADER_CONTENT_TYPE, JcrValueType.contentTypeFromType(value.getType()));
+                method.setRequestEntity(ent);
+                methods.add(method);
             }
-            internalSetValue(propertyId, setProperties);
         }
 
         /**
@@ -2043,42 +2169,55 @@
          */
         public void setValue(PropertyId propertyId, QValue[] values) throws ValueFormatException, VersionException, LockException, ConstraintViolationException, AccessDeniedException, UnsupportedRepositoryOperationException, RepositoryException {
             checkConsumed();
-            DavPropertySet setProperties = new DavPropertySet();
             if (values == null) {
                 // setting property value to 'null' is identical to a removal
                 remove(propertyId);
             } else {
+                // TODO: use multipart-POST instead of ValuesProperty
+                DavPropertySet setProperties = new DavPropertySet();
                 // qualified values must be converted to jcr values
                 Value[] jcrValues = new Value[values.length];
                 for (int i = 0; i < values.length; i++) {
                     jcrValues[i] = ValueFormat.getJCRValue(values[i], resolver, valueFactory);
                 }
                 setProperties.add(new ValuesProperty(jcrValues));
+                try {
+                    String uri = getItemUri(propertyId, sessionInfo);
+                    PropPatchMethod method = new PropPatchMethod(uri, setProperties, new DavPropertyNameSet());
+                    methods.add(method);
+                } catch (IOException e) {
+                    throw new RepositoryException(e);
+                }
             }
-            internalSetValue(propertyId, setProperties);
         }
 
-        /**
-         *
-         * @param propertyId
-         * @param setProperties
-         * @throws ValueFormatException
-         * @throws VersionException
-         * @throws LockException
-         * @throws ConstraintViolationException
-         * @throws AccessDeniedException
-         * @throws UnsupportedRepositoryOperationException
-         * @throws RepositoryException
-         */
-        private void internalSetValue(PropertyId propertyId, DavPropertySet setProperties) throws ValueFormatException, VersionException, LockException, ConstraintViolationException, AccessDeniedException, UnsupportedRepositoryOperationException, RepositoryException {
+        private RequestEntity getEntity(QValue value) throws RepositoryException {
+            // qualified value must be converted to jcr value
+            InputStream in;
+            int type = value.getType();
+            String contentType = JcrValueType.contentTypeFromType(type);
+            RequestEntity ent;
             try {
-                String uri = getItemUri(propertyId, sessionInfo);
-                PropPatchMethod method = new PropPatchMethod(uri, setProperties, new DavPropertyNameSet());
-
-                methods.add(method);
-            } catch (IOException e) {
-                throw new RepositoryException(e);
+                switch (type) {
+                    case PropertyType.NAME:
+                    case PropertyType.PATH:
+                        Value v = ValueFormat.getJCRValue(value, resolver, valueFactory);
+                        ent = new StringRequestEntity(v.getString(), contentType, "UTF-8");
+                        break;
+                    case PropertyType.BINARY:
+                        in = value.getStream();
+                        ent = new InputStreamRequestEntity(in, contentType);
+                        break;
+                    default:
+                        String str = value.getString();
+                        ent = new StringRequestEntity(str, contentType, "UTF-8");
+                        break;
+                }
+            } catch (UnsupportedEncodingException e) {
+                // should never get here
+                throw new RepositoryException(e.getMessage());
             }
+            return ent;
         }
 
         /**