Return-Path: Delivered-To: apmail-jackrabbit-commits-archive@www.apache.org Received: (qmail 57434 invoked from network); 20 Aug 2008 13:15:25 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.2) by minotaur.apache.org with SMTP; 20 Aug 2008 13:15:25 -0000 Received: (qmail 64346 invoked by uid 500); 20 Aug 2008 13:15:24 -0000 Delivered-To: apmail-jackrabbit-commits-archive@jackrabbit.apache.org Received: (qmail 64317 invoked by uid 500); 20 Aug 2008 13:15:24 -0000 Mailing-List: contact commits-help@jackrabbit.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@jackrabbit.apache.org Delivered-To: mailing list commits@jackrabbit.apache.org Received: (qmail 64308 invoked by uid 99); 20 Aug 2008 13:15:24 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 20 Aug 2008 06:15:24 -0700 X-ASF-Spam-Status: No, hits=-2000.0 required=10.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 20 Aug 2008 13:14:35 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id BF3262388961; Wed, 20 Aug 2008 06:15:04 -0700 (PDT) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r687317 - in /jackrabbit/sandbox/spi/spi2dav/src/main/java/org/apache/jackrabbit/spi2dav: ExceptionConverter.java ItemInfoImpl.java PropertyInfoImpl.java RepositoryServiceImpl.java Date: Wed, 20 Aug 2008 13:15:04 -0000 To: commits@jackrabbit.apache.org From: angela@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20080820131504.BF3262388961@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org 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; } /**