You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by en...@apache.org on 2012/03/17 23:33:46 UTC

svn commit: r1302034 - in /sling/trunk: bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/ launchpad/integration-tests/src/main/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/post/

Author: enorman
Date: Sat Mar 17 22:33:45 2012
New Revision: 1302034

URL: http://svn.apache.org/viewvc?rev=1302034&view=rev
Log:
SLING-2415 Added ability to match all child nodes for the :applyTo parameter by using '*' as the last segment of the value.  The applies to the delete, move and copy operations.

Modified:
    sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/AbstractPostOperation.java
    sling/trunk/launchpad/integration-tests/src/main/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/post/PostServletCopyTest.java
    sling/trunk/launchpad/integration-tests/src/main/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/post/PostServletDeleteTest.java
    sling/trunk/launchpad/integration-tests/src/main/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/post/PostServletMoveTest.java

Modified: sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/AbstractPostOperation.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/AbstractPostOperation.java?rev=1302034&r1=1302033&r2=1302034&view=diff
==============================================================================
--- sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/AbstractPostOperation.java (original)
+++ sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/AbstractPostOperation.java Sat Mar 17 22:33:45 2012
@@ -478,6 +478,8 @@ public abstract class AbstractPostOperat
 
         private Resource nextResource;
 
+        private Iterator<Resource> resourceIterator = null;
+        
         ApplyToIterator(SlingHttpServletRequest request, String[] paths) {
             this.resolver = request.getResourceResolver();
             this.baseResource = request.getResource();
@@ -507,13 +509,48 @@ public abstract class AbstractPostOperat
         }
 
         private Resource seek() {
+        	if (resourceIterator != null) {
+        		if (resourceIterator.hasNext()) {
+            		//return the next resource in the iterator
+        			Resource res = resourceIterator.next();
+        			return res;
+        		} else {
+        			resourceIterator = null;
+        		}
+        	}
             while (pathIndex < paths.length) {
                 String path = paths[pathIndex];
                 pathIndex++;
 
-                Resource res = resolver.getResource(baseResource, path);
-                if (res != null) {
-                    return res;
+                //SLING-2415 - support wildcard as the last segment of the applyTo path
+                if (path.endsWith("*")) {
+                	if (path.length() == 1) {
+                		resourceIterator = baseResource.listChildren();
+                	} else if (path.endsWith("/*")) {
+                    	path = path.substring(0, path.length() - 2);
+                    	if (path.length() == 0) {
+                    		resourceIterator = baseResource.listChildren();
+                    	} else {
+                        	Resource res = resolver.getResource(baseResource, path);
+                            if (res != null) {
+                            	resourceIterator = res.listChildren();
+                            }
+                    	}
+                    } 
+                	if (resourceIterator != null) {
+                		//return the first resource in the iterator
+                		if (resourceIterator.hasNext()) {
+                			Resource res = resourceIterator.next();
+                			return res;
+                		} else {
+                			resourceIterator = null;
+                		}
+                	}
+                } else {
+                    Resource res = resolver.getResource(baseResource, path);
+                    if (res != null) {
+                        return res;
+                    }
                 }
             }
 

Modified: sling/trunk/launchpad/integration-tests/src/main/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/post/PostServletCopyTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/launchpad/integration-tests/src/main/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/post/PostServletCopyTest.java?rev=1302034&r1=1302033&r2=1302034&view=diff
==============================================================================
--- sling/trunk/launchpad/integration-tests/src/main/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/post/PostServletCopyTest.java (original)
+++ sling/trunk/launchpad/integration-tests/src/main/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/post/PostServletCopyTest.java Sat Mar 17 22:33:45 2012
@@ -442,4 +442,140 @@ public class PostServletCopyTest extends
         // clean up
         testClient.delete(testRoot);
     }
+    
+    
+    /**
+     * Test for SLING-2415 Ability to move all child nodes, without the parent node
+     * Using :applyTo value of "*"
+     */
+    public void testCopyAllChildren() throws IOException {
+        final String testPath = TEST_BASE_PATH + "/cpmultwc/"
+            + System.currentTimeMillis();
+        final String testRoot = testClient.createNode(HTTP_BASE_URL + testPath,
+            null);
+
+        // create multiple source nodes
+        Map<String, String> props = new HashMap<String, String>();
+        props.put("text", "Hello");
+        testClient.createNode(HTTP_BASE_URL + testPath + "/test/src1", props);
+        testClient.createNode(HTTP_BASE_URL + testPath + "/test/src2", props);
+        testClient.createNode(HTTP_BASE_URL + testPath + "/test/src3", props);
+        testClient.createNode(HTTP_BASE_URL + testPath + "/test/src4", props);
+
+        // create destination parent
+        testClient.createNode(HTTP_BASE_URL + testPath + "/dest", props);
+
+        // copy the src? nodes
+        List<NameValuePair> nvPairs = new ArrayList<NameValuePair>();
+        nvPairs.add(new NameValuePair(SlingPostConstants.RP_OPERATION,
+            SlingPostConstants.OPERATION_COPY));
+        nvPairs.add(new NameValuePair(SlingPostConstants.RP_DEST, testPath
+            + "/dest/"));
+        nvPairs.add(new NameValuePair(SlingPostConstants.RP_APPLY_TO, "*"));
+        // we expect success
+        assertPostStatus(testRoot + "/test", HttpServletResponse.SC_OK, nvPairs,
+            "Expecting Copy Success");
+
+        // assert existence of the src?/text properties
+        assertHttpStatus(HTTP_BASE_URL + testPath + "/dest/src1/text",
+            HttpServletResponse.SC_OK);
+        assertHttpStatus(HTTP_BASE_URL + testPath + "/dest/src2/text",
+            HttpServletResponse.SC_OK);
+        assertHttpStatus(HTTP_BASE_URL + testPath + "/dest/src3/text",
+            HttpServletResponse.SC_OK);
+        assertHttpStatus(HTTP_BASE_URL + testPath + "/dest/src4/text",
+            HttpServletResponse.SC_OK);
+
+        testClient.delete(testRoot);
+    }
+    
+    /**
+     * Test for SLING-2415 Ability to move all child nodes, without the parent node
+     * Using :applyTo value of "/*"
+     */
+    public void testCopyAllChildrenByPath() throws IOException {
+        final String testPath = TEST_BASE_PATH + "/cpmultwc/"
+            + System.currentTimeMillis();
+        final String testRoot = testClient.createNode(HTTP_BASE_URL + testPath,
+            null);
+
+        // create multiple source nodes
+        Map<String, String> props = new HashMap<String, String>();
+        props.put("text", "Hello");
+        testClient.createNode(HTTP_BASE_URL + testPath + "/test/src1", props);
+        testClient.createNode(HTTP_BASE_URL + testPath + "/test/src2", props);
+        testClient.createNode(HTTP_BASE_URL + testPath + "/test/src3", props);
+        testClient.createNode(HTTP_BASE_URL + testPath + "/test/src4", props);
+
+        // create destination parent
+        testClient.createNode(HTTP_BASE_URL + testPath + "/dest", props);
+
+        // copy the src? nodes
+        List<NameValuePair> nvPairs = new ArrayList<NameValuePair>();
+        nvPairs.add(new NameValuePair(SlingPostConstants.RP_OPERATION,
+            SlingPostConstants.OPERATION_COPY));
+        nvPairs.add(new NameValuePair(SlingPostConstants.RP_DEST, testPath
+            + "/dest/"));
+        nvPairs.add(new NameValuePair(SlingPostConstants.RP_APPLY_TO, "/*"));
+        // we expect success
+        assertPostStatus(testRoot + "/test", HttpServletResponse.SC_OK, nvPairs,
+            "Expecting Copy Success");
+
+        // assert existence of the src?/text properties
+        assertHttpStatus(HTTP_BASE_URL + testPath + "/dest/src1/text",
+            HttpServletResponse.SC_OK);
+        assertHttpStatus(HTTP_BASE_URL + testPath + "/dest/src2/text",
+            HttpServletResponse.SC_OK);
+        assertHttpStatus(HTTP_BASE_URL + testPath + "/dest/src3/text",
+            HttpServletResponse.SC_OK);
+        assertHttpStatus(HTTP_BASE_URL + testPath + "/dest/src4/text",
+            HttpServletResponse.SC_OK);
+
+        testClient.delete(testRoot);
+    }
+    
+    /**
+     * Test for SLING-2415 Ability to copy all child nodes of a subnode, without the parent node
+     * Using :applyTo value of "subnode_path/*"
+     */
+    public void testCopyAllChildrenOfSubNode() throws IOException {
+        final String testPath = TEST_BASE_PATH + "/cpmultwc/"
+            + System.currentTimeMillis();
+        final String testRoot = testClient.createNode(HTTP_BASE_URL + testPath,
+            null);
+
+        // create multiple source nodes
+        Map<String, String> props = new HashMap<String, String>();
+        props.put("text", "Hello");
+        testClient.createNode(HTTP_BASE_URL + testPath + "/test/src1", props);
+        testClient.createNode(HTTP_BASE_URL + testPath + "/test/src2", props);
+        testClient.createNode(HTTP_BASE_URL + testPath + "/test/src3", props);
+        testClient.createNode(HTTP_BASE_URL + testPath + "/test/src4", props);
+
+        // create destination parent
+        testClient.createNode(HTTP_BASE_URL + testPath + "/dest", props);
+
+        // copy the src? nodes
+        List<NameValuePair> nvPairs = new ArrayList<NameValuePair>();
+        nvPairs.add(new NameValuePair(SlingPostConstants.RP_OPERATION,
+            SlingPostConstants.OPERATION_COPY));
+        nvPairs.add(new NameValuePair(SlingPostConstants.RP_DEST, testPath
+            + "/dest/"));
+        nvPairs.add(new NameValuePair(SlingPostConstants.RP_APPLY_TO, "test/*"));
+        // we expect success
+        assertPostStatus(testRoot, HttpServletResponse.SC_OK, nvPairs,
+            "Expecting Copy Success");
+
+        // assert existence of the src?/text properties
+        assertHttpStatus(HTTP_BASE_URL + testPath + "/dest/src1/text",
+            HttpServletResponse.SC_OK);
+        assertHttpStatus(HTTP_BASE_URL + testPath + "/dest/src2/text",
+            HttpServletResponse.SC_OK);
+        assertHttpStatus(HTTP_BASE_URL + testPath + "/dest/src3/text",
+            HttpServletResponse.SC_OK);
+        assertHttpStatus(HTTP_BASE_URL + testPath + "/dest/src4/text",
+            HttpServletResponse.SC_OK);
+
+        testClient.delete(testRoot);
+    }
 }
\ No newline at end of file

Modified: sling/trunk/launchpad/integration-tests/src/main/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/post/PostServletDeleteTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/launchpad/integration-tests/src/main/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/post/PostServletDeleteTest.java?rev=1302034&r1=1302033&r2=1302034&view=diff
==============================================================================
--- sling/trunk/launchpad/integration-tests/src/main/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/post/PostServletDeleteTest.java (original)
+++ sling/trunk/launchpad/integration-tests/src/main/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/post/PostServletDeleteTest.java Sat Mar 17 22:33:45 2012
@@ -110,4 +110,86 @@ public class PostServletDeleteTest exten
         assertHttpStatus(urlC + DEFAULT_EXT, HttpServletResponse.SC_NOT_FOUND, "C must be deleted (2)");
         assertHttpStatus(urlD + DEFAULT_EXT, HttpServletResponse.SC_NOT_FOUND, "D must be deleted (2)");
     }
+
+    /**
+     * Test for SLING-2415 Ability to delete child nodes, without deleting the parent node
+     * Using :applyTo value of "*"
+     */
+    public void testDeleteAllChildren() throws IOException {
+        final String urlA = testClient.createNode(postUrl + SlingPostConstants.DEFAULT_CREATE_SUFFIX, null);
+        final String urlB = testClient.createNode(postUrl + SlingPostConstants.DEFAULT_CREATE_SUFFIX, null);
+        final String urlC = testClient.createNode(postUrl + SlingPostConstants.DEFAULT_CREATE_SUFFIX, null);
+        final String urlD = testClient.createNode(postUrl + "/specific-location/for-delete", null);
+
+        // initially all nodes must be found
+        assertHttpStatus(urlA + DEFAULT_EXT, HttpServletResponse.SC_OK, "A must initially exist");
+        assertHttpStatus(urlB + DEFAULT_EXT, HttpServletResponse.SC_OK, "B must initially exist");
+        assertHttpStatus(urlC + DEFAULT_EXT, HttpServletResponse.SC_OK, "C must initially exist");
+        assertHttpStatus(urlD + DEFAULT_EXT, HttpServletResponse.SC_OK, "D must initially exist");
+
+        // delete and check
+        final List <NameValuePair> params = new LinkedList<NameValuePair> ();
+        params.add(new NameValuePair(SlingPostConstants.RP_OPERATION, SlingPostConstants.OPERATION_DELETE));
+        params.add(new NameValuePair(SlingPostConstants.RP_APPLY_TO, "*"));
+        assertPostStatus(postUrl,HttpServletResponse.SC_OK,params,"Delete must return expected status");
+        assertHttpStatus(urlA + DEFAULT_EXT, HttpServletResponse.SC_NOT_FOUND, "A must be deleted");
+        assertHttpStatus(urlB + DEFAULT_EXT, HttpServletResponse.SC_NOT_FOUND, "B must be deleted");
+        assertHttpStatus(urlC + DEFAULT_EXT, HttpServletResponse.SC_NOT_FOUND, "C must be deleted");
+        assertHttpStatus(urlD + DEFAULT_EXT, HttpServletResponse.SC_NOT_FOUND, "D must be deleted");
+    }
+    /**
+     * Test for SLING-2415 Ability to delete child nodes, without deleting the parent node
+     * Using :applyTo value of "/*"
+     */
+    public void testDeleteAllChildrenByPath() throws IOException {
+        final String urlA = testClient.createNode(postUrl + SlingPostConstants.DEFAULT_CREATE_SUFFIX, null);
+        final String urlB = testClient.createNode(postUrl + SlingPostConstants.DEFAULT_CREATE_SUFFIX, null);
+        final String urlC = testClient.createNode(postUrl + SlingPostConstants.DEFAULT_CREATE_SUFFIX, null);
+        final String urlD = testClient.createNode(postUrl + "/specific-location/for-delete", null);
+
+        // initially all nodes must be found
+        assertHttpStatus(urlA + DEFAULT_EXT, HttpServletResponse.SC_OK, "A must initially exist");
+        assertHttpStatus(urlB + DEFAULT_EXT, HttpServletResponse.SC_OK, "B must initially exist");
+        assertHttpStatus(urlC + DEFAULT_EXT, HttpServletResponse.SC_OK, "C must initially exist");
+        assertHttpStatus(urlD + DEFAULT_EXT, HttpServletResponse.SC_OK, "D must initially exist");
+
+        // delete and check
+        final List <NameValuePair> params = new LinkedList<NameValuePair> ();
+        params.add(new NameValuePair(SlingPostConstants.RP_OPERATION, SlingPostConstants.OPERATION_DELETE));
+        params.add(new NameValuePair(SlingPostConstants.RP_APPLY_TO, "/*"));
+        assertPostStatus(postUrl,HttpServletResponse.SC_OK,params,"Delete must return expected status");
+        assertHttpStatus(urlA + DEFAULT_EXT, HttpServletResponse.SC_NOT_FOUND, "A must be deleted");
+        assertHttpStatus(urlB + DEFAULT_EXT, HttpServletResponse.SC_NOT_FOUND, "B must be deleted");
+        assertHttpStatus(urlC + DEFAULT_EXT, HttpServletResponse.SC_NOT_FOUND, "C must be deleted");
+        assertHttpStatus(urlD + DEFAULT_EXT, HttpServletResponse.SC_NOT_FOUND, "D must be deleted");
+    }
+    /**
+     * Test for SLING-2415 Ability to delete child nodes of a subnode, without deleting the parent node
+     * Using :applyTo value of "subnode_path/*"
+     */
+    public void testDeleteAllChildrenOfSubNode() throws IOException {
+        final String urlA = testClient.createNode(postUrl + SlingPostConstants.DEFAULT_CREATE_SUFFIX, null);
+        final String urlB = testClient.createNode(postUrl + SlingPostConstants.DEFAULT_CREATE_SUFFIX, null);
+        final String urlC = testClient.createNode(postUrl + SlingPostConstants.DEFAULT_CREATE_SUFFIX, null);
+        final String urlD = testClient.createNode(postUrl + "/specific-location/for-delete", null);
+
+        // initially all nodes must be found
+        assertHttpStatus(urlA + DEFAULT_EXT, HttpServletResponse.SC_OK, "A must initially exist");
+        assertHttpStatus(urlB + DEFAULT_EXT, HttpServletResponse.SC_OK, "B must initially exist");
+        assertHttpStatus(urlC + DEFAULT_EXT, HttpServletResponse.SC_OK, "C must initially exist");
+        assertHttpStatus(urlD + DEFAULT_EXT, HttpServletResponse.SC_OK, "D must initially exist");
+
+        String testBaseUrl = HTTP_BASE_URL + TEST_BASE_PATH;
+        String subPath = postUrl.substring(testBaseUrl.length() + 1);
+        // delete and check
+        final List <NameValuePair> params = new LinkedList<NameValuePair> ();
+        params.add(new NameValuePair(SlingPostConstants.RP_OPERATION, SlingPostConstants.OPERATION_DELETE));
+        params.add(new NameValuePair(SlingPostConstants.RP_APPLY_TO, String.format("%s/*", subPath)));
+        assertPostStatus(testBaseUrl,HttpServletResponse.SC_OK,params,"Delete must return expected status");
+        assertHttpStatus(urlA + DEFAULT_EXT, HttpServletResponse.SC_NOT_FOUND, "A must be deleted");
+        assertHttpStatus(urlB + DEFAULT_EXT, HttpServletResponse.SC_NOT_FOUND, "B must be deleted");
+        assertHttpStatus(urlC + DEFAULT_EXT, HttpServletResponse.SC_NOT_FOUND, "C must be deleted");
+        assertHttpStatus(urlD + DEFAULT_EXT, HttpServletResponse.SC_NOT_FOUND, "D must be deleted");
+    }
+
 }
\ No newline at end of file

Modified: sling/trunk/launchpad/integration-tests/src/main/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/post/PostServletMoveTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/launchpad/integration-tests/src/main/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/post/PostServletMoveTest.java?rev=1302034&r1=1302033&r2=1302034&view=diff
==============================================================================
--- sling/trunk/launchpad/integration-tests/src/main/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/post/PostServletMoveTest.java (original)
+++ sling/trunk/launchpad/integration-tests/src/main/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/post/PostServletMoveTest.java Sat Mar 17 22:33:45 2012
@@ -500,4 +500,169 @@ public class PostServletMoveTest extends
         assertHttpStatus(HTTP_BASE_URL + pathA, HttpServletResponse.SC_NOT_FOUND);
     }
 
+    
+    /**
+     * Test for SLING-2415 Ability to move all child nodes, without the parent node
+     * Using :applyTo value of "*"
+     */
+    public void testMoveAllChildren() throws IOException {
+        final String testPath = TEST_BASE_PATH + "/mvmultwc/"
+            + System.currentTimeMillis();
+        final String testRoot = testClient.createNode(HTTP_BASE_URL + testPath,
+            null);
+
+        // create multiple source nodes
+        Map<String, String> props = new HashMap<String, String>();
+        props.put("text", "Hello");
+        testClient.createNode(HTTP_BASE_URL + testPath + "/test/src1", props);
+        testClient.createNode(HTTP_BASE_URL + testPath + "/test/src2", props);
+        testClient.createNode(HTTP_BASE_URL + testPath + "/test/src3", props);
+        testClient.createNode(HTTP_BASE_URL + testPath + "/test/src4", props);
+
+        // create destination parent
+        testClient.createNode(HTTP_BASE_URL + testPath + "/dest", props);
+
+        // move the src? nodes
+        List<NameValuePair> nvPairs = new ArrayList<NameValuePair>();
+        nvPairs.add(new NameValuePair(SlingPostConstants.RP_OPERATION,
+            SlingPostConstants.OPERATION_MOVE));
+        nvPairs.add(new NameValuePair(SlingPostConstants.RP_DEST, testPath
+            + "/dest/"));
+        nvPairs.add(new NameValuePair(SlingPostConstants.RP_APPLY_TO, "*"));
+        // we expect success
+        assertPostStatus(testRoot + "/test", HttpServletResponse.SC_OK, nvPairs,
+            "Expecting Move Success");
+
+        // assert existence of the src?/text properties
+        assertHttpStatus(HTTP_BASE_URL + testPath + "/dest/src1/text",
+            HttpServletResponse.SC_OK);
+        assertHttpStatus(HTTP_BASE_URL + testPath + "/dest/src2/text",
+            HttpServletResponse.SC_OK);
+        assertHttpStatus(HTTP_BASE_URL + testPath + "/dest/src3/text",
+            HttpServletResponse.SC_OK);
+        assertHttpStatus(HTTP_BASE_URL + testPath + "/dest/src4/text",
+            HttpServletResponse.SC_OK);
+
+        // assert non-existence of src?
+        assertHttpStatus(HTTP_BASE_URL + testPath + "/test/src1.html",
+            HttpServletResponse.SC_NOT_FOUND);
+        assertHttpStatus(HTTP_BASE_URL + testPath + "/test/src2.html",
+            HttpServletResponse.SC_NOT_FOUND);
+        assertHttpStatus(HTTP_BASE_URL + testPath + "/test/src3.html",
+            HttpServletResponse.SC_NOT_FOUND);
+        assertHttpStatus(HTTP_BASE_URL + testPath + "/test/src4.html",
+            HttpServletResponse.SC_NOT_FOUND);
+
+        testClient.delete(testRoot);
+    }
+
+    /**
+     * Test for SLING-2415 Ability to move all child nodes, without the parent node
+     * Using :applyTo value of "/*"
+     */
+    public void testMoveAllChildrenByPath() throws IOException {
+        final String testPath = TEST_BASE_PATH + "/mvmultwc/"
+            + System.currentTimeMillis();
+        final String testRoot = testClient.createNode(HTTP_BASE_URL + testPath,
+            null);
+
+        // create multiple source nodes
+        Map<String, String> props = new HashMap<String, String>();
+        props.put("text", "Hello");
+        testClient.createNode(HTTP_BASE_URL + testPath + "/test/src1", props);
+        testClient.createNode(HTTP_BASE_URL + testPath + "/test/src2", props);
+        testClient.createNode(HTTP_BASE_URL + testPath + "/test/src3", props);
+        testClient.createNode(HTTP_BASE_URL + testPath + "/test/src4", props);
+
+        // create destination parent
+        testClient.createNode(HTTP_BASE_URL + testPath + "/dest", props);
+
+        // move the src? nodes
+        List<NameValuePair> nvPairs = new ArrayList<NameValuePair>();
+        nvPairs.add(new NameValuePair(SlingPostConstants.RP_OPERATION,
+            SlingPostConstants.OPERATION_MOVE));
+        nvPairs.add(new NameValuePair(SlingPostConstants.RP_DEST, testPath
+            + "/dest/"));
+        nvPairs.add(new NameValuePair(SlingPostConstants.RP_APPLY_TO, "/*"));
+        // we expect success
+        assertPostStatus(testRoot + "/test", HttpServletResponse.SC_OK, nvPairs,
+            "Expecting Move Success");
+
+        // assert existence of the src?/text properties
+        assertHttpStatus(HTTP_BASE_URL + testPath + "/dest/src1/text",
+            HttpServletResponse.SC_OK);
+        assertHttpStatus(HTTP_BASE_URL + testPath + "/dest/src2/text",
+            HttpServletResponse.SC_OK);
+        assertHttpStatus(HTTP_BASE_URL + testPath + "/dest/src3/text",
+            HttpServletResponse.SC_OK);
+        assertHttpStatus(HTTP_BASE_URL + testPath + "/dest/src4/text",
+            HttpServletResponse.SC_OK);
+
+        // assert non-existence of src?
+        assertHttpStatus(HTTP_BASE_URL + testPath + "/test/src1.html",
+            HttpServletResponse.SC_NOT_FOUND);
+        assertHttpStatus(HTTP_BASE_URL + testPath + "/test/src2.html",
+            HttpServletResponse.SC_NOT_FOUND);
+        assertHttpStatus(HTTP_BASE_URL + testPath + "/test/src3.html",
+            HttpServletResponse.SC_NOT_FOUND);
+        assertHttpStatus(HTTP_BASE_URL + testPath + "/test/src4.html",
+            HttpServletResponse.SC_NOT_FOUND);
+
+        testClient.delete(testRoot);
+    }
+    
+    /**
+     * Test for SLING-2415 Ability to move all child nodes of a subnode, without the parent node
+     * Using :applyTo value of "subnode_path/*"
+     */
+    public void testMoveAllChildrenOfSubNode() throws IOException {
+        final String testPath = TEST_BASE_PATH + "/mvmultwc/"
+            + System.currentTimeMillis();
+        final String testRoot = testClient.createNode(HTTP_BASE_URL + testPath,
+            null);
+
+        // create multiple source nodes
+        Map<String, String> props = new HashMap<String, String>();
+        props.put("text", "Hello");
+        testClient.createNode(HTTP_BASE_URL + testPath + "/test/src1", props);
+        testClient.createNode(HTTP_BASE_URL + testPath + "/test/src2", props);
+        testClient.createNode(HTTP_BASE_URL + testPath + "/test/src3", props);
+        testClient.createNode(HTTP_BASE_URL + testPath + "/test/src4", props);
+
+        // create destination parent
+        testClient.createNode(HTTP_BASE_URL + testPath + "/dest", props);
+
+        // move the src? nodes
+        List<NameValuePair> nvPairs = new ArrayList<NameValuePair>();
+        nvPairs.add(new NameValuePair(SlingPostConstants.RP_OPERATION,
+            SlingPostConstants.OPERATION_MOVE));
+        nvPairs.add(new NameValuePair(SlingPostConstants.RP_DEST, testPath
+            + "/dest/"));
+        nvPairs.add(new NameValuePair(SlingPostConstants.RP_APPLY_TO, "test/*"));
+        // we expect success
+        assertPostStatus(testRoot, HttpServletResponse.SC_OK, nvPairs,
+            "Expecting Move Success");
+
+        // assert existence of the src?/text properties
+        assertHttpStatus(HTTP_BASE_URL + testPath + "/dest/src1/text",
+            HttpServletResponse.SC_OK);
+        assertHttpStatus(HTTP_BASE_URL + testPath + "/dest/src2/text",
+            HttpServletResponse.SC_OK);
+        assertHttpStatus(HTTP_BASE_URL + testPath + "/dest/src3/text",
+            HttpServletResponse.SC_OK);
+        assertHttpStatus(HTTP_BASE_URL + testPath + "/dest/src4/text",
+            HttpServletResponse.SC_OK);
+
+        // assert non-existence of src?
+        assertHttpStatus(HTTP_BASE_URL + testPath + "/test/src1.html",
+            HttpServletResponse.SC_NOT_FOUND);
+        assertHttpStatus(HTTP_BASE_URL + testPath + "/test/src2.html",
+            HttpServletResponse.SC_NOT_FOUND);
+        assertHttpStatus(HTTP_BASE_URL + testPath + "/test/src3.html",
+            HttpServletResponse.SC_NOT_FOUND);
+        assertHttpStatus(HTTP_BASE_URL + testPath + "/test/src4.html",
+            HttpServletResponse.SC_NOT_FOUND);
+
+        testClient.delete(testRoot);
+    }
 }
\ No newline at end of file