You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by ju...@apache.org on 2011/10/06 12:30:33 UTC

svn commit: r1179564 - in /jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex: JcrRemotingServlet.java JsonWriter.java

Author: jukka
Date: Thu Oct  6 10:30:32 2011
New Revision: 1179564

URL: http://svn.apache.org/viewvc?rev=1179564&view=rev
Log:
JCR-3005: Make it possible to get multiple nodes in one call via davex

Use GET instead of POST for the multi-node requests.

The request needs to be addressed to the workspace resource, and contain one or more :path parameters:

    curl http://localhost:8080/server/default?:path=/node1&:path=/node2

An optional :depth parameter can be used to override the configured default depth.

Modified:
    jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/JcrRemotingServlet.java
    jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/JsonWriter.java

Modified: jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/JcrRemotingServlet.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/JcrRemotingServlet.java?rev=1179564&r1=1179563&r2=1179564&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/JcrRemotingServlet.java (original)
+++ jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/JcrRemotingServlet.java Thu Oct  6 10:30:32 2011
@@ -16,49 +16,50 @@
  */
 package org.apache.jackrabbit.server.remoting.davex;
 
-import java.io.PrintWriter;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+import javax.jcr.Item;
+import javax.jcr.ItemNotFoundException;
+import javax.jcr.Node;
+import javax.jcr.NodeIterator;
+import javax.jcr.PathNotFoundException;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.Workspace;
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.jackrabbit.JcrConstants;
+import org.apache.jackrabbit.server.util.RequestData;
+import org.apache.jackrabbit.util.Text;
 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.DavResourceLocator;
 import org.apache.jackrabbit.webdav.DavServletResponse;
 import org.apache.jackrabbit.webdav.DavSession;
 import org.apache.jackrabbit.webdav.WebdavRequest;
 import org.apache.jackrabbit.webdav.WebdavResponse;
-import org.apache.jackrabbit.webdav.DavResourceFactory;
-import org.apache.jackrabbit.webdav.observation.SubscriptionManager;
-import org.apache.jackrabbit.webdav.version.DeltaVConstants;
+import org.apache.jackrabbit.webdav.jcr.JCRWebdavServerServlet;
 import org.apache.jackrabbit.webdav.jcr.JcrDavException;
 import org.apache.jackrabbit.webdav.jcr.JcrDavSession;
-import org.apache.jackrabbit.webdav.jcr.JCRWebdavServerServlet;
 import org.apache.jackrabbit.webdav.jcr.transaction.TxLockManagerImpl;
-import org.apache.jackrabbit.util.Text;
-import org.apache.jackrabbit.JcrConstants;
-import org.apache.jackrabbit.server.util.RequestData;
+import org.apache.jackrabbit.webdav.observation.SubscriptionManager;
+import org.apache.jackrabbit.webdav.version.DeltaVConstants;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import javax.jcr.Item;
-import javax.jcr.Node;
-import javax.jcr.Repository;
-import javax.jcr.RepositoryException;
-import javax.jcr.Session;
-import javax.jcr.Workspace;
-import javax.jcr.ItemNotFoundException;
-import javax.jcr.NodeIterator;
-import javax.jcr.PathNotFoundException;
-import javax.servlet.ServletConfig;
-import javax.servlet.ServletContext;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletResponse;
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
-
 /**
  * <code>JcrRemotingServlet</code> is an extended version of the
  * {@link org.apache.jackrabbit.webdav.jcr.JCRWebdavServerServlet JCR Remoting Servlet}
@@ -218,7 +219,8 @@ public abstract class JcrRemotingServlet
     private static final String PARAM_DIFF = ":diff";
     private static final String PARAM_COPY = ":copy";
     private static final String PARAM_CLONE = ":clone";
-    private static final String PARAM_GET = ":get";
+    private static final String PARAM_PATH = ":path";
+    private static final String PARAM_DEPTH = ":depth";
 
     private BatchReadConfig brConfig;
 
@@ -289,7 +291,9 @@ public abstract class JcrRemotingServlet
     protected void doGet(WebdavRequest webdavRequest,
                          WebdavResponse webdavResponse,
                          DavResource davResource) throws IOException, DavException {
-        if (canHandle(DavMethods.DAV_GET, webdavRequest, davResource)) {
+        if (doGetMultiple(webdavRequest, webdavResponse, davResource)) {
+            // request was handled by the multi-get handler
+        } else if (canHandle(DavMethods.DAV_GET, webdavRequest, davResource)) {
             // return json representation of the requested resource
             try {
                 Item item = ((JcrDavSession) webdavRequest.getDavSession()).getRepositorySession().getItem(davResource.getLocator().getRepositoryPath());
@@ -330,9 +334,6 @@ public abstract class JcrRemotingServlet
                 String[] pValues;
                 if ((pValues = data.getParameterValues(PARAM_CLONE)) != null) {
                     loc = clone(session, pValues, davResource.getLocator());
-                } else if ((pValues = data.getParameterValues(PARAM_GET)) != null) {
-                   getMultiple(session, pValues, davResource.getLocator(), webdavResponse);
-                   return;
                 } else if ((pValues = data.getParameterValues(PARAM_COPY)) != null) {
                     loc = copy(session, pValues, davResource.getLocator());
                 } else if (data.getParameterValues(PARAM_DIFF) != null) {
@@ -556,30 +557,57 @@ public abstract class JcrRemotingServlet
         return (File) servletCtx.getAttribute(ATTR_TMP_DIRECTORY);
     }
 
-    protected void getMultiple(
-            Session session, String[] paths, DavResourceLocator locator,
-            WebdavResponse webdavResponse)
-            throws IOException, RepositoryException {
-        // Collect all requested nodes
-        Map<String, Node> nodes = new HashMap<String, Node>();
-        Node node = session.getNode(locator.getRepositoryPath());
-        nodes.put(node.getPath(), node);
-        for (String path : paths) {
+    protected boolean doGetMultiple(
+            WebdavRequest request, WebdavResponse response,
+            DavResource resource) throws IOException, DavException {
+        String[] paths = request.getParameterValues(PARAM_PATH);
+        if (paths == null
+                || resource.getLocator().getWorkspaceName() == null
+                || resource.getLocator().getRepositoryPath() != null) {
+            return false;
+        }
+
+        // Get the depth
+        int depth = brConfig.getDefaultDepth();
+        String depthParam = request.getParameter(PARAM_DEPTH);
+        if (depthParam != null) {
             try {
-                nodes.put(path, session.getNode(path));
-            } catch (PathNotFoundException ignore) {
-                // skip a missing node
+                depth = Integer.parseInt(depthParam);
+            } catch (NumberFormatException e) {
+                throw new DavException(
+                        DavServletResponse.SC_BAD_REQUEST,
+                        "Invalid depth parameter: " + depthParam);
             }
         }
 
-        int depth = ((WrappingLocator) locator).getDepth();
-        if (depth < BatchReadConfig.DEPTH_INFINITE) {
-            depth = getDepth(node);
+        // Collect all requested nodes
+        Collection<Node> nodes = new ArrayList<Node>(paths.length);
+        Set<String> alreadyAdded = new HashSet<String>();
+        Session session =
+                JcrDavSession.getRepositorySession(resource.getSession());
+        for (String path : paths) {
+            if (!alreadyAdded.contains(paths)) {
+                try {
+                    nodes.add(session.getNode(path));
+                    alreadyAdded.add(path);
+                } catch (PathNotFoundException ignore) {
+                    // skip a missing node
+                } catch (RepositoryException e) {
+                    throw new DavException(
+                            WebdavResponse.SC_INTERNAL_SERVER_ERROR,
+                            "Unable to access path " + path, e, null);
+                }
+            }
         }
 
-        webdavResponse.setContentType("text/plain;charset=utf-8");
-        webdavResponse.setStatus(DavServletResponse.SC_OK);
-        new JsonWriter(webdavResponse.getWriter()).write(nodes, depth);
+        response.setContentType("text/plain;charset=utf-8");
+        response.setStatus(DavServletResponse.SC_OK);
+        try {
+            new JsonWriter(response.getWriter()).write(nodes, depth);
+        } catch (RepositoryException e) {
+            throw new DavException(WebdavResponse.SC_INTERNAL_SERVER_ERROR, e);
+        }
+        return true;
     }
 
     //--------------------------------------------------------------------------

Modified: jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/JsonWriter.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/JsonWriter.java?rev=1179564&r1=1179563&r2=1179564&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/JsonWriter.java (original)
+++ jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/JsonWriter.java Thu Oct  6 10:30:32 2011
@@ -25,7 +25,7 @@ import javax.jcr.RepositoryException;
 import javax.jcr.Value;
 import java.io.Writer;
 import java.io.IOException;
-import java.util.Map;
+import java.util.Collection;
 
 import org.apache.jackrabbit.JcrConstants;
 import org.apache.jackrabbit.commons.json.JsonUtil;
@@ -69,20 +69,20 @@ class JsonWriter {
         write(node, 0, maxLevels);
     }
 
-    void write(Map<String, Node> nodes, int maxLevels)
+    void write(Collection<Node> nodes, int maxLevels)
             throws RepositoryException, IOException {
         writer.write('{');
         writeKey(writer, "nodes");
         writer.write('{');
         boolean first = true;
-        for (Map.Entry<String, Node> entry : nodes.entrySet()) {
+        for (Node node : nodes) {
             if (first) {
                 first = false;
             } else {
                 writer.write(',');
             }
-            writeKey(writer, entry.getKey());
-            write(entry.getValue(), maxLevels);
+            writeKey(writer, node.getPath());
+            write(node, maxLevels);
         }
         writer.write('}');
         writer.write('}');