You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by an...@apache.org on 2010/02/25 14:10:45 UTC

svn commit: r916278 - in /jackrabbit/trunk: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/ jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/ jackrabbit-spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/ jackrabbit...

Author: angela
Date: Thu Feb 25 13:10:45 2010
New Revision: 916278

URL: http://svn.apache.org/viewvc?rev=916278&view=rev
Log:
JCR-2519: spi2davex: use srcWorkspaceName to build srcPath for clone and copy
JCR-2104: JSR 283 Full Versioning 
- jcr2spi: simplify VersionManager.checkpoint if Node is already checkedin
- spi2dav: implement shallow merge
- spi2dav: fix bug in merge (besteffort <-> DAV:no-auto-merge)
- spi2dav: fix bug in restore (nodeId may point to non-existing node -> extract existing parent + relPath
- jcr-server: implement shallow merge
- jcr-server: fix merge. for 1:1 remoting the MERGE response body should list the failed ids instead of the affected resource [DeltaV specified behaviour that doesn't make sense for remoting over SPI]
- jcr-server: prefer VersionManager over deprecated version methods
- jcr-server: fix restore with relPath


Modified:
    jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/VersionControlledItemCollection.java
    jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/NodeImpl.java
    jackrabbit/trunk/jackrabbit-spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/RepositoryServiceImpl.java
    jackrabbit/trunk/jackrabbit-spi2dav/src/main/java/org/apache/jackrabbit/spi2davex/RepositoryServiceImpl.java

Modified: jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/VersionControlledItemCollection.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/VersionControlledItemCollection.java?rev=916278&r1=916277&r2=916278&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/VersionControlledItemCollection.java (original)
+++ jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/VersionControlledItemCollection.java Thu Feb 25 13:10:45 2010
@@ -17,6 +17,7 @@
 package org.apache.jackrabbit.webdav.jcr;
 
 import org.apache.jackrabbit.JcrConstants;
+import org.apache.jackrabbit.webdav.DavConstants;
 import org.apache.jackrabbit.webdav.DavException;
 import org.apache.jackrabbit.webdav.DavLocatorFactory;
 import org.apache.jackrabbit.webdav.DavResource;
@@ -54,6 +55,7 @@
 import javax.jcr.observation.EventListener;
 import javax.jcr.version.Version;
 import javax.jcr.version.VersionHistory;
+import javax.jcr.version.VersionManager;
 import java.util.List;
 import java.util.Collections;
 
@@ -153,6 +155,9 @@
         }
         try {
             Node n = (Node) item;
+            VersionManager vMgr = getVersionManager();
+            String path = item.getPath();
+
             DavProperty<?> autoMergeSet = null;
             DavProperty<?> predecessorSet = null;
             /* find DAV:auto-merge-set entries. If none exists no attempt is made
@@ -168,7 +173,7 @@
                     }
                     Value[] mergeFailed = n.getProperty(JcrConstants.JCR_MERGEFAILED).getValues();
                     for (Value value : mergeFailed) {
-                        n.cancelMerge((Version) getRepositorySession().getNodeByUUID(value.getString()));
+                        vMgr.cancelMerge(path, (Version) getRepositorySession().getNodeByIdentifier(value.getString()));
                     }
                     // remove this entry from the changeList
                     changeList.remove(propEntry);
@@ -204,7 +209,7 @@
                 for (Value value : mergeFailed) {
                     // build version-href from each entry in the jcr:mergeFailed property
                     // in order to be able to compare to the entries in the HrefProperty.
-                    Version version = (Version) session.getNodeByUUID(value.getString());
+                    Version version = (Version) session.getNodeByIdentifier(value.getString());
                     String href = getLocatorFromItem(version).getHref(true);
 
                     // Test if that version has been removed from the merge-set.
@@ -216,9 +221,9 @@
                         // merge-set but not added to the predecessors 'cancelMerge'
                         // must be called.
                         if (predecL.contains(href)) {
-                            n.doneMerge(version);
+                            vMgr.doneMerge(path, version);
                         } else {
-                            n.cancelMerge(version);
+                            vMgr.cancelMerge(path, version);
                         }
                     }
                 }
@@ -273,7 +278,7 @@
             throw new DavException(DavServletResponse.SC_METHOD_NOT_ALLOWED);
         }
         try {
-            Version v = ((Node) item).checkin();
+            Version v = getVersionManager().checkin(item.getPath());
             String versionHref = getLocatorFromItem(v).getHref(true);
             return versionHref;
         } catch (RepositoryException e) {
@@ -296,7 +301,7 @@
             throw new DavException(DavServletResponse.SC_METHOD_NOT_ALLOWED);
         }
         try {
-            ((Node) item).checkout();
+            getVersionManager().checkout(item.getPath());
         } catch (RepositoryException e) {
             // UnsupportedRepositoryException should not occur
             throw new JcrDavException(e);
@@ -365,8 +370,11 @@
                 if (relPath == null) {
                     // restore version by name
                     node.restore(versionName, removeExisting);
+                } else if (node.hasNode(relPath)) {
+                    Version v = node.getNode(relPath).getVersionHistory().getVersion(versionName);
+                    node.restore(v, relPath, removeExisting);
                 } else {
-                    Version v = node.getVersionHistory().getVersion(versionName);
+                    Version v = (Version) getRepositorySession().getNode(versionPath);
                     node.restore(v, relPath, removeExisting);
                 }
 
@@ -416,19 +424,18 @@
 
         MultiStatus ms = new MultiStatus();
         try {
-            Node node = (Node)item;
-
-            // register eventListener in order to be able to report all
-            // modified resources.
-            EventListener el = new EListener(mergeInfo.getPropertyNameSet(), ms);
-            registerEventListener(el, node.getPath());
-
+            // NOTE: RFC requires that all modified resources are reported in the
+            // multistatus response. this doesn't work however with the remoting
+            // there is no way to distinguish the 'failedId's from any other
+            // resources that got modified by this merge operation -> omitted.
+            
             // todo: RFC allows multiple href elements inside the DAV:source element
             String workspaceName = getLocatorFromHref(mergeInfo.getSourceHrefs()[0]).getWorkspaceName();
-            NodeIterator failed = node.merge(workspaceName, !mergeInfo.isNoAutoMerge());
 
-            // unregister the event listener again
-            unregisterEventListener(el);
+            String depth = DomUtil.getChildTextTrim(mergeInfo.getMergeElement(), DavConstants.XML_DEPTH, DavConstants.NAMESPACE);
+            boolean isShallow = "0".equals(depth);
+
+            NodeIterator failed = getVersionManager().merge(item.getPath(), workspaceName, !mergeInfo.isNoAutoMerge(), isShallow);
 
             // add resources to the multistatus, that failed to be merged
             while (failed.hasNext()) {
@@ -612,4 +619,8 @@
         String prefix = getLocator().getPrefix();
         return f.createResourceLocator(prefix, href);
     }
+
+    private VersionManager getVersionManager() throws RepositoryException {
+        return getRepositorySession().getWorkspace().getVersionManager();
+    }
 }

Modified: jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/NodeImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/NodeImpl.java?rev=916278&r1=916277&r2=916278&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/NodeImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/NodeImpl.java Thu Feb 25 13:10:45 2010
@@ -898,8 +898,13 @@
         checkIsVersionable();
         checkHasPendingChanges();
         checkIsLocked();
-        NodeEntry newVersion = session.getVersionStateManager().checkpoint(getNodeState());
-        return (Version) getItemManager().getItem(newVersion);
+        if (!isCheckedOut()) {
+            checkout();
+            return getBaseVersion();
+        } else {
+            NodeEntry newVersion = session.getVersionStateManager().checkpoint(getNodeState());
+            return (Version) getItemManager().getItem(newVersion);
+        }
     }
 
     /**

Modified: jackrabbit/trunk/jackrabbit-spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/RepositoryServiceImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/RepositoryServiceImpl.java?rev=916278&r1=916277&r2=916278&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/RepositoryServiceImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/RepositoryServiceImpl.java Thu Feb 25 13:10:45 2010
@@ -65,6 +65,7 @@
 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.HeadMethod;
 import org.apache.commons.httpclient.methods.InputStreamRequestEntity;
 import org.apache.commons.httpclient.methods.RequestEntity;
 import org.apache.commons.httpclient.methods.StringRequestEntity;
@@ -402,7 +403,11 @@
     }
 
     protected String getItemUri(ItemId itemId, SessionInfo sessionInfo) throws RepositoryException {
-        return uriResolver.getItemUri(itemId, sessionInfo.getWorkspaceName(), sessionInfo);
+        return getItemUri(itemId, sessionInfo, sessionInfo.getWorkspaceName());
+    }
+
+    protected String getItemUri(ItemId itemId, SessionInfo sessionInfo, String workspaceName) throws RepositoryException {
+        return uriResolver.getItemUri(itemId, workspaceName, sessionInfo);
     }
 
     /**
@@ -1111,10 +1116,11 @@
 
             boolean isMultiValued;
             QValue[] values;
-            int type = JcrValueType.typeFromContentType(ct);
+            int type;
 
             NamePathResolver resolver = getNamePathResolver(sessionInfo);
-            if (type != PropertyType.UNDEFINED) {
+            if (ct.startsWith("jcr-value")) {
+                type = JcrValueType.typeFromContentType(ct);                
                 QValue v;
                 if (type == PropertyType.BINARY) {
                     v = getQValueFactory().create(method.getResponseBodyAsStream());
@@ -1144,6 +1150,7 @@
             }
 
             return new PropertyInfoImpl(propertyId, path, type, isMultiValued, values);
+            
         } catch (IOException e) {
             throw new RepositoryException(e);
         } catch (DavException e) {
@@ -1322,7 +1329,7 @@
         String uri = getItemUri(nodeId, sessionInfo);
         String workspUri = uriResolver.getWorkspaceUri(srcWorkspaceName);
 
-        update(uri, new String[] {workspUri}, UpdateInfo.UPDATE_BY_WORKSPACE, false, sessionInfo);
+        update(uri, null, new String[] {workspUri}, UpdateInfo.UPDATE_BY_WORKSPACE, false, sessionInfo);
     }
 
     /**
@@ -1502,16 +1509,22 @@
      * @see RepositoryService#checkout(SessionInfo, NodeId, NodeId)
      */
     public void checkout(SessionInfo sessionInfo, NodeId nodeId, NodeId activityId) throws UnsupportedRepositoryOperationException, LockException, RepositoryException {
-        // TODO
-        throw new UnsupportedOperationException("JCR-2104: JSR 283 Versioning. Implementation missing");
+        if (activityId == null) {
+            checkout(sessionInfo, nodeId);
+        } else {
+            // TODO
+            throw new UnsupportedOperationException("JCR-2104: JSR 283 Versioning. Implementation missing");
+        }
     }
 
     /**
      * @see RepositoryService#checkpoint(SessionInfo, NodeId)
      */
     public NodeId checkpoint(SessionInfo sessionInfo, NodeId nodeId) throws UnsupportedRepositoryOperationException, RepositoryException {
-        // TODO
-        throw new UnsupportedOperationException("JCR-2104: JSR 283 Versioning. Implementation missing");
+        // TODO review again.
+        NodeId vID = checkin(sessionInfo, nodeId);
+        checkout(sessionInfo, nodeId);
+        return vID;
     }
 
     /**
@@ -1530,9 +1543,49 @@
         String uri = getItemUri(nodeId, sessionInfo);
         String vUri = getItemUri(versionId, sessionInfo);
 
-        update(uri, new String[] {vUri}, UpdateInfo.UPDATE_BY_VERSION, removeExisting, sessionInfo);
+        Path relPath = null;
+        if (!exists(sessionInfo, uri)) {
+            // restore with rel-Path part
+            Path path = nodeId.getPath();
+            if (nodeId.getUniqueID() != null) {
+                uri = getItemUri(idFactory.createNodeId(nodeId.getUniqueID(), null), sessionInfo);
+                relPath = (path.isAbsolute()) ? getPathFactory().getRootPath().computeRelativePath(path) : path;
+            } else {
+                int degree = 0;
+                while (degree < path.getLength()) {
+                    Path ancestorPath = path.getAncestor(degree);
+                    NodeId parentId = idFactory.createNodeId(nodeId.getUniqueID(), ancestorPath);
+                    if (exists(sessionInfo, getItemUri(parentId, sessionInfo))) {
+                        uri = getItemUri(parentId, sessionInfo);
+                        relPath = ancestorPath.computeRelativePath(path);
+                        break;
+                    }
+                    degree++;
+                }
+            }
+        }
+
+        update(uri, relPath, new String[] {vUri}, UpdateInfo.UPDATE_BY_VERSION, removeExisting, sessionInfo);
     }
 
+    private boolean exists(SessionInfo sInfo, String uri) {
+        HeadMethod method = new HeadMethod(uri);
+        try {
+            int statusCode = getClient(sInfo).executeMethod(method);
+            if (statusCode == DavServletResponse.SC_OK) {
+                return true;
+            }
+        } catch (IOException e) {
+            log.error("Unexpected error while testing existence of item.",e);
+        } catch (RepositoryException e) {
+            log.error(e.getMessage());
+        } finally {
+            method.releaseConnection();
+        }
+        return false;
+    }
+
+
     /**
      * @see RepositoryService#restore(SessionInfo, NodeId[], boolean)
      */
@@ -1543,15 +1596,21 @@
             vUris[i] = getItemUri(versionIds[i], sessionInfo);
         }
 
-        update(uri, vUris, UpdateInfo.UPDATE_BY_VERSION, removeExisting, sessionInfo);
+        update(uri, null, vUris, UpdateInfo.UPDATE_BY_VERSION, removeExisting, sessionInfo);
     }
 
-    private void update(String uri, String[] updateSource, int updateType, boolean removeExisting, SessionInfo sessionInfo) throws RepositoryException {
+    private void update(String uri, Path relPath, String[] updateSource, int updateType, boolean removeExisting, SessionInfo sessionInfo) throws RepositoryException {
         try {
             UpdateInfo uInfo;
-            if (removeExisting) {
+            if (removeExisting || relPath != null) {
                 Element uElem = UpdateInfo.createUpdateElement(updateSource, updateType, domFactory);
-                DomUtil.addChildElement(uElem, ItemResourceConstants.XML_REMOVEEXISTING, ItemResourceConstants.NAMESPACE);
+                if (removeExisting) {
+                    DomUtil.addChildElement(uElem, ItemResourceConstants.XML_REMOVEEXISTING, ItemResourceConstants.NAMESPACE);
+                }
+                if (relPath != null) {
+                    DomUtil.addChildElement(uElem, ItemResourceConstants.XML_RELPATH, ItemResourceConstants.NAMESPACE, getNamePathResolver(sessionInfo).getJCRPath(relPath));
+                }
+
                 uInfo = new UpdateInfo(uElem);
             } else {
                 uInfo = new UpdateInfo(updateSource, updateType, new DavPropertyNameSet());
@@ -1577,30 +1636,28 @@
      * @see RepositoryService#merge(SessionInfo, NodeId, String, boolean, boolean)
      */
     public Iterator<NodeId> merge(SessionInfo sessionInfo, NodeId nodeId, String srcWorkspaceName, boolean bestEffort, boolean isShallow) throws NoSuchWorkspaceException, AccessDeniedException, MergeException, LockException, InvalidItemStateException, RepositoryException {
-        if (!isShallow) {
-            try {
-                String wspHref = uriResolver.getWorkspaceUri(srcWorkspaceName);
-                Element mElem = MergeInfo.createMergeElement(new String[] {wspHref}, bestEffort, false, domFactory);
-                MergeInfo mInfo = new MergeInfo(mElem);
-
-                MergeMethod method = new MergeMethod(getItemUri(nodeId, sessionInfo), mInfo);
-                execute(method, sessionInfo);
-
-                MultiStatusResponse[] resps = method.getResponseBodyAsMultiStatus().getResponses();
-                List<NodeId> failedIds = new ArrayList<NodeId>(resps.length);
-                for (MultiStatusResponse resp : resps) {
-                    String href = resp.getHref();
-                    failedIds.add(uriResolver.getNodeId(href, sessionInfo));
-                }
-                return failedIds.iterator();
-            } catch (IOException e) {
-                throw new RepositoryException(e);
-            } catch (DavException e) {
-                throw ExceptionConverter.generate(e);
+        try {
+            String wspHref = uriResolver.getWorkspaceUri(srcWorkspaceName);
+            Element mElem = MergeInfo.createMergeElement(new String[] {wspHref}, !bestEffort, false, domFactory);
+            if (isShallow) {
+                mElem.appendChild(DomUtil.depthToXml(false, domFactory));
             }
-        } else {
-            // TODO
-            throw new UnsupportedOperationException("JCR-2104: JSR 283 Versioning. Implementation missing");
+            MergeInfo mInfo = new MergeInfo(mElem);
+
+            MergeMethod method = new MergeMethod(getItemUri(nodeId, sessionInfo), mInfo);
+            execute(method, sessionInfo);
+
+            MultiStatusResponse[] resps = method.getResponseBodyAsMultiStatus().getResponses();
+            List<NodeId> failedIds = new ArrayList<NodeId>(resps.length);
+            for (MultiStatusResponse resp : resps) {
+                String href = resp.getHref();
+                failedIds.add(uriResolver.getNodeId(href, sessionInfo));
+            }
+            return failedIds.iterator();
+        } catch (IOException e) {
+            throw new RepositoryException(e);
+        } catch (DavException e) {
+            throw ExceptionConverter.generate(e);
         }
     }
 

Modified: jackrabbit/trunk/jackrabbit-spi2dav/src/main/java/org/apache/jackrabbit/spi2davex/RepositoryServiceImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi2dav/src/main/java/org/apache/jackrabbit/spi2davex/RepositoryServiceImpl.java?rev=916278&r1=916277&r2=916278&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi2dav/src/main/java/org/apache/jackrabbit/spi2davex/RepositoryServiceImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-spi2dav/src/main/java/org/apache/jackrabbit/spi2davex/RepositoryServiceImpl.java Thu Feb 25 13:10:45 2010
@@ -137,6 +137,10 @@
     }
 
     private Path getPath(ItemId itemId, SessionInfo sessionInfo) throws RepositoryException {
+        return getPath(itemId, sessionInfo, sessionInfo.getWorkspaceName());
+    }
+
+    private Path getPath(ItemId itemId, SessionInfo sessionInfo, String workspaceName) throws RepositoryException {
         if (itemId.denotesNode()) {
             Path p = itemId.getPath();
             String uid = itemId.getUniqueID();
@@ -144,7 +148,7 @@
                 return p;
             } else {
                 NamePathResolver resolver = getNamePathResolver(sessionInfo);
-                String uri = super.getItemUri(itemId, sessionInfo);
+                String uri = super.getItemUri(itemId, sessionInfo, workspaceName);
                 String rootUri = getRootURI(sessionInfo);
                 String jcrPath;
                 if (uri.startsWith(rootUri)) {
@@ -162,7 +166,7 @@
             }
         } else {
             PropertyId pId = (PropertyId) itemId;
-            Path parentPath = getPath(pId.getParentId(), sessionInfo);
+            Path parentPath = getPath(pId.getParentId(), sessionInfo, workspaceName);
             return getPathFactory().create(parentPath, pId.getName(), true);
         }
     }
@@ -332,7 +336,7 @@
             StringBuffer args = new StringBuffer();
             args.append(srcWorkspaceName);
             args.append(",");
-            args.append(resolver.getJCRPath(getPath(srcNodeId, sessionInfo)));
+            args.append(resolver.getJCRPath(getPath(srcNodeId, sessionInfo, srcWorkspaceName)));
             args.append(",");
             String destParentPath = resolver.getJCRPath(getPath(destParentNodeId, sessionInfo));
             String destPath = (destParentPath.endsWith("/") ?
@@ -366,7 +370,7 @@
             StringBuffer args = new StringBuffer();
             args.append(srcWorkspaceName);
             args.append(",");
-            args.append(resolver.getJCRPath(getPath(srcNodeId, sessionInfo)));
+            args.append(resolver.getJCRPath(getPath(srcNodeId, sessionInfo, srcWorkspaceName)));
             args.append(",");
             String destParentPath = resolver.getJCRPath(getPath(destParentNodeId, sessionInfo));
             String destPath = (destParentPath.endsWith("/") ?