You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by ro...@apache.org on 2014/10/09 14:27:42 UTC

svn commit: r1630401 - in /sling/trunk/tooling/ide: eclipse-core/src/org/apache/sling/ide/eclipse/core/internal/ eclipse-test/src/org/apache/sling/ide/test/impl/ eclipse-test/src/org/apache/sling/ide/test/impl/helpers/jcr/

Author: rombert
Date: Thu Oct  9 12:27:42 2014
New Revision: 1630401

URL: http://svn.apache.org/r1630401
Log:
SLING-3586 - Publishing content fails if intermediate nodes are not
present in the repository

Ensure that when a resource is published all its parents, up to the
repository root, are created.

Added:
    sling/trunk/tooling/ide/eclipse-test/src/org/apache/sling/ide/test/impl/helpers/jcr/NtFileContentMatcher.java
Modified:
    sling/trunk/tooling/ide/eclipse-core/src/org/apache/sling/ide/eclipse/core/internal/SlingLaunchpadBehaviour.java
    sling/trunk/tooling/ide/eclipse-test/src/org/apache/sling/ide/test/impl/ContentDeploymentTest.java
    sling/trunk/tooling/ide/eclipse-test/src/org/apache/sling/ide/test/impl/helpers/jcr/JcrMatchers.java

Modified: sling/trunk/tooling/ide/eclipse-core/src/org/apache/sling/ide/eclipse/core/internal/SlingLaunchpadBehaviour.java
URL: http://svn.apache.org/viewvc/sling/trunk/tooling/ide/eclipse-core/src/org/apache/sling/ide/eclipse/core/internal/SlingLaunchpadBehaviour.java?rev=1630401&r1=1630400&r2=1630401&view=diff
==============================================================================
--- sling/trunk/tooling/ide/eclipse-core/src/org/apache/sling/ide/eclipse/core/internal/SlingLaunchpadBehaviour.java (original)
+++ sling/trunk/tooling/ide/eclipse-core/src/org/apache/sling/ide/eclipse/core/internal/SlingLaunchpadBehaviour.java Thu Oct  9 12:27:42 2014
@@ -21,7 +21,9 @@ import java.io.InputStream;
 import java.net.URISyntaxException;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
 
 import org.apache.commons.io.IOUtils;
 import org.apache.sling.ide.artifacts.EmbeddedArtifact;
@@ -379,6 +381,9 @@ public class SlingLaunchpadBehaviour ext
         // would be an incorrect ( or at least suprising ) behaviour at development time
 
         List<IModuleResource> addedOrUpdatedResources = new ArrayList<IModuleResource>();
+        IModuleResource[] allResources = getResources(module);
+        IModuleResource[] publishedResources = getPublishedResources(module);
+        Set<IPath> handledPaths = new HashSet<IPath>();
 
         switch (deltaKind) {
             case ServerBehaviourDelegate.CHANGED:
@@ -412,6 +417,8 @@ public class SlingLaunchpadBehaviour ext
                         case IModuleResourceDelta.ADDED:
                         case IModuleResourceDelta.CHANGED:
                         case IModuleResourceDelta.NO_CHANGE: // TODO is this needed?
+                            ensureParentIsPublished(resourceDelta.getModuleResource(), repository, allResources,
+                                    publishedResources, handledPaths);
                             execute(addFileCommand(repository, resourceDelta.getModuleResource()));
                             addedOrUpdatedResources.add(resourceDelta.getModuleResource());
                             break;
@@ -448,6 +455,73 @@ public class SlingLaunchpadBehaviour ext
 //        setServerPublishState(IServer.PUBLISH_STATE_NONE);
 	}
 
+    /**
+     * Ensures that the parent of this resource has been published to the repository
+     * 
+     * <p>
+     * Note that the parents explicitly do not have their child nodes reordered, this will happen when they are
+     * published due to a resource change
+     * </p>
+     * 
+     * @param moduleResource the current resource
+     * @param repository the repository to publish to
+     * @param allResources all of the module's resources
+     * @param publishedResources the resources which have been already published
+     * @param handledPaths the paths that have been handled already in this publish operation, but possibly not
+     *            registered as published
+     * @throws IOException
+     * @throws SerializationException
+     * @throws CoreException
+     */
+    private void ensureParentIsPublished(IModuleResource moduleResource, Repository repository,
+            IModuleResource[] allResources, IModuleResource[] publishedResources, Set<IPath> handledPaths)
+            throws CoreException, SerializationException, IOException {
+
+        Logger logger = Activator.getDefault().getPluginLogger();
+
+        IPath currentPath = moduleResource.getModuleRelativePath();
+
+        logger.trace("Ensuring that parent of path {0} is published", currentPath);
+
+        // we assume the root is always published
+        if (currentPath.segmentCount() == 0) {
+            logger.trace("Path {0} can not have a parent, skipping", currentPath);
+            return;
+        }
+
+        IPath parentPath = currentPath.removeLastSegments(1);
+
+        // already published by us, a parent of another resource that was published in this execution
+        if (handledPaths.contains(parentPath)) {
+            logger.trace("Parent path {0} was already handled, skipping", parentPath);
+            return;
+        }
+
+        // already published earlier as part of the publish job
+        for (IModuleResource alreadyPublished : publishedResources) {
+            if (alreadyPublished.getModuleRelativePath().equals(parentPath)) {
+                logger.trace("Parent path {0} was already published, skipping", parentPath);
+                return;
+            }
+        }
+
+        for (IModuleResource maybeParent : allResources) {
+            if (maybeParent.getModuleRelativePath().equals(parentPath)) {
+                // handle the parent's parent first, if needed
+                ensureParentIsPublished(maybeParent, repository, allResources, publishedResources, handledPaths);
+                // create this resource
+                execute(addFileCommand(repository, maybeParent));
+                handledPaths.add(maybeParent.getModuleRelativePath());
+                logger.trace("Ensured that resource at path {0} is published", parentPath);
+                return;
+            }
+        }
+
+        throw new IllegalArgumentException("Resource at " + moduleResource.getModuleRelativePath()
+                + " has parent path " + parentPath + " but no resource with that path is in the module's resources.");
+
+    }
+
     private void execute(Command<?> command) throws CoreException {
         if (command == null) {
             return;

Modified: sling/trunk/tooling/ide/eclipse-test/src/org/apache/sling/ide/test/impl/ContentDeploymentTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/tooling/ide/eclipse-test/src/org/apache/sling/ide/test/impl/ContentDeploymentTest.java?rev=1630401&r1=1630400&r2=1630401&view=diff
==============================================================================
--- sling/trunk/tooling/ide/eclipse-test/src/org/apache/sling/ide/test/impl/ContentDeploymentTest.java (original)
+++ sling/trunk/tooling/ide/eclipse-test/src/org/apache/sling/ide/test/impl/ContentDeploymentTest.java Thu Oct  9 12:27:42 2014
@@ -17,6 +17,7 @@
 package org.apache.sling.ide.test.impl;
 
 import static org.apache.sling.ide.test.impl.helpers.jcr.JcrMatchers.hasChildrenCount;
+import static org.apache.sling.ide.test.impl.helpers.jcr.JcrMatchers.hasFileContent;
 import static org.apache.sling.ide.test.impl.helpers.jcr.JcrMatchers.hasPath;
 import static org.apache.sling.ide.test.impl.helpers.jcr.JcrMatchers.hasPrimaryType;
 import static org.apache.sling.ide.test.impl.helpers.jcr.JcrMatchers.hasPropertyValue;
@@ -49,7 +50,6 @@ import org.eclipse.core.runtime.Path;
 import org.eclipse.jdt.core.JavaCore;
 import org.hamcrest.Matcher;
 import org.junit.After;
-import org.junit.Ignore;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.RuleChain;
@@ -235,8 +235,13 @@ public class ContentDeploymentTest {
 
     }
 
+    /**
+     * This test validates that if the parent of a resource that does not exist in the repository the resource is
+     * successfully created
+     * 
+     * @throws Exception
+     */
     @Test
-    @Ignore("SLING-3586")
     public void deployFileWithMissingParentFromRepository() throws Exception {
 
         wstServer.waitForServerToStart();
@@ -254,7 +259,7 @@ public class ContentDeploymentTest {
         server.installModule(contentProject);
 
         // create filter.xml
-        project.createVltFilterWithRoots("/test/demo/nested/structure");
+        project.createVltFilterWithRoots("/test");
         // create file
         project.createOrUpdateFile(Path.fromPortableString("jcr_root/test/demo/nested/structure/hello.txt"),
                 new ByteArrayInputStream("hello, world".getBytes()));
@@ -267,7 +272,7 @@ public class ContentDeploymentTest {
             public Node call() throws RepositoryException {
                 return repo.getNode("/test/demo/nested/structure/hello.txt");
             }
-        }, nullValue(Node.class));
+        }, hasFileContent("hello, world"));
     }
 
     private void assertThatNode(final RepositoryAccessor repo, Poller poller, final String nodePath, Matcher<Node> matcher)

Modified: sling/trunk/tooling/ide/eclipse-test/src/org/apache/sling/ide/test/impl/helpers/jcr/JcrMatchers.java
URL: http://svn.apache.org/viewvc/sling/trunk/tooling/ide/eclipse-test/src/org/apache/sling/ide/test/impl/helpers/jcr/JcrMatchers.java?rev=1630401&r1=1630400&r2=1630401&view=diff
==============================================================================
--- sling/trunk/tooling/ide/eclipse-test/src/org/apache/sling/ide/test/impl/helpers/jcr/JcrMatchers.java (original)
+++ sling/trunk/tooling/ide/eclipse-test/src/org/apache/sling/ide/test/impl/helpers/jcr/JcrMatchers.java Thu Oct  9 12:27:42 2014
@@ -46,6 +46,10 @@ public final class JcrMatchers {
         return new PropertyMatcher(propertyName, propertyValue);
     }
 
+    public static Matcher<Node> hasFileContent(String value) {
+        return new NtFileContentMatcher(value);
+    }
+
     private JcrMatchers() {
 
     }

Added: sling/trunk/tooling/ide/eclipse-test/src/org/apache/sling/ide/test/impl/helpers/jcr/NtFileContentMatcher.java
URL: http://svn.apache.org/viewvc/sling/trunk/tooling/ide/eclipse-test/src/org/apache/sling/ide/test/impl/helpers/jcr/NtFileContentMatcher.java?rev=1630401&view=auto
==============================================================================
--- sling/trunk/tooling/ide/eclipse-test/src/org/apache/sling/ide/test/impl/helpers/jcr/NtFileContentMatcher.java (added)
+++ sling/trunk/tooling/ide/eclipse-test/src/org/apache/sling/ide/test/impl/helpers/jcr/NtFileContentMatcher.java Thu Oct  9 12:27:42 2014
@@ -0,0 +1,82 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.sling.ide.test.impl.helpers.jcr;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+
+import org.hamcrest.Description;
+import org.hamcrest.TypeSafeMatcher;
+
+/**
+ * The <tt>NtFileContentMatcher</tt> verifies the content of an <tt>nt:file</tt> node.
+ * 
+ * <p>
+ * However, this matcher does not verify the actual type of the node, just the value of the jcr:content/jcr:data
+ * property.
+ * </p>
+ *
+ */
+public class NtFileContentMatcher extends TypeSafeMatcher<Node> {
+
+    private final String value;
+
+    public NtFileContentMatcher(String value) {
+        this.value = value;
+    }
+
+    @Override
+    public void describeTo(Description description) {
+        description.appendText("node[jcr:content][jcr:data] = ").appendValue(value);
+    }
+
+    @Override
+    public boolean matchesSafely(Node item) {
+        try {
+            if (item == null || !item.hasNode("jcr:content")) {
+                return false;
+            }
+
+            Node jcrContent = item.getNode("jcr:content");
+
+            return jcrContent.hasProperty("jcr:data") && jcrContent.getProperty("jcr:data").getString().equals(value);
+        } catch (RepositoryException e) {
+            return false;
+        }
+    }
+
+    @Override
+    protected void describeMismatchSafely(Node item, Description mismatchDescription) {
+        try {
+            if (!item.hasNode("jcr:content")) {
+                mismatchDescription.appendValue("was node with a jcr:content child node");
+                return;
+            }
+
+            Node jcrContent = item.getNode("jcr:content");
+
+            if (jcrContent.hasProperty("jcr:data")) {
+                mismatchDescription.appendText("was node [jcr:content] = ").appendValue(
+                        item.getProperty("jcr:data").getString());
+            } else {
+                mismatchDescription.appendText("was node without a property named jcr:data");
+            }
+        } catch (RepositoryException e) {
+            super.describeMismatchSafely(item, mismatchDescription);
+        }
+    }
+}