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/11 14:18:11 UTC

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

Author: jukka
Date: Tue Oct 11 12:18:11 2011
New Revision: 1181746

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

Use :include parameters in a normal batch read request to signal a multi-read request.

Add a -DJCR-3005=true feature flag for enabling this functionality until finalized.

Modified:
    jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/JcrRemotingServlet.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=1181746&r1=1181745&r2=1181746&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 Tue Oct 11 12:18:11 2011
@@ -33,6 +33,7 @@ import javax.jcr.PathNotFoundException;
 import javax.jcr.RepositoryException;
 import javax.jcr.Session;
 import javax.jcr.Workspace;
+import javax.jcr.nodetype.NodeType;
 import javax.servlet.ServletConfig;
 import javax.servlet.ServletContext;
 import javax.servlet.ServletException;
@@ -66,7 +67,7 @@ import org.slf4j.LoggerFactory;
  * that provides improved
  * <ul>
  * <li><a href="#bread">Batch read</a></li>
- * <li><a href="#mread">Multi read</a></li>
+ * <!-- <li><a href="#mread">Multi read</a></li> -->
  * <li><a href="#bwrite">Batch write</a></li>
  * </ul>
  * functionality and supports cross workspace copy and cloning.
@@ -129,23 +130,24 @@ import org.slf4j.LoggerFactory;
  *   JSON value must not have any trailing ".0" removed.
  * </pre>
  *
+ * <!--
  * <h3><a name="mread">Multi Read</a></h3>
  * <p>
  * Since Jackrabbit 2.3.1 it is also possible to request multiple subtrees
- * in a single request. This is done by sending a GET or a POST request to
- * a workspace request and specifying the paths of the selected subtrees
- * as ":path" parameters of the request. The response is a JSON object
- * whose "nodes" property contains all the selected nodes keyed by
- * path. Missing nodes are not included in the response. Each included
- * node is serialized as defined above for <a href="#bread">batch read</a>.
- * The configured default subtree depth can be overridden by specifying the
- * optional ":depth" parameter.
+ * in a single request. This is done by adding one or more ":include"
+ * parameters to a batch read request describe above. These extra parameters
+ * specify the (relative) paths of all the nodes to be included in the
+ * response. The response is a JSON object whose "nodes" property contains
+ * all the selected nodes keyed by path. Missing nodes are not included in
+ * the response. Each included node is serialized as defined above for
+ * <a href="#bread">batch read</a>.
  * <p>
  * Example:
  * <pre>
- * $ curl 'http://localhost:8080/server/default?:path=/node1&:path=/node2'
- * {"nodes":{"/node1":{...},"/node2":{...}}}
+ * $ curl 'http://.../parent.json?:path=child1&:path=child2'
+ * {"nodes":{"/parent/child1":{...},"/parent/child2":{...}}}
  * </pre>
+ * -->
  *
  * <h3><a name="bwrite">Batch Write</a></h3>
  *
@@ -215,6 +217,9 @@ public abstract class JcrRemotingServlet
 
     private static Logger log = LoggerFactory.getLogger(JcrRemotingServlet.class);
 
+    /** Temporary feature switch, remove when JCR-3005 is resolved. */
+    private static final boolean JCR_3005 = Boolean.getBoolean("JCR-3005");
+
     /**
      * the home init parameter. other relative filesystem paths are
      * relative to this location.
@@ -238,8 +243,7 @@ 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_PATH = ":path";
-    private static final String PARAM_DEPTH = ":depth";
+    private static final String PARAM_INCLUDE = ":include";
 
     private BatchReadConfig brConfig;
 
@@ -310,26 +314,55 @@ public abstract class JcrRemotingServlet
     protected void doGet(WebdavRequest webdavRequest,
                          WebdavResponse webdavResponse,
                          DavResource davResource) throws IOException, DavException {
-        if (doGetMultiple(webdavRequest, webdavResponse, davResource)) {
-            // request was handled by the multi-get handler
-        } else if (canHandle(DavMethods.DAV_GET, webdavRequest, davResource)) {
+        if (canHandle(DavMethods.DAV_GET, webdavRequest, davResource)) {
             // return json representation of the requested resource
+            DavResourceLocator locator = davResource.getLocator();
+            String path = locator.getRepositoryPath();
+
+            Session session = JcrDavSession.getRepositorySession(
+                    webdavRequest.getDavSession());
             try {
-                Item item = ((JcrDavSession) webdavRequest.getDavSession()).getRepositorySession().getItem(davResource.getLocator().getRepositoryPath());
-                if (item.isNode()) {
-                    webdavResponse.setContentType("text/plain;charset=utf-8");
-                    webdavResponse.setStatus(DavServletResponse.SC_OK);
-
-                    JsonWriter writer = new JsonWriter(webdavResponse.getWriter());
-                    int depth = ((WrappingLocator) davResource.getLocator()).getDepth();
-                    if (depth < BatchReadConfig.DEPTH_INFINITE) {
-                        depth = getDepth((Node) item);
-                    }
-                    writer.write((Node) item, depth);
+                Node node = session.getNode(path);
+                int depth = ((WrappingLocator) locator).getDepth();
+                if (depth < BatchReadConfig.DEPTH_INFINITE) {
+                    NodeType type = node.getPrimaryNodeType();
+                    depth = brConfig.getDepth(type.getName());
+                }
+
+                webdavResponse.setContentType("text/plain;charset=utf-8");
+                webdavResponse.setStatus(DavServletResponse.SC_OK);
+                JsonWriter writer = new JsonWriter(webdavResponse.getWriter());
+
+                String[] includes =
+                        webdavRequest.getParameterValues(PARAM_INCLUDE);
+                if (includes == null || !JCR_3005) {
+                    writer.write(node, depth);
                 } else {
-                    // properties cannot be requested as json object.
-                    throw new JcrDavException(new ItemNotFoundException("No node at " + item.getPath()), DavServletResponse.SC_NOT_FOUND);
+                    Collection<Node> nodes = new ArrayList<Node>();
+                    Set<String> alreadyAdded = new HashSet<String>();
+                    for (int i = 0; i < includes.length; i++) {
+                        try {
+                            Node n;
+                            if (includes[i].startsWith("/")) {
+                                n = session.getNode(includes[i]);
+                            } else {
+                                n = node.getNode(includes[i]);
+                            }
+                            if (!alreadyAdded.contains(n.getPath())) {
+                                nodes.add(n);
+                                alreadyAdded.add(n.getPath());
+                            }
+                        } catch (PathNotFoundException e) {
+                            // skip missing node
+                        }
+                    }
+                    writer.write(nodes, depth);
                 }
+            } catch (PathNotFoundException e) {
+                // properties cannot be requested as json object.
+                throw new JcrDavException(
+                        new ItemNotFoundException("No node at " + path),
+                        DavServletResponse.SC_NOT_FOUND);
             } catch (RepositoryException e) {
                 // should only get here if the item does not exist.
                 log.debug(e.getMessage());
@@ -343,9 +376,7 @@ public abstract class JcrRemotingServlet
     @Override
     protected void doPost(WebdavRequest webdavRequest, WebdavResponse webdavResponse, DavResource davResource)
             throws IOException, DavException {
-        if (doGetMultiple(webdavRequest, webdavResponse, davResource)) {
-            // request was handled by the multi-get handler
-        } else if (canHandle(DavMethods.DAV_POST, webdavRequest, davResource)) {
+        if (canHandle(DavMethods.DAV_POST, webdavRequest, davResource)) {
             // special remoting request: the defined parameters are exclusive
             // and cannot be combined.
             Session session = getRepositorySession(webdavRequest);
@@ -406,10 +437,6 @@ public abstract class JcrRemotingServlet
         }
     }
 
-    private int getDepth(Node node) throws RepositoryException {
-        return brConfig.getDepth(node.getPrimaryNodeType().getName());
-    }
-
     private static String clone(Session session, String[] cloneArgs, DavResourceLocator reqLocator) throws RepositoryException {
         Workspace wsp = session.getWorkspace();
         String destPath = null;
@@ -578,73 +605,6 @@ public abstract class JcrRemotingServlet
         return (File) servletCtx.getAttribute(ATTR_TMP_DIRECTORY);
     }
 
-    /**
-     * Conditionally processes a multi read request.
-     *
-     * @since Apache Jackrabbit 2.3.1
-     * @param request request object
-     * @param response response object
-     * @param resource resource object
-     * @return <code>true</code> if this was a multi read request,
-     *         <code>false</code> otherwise
-     * @throws IOException if the response could not be written
-     * @throws DavException if another error occurred
-     */
-    protected boolean doGetMultiple(
-            WebdavRequest request, WebdavResponse response,
-            DavResource resource) throws IOException, DavException {
-        // Check if this is a multi-GET request
-        String[] paths = request.getParameterValues(PARAM_PATH);
-        if (paths == null
-                || resource.getLocator().getWorkspaceName() == null
-                || resource.getLocator().getRepositoryPath() != null) {
-            return false;
-        }
-
-        // Get the depth (TODO: support depth per node type)
-        int depth = brConfig.getDefaultDepth();
-        String depthParam = request.getParameter(PARAM_DEPTH);
-        if (depthParam != null) {
-            try {
-                depth = Integer.parseInt(depthParam);
-            } catch (NumberFormatException e) {
-                throw new DavException(
-                        DavServletResponse.SC_BAD_REQUEST,
-                        "Invalid depth parameter: " + depthParam);
-            }
-        }
-
-        // 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(path)) {
-                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);
-                }
-            }
-        }
-
-        // Send the response
-        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;
-    }
-
     //--------------------------------------------------------------------------
     /**
      * Locator factory that specially deals with hrefs having a .json extension.