jackrabbit-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From tri...@apache.org
Subject svn commit: r293331 [1/3] - in /incubator/jackrabbit/trunk/contrib/jcr-server: server/src/java/org/apache/jackrabbit/server/ server/src/java/org/apache/jackrabbit/server/io/ server/src/java/org/apache/jackrabbit/util/ server/src/java/org/apache/jackrab...
Date Mon, 03 Oct 2005 13:13:32 GMT
Author: tripod
Date: Mon Oct  3 06:12:18 2005
New Revision: 293331

URL: http://svn.apache.org/viewcvs?rev=293331&view=rev
Log:
JCR-193, JCR-216, JCR-203, JCR 184 + various minor fixes

Added:
    incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/util/
    incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/util/ISO9075.java   (with props)
    incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/simple/ResourceConfig.java   (with props)
    incubator/jackrabbit/trunk/contrib/jcr-server/webapp/src/webapp/WEB-INF/config.xml   (with props)
Removed:
    incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/simple/ResourceFilterConfig.java
    incubator/jackrabbit/trunk/contrib/jcr-server/webapp/src/webapp/WEB-INF/filter.xml
Modified:
    incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/server/AbstractWebdavServlet.java
    incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/server/io/AddNodeCommand.java
    incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/server/io/BoundedInputStream.java
    incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/server/io/FileImportCommand.java
    incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/AbstractItemResource.java
    incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/AbstractResource.java
    incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/DavLocatorFactoryImpl.java
    incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/DavResourceFactoryImpl.java
    incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/DefaultItemCollection.java
    incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/DefaultItemResource.java
    incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/JcrDavException.java
    incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/RootCollection.java
    incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/RootItemCollection.java
    incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/VersionControlledItemCollection.java
    incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/observation/SubscriptionImpl.java
    incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/observation/SubscriptionManagerImpl.java
    incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/property/LengthsProperty.java
    incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/search/SearchResourceImpl.java
    incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/transaction/TxLockManagerImpl.java
    incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/version/VersionHistoryItemCollection.java
    incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/version/VersionItemCollection.java
    incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/version/report/ExportViewReport.java
    incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/version/report/LocateByUuidReport.java
    incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/version/report/LocateCorrespondingNodeReport.java
    incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/simple/DavResourceImpl.java
    incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/simple/DavSessionImpl.java
    incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/simple/DavSessionProviderImpl.java
    incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/simple/LocatorFactoryImpl.java
    incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/simple/NodeResource.java
    incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/simple/ResourceFactoryImpl.java
    incubator/jackrabbit/trunk/contrib/jcr-server/webapp/src/java/org/apache/jackrabbit/j2ee/SimpleWebdavServlet.java
    incubator/jackrabbit/trunk/contrib/jcr-server/webapp/src/webapp/WEB-INF/web.xml
    incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/DavLocatorFactory.java
    incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/DavResource.java
    incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/DavResourceLocator.java
    incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/DavServletResponse.java
    incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/MultiStatus.java
    incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/MultiStatusResponse.java
    incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/WebdavRequestImpl.java
    incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/WebdavResponseImpl.java
    incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/header/IfHeader.java
    incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/util/XmlUtil.java
    incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/version/VersionControlledResource.java

Modified: incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/server/AbstractWebdavServlet.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/server/AbstractWebdavServlet.java?rev=293331&r1=293330&r2=293331&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/server/AbstractWebdavServlet.java (original)
+++ incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/server/AbstractWebdavServlet.java Mon Oct  3 06:12:18 2005
@@ -15,19 +15,7 @@
  */
 package org.apache.jackrabbit.server;
 
-import org.apache.jackrabbit.webdav.DavConstants;
-import org.apache.jackrabbit.webdav.DavException;
-import org.apache.jackrabbit.webdav.DavLocatorFactory;
-import org.apache.jackrabbit.webdav.DavMethods;
-import org.apache.jackrabbit.webdav.DavResource;
-import org.apache.jackrabbit.webdav.DavResourceFactory;
-import org.apache.jackrabbit.webdav.DavServletResponse;
-import org.apache.jackrabbit.webdav.DavSessionProvider;
-import org.apache.jackrabbit.webdav.MultiStatus;
-import org.apache.jackrabbit.webdav.WebdavRequest;
-import org.apache.jackrabbit.webdav.WebdavRequestImpl;
-import org.apache.jackrabbit.webdav.WebdavResponse;
-import org.apache.jackrabbit.webdav.WebdavResponseImpl;
+import org.apache.jackrabbit.webdav.*;
 import org.apache.jackrabbit.webdav.io.InputContext;
 import org.apache.jackrabbit.webdav.lock.ActiveLock;
 import org.apache.jackrabbit.webdav.lock.LockInfo;
@@ -37,10 +25,7 @@
 import org.apache.jackrabbit.webdav.observation.SubscriptionInfo;
 import org.apache.jackrabbit.webdav.ordering.OrderPatch;
 import org.apache.jackrabbit.webdav.ordering.OrderingResource;
-import org.apache.jackrabbit.webdav.property.DavProperty;
-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.*;
 import org.apache.jackrabbit.webdav.search.SearchConstants;
 import org.apache.jackrabbit.webdav.search.SearchInfo;
 import org.apache.jackrabbit.webdav.search.SearchResource;
@@ -187,7 +172,7 @@
                 webdavResponse.setHeader("WWW-Authenticate", getAuthenticateHeaderValue());
                 webdavResponse.sendError(e.getErrorCode(), e.getStatusPhrase());
             } else {
-                webdavResponse.sendErrorResponse(e);
+                webdavResponse.sendError(e);
             }
         } finally {
             getDavSessionProvider().releaseSession(webdavRequest);
@@ -459,7 +444,7 @@
 
         MultiStatus mstatus = new MultiStatus();
         mstatus.addResourceProperties(resource, requestProperties, propfindType, depth);
-        response.sendMultiStatusResponse(mstatus);
+        response.sendMultiStatus(mstatus);
     }
 
     /**
@@ -481,18 +466,19 @@
             return;
         }
 
-        // first resolve merge conflicts
-        // TODO: not correct resolution of merge conflicts are immediately perstisted
-        // TODO: rfc 2518 requires, that no changes must only be persisted if the complete proppatch-req succeeds
-        if (resource instanceof VersionControlledResource) {
-            ((VersionControlledResource) resource).resolveMergeConflict(setProperties, removeProperties);
+        MultiStatus ms = new MultiStatus();
+        try {
+            MultiStatusResponse msr = resource.alterProperties(setProperties, removeProperties);
+            ms.addResponse(msr);
+        } catch (DavException e) {
+            /* NOTE: known bug with litmus, which expects the exception (e.g. 423)
+               to the set instead of the MultiStatus Code. RFC 2518 explicitely
+               expects the errors to be included in the multistatus.
+               Remove the catch if this turns out to be an problem with clients
+               in general. */
+            ms.addResourceStatus(resource, e.getErrorCode(), DEPTH_0);
         }
-
-        // complete any other property setting or removing
-        resource.alterProperties(setProperties, removeProperties);
-        response.setStatus(DavServletResponse.SC_OK);
-
-        // todo return multistatus response in case of failure
+        response.sendMultiStatus(ms);
     }
 
     /**
@@ -558,6 +544,10 @@
             response.sendError(DavServletResponse.SC_CONFLICT);
             return;
         }
+        // shortcut: mkcol is only allowed on deleted/non-existing resources
+        if (resource.exists()) {
+            response.sendError(DavServletResponse.SC_METHOD_NOT_ALLOWED);
+        }
 
         if (request.getContentLength() > 0 || request.getHeader("Transfer-Encoding") != null) {
             parentResource.addMember(resource, getInputContext(request));
@@ -569,7 +559,7 @@
 
     /**
      * Build an InputContext for the given request
-     * 
+     *
      * @param request
      * @return
      * @throws IOException
@@ -718,9 +708,10 @@
                 // adjust lockinfo with type/scope retrieved from the lock.
                 lockInfo.setType(activeLocks[i].getType());
                 lockInfo.setScope(activeLocks[i].getScope());
-                
-                // todo: do not ignore etag
-                if (request.matchesIfHeader(resource.getHref(), activeLocks[i].getToken(), "")) {
+
+                DavProperty etagProp = resource.getProperty(DavPropertyName.GETETAG);
+                String etag = etagProp != null ? String.valueOf(etagProp.getValue()) : "";
+                if (request.matchesIfHeader(resource.getHref(), activeLocks[i].getToken(), etag)) {
                     lList.add(resource.refreshLock(lockInfo, activeLocks[i].getToken()));
                 }
             }
@@ -734,9 +725,6 @@
             ActiveLock lock = resource.lock(lockInfo);
             response.sendLockResponse(lock);
         }
-
-        // TODO multistatus in case of failure...
-        // NOTE: spec says 409 status, but example says 207 (multistatus)
     }
 
     /**
@@ -787,8 +775,6 @@
         // perform reordering of internal members
         ((OrderingResource) resource).orderMembers(op);
         response.setStatus(DavServletResponse.SC_OK);
-
-        //TODO: in case of failure Multistatus is required...
     }
 
     /**
@@ -1004,7 +990,7 @@
         }
         MergeInfo info = request.getMergeInfo();
         MultiStatus ms = ((VersionControlledResource) resource).merge(info);
-        response.sendMultiStatusResponse(ms);
+        response.sendMultiStatus(ms);
     }
 
     /**
@@ -1025,7 +1011,7 @@
         }
         UpdateInfo info = request.getUpdateInfo();
         MultiStatus ms = ((VersionControlledResource) resource).update(info);
-        response.sendMultiStatusResponse(ms);
+        response.sendMultiStatus(ms);
     }
 
     /**
@@ -1079,11 +1065,11 @@
             Document doc = request.getRequestDocument();
             if (doc != null) {
                 SearchInfo sR = new SearchInfo(doc);
-                response.sendMultiStatusResponse(((SearchResource) resource).search(sR));
+                response.sendMultiStatus(((SearchResource) resource).search(sR));
             } else {
                 // request without request body is valid if requested resource
                 // is a 'query' resource.
-                response.sendMultiStatusResponse(((SearchResource) resource).search(null));
+                response.sendMultiStatus(((SearchResource) resource).search(null));
             }
         } catch (IllegalArgumentException e) {
             response.sendError(DavServletResponse.SC_BAD_REQUEST);

Modified: incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/server/io/AddNodeCommand.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/server/io/AddNodeCommand.java?rev=293331&r1=293330&r2=293331&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/server/io/AddNodeCommand.java (original)
+++ incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/server/io/AddNodeCommand.java Mon Oct  3 06:12:18 2005
@@ -19,7 +19,7 @@
 import javax.jcr.Node;
 
 /**
- * This Class implements a import command that adds a mixin node type to the
+ * This Class implements a import command that adds a child node to the
  * current node.
  */
 public class AddNodeCommand extends AbstractCommand {

Modified: incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/server/io/BoundedInputStream.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/server/io/BoundedInputStream.java?rev=293331&r1=293330&r2=293331&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/server/io/BoundedInputStream.java (original)
+++ incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/server/io/BoundedInputStream.java Mon Oct  3 06:12:18 2005
@@ -32,7 +32,6 @@
  *
  * @version $Revision: 13729 $, $Date: 2004/06/04 15:48:16 $
  * @author InigoSurguy
- * @since antbear
  */
 public class BoundedInputStream extends InputStream {
 

Modified: incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/server/io/FileImportCommand.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/server/io/FileImportCommand.java?rev=293331&r1=293330&r2=293331&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/server/io/FileImportCommand.java (original)
+++ incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/server/io/FileImportCommand.java Mon Oct  3 06:12:18 2005
@@ -26,6 +26,7 @@
  * data as binary property. It further sets the following properties:
  * <ul>
  * <li>jcr:mimeType (from {@link ImportContext#getContentType()})
+ * <li>jcr:encoding (from {@link ImportContext#getContentType()})
  * <li>jcr:lastModified (from current time)
  * <li>jcr:data (from {@link ImportContext#getInputStream()})
  * </ul>
@@ -52,7 +53,9 @@
         Node content = parentNode.hasNode(JCR_CONTENT)
                 ? parentNode.getNode(JCR_CONTENT)
                 : parentNode.addNode(JCR_CONTENT, resourceNodeType);
-        content.setProperty(JCR_MIMETYPE, ctx.getContentType());
+        String contentType = ctx.getContentType();
+        content.setProperty(JCR_MIMETYPE, getMimeType(contentType));
+        content.setProperty(JCR_ENCODING, getEncoding(contentType));
         content.setProperty(JCR_DATA, in);
         Calendar lastMod = Calendar.getInstance();
         if (ctx.getModificationTime() != 0) {
@@ -79,5 +82,46 @@
      */
     public boolean canHandle(String contentType) {
         return true;
+    }
+
+    /**
+     * Returns the main media type from a MIME Content-Type
+     * specification.
+     */
+    private String getMimeType(String contentType) {
+        if (contentType == null) {
+            // property will be removed.
+            // Note however, that jcr:mimetype is a mandatory property with the
+            // built-in nt:file nodetype.
+            return contentType;
+        }
+        // strip any parameters
+        int semi = contentType.indexOf(";");
+        return (semi > 0) ? contentType.substring(0, semi) : contentType;
+    }
+
+    /**
+     * Returns the charset parameter of a MIME Content-Type specification, or
+     * <code>null</code> if the specified String is <null> or if the charset
+     * is not included.
+     */
+    private String getEncoding(String contentType) {
+        // find the charset parameter
+        int equal;
+        if (contentType == null || (equal = contentType.indexOf("charset=")) == -1) {
+            // jcr:encoding property will be removed
+            return null;
+        }
+        String charset = contentType.substring(equal + 8);
+        // get rid of any other parameters that might be specified after the charset
+        int semi = charset.indexOf(";");
+        if (semi != -1) {
+            charset = charset.substring(0, semi);
+        }
+        // strip off enclosing quotes
+        if (charset.startsWith("\"") || charset.startsWith("'")) {
+            charset = charset.substring(1, charset.length() - 1);
+        }
+        return charset;
     }
 }

Added: incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/util/ISO9075.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/util/ISO9075.java?rev=293331&view=auto
==============================================================================
--- incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/util/ISO9075.java (added)
+++ incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/util/ISO9075.java Mon Oct  3 06:12:18 2005
@@ -0,0 +1,185 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation or its licensors,
+ *                     as applicable.
+ *
+ * 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.jackrabbit.util;
+
+import org.apache.jackrabbit.name.QName;
+import org.apache.xml.utils.XMLChar;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Implements the encode and decode routines as specified for XML name to SQL
+ * identifier conversion in ISO 9075-14:2003.<br/>
+ * If a character <code>c</code> is not valid at a certain position in an XML 1.0
+ * NCName it is encoded in the form: '_x' + hexValueOf(c) + '_'
+ * <p/>
+ * Note that only the local part of a {@link org.apache.jackrabbit.name.QName}
+ * is encoded / decoded. A URI namespace will always be valid and does not
+ * need encoding.
+ */
+// TODO: class copied from org.apache.jackrabbit.core.util because it is not included in the commons.jar
+public class ISO9075 {
+
+    /** Hidden constructor. */
+    private ISO9075() { }
+
+    /** Pattern on an encoded character */
+    private static final Pattern ENCODE_PATTERN = Pattern.compile("_x\\p{XDigit}{4}_");
+
+    /** Padding characters */
+    private static final char[] PADDING = new char[] {'0', '0', '0'};
+
+    /** All the possible hex digits */
+    private static final String HEX_DIGITS = "0123456789abcdefABCDEF";
+
+    /**
+     * Encodes the local part of <code>name</code> as specified in ISO 9075.
+     * @param name the <code>QName</code> to encode.
+     * @return the encoded <code>QName</code> or <code>name</code> if it does
+     *   not need encoding.
+     */
+    public static QName encode(QName name) {
+        String encoded = encode(name.getLocalName());
+        if (encoded == name.getLocalName()) {
+            return name;
+        } else {
+            return new QName(name.getNamespaceURI(), encoded);
+        }
+    }
+
+    /**
+     * Encodes <code>name</code> as specified in ISO 9075.
+     * @param name the <code>String</code> to encode.
+     * @return the encoded <code>String</code> or <code>name</code> if it does
+     *   not need encoding.
+     */
+    public static String encode(String name) {
+        // quick check for root node name
+        if (name.length() == 0) {
+            return name;
+        }
+        if (XMLChar.isValidName(name) && name.indexOf("_x") < 0) {
+            // already valid
+            return name;
+        } else {
+            // encode
+            StringBuffer encoded = new StringBuffer();
+            for (int i = 0; i < name.length(); i++) {
+                if (i == 0) {
+                    // first character of name
+                    if (XMLChar.isNameStart(name.charAt(i))) {
+                        if (needsEscaping(name, i)) {
+                            // '_x' must be encoded
+                            encode('_', encoded);
+                        } else {
+                            encoded.append(name.charAt(i));
+                        }
+                    } else {
+                        // not valid as first character -> encode
+                        encode(name.charAt(i), encoded);
+                    }
+                } else if (!XMLChar.isName(name.charAt(i))) {
+                    encode(name.charAt(i), encoded);
+                } else {
+                    if (needsEscaping(name, i)) {
+                        // '_x' must be encoded
+                        encode('_', encoded);
+                    } else {
+                        encoded.append(name.charAt(i));
+                    }
+                }
+            }
+            return encoded.toString();
+        }
+    }
+
+    /**
+     * Decodes the <code>name</code>.
+     * @param name the <code>QName</code> to decode.
+     * @return the decoded <code>QName</code>.
+     */
+    public static QName decode(QName name) {
+        String decoded = decode(name.getLocalName());
+        if (decoded == name.getLocalName()) {
+            return name;
+        } else {
+            return new QName(name.getNamespaceURI(), decoded.toString());
+        }
+    }
+
+    /**
+     * Decodes the <code>name</code>.
+     * @param name the <code>String</code> to decode.
+     * @return the decoded <code>String</code>.
+     */
+    public static String decode(String name) {
+        // quick check
+        if (name.indexOf("_x") < 0) {
+            // not encoded
+            return name;
+        }
+        StringBuffer decoded = new StringBuffer();
+        Matcher m = ENCODE_PATTERN.matcher(name);
+        while (m.find()) {
+            m.appendReplacement(decoded, Character.toString((char) Integer.parseInt(m.group().substring(2, 6), 16)));
+        }
+        m.appendTail(decoded);
+        return decoded.toString();
+    }
+
+    //-------------------------< internal >-------------------------------------
+
+    /**
+     * Encodes the character <code>c</code> as a String in the following form:
+     * <code>"_x" + hex value of c + "_"</code>. Where the hex value has
+     * four digits if the character with possibly leading zeros.
+     * <p/>
+     * Example: ' ' (the space character) is encoded to: _x0020_
+     * @param c the character to encode
+     * @param b the encoded character is appended to <code>StringBuffer</code>
+     *  <code>b</code>.
+     */
+    private static void encode(char c, StringBuffer b) {
+        b.append("_x");
+        String hex = Integer.toHexString(c);
+        b.append(PADDING, 0, 4 - hex.length());
+        b.append(hex);
+        b.append("_");
+    }
+
+    /**
+     * Returns true if <code>name.charAt(location)</code> is the underscore
+     * character and the following character sequence is 'xHHHH_' where H
+     * is a hex digit.
+     * @param name the name to check.
+     * @param location the location to look at.
+     * @throws ArrayIndexOutOfBoundsException if location > name.length()
+     */
+    private static boolean needsEscaping(String name, int location)
+            throws ArrayIndexOutOfBoundsException {
+        if (name.charAt(location) == '_' && name.length() >= location + 6) {
+            return name.charAt(location + 1) == 'x'
+                && HEX_DIGITS.indexOf(name.charAt(location + 2)) != -1
+                && HEX_DIGITS.indexOf(name.charAt(location + 3)) != -1
+                && HEX_DIGITS.indexOf(name.charAt(location + 4)) != -1
+                && HEX_DIGITS.indexOf(name.charAt(location + 5)) != -1;
+        } else {
+            return false;
+        }
+    }
+}

Propchange: incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/util/ISO9075.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/util/ISO9075.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision

Modified: incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/AbstractItemResource.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/AbstractItemResource.java?rev=293331&r1=293330&r2=293331&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/AbstractItemResource.java (original)
+++ incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/AbstractItemResource.java Mon Oct  3 06:12:18 2005
@@ -78,30 +78,18 @@
     }
 
     /**
+     * Retrieves the last segment of the item path (or the resource path if
+     * this resource does not exist). An item path is in addition first translated
+     * to the corresponding resource path.<br>
+     * NOTE: the displayname is not equivalent to {@link Item#getName() item name}
+     * which is exposed with the {@link #JCR_NAME &#123;http://www.day.com/jcr/webdav/1.0&#125;name}
+     * property.
+     *
      * @see DavResource#getDisplayName() )
      */
     public String getDisplayName() {
-        String name = null;
-        if (exists()) {
-            try {
-                name = item.getName();
-            } catch (RepositoryException e) {
-                // ignore: should not occure
-                log.warn(e.getMessage());
-            }
-        }
         String resPath = getResourcePath();
-        if (name == null && resPath != null) {
-            int pos = resPath.lastIndexOf('/');
-            if (pos>=0) {
-                name = resPath.substring(pos+1);
-            } else {
-                name = resPath;
-            }
-            // note: since index info is present only with existing resources
-            // there is no need to check for any '[index]' suffix.
-        }
-        return name;
+        return (resPath != null) ? Text.getName(resPath) : resPath;
     }
 
     /**
@@ -151,12 +139,14 @@
         }
 
         try {
+            String itemPath = getLocator().getJcrPath();
+            String destItemPath = destination.getLocator().getJcrPath();
             if (getTransactionId() == null) {
                 // if not part of a transaction directely import on workspace
-                getRepositorySession().getWorkspace().move(getResourcePath(), destination.getResourcePath());
+                getRepositorySession().getWorkspace().move(itemPath, destItemPath);
             } else {
                 // changes will not be persisted unless the tx is completed.
-                getRepositorySession().move(getResourcePath(), destination.getResourcePath());
+                getRepositorySession().move(itemPath, destItemPath);
             }
             // no use in calling 'complete' that would fail for a moved item anyway.
         } catch (PathNotFoundException e) {
@@ -192,9 +182,11 @@
         }
 
         try {
+            String itemPath = getLocator().getJcrPath();
+            String destItemPath = destination.getLocator().getJcrPath();
             Workspace workspace = getRepositorySession().getWorkspace();
             if (getLocator().isSameWorkspace(destination.getLocator())) {
-                workspace.copy(getResourcePath(), destination.getResourcePath());
+                workspace.copy(itemPath, destItemPath);
             } else {
                 log.error("Copy between workspaces is not yet implemented (src: '" + getHref() + "', dest: '" + destination.getHref() + "')");
                 throw new DavException(DavServletResponse.SC_NOT_IMPLEMENTED);
@@ -254,7 +246,7 @@
                 properties.add(new DefaultDavProperty(JCR_DEPTH, String.valueOf(item.getDepth())));
                 // add href-property for the items parent unless its the root item
                 if (item.getDepth() > 0) {
-                    String parentHref = getLocatorFromResourcePath(item.getParent().getPath()).getHref(true);
+                    String parentHref = getLocatorFromItem(item.getParent()).getHref(true);
                     properties.add(new HrefProperty(JCR_PARENT, parentHref, false));
                 }
             } catch (RepositoryException e) {
@@ -281,10 +273,8 @@
         String workspaceHref = null;
 	DavResourceLocator locator = getLocator();
         if (locator != null && locator.getWorkspaceName() != null) {
-            workspaceHref = locator.getHref(isCollection());
-            if (locator.getResourcePath() != null) {
-                workspaceHref = workspaceHref.substring(workspaceHref.indexOf(locator.getResourcePath()));
-            }
+            DavResourceLocator wspLocator = locator.getFactory().createResourceLocator(locator.getPrefix(), locator.getWorkspacePath(), ItemResourceConstants.ROOT_ITEM_PATH);
+            workspaceHref = wspLocator.getHref(true);
         }
 	log.info(workspaceHref);
         return workspaceHref;
@@ -292,8 +282,8 @@
 
     /**
      * If this resource exists but does not contain a transaction id, complete
-     * will try to persist any modifications prsent on the underlaying repository
-     * item.
+     * will try to persist any modifications present on the underlaying
+     * repository item.
      *
      * @throws DavException if calling {@link Item#save()} fails
      */
@@ -317,22 +307,22 @@
     }
 
     /**
-     * Build a new {@link DavResourceLocator} from the given repository item.
+     * Retrieves the last segment of the given path and removes the index if
+     * present.
      *
-     * @param repositoryItem
-     * @return a new locator for the specified item.
-     * @see #getLocatorFromResourcePath(String)
+     * @param itemPath
+     * @return valid jcr item name
      */
-    protected DavResourceLocator getLocatorFromItem(Item repositoryItem) {
-        String itemPath = null;
-        try {
-            if (repositoryItem != null) {
-                itemPath = repositoryItem.getPath();
-            }
-        } catch (RepositoryException e) {
-            // ignore: should not occur
-            log.warn(e.getMessage());
+    protected static String getItemName(String itemPath) {
+        if (itemPath == null) {
+            throw new IllegalArgumentException("Cannot retrieve name from a 'null' item path.");
+        }
+        // retrieve the last part of the path
+        String name = Text.getName(itemPath);
+        // remove index
+        if (name.endsWith("]")) {
+            name = name.substring(0, name.lastIndexOf('['));
         }
-        return getLocatorFromResourcePath(itemPath);
+        return name;
     }
 }

Modified: incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/AbstractResource.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/AbstractResource.java?rev=293331&r1=293330&r2=293331&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/AbstractResource.java (original)
+++ incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/AbstractResource.java Mon Oct  3 06:12:18 2005
@@ -35,10 +35,10 @@
 import org.apache.jackrabbit.webdav.lock.*;
 import org.apache.jackrabbit.webdav.property.*;
 import org.apache.jackrabbit.webdav.property.ResourceType;
-import org.apache.jackrabbit.util.Text;
 
 import javax.jcr.Session;
 import javax.jcr.RepositoryException;
+import javax.jcr.Item;
 import java.io.InputStream;
 import java.util.*;
 
@@ -189,12 +189,9 @@
     /**
      * Throws {@link DavServletResponse#SC_METHOD_NOT_ALLOWED}
      *
-     * @param setProperties
-     * @param removePropertyNames
-     * @throws DavException
      * @see DavResource#alterProperties(org.apache.jackrabbit.webdav.property.DavPropertySet, org.apache.jackrabbit.webdav.property.DavPropertyNameSet) 
      */
-    public void alterProperties(DavPropertySet setProperties,
+    public MultiStatusResponse alterProperties(DavPropertySet setProperties,
                                 DavPropertyNameSet removePropertyNames)
         throws DavException {
         throw new DavException(DavServletResponse.SC_METHOD_NOT_ALLOWED);
@@ -418,7 +415,9 @@
             // currently on DAV:version-history-collection-set and
             // DAV:workspace-collection-set is supported.
             if (optionsInfo.containsElement(DeltaVConstants.XML_VH_COLLECTION_SET, DeltaVConstants.NAMESPACE)) {
-                String[] hrefs = new String[] { getLocatorFromResourcePath(ItemResourceConstants.VERSIONSTORAGE_PATH).getHref(true)};
+                String[] hrefs = new String[] {
+                    getLocatorFromItemPath(ItemResourceConstants.VERSIONSTORAGE_PATH).getHref(true)
+                };
                 oR.addEntry(DeltaVConstants.XML_VH_COLLECTION_SET, DeltaVConstants.NAMESPACE, hrefs);
             } else if (optionsInfo.containsElement(DeltaVConstants.XML_WSP_COLLECTION_SET, DeltaVConstants.NAMESPACE)) {
                 // workspaces cannot be created anywhere.
@@ -506,15 +505,12 @@
         // build a new locator: remove trailing prefix
         DavResourceLocator locator = getLocator();
         String prefix = locator.getPrefix();
-        if (href.startsWith(prefix)) {
-            href = href.substring(prefix.length());
-        }
         DavResourceLocator loc = locator.getFactory().createResourceLocator(prefix, href);
 
         // create a new resource object
         try {
             DavResource res;
-            if (getRepositorySession().itemExists(loc.getResourcePath())) {
+            if (getRepositorySession().itemExists(loc.getJcrPath())) {
                 res = createResourceFromLocator(loc);
             } else {
                 throw new DavException(DavServletResponse.SC_NOT_FOUND);
@@ -609,48 +605,35 @@
     }
 
     /**
-     * Build a <code>DavResourceLocator</code> from the given resource path.
+     * Build a <code>DavResourceLocator</code> from the given itemPath path.
      *
-     * @param resourcePath
+     * @param itemPath
      * @return a new <code>DavResourceLocator</code>
      * @see DavLocatorFactory#createResourceLocator(String, String, String)
      */
-    protected DavResourceLocator getLocatorFromResourcePath(String resourcePath) {
-        DavResourceLocator loc = locator.getFactory().createResourceLocator(locator.getPrefix(), locator.getWorkspacePath(), resourcePath);
+    protected DavResourceLocator getLocatorFromItemPath(String itemPath) {
+        DavResourceLocator loc = locator.getFactory().createResourceLocator(locator.getPrefix(), locator.getWorkspacePath(), itemPath, false);
         return loc;
     }
 
     /**
-     * Retrieve the name/label of a repository item from the given href by
-     * splitting of the part after the last slash. If the removeIndex
-     * flag is set to true, any trailing index (e.g. '[1]') will be removed.
-     *
-     * @param resourceHref
-     * @param removeIndex
-     * @return the name of the item
-     */
-    protected static String getResourceName(String resourceHref, boolean removeIndex) {
-        if (resourceHref == null) {
-            return resourceHref;
-        }
-
-        // cut the extension
-        int pos = resourceHref.lastIndexOf('.');
-        if (pos > 0) {
-            resourceHref = resourceHref.substring(pos+1);
-        } else if (resourceHref.endsWith("/")) {
-            resourceHref = resourceHref.substring(0, resourceHref.length()-1);
-        }
-
-        // retrieve the last part of the path
-        String name = Text.getName(resourceHref);
-        // remove index
-        if (removeIndex) {
-            if (name.endsWith("]")) {
-                name = name.substring(0, name.lastIndexOf('['));
+     * Build a new {@link DavResourceLocator} from the given repository item.
+     *
+     * @param repositoryItem
+     * @return a new locator for the specified item.
+     * @see #getLocatorFromItemPath(String)
+     */
+    protected DavResourceLocator getLocatorFromItem(Item repositoryItem) {
+        String itemPath = null;
+        try {
+            if (repositoryItem != null) {
+                itemPath = repositoryItem.getPath();
             }
+        } catch (RepositoryException e) {
+            // ignore: should not occur
+            log.warn(e.getMessage());
         }
-        return name;
+        return getLocatorFromItemPath(itemPath);
     }
 
     /**

Modified: incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/DavLocatorFactoryImpl.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/DavLocatorFactoryImpl.java?rev=293331&r1=293330&r2=293331&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/DavLocatorFactoryImpl.java (original)
+++ incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/DavLocatorFactoryImpl.java Mon Oct  3 06:12:18 2005
@@ -18,6 +18,7 @@
 import org.apache.log4j.Logger;
 import org.apache.jackrabbit.webdav.DavResourceLocator;
 import org.apache.jackrabbit.webdav.DavLocatorFactory;
+import org.apache.jackrabbit.util.Text;
 
 /**
  * <code>DavLocatorFactoryImpl</code>...
@@ -32,10 +33,10 @@
      * Create a new factory
      *
      * @param pathPrefix Prefix, that needs to be removed in order to retrieve
-     * the path of the repository item from a given <code>DavResourceLocator</code>.
+     *                   the path of the repository item from a given <code>DavResourceLocator</code>.
      */
     public DavLocatorFactoryImpl(String pathPrefix) {
-	this.pathPrefix = pathPrefix;
+        this.pathPrefix = pathPrefix;
     }
 
     /**
@@ -50,60 +51,61 @@
      * repository.
      *
      * @param prefix
-     * @param requestHandle
+     * @param href
      * @return a new <code>DavResourceLocator</code>
      * @throws IllegalArgumentException if the request handle is <code>null</code>
      */
-    public DavResourceLocator createResourceLocator(String prefix, String requestHandle) {
-	if (requestHandle == null) {
-	    throw new IllegalArgumentException("Request handle must not be null.");
-	}
-
-	StringBuffer b = new StringBuffer("");
-	if (prefix != null) {
-	    b.append(prefix);
-	    if (pathPrefix != null && !prefix.endsWith(pathPrefix)) {
-		b.append(pathPrefix);
-	    }
-	}
-	String rlPrefix = b.toString();
-
-	// remove path-prefix defined with the servlet that may preceed the
-	// the requestHandle
-	if (pathPrefix != null && requestHandle.startsWith(pathPrefix)) {
-	    requestHandle = requestHandle.substring(pathPrefix.length());
-	}
-
-	// remove trailing "/" that is present with collections
-	if (requestHandle.endsWith("/")) {
-	    requestHandle = requestHandle.substring(0, requestHandle.length()-1);
-	}
-
-	String resourcePath;
-	String workspacePath;
-
-	// an empty requestHandle (after removal of the "/") signifies a request
-	// to the root that does not represent a repository item.
-	if ("".equals(requestHandle)) {
-	    resourcePath = null;
-	    workspacePath = null;
-	} else {
-	    // look for the first slash ignoring the leading one
-	    int pos = requestHandle.indexOf('/', 1);
-	    if (pos == -1) {
-		// request to a 'workspace' resource that in the same time
-		// represent the root node of the repository.
-		workspacePath = requestHandle;
-		resourcePath = ItemResourceConstants.ROOT_ITEM_PATH;
-	    } else {
-		// separate the workspace name from the path of the repository
-		// item.
-		workspacePath = requestHandle.substring(0, pos);
-		resourcePath = requestHandle.substring(pos);
-	    }
-	}
+    public DavResourceLocator createResourceLocator(String prefix, String href) {
+        if (href == null) {
+            throw new IllegalArgumentException("Request handle must not be null.");
+        }
+
+        StringBuffer b = new StringBuffer("");
+        if (prefix != null) {
+            b.append(prefix);
+            if (pathPrefix != null && !prefix.endsWith(pathPrefix)) {
+                b.append(pathPrefix);
+            }
+        }
+        String rlPrefix = b.toString();
+
+        // remove any prefix that may still be present with the given href
+        if (pathPrefix != null && href.startsWith(pathPrefix)) {
+            href = href.substring(pathPrefix.length());
+        } else if (!"".equals(rlPrefix) && href.startsWith(rlPrefix)) {
+            href = href.substring(rlPrefix.length());
+        }
+
+        // remove trailing "/" that is present with collections
+        if (href.endsWith("/")) {
+            href = href.substring(0, href.length() - 1);
+        }
+
+        String resourcePath;
+        String workspacePath;
+
+        // an empty requestHandle (after removal of the "/") signifies a request
+        // to the root that does not represent a repository item.
+        if ("".equals(href)) {
+            resourcePath = null;
+            workspacePath = null;
+        } else {
+            // look for the first slash ignoring the leading one
+            int pos = href.indexOf('/', 1);
+            if (pos == -1) {
+                // request to a 'workspace' resource that in the same time
+                // represent the root node of the repository.
+                workspacePath = href;
+                resourcePath = ItemResourceConstants.ROOT_ITEM_PATH;
+            } else {
+                // separate the workspace name from the path of the repository
+                // item.
+                workspacePath = href.substring(0, pos);
+                resourcePath = Text.unescape(href.substring(pos));
+            }
+        }
 
-	return new DavResourceLocatorImpl(rlPrefix, workspacePath, resourcePath, this);
+        return new DavResourceLocatorImpl(rlPrefix, workspacePath, resourcePath, this);
     }
 
     /**
@@ -117,7 +119,20 @@
      * @see DavLocatorFactory#createResourceLocator(String, String, String)
      */
     public DavResourceLocator createResourceLocator(String prefix, String workspacePath, String resourcePath) {
-	return new DavResourceLocatorImpl(prefix, workspacePath, resourcePath, this);
+        return createResourceLocator(prefix, workspacePath, resourcePath, true);
+    }
+
+    /**
+     *
+     * @param prefix
+     * @param workspacePath
+     * @param path
+     * @param isResourcePath
+     * @return
+     * @see DavLocatorFactory#createResourceLocator(String, String, String, boolean)
+     */
+    public DavResourceLocator createResourceLocator(String prefix, String workspacePath, String path, boolean isResourcePath) {
+        return new DavResourceLocatorImpl(prefix, workspacePath, path, this);
     }
 
     /**
@@ -126,180 +141,185 @@
      */
     private class DavResourceLocatorImpl implements DavResourceLocator {
 
-	private final String prefix;
-	private final String workspacePath;
-	private final String resourcePath;
-	private final DavLocatorFactory factory;
-
-	/**
-	 * Create a new <code>DavResourceLocatorImpl</code>.
-	 *
-	 * @param prefix
-	 * @param workspacePath
-	 * @param resourcePath
-	 */
-	DavResourceLocatorImpl(String prefix, String workspacePath, String resourcePath, DavLocatorFactory factory) {
-	    this.prefix = prefix;
-	    this.workspacePath = workspacePath;
-	    this.resourcePath = resourcePath;
-	    this.factory = factory;
-	}
-
-	/**
-	 * Return the prefix used to build the href String. This includes the initial
-	 * hrefPrefix as well a the path prefix.
-	 *
-	 * @return prefix String used to build the href.
-	 */
-	public String getPrefix() {
-	    return prefix;
-	}
-
-	/**
-	 * Return the resource path of <code>null</code> if this locator object
-	 * represents the '/' request handle. To a request handle specifying a
-	 * workspace name only the '/' resource path is assigned, which represents
-	 * the root node of the repository.
-	 *
-	 * @return resource path or <code>null</code>
-	 * @see org.apache.jackrabbit.webdav.DavResourceLocator#getResourcePath()
-	 */
-	public String getResourcePath() {
-	    return resourcePath;
-	}
-
-	/**
-	 * Return the workspace path or <code>null</code> if this locator object
-	 * represents the '/' request handle.
-	 *
-	 * @return workspace path or <code>null</code>
-	 * @see org.apache.jackrabbit.webdav.DavResourceLocator#getWorkspacePath()
-	 */
-	public String getWorkspacePath() {
-	    return workspacePath;
-	}
-
-	/**
-	 * Return the workspace name or <code>null</code> if this locator object
-	 * represents the '/' request handle.
-	 *
-	 * @return workspace name or <code>null</code>
-	 * @see org.apache.jackrabbit.webdav.DavResourceLocator#getWorkspaceName()
-	 */
-	public String getWorkspaceName() {
-	    if (workspacePath != null) {
-		return workspacePath.substring(1);
-	    }
-	    return null;
-	}
-
-	/**
-	 * Returns true if the specified locator object refers to a resource within
-	 * the same workspace.
-	 *
-	 * @param locator
-	 * @return true if the workspace name is equal to this workspace name.
-	 * @see DavResourceLocator#isSameWorkspace(org.apache.jackrabbit.webdav.DavResourceLocator)
-	 */
-	public boolean isSameWorkspace(DavResourceLocator locator) {
-	    return (locator == null) ? false : isSameWorkspace(locator.getWorkspaceName());
-	}
-
-	/**
-	 * Returns true if the specified string equals to this workspace name or
-	 * if this workspace name is null.
-	 *
-	 * @param workspaceName
-	 * @return true if the workspace name is equal to this workspace name.
-	 * @see DavResourceLocator#isSameWorkspace(String)
-	 */
-	public boolean isSameWorkspace(String workspaceName) {
-	    if (getWorkspaceName() == null) {
-		return true;
-	    } else {
-		return getWorkspaceName().equals(workspaceName);
-	    }
-	}
-
-	/**
-	 * Builds the 'href' from the prefix, the workspace name and the
-	 * resource path present and assures a trailing '/' in case the href
-	 * is used for collection.
-	 *
-	 * @param isCollection
-	 * @return href String representing the text of the href element
-	 * @see org.apache.jackrabbit.webdav.DavConstants#XML_HREF
-	 * @see DavResourceLocator#getHref(boolean)
-	 */
-	public String getHref(boolean isCollection) {
-	    StringBuffer href = new StringBuffer(prefix);
-	    if (workspacePath != null) {
-		href.append(workspacePath);
-	    }
-	    if (resourcePath != null) {
-		href.append(resourcePath);
-	    }
-	    if (isCollection && href.charAt(href.length()-1) != '/') {
-		href.append("/");
-	    }
-	    return href.toString();
-	}
-
-	/**
-	 * Returns true if the 'workspaceName' field is <code>null</code>.
-	 *
-	 * @return true if the 'workspaceName' field is <code>null</code>.
-	 * @see org.apache.jackrabbit.webdav.DavResourceLocator#isRootLocation()
-	 */
-	public boolean isRootLocation() {
-	    return workspacePath == null;
-	}
-
-	/**
-	 * Return the factory that created this locator.
-	 *
-	 * @return factory
-	 * @see org.apache.jackrabbit.webdav.DavResourceLocator#getFactory()
-	 */
-	public DavLocatorFactory getFactory() {
-	    return factory;
-	}
-
-	/**
-	 * Computes the hash code using the prefix, the workspace name and the
-	 * resource path.
-	 *
-	 * @return the hash code
-	 */
-	public int hashCode() {
-	    int hashCode = prefix.hashCode();
-	    if (workspacePath != null) {
-		hashCode += workspacePath.hashCode();
-	    }
-	    if (resourcePath != null) {
-		hashCode += resourcePath.hashCode();
-	    }
-	    return hashCode % Integer.MAX_VALUE;
-	}
-
-	/**
-	 * Equality of locators is achieved if prefix and resource path
-	 * are equal.
-	 *
-	 * @param obj the object to compare to
-	 * @return <code>true</code> if the 2 objects are equal;
-	 *         <code>false</code> otherwise
-	 */
-	public boolean equals(Object obj) {
-	    if (obj instanceof DavResourceLocatorImpl) {
-		DavResourceLocatorImpl locator = (DavResourceLocatorImpl) obj;
-		boolean equalWsName = (workspacePath == null) ? locator.workspacePath == null : workspacePath.equals(locator.workspacePath);
-		boolean equalRPath = (resourcePath == null) ? locator.resourcePath == null : resourcePath.equals(locator.resourcePath);
-
-		return prefix.equals(locator.prefix) && equalWsName && equalRPath;
-	    }
-	    return false;
-	}
+        private final String prefix;
+        private final String workspacePath;
+        private final String resourcePath;
+        private final DavLocatorFactory factory;
+
+        private final String href;
+
+        /**
+         * Create a new <code>DavResourceLocatorImpl</code>.
+         *
+         * @param prefix
+         * @param workspacePath
+         * @param resourcePath
+         */
+        DavResourceLocatorImpl(String prefix, String workspacePath, String resourcePath, DavLocatorFactory factory) {
+            this.prefix = prefix;
+            this.workspacePath = workspacePath;
+            this.resourcePath = resourcePath;
+            this.factory = factory;
+
+            StringBuffer buf = new StringBuffer(prefix);
+            if (workspacePath != null) {
+                buf.append(workspacePath);
+            }
+            if (resourcePath != null) {
+                buf.append(Text.escapePath(resourcePath));
+            }
+            if (buf.charAt(buf.length() - 1) != '/') {
+                buf.append("/");
+            }
+            href = buf.toString();
+        }
+
+        /**
+         * Return the prefix used to build the href String. This includes the initial
+         * hrefPrefix as well a the path prefix.
+         *
+         * @return prefix String used to build the href.
+         */
+        public String getPrefix() {
+            return prefix;
+        }
+
+        /**
+         * Return the resource path of <code>null</code> if this locator object
+         * represents the '/' request handle. To a request handle specifying a
+         * workspace name only the '/' resource path is assigned, which represents
+         * the root node of the repository.
+         *
+         * @return resource path or <code>null</code>
+         * @see org.apache.jackrabbit.webdav.DavResourceLocator#getResourcePath()
+         */
+        public String getResourcePath() {
+            return resourcePath;
+        }
+
+        /**
+         * Return the workspace path or <code>null</code> if this locator object
+         * represents the '/' request handle.
+         *
+         * @return workspace path or <code>null</code>
+         * @see org.apache.jackrabbit.webdav.DavResourceLocator#getWorkspacePath()
+         */
+        public String getWorkspacePath() {
+            return workspacePath;
+        }
+
+        /**
+         * Return the workspace name or <code>null</code> if this locator object
+         * represents the '/' request handle.
+         *
+         * @return workspace name or <code>null</code>
+         * @see org.apache.jackrabbit.webdav.DavResourceLocator#getWorkspaceName()
+         */
+        public String getWorkspaceName() {
+            if (workspacePath != null) {
+                return workspacePath.substring(1);
+            }
+            return null;
+        }
+
+        /**
+         * Returns true if the specified locator object refers to a resource within
+         * the same workspace.
+         *
+         * @param locator
+         * @return true if the workspace name is equal to this workspace name.
+         * @see DavResourceLocator#isSameWorkspace(org.apache.jackrabbit.webdav.DavResourceLocator)
+         */
+        public boolean isSameWorkspace(DavResourceLocator locator) {
+            return (locator == null) ? false : isSameWorkspace(locator.getWorkspaceName());
+        }
+
+        /**
+         * Returns true if the specified string equals to this workspace name or
+         * if this workspace name is null.
+         *
+         * @param workspaceName
+         * @return true if the workspace name is equal to this workspace name.
+         * @see DavResourceLocator#isSameWorkspace(String)
+         */
+        public boolean isSameWorkspace(String workspaceName) {
+            if (getWorkspaceName() == null) {
+                return true;
+            } else {
+                return getWorkspaceName().equals(workspaceName);
+            }
+        }
+
+        /**
+         * Builds the 'href' from the prefix, the workspace name and the
+         * resource path present and assures a trailing '/' in case the href
+         * is used for collection. Note, that the resource path is
+         * {@link Text#escapePath(String) escaped}.
+         *
+         * @param isCollection
+         * @return href String representing the text of the href element
+         * @see org.apache.jackrabbit.webdav.DavConstants#XML_HREF
+         * @see DavResourceLocator#getHref(boolean)
+         */
+        public String getHref(boolean isCollection) {
+            return (isCollection) ? href : href.substring(0, href.length() - 1);
+        }
+
+        /**
+         * Returns true if the 'workspaceName' field is <code>null</code>.
+         *
+         * @return true if the 'workspaceName' field is <code>null</code>.
+         * @see org.apache.jackrabbit.webdav.DavResourceLocator#isRootLocation()
+         */
+        public boolean isRootLocation() {
+            return workspacePath == null;
+        }
+
+        /**
+         * Return the factory that created this locator.
+         *
+         * @return factory
+         * @see org.apache.jackrabbit.webdav.DavResourceLocator#getFactory()
+         */
+        public DavLocatorFactory getFactory() {
+            return factory;
+        }
+
+        /**
+         * Returns the same as {@link #getResourcePath()}. No encoding is performed
+         * at all.
+         * @see DavResourceLocator#getJcrPath()
+         */
+        public String getJcrPath() {
+            return getResourcePath();
+        }
+
+        /**
+         * Computes the hash code from the href, that is built from the prefix,
+         * the workspace name and the resource path all of them representing
+         * final instance fields.
+         *
+         * @return the hash code
+         */
+        public int hashCode() {
+            return href.hashCode();
+        }
+
+        /**
+         * Returns true, if the given object is a <code>DavResourceLocator</code>
+         * with the same hash code.
+         *
+         * @param obj the object to compare to
+         * @return <code>true</code> if the 2 objects are equal;
+         *         <code>false</code> otherwise
+         */
+        public boolean equals(Object obj) {
+            if (obj instanceof DavResourceLocator) {
+                DavResourceLocator other = (DavResourceLocator) obj;
+                return hashCode() == other.hashCode();
+            }
+            return false;
+        }
     }
 }
 

Modified: incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/DavResourceFactoryImpl.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/DavResourceFactoryImpl.java?rev=293331&r1=293330&r2=293331&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/DavResourceFactoryImpl.java (original)
+++ incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/DavResourceFactoryImpl.java Mon Oct  3 06:12:18 2005
@@ -73,7 +73,6 @@
                                       DavServletResponse response) throws DavException {
 
         DavSession session = request.getDavSession();
-
         DavResource resource;
         if (locator.isRootLocation()) {
             resource = new RootCollection(locator, session, this);
@@ -87,9 +86,9 @@
                 if (request instanceof DeltaVServletRequest && isVersionControlled(resource)) {
                     String labelHeader = ((DeltaVServletRequest)request).getLabel();
                     if (labelHeader != null && DavMethods.isMethodAffectedByLabel(request.getMethod())) {
-                        Item item = session.getRepositorySession().getItem(locator.getResourcePath());
+                        Item item = getItem(session, locator);
                         Version v = ((Node)item).getVersionHistory().getVersionByLabel(labelHeader);
-                        DavResourceLocator vloc = locator.getFactory().createResourceLocator(locator.getPrefix(), locator.getWorkspacePath(), v.getPath());
+                        DavResourceLocator vloc = locator.getFactory().createResourceLocator(locator.getPrefix(), locator.getWorkspacePath(), v.getPath(), false);
                         resource =  new VersionItemCollection(vloc, session, this, v);
                     }
                 }
@@ -157,14 +156,14 @@
      */
     private DavResource createResourceForItem(DavResourceLocator locator, DavSession session) throws RepositoryException {
         DavResource resource;
-        Item item = session.getRepositorySession().getItem(locator.getResourcePath());
+        Item item = getItem(session, locator);
         if (item.isNode()) {
             // create special resources for Version and VersionHistory
             if (item instanceof Version) {
                 resource = new VersionItemCollection(locator, session, this, item);
             } else if (item instanceof VersionHistory) {
                 resource = new VersionHistoryItemCollection(locator, session, this, item);
-            } else if (ItemResourceConstants.ROOT_ITEM_PATH.equals(locator.getResourcePath())) {
+            } else if (ItemResourceConstants.ROOT_ITEM_PATH.equals(item.getPath())) {
                 resource =  new RootItemCollection(locator, session, this, item);
             }  else{
                 resource = new VersionControlledItemCollection(locator, session, this, item);
@@ -173,6 +172,11 @@
             resource = new DefaultItemResource(locator, session, this, item);
         }
         return resource;
+    }
+
+    private Item getItem(DavSession davSession, DavResourceLocator locator) throws PathNotFoundException, RepositoryException {
+        Session s = davSession.getRepositorySession();
+        return s.getItem(locator.getJcrPath());
     }
 
     /**

Modified: incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/DefaultItemCollection.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/DefaultItemCollection.java?rev=293331&r1=293330&r2=293331&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/DefaultItemCollection.java (original)
+++ incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/DefaultItemCollection.java Mon Oct  3 06:12:18 2005
@@ -115,7 +115,6 @@
      * @throws org.apache.jackrabbit.webdav.DavException
      * @see org.apache.jackrabbit.webdav.DavResource#setProperty(org.apache.jackrabbit.webdav.property.DavProperty)
      * @see #JCR_MIXINNODETYPES
-     * @todo undo incomplete modifications...
      */
     public void setProperty(DavProperty property) throws DavException {
         internalSetProperty(property);
@@ -135,8 +134,8 @@
             throw new DavException(DavServletResponse.SC_NOT_FOUND);
         }
         if (property.getName().equals(JCR_MIXINNODETYPES)) {
+            Node n = (Node)item;
             try {
-                Node n = (Node)item;
                 NodeType[] existingMixin = n.getMixinNodeTypes();
                 NodeTypeProperty mix = new NodeTypeProperty(property);
                 Set mixins = mix.getNodeTypeNames();
@@ -174,7 +173,6 @@
      * @throws org.apache.jackrabbit.webdav.DavException
      * @see org.apache.jackrabbit.webdav.DavResource#removeProperty(org.apache.jackrabbit.webdav.property.DavPropertyName)
      * @see #JCR_MIXINNODETYPES
-     * @todo undo incomplete modifications...
      */
     public void removeProperty(DavPropertyName propertyName) throws DavException {
         internalRemoveProperty(propertyName);
@@ -212,27 +210,41 @@
     }
 
     /**
+     * Loops over the given <code>Set</code>s and alters the properties accordingly.
+     * Changes are persisted at the end according to the rules defined with
+     * the {@link #complete()} method.<p>
+     * Please note: since there is only a single property ({@link #JCR_MIXINNODETYPES}
+     * that can be set or removed with PROPPATCH, this method either succeeds
+     * or throws an exception, even if this violates RFC 2518. Thus no property
+     * specific multistatus will be created in case of an error.
      *
      * @param setProperties
      * @param removePropertyNames
+     * @return
      * @throws DavException
-     * @todo undo incomplete modifications...
+     * @see DavResource#alterProperties(org.apache.jackrabbit.webdav.property.DavPropertySet, org.apache.jackrabbit.webdav.property.DavPropertyNameSet)
      */
-    public void alterProperties(DavPropertySet setProperties,
+    public MultiStatusResponse alterProperties(DavPropertySet setProperties,
                                 DavPropertyNameSet removePropertyNames)
         throws DavException {
         DavPropertyIterator setIter = setProperties.iterator();
         while (setIter.hasNext()) {
             DavProperty prop = setIter.nextProperty();
+            // use the internal set method in order to prevent premature 'save'
             internalSetProperty(prop);
         }
         Iterator remNameIter = removePropertyNames.iterator();
         while (remNameIter.hasNext()) {
             DavPropertyName propName = (DavPropertyName) remNameIter.next();
+            // use the internal set method in order to prevent premature 'save'
             internalRemoveProperty(propName);
         }
-        // save all changes together
+        // TODO: missing undo of successful set/remove if subsequent operation fails
+        // NOTE, that this is relevant with transactions only.
+
+        // success: save all changes together if no error occured
         complete();
+        return new MultiStatusResponse(getHref(), DavServletResponse.SC_OK);
     }
 
     /**
@@ -268,20 +280,21 @@
         try {
             Node n = (Node) item;
             InputStream in = (inputCxt != null) ? inputCxt.getInputStream() : null;
+            String itemPath = getLocator().getJcrPath();
             if (resource.isCollection()) {
                 if (in == null) {
                     // MKCOL without a request body, try if a default-primary-type is defined.
-                    n.addNode(resource.getDisplayName());
+                    n.addNode(getItemName(itemPath));
                 } else {
                     // MKCOL, which is not allowed for existing resources
                     if (getTransactionId() == null) {
                         // if not part of a transaction directely import on workspace
                         // since changes would be explicitely saved in the
                         // complete-call.
-                        getRepositorySession().getWorkspace().importXML(getResourcePath(), in, ImportUUIDBehavior.IMPORT_UUID_CREATE_NEW);
+                        getRepositorySession().getWorkspace().importXML(itemPath, in, ImportUUIDBehavior.IMPORT_UUID_CREATE_NEW);
                     } else {
                         // changes will not be persisted unless the tx is completed.
-                        getRepositorySession().importXML(getResourcePath(), in, ImportUUIDBehavior.IMPORT_UUID_CREATE_NEW);
+                        getRepositorySession().importXML(itemPath, in, ImportUUIDBehavior.IMPORT_UUID_CREATE_NEW);
                     }
                 }
             } else {
@@ -292,7 +305,7 @@
                     // TODO: find a way to create non-binary and multivalue properties
                     // PUT : create new or overwrite existing property.
                     // NOTE: will fail for multivalue properties.
-                    n.setProperty(getResourceName(resource.getResourcePath(), true), in);
+                    n.setProperty(getItemName(itemPath), in);
                 }
             }
             complete();
@@ -360,13 +373,14 @@
     public void removeMember(DavResource member) throws DavException {
         Session session = getRepositorySession();
         try {
-            if (!exists() || !session.itemExists(member.getResourcePath())) {
+            String itemPath = member.getLocator().getJcrPath();
+            if (!exists() || !session.itemExists(itemPath)) {
                 throw new DavException(DavServletResponse.SC_NOT_FOUND);
             }
             if (!getResourcePath().equals(Text.getRelativeParent(member.getResourcePath(), 1))) {
                 throw new DavException(DavServletResponse.SC_CONFLICT, member.getResourcePath() + "is not member of this resource (" + getResourcePath() + ")");
             }
-            session.getItem(member.getResourcePath()).remove();
+            getRepositorySession().getItem(itemPath).remove();
             complete();
         } catch (RepositoryException e) {
             log.error("Unexpected error: " + e.getMessage());
@@ -600,10 +614,10 @@
         Node n = (Node)item;
         try {
             for (int i = 0; i < instructions.length; i++) {
-                String srcRelPath = getResourceName(n.getPath() + instructions[i].getMemberHandle(), false);
+                String srcRelPath = Text.getName(instructions[i].getMemberHandle());
                 Position pos = instructions[i].getPosition();
                 String destRelPath = getRelDestinationPath(pos, n.getNodes());
-
+                // preform the reordering
                 n.orderBefore(srcRelPath, destRelPath);
             }
         } catch (RepositoryException e) {
@@ -626,36 +640,34 @@
     private String getRelDestinationPath(Position position, NodeIterator childNodes)
             throws RepositoryException {
 
-        String destRelPath = null;
+        String destPath = null;
         if (position.getType() == Position.TYPE_FIRST) {
-            while (childNodes.hasNext()) {
+            if (childNodes.hasNext()) {
                 Node firstChild = childNodes.nextNode();
-                destRelPath = firstChild.getPath();
+                destPath = firstChild.getPath();
             }
             // no child nodes available > reordering to 'first' position fails.
-            if (destRelPath == null) {
+            if (destPath == null) {
                 throw new ItemNotFoundException("No 'first' item found for reordering.");
             }
         } else if (position.getType() == Position.TYPE_AFTER) {
-            String afterRelPath = getResourceName(position.getSegment(), false);
+            String afterRelPath = Text.getName(position.getSegment());
             boolean found = false;
-            while (childNodes.hasNext() && destRelPath == null) {
+            // jcr only knows order-before > retrieve the node that follows the
+            // one incidated by the 'afterRelPath'.
+            while (childNodes.hasNext() && destPath == null) {
                 String childPath = childNodes.nextNode().getPath();
                 if (found) {
-                    destRelPath = childPath;
+                    destPath = childPath;
                 } else {
                     found = afterRelPath.equals(Text.getName(childPath));
                 }
             }
         } else {
-            destRelPath = position.getSegment();
+            destPath = position.getSegment();
         }
 
-        if (destRelPath != null) {
-            destRelPath = getResourceName(destRelPath, false);
-        }
-
-        return destRelPath;
+        return (destPath != null) ? Text.getName(destPath) : destPath;
     }
 
     //--------------------------------------------------------------------------
@@ -747,17 +759,17 @@
 	    try {
                 properties.add(new NodeTypeProperty(JCR_PRIMARYNODETYPE, n.getPrimaryNodeType(), false));
                 properties.add(new NodeTypeProperty(JCR_MIXINNODETYPES, n.getMixinNodeTypes(), false));
-                properties.add(new DefaultDavProperty(JCR_INDEX, new Integer(n.getIndex())));
-		addHrefProperty(JCR_REFERENCES, n.getReferences(), false);
+                properties.add(new DefaultDavProperty(JCR_INDEX, new Integer(n.getIndex()), true));
+                addHrefProperty(JCR_REFERENCES, n.getReferences(), true);
                 if (n.isNodeType(JcrConstants.MIX_REFERENCEABLE)) {
-                    properties.add(new DefaultDavProperty(JCR_UUID, n.getUUID()));
+                    properties.add(new DefaultDavProperty(JCR_UUID, n.getUUID(), true));
                 }
             } catch (RepositoryException e) {
                 log.error("Failed to retrieve primary nodetype property: " + e.getMessage());
             }
             try {
                 Item primaryItem = n.getPrimaryItem();
-                addHrefProperty(JCR_PRIMARYITEM, new Item[] {primaryItem}, false);
+                addHrefProperty(JCR_PRIMARYITEM, new Item[] {primaryItem}, true);
             } catch (ItemNotFoundException e) {
                 log.info("No primary item present on this node '" + getResourcePath() + "'");
             } catch (RepositoryException e) {
@@ -784,15 +796,11 @@
         if (values == null) {
             return;
         }
-        try {
-            String[] pHref = new String[values.length];
-            for (int i = 0; i < values.length; i++) {
-                pHref[i] = getLocatorFromResourcePath(values[i].getPath()).getHref(true);
-            }
-            properties.add(new HrefProperty(name, pHref, isProtected));
-        } catch (RepositoryException e) {
-            e.getMessage();
+        String[] pHref = new String[values.length];
+        for (int i = 0; i < values.length; i++) {
+            pHref[i] = getLocatorFromItem(values[i]).getHref(true);
         }
+        properties.add(new HrefProperty(name, pHref, isProtected));
     }
 
     /**

Modified: incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/DefaultItemResource.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/DefaultItemResource.java?rev=293331&r1=293330&r2=293331&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/DefaultItemResource.java (original)
+++ incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/DefaultItemResource.java Mon Oct  3 06:12:18 2005
@@ -97,8 +97,6 @@
      * @param property
      * @throws DavException
      * @see DavResource#setProperty(org.apache.jackrabbit.webdav.property.DavProperty)
-     *
-     * todo: undo incomplete modifications...
      */
     public void setProperty(DavProperty property) throws DavException {
         internalSetProperty(property);
@@ -155,20 +153,26 @@
     /**
      * Loops over the given <code>Set</code>s and alters the properties accordingly.
      * Changes are persisted at the end only according to the rules defined with
-     * the {@link #complete()} method.
+     * the {@link #complete()} method.<p>
+     * Please note: since there is only a single property than can be set
+     * from a client (i.e. jcr:value OR jcr:values) this method either succeeds
+     * or throws an exception, even if this violates RFC 2518.
      *
      * @param setProperties
      * @param removePropertyNames
      * @throws DavException
      * @see DavResource#alterProperties(DavPropertySet, DavPropertyNameSet)
      */
-    public void alterProperties(DavPropertySet setProperties,
+    public MultiStatusResponse alterProperties(DavPropertySet setProperties,
                                 DavPropertyNameSet removePropertyNames)
         throws DavException {
 
         // altering any properties fails if an attempt is made to remove a property
         if (removePropertyNames != null && !removePropertyNames.isEmpty()) {
-            throw new DavException(DavServletResponse.SC_FORBIDDEN);
+            Iterator it = removePropertyNames.iterator();
+            while (it.hasNext()) {
+                throw new DavException(DavServletResponse.SC_FORBIDDEN);
+            }
         }
 
         // only set/add >> existance of resource is checked inside internal method
@@ -178,12 +182,13 @@
             internalSetProperty(prop);
         }
         complete();
+        return new MultiStatusResponse(getHref(), DavServletResponse.SC_OK);
     }
 
     /**
      * Method is not allowed.
      *
-     * @see org.apache.jackrabbit.webdav.DavResource#addMember(org.apache.jackrabbit.webdav.DavResource, InputStream)
+     * @see org.apache.jackrabbit.webdav.DavResource#addMember(org.apache.jackrabbit.webdav.DavResource, InputContext)
      */
     public void addMember(DavResource resource, InputContext inputCxt) throws DavException {
         throw new DavException(DavServletResponse.SC_METHOD_NOT_ALLOWED, "Cannot add members to a non-collection resource");
@@ -264,7 +269,7 @@
                     properties.add(new LengthsProperty(prop.getLengths()));
                 } else {
                     properties.add(new DefaultDavProperty(JCR_VALUE, ValueHelper.serialize(prop.getValue(), false)));
-                    properties.add(new DefaultDavProperty(JCR_LENGTH, String.valueOf(prop.getLength())));
+                    properties.add(new DefaultDavProperty(JCR_LENGTH, String.valueOf(prop.getLength()), true));
                 }
             } catch (RepositoryException e) {
                 log.error("Failed to retrieve resource properties: "+e.getMessage());

Modified: incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/JcrDavException.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/JcrDavException.java?rev=293331&r1=293330&r2=293331&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/JcrDavException.java (original)
+++ incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/JcrDavException.java Mon Oct  3 06:12:18 2005
@@ -25,6 +25,7 @@
 import javax.jcr.lock.LockException;
 import javax.jcr.version.VersionException;
 import javax.jcr.nodetype.*;
+import java.util.HashMap;
 
 /**
  * <code>JcrDavException</code> extends the {@link DavException} in order to
@@ -34,6 +35,30 @@
 
     private static Logger log = Logger.getLogger(JcrDavException.class);
 
+    // mapping of Jcr exceptions to error codes.
+    private static HashMap codeMap = new HashMap();
+    static {
+        codeMap.put(AccessDeniedException.class, new Integer(DavServletResponse.SC_FORBIDDEN));
+        codeMap.put(ConstraintViolationException.class, new Integer(DavServletResponse.SC_CONFLICT));
+        codeMap.put(InvalidItemStateException.class, new Integer(DavServletResponse.SC_CONFLICT));
+        codeMap.put(InvalidSerializedDataException.class, new Integer(DavServletResponse.SC_BAD_REQUEST));
+        codeMap.put(InvalidQueryException.class, new Integer(DavServletResponse.SC_BAD_REQUEST));
+        codeMap.put(ItemExistsException.class, new Integer(DavServletResponse.SC_CONFLICT));
+        codeMap.put(ItemNotFoundException.class, new Integer(DavServletResponse.SC_FORBIDDEN));
+        codeMap.put(LockException.class, new Integer(DavServletResponse.SC_LOCKED));
+        codeMap.put(MergeException.class, new Integer(DavServletResponse.SC_CONFLICT));
+        codeMap.put(NamespaceException.class, new Integer(DavServletResponse.SC_CONFLICT));
+        codeMap.put(NoSuchNodeTypeException.class, new Integer(DavServletResponse.SC_CONFLICT));
+        codeMap.put(NoSuchWorkspaceException.class, new Integer(DavServletResponse.SC_CONFLICT));
+        codeMap.put(PathNotFoundException.class, new Integer(DavServletResponse.SC_CONFLICT));
+        codeMap.put(ReferentialIntegrityException.class, new Integer(DavServletResponse.SC_CONFLICT));
+        codeMap.put(RepositoryException.class, new Integer(DavServletResponse.SC_FORBIDDEN));
+        codeMap.put(LoginException.class, new Integer(DavServletResponse.SC_UNAUTHORIZED));
+        codeMap.put(UnsupportedRepositoryOperationException.class, new Integer(DavServletResponse.SC_NOT_IMPLEMENTED));
+        codeMap.put(ValueFormatException.class, new Integer(DavServletResponse.SC_CONFLICT));
+        codeMap.put(VersionException.class, new Integer(DavServletResponse.SC_CONFLICT));
+    }
+
     private Class exceptionClass;
 
     public JcrDavException(Exception e, int errorCode) {
@@ -41,80 +66,8 @@
         exceptionClass = e.getClass();
     }
 
-    public JcrDavException(AccessDeniedException e) {
-        this(e, DavServletResponse.SC_FORBIDDEN);
-    }
-
-    public JcrDavException(ConstraintViolationException e) {
-        this(e, DavServletResponse.SC_CONFLICT);
-    }
-
-    public JcrDavException(InvalidItemStateException e) {
-        this(e, DavServletResponse.SC_CONFLICT);
-    }
-
-    public JcrDavException(InvalidSerializedDataException e) {
-        this(e, DavServletResponse.SC_BAD_REQUEST);
-    }
-
-    public JcrDavException(InvalidQueryException e) {
-        this(e, DavServletResponse.SC_BAD_REQUEST);
-    }
-
-    public JcrDavException(ItemExistsException e) {
-        this(e, DavServletResponse.SC_CONFLICT);
-    }
-
-    public JcrDavException(ItemNotFoundException e) {
-        this(e, DavServletResponse.SC_FORBIDDEN);
-    }
-
-    public JcrDavException(LockException e) {
-        this(e, DavServletResponse.SC_LOCKED);
-    }
-
-    public JcrDavException(MergeException e) {
-        this(e, DavServletResponse.SC_CONFLICT);
-    }
-
-    public JcrDavException(NamespaceException e) {
-        this(e, DavServletResponse.SC_CONFLICT);
-    }
-
-    public JcrDavException(NoSuchNodeTypeException e) {
-        this(e, DavServletResponse.SC_CONFLICT);
-    }
-
-    public JcrDavException(NoSuchWorkspaceException e) {
-        this(e, DavServletResponse.SC_CONFLICT);
-    }
-
-    public JcrDavException(PathNotFoundException e) {
-        this(e, DavServletResponse.SC_CONFLICT);
-    }
-
-    public JcrDavException(ReferentialIntegrityException e) {
-        this(e, DavServletResponse.SC_CONFLICT);
-    }
-
     public JcrDavException(RepositoryException e) {
-        this(e, DavServletResponse.SC_FORBIDDEN);
-    }
-
-    public JcrDavException(LoginException e) {
-        this(e, DavServletResponse.SC_UNAUTHORIZED);
-    }
-
-    public JcrDavException(UnsupportedRepositoryOperationException e) {
-        this(e, DavServletResponse.SC_NOT_IMPLEMENTED);
-    }
-
-    public JcrDavException(ValueFormatException e) {
-        this(e, DavServletResponse.SC_CONFLICT);
-    }
-
-    public JcrDavException(VersionException e) {
-        this(e, DavServletResponse.SC_CONFLICT);
+        this(e, ((Integer)codeMap.get(e.getClass())).intValue());
     }
 
     /**

Modified: incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/RootCollection.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/RootCollection.java?rev=293331&r1=293330&r2=293331&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/RootCollection.java (original)
+++ incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/RootCollection.java Mon Oct  3 06:12:18 2005
@@ -27,7 +27,6 @@
 import javax.jcr.RepositoryException;
 import javax.jcr.Session;
 import java.util.*;
-import java.io.InputStream;
 
 /**
  * <code>RootCollection</code> represent the WebDAV root resource that does not
@@ -120,7 +119,7 @@
 
     /**
      * Throws exception: 403 Forbidden.
-     * @see DavResource#addMember(DavResource, InputStream)
+     * @see DavResource#addMember(DavResource, InputContext)
      */
     public void addMember(DavResource resource, InputContext inputCxt) throws DavException {
         throw new DavException(DavServletResponse.SC_FORBIDDEN);
@@ -196,7 +195,7 @@
      * @see AbstractResource#getWorkspaceHref()
      */
     protected String getWorkspaceHref() {
-        Session session = this.getRepositorySession();
+        Session session = getRepositorySession();
         if (session != null) {
             String workspaceName = session.getWorkspace().getName();
             DavResourceLocator loc = getLocator().getFactory().createResourceLocator(getLocator().getPrefix(), "/"+workspaceName, ItemResourceConstants.ROOT_ITEM_PATH);

Modified: incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/RootItemCollection.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/RootItemCollection.java?rev=293331&r1=293330&r2=293331&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/RootItemCollection.java (original)
+++ incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/webdav/jcr/RootItemCollection.java Mon Oct  3 06:12:18 2005
@@ -79,11 +79,13 @@
 
     /**
      * Allows to alter the registered namespaces ({@link #JCR_NAMESPACES}) and
-     * forwards any other property to the super class.
+     * forwards any other property to the super class.<p/>
+     * Note that again no property status is set. Any failure while setting
+     * a property results in an exception (violating RFC 2518).
      *
      * @param property
      * @throws DavException
-     * @see VersionControlledItemCollection#setProperty(org.apache.jackrabbit.webdav.property.DavProperty)
+     * @see DavResource#setProperty(org.apache.jackrabbit.webdav.property.DavProperty)
      */
     public void setProperty(DavProperty property) throws DavException {
         if (JCR_NAMESPACES.equals(property.getName())) {
@@ -139,15 +141,22 @@
     }
 
     /**
+     * Handles an attempt to set {@link #JCR_NAMESPACES} and forwards any other
+     * set or remove requests to the super class.
+     * Please note, that RFC 2518 is violated because setting {@link #JCR_NAMESPACES}
+     * is handled out of the order indicated by the set and changes may be persisted
+     * even if altering another property fails.
+     *
      * @see #setProperty(DavProperty)
-     * @see DavResource#alterProperties(org.apache.jackrabbit.webdav.property.DavPropertySet, org.apache.jackrabbit.webdav.property.DavPropertyNameSet)
+     * @see DefaultItemCollection#alterProperties(org.apache.jackrabbit.webdav.property.DavPropertySet, org.apache.jackrabbit.webdav.property.DavPropertyNameSet)
      */
-    public void alterProperties(DavPropertySet setProperties, DavPropertyNameSet removePropertyNames) throws DavException {
+    public MultiStatusResponse alterProperties(DavPropertySet setProperties, DavPropertyNameSet removePropertyNames) throws DavException {
+        // TODO: respect order of the set and do not persist if super.alterProperties fails
         if (setProperties.contains(JCR_NAMESPACES)) {
             setProperty(setProperties.remove(JCR_NAMESPACES));
         }
         // let super-class handle the rest of the properties
-        super.alterProperties(setProperties, removePropertyNames);
+        return super.alterProperties(setProperties, removePropertyNames);
     }
 
     //--------------------------------------------------------------------------
@@ -166,7 +175,7 @@
             }
             properties.add(new DefaultDavProperty(JCR_NAMESPACES, nsElems, false));
         } catch (RepositoryException e) {
-            log.error("Failed to access NamespaceRegistry from the session/workspace: " + e.getMessage());
+            log.error("Failed to access NamespaceRegistry: " + e.getMessage());
         }
     }
 }



Mime
View raw message