| /* |
| * 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; |
| |
| 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; |
| import static org.hamcrest.CoreMatchers.allOf; |
| import static org.hamcrest.CoreMatchers.nullValue; |
| |
| import java.io.ByteArrayInputStream; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.util.concurrent.Callable; |
| |
| import javax.jcr.Node; |
| import javax.jcr.RepositoryException; |
| |
| import org.apache.commons.httpclient.HttpException; |
| import org.apache.commons.httpclient.URIException; |
| import org.apache.sling.ide.test.impl.helpers.DisableDebugStatusHandlers; |
| import org.apache.sling.ide.test.impl.helpers.ExternalSlingLaunchpad; |
| import org.apache.sling.ide.test.impl.helpers.FailOnUnsuccessfulEventsRule; |
| import org.apache.sling.ide.test.impl.helpers.LaunchpadConfig; |
| import org.apache.sling.ide.test.impl.helpers.Poller; |
| import org.apache.sling.ide.test.impl.helpers.ProjectAdapter; |
| import org.apache.sling.ide.test.impl.helpers.RepositoryAccessor; |
| import org.apache.sling.ide.test.impl.helpers.ServerAdapter; |
| import org.apache.sling.ide.test.impl.helpers.SlingWstServer; |
| import org.apache.sling.ide.test.impl.helpers.TemporaryProject; |
| import org.eclipse.core.resources.IProject; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.Path; |
| import org.eclipse.jdt.core.JavaCore; |
| import org.hamcrest.Matcher; |
| import org.junit.After; |
| import org.junit.Rule; |
| import org.junit.Test; |
| import org.junit.rules.RuleChain; |
| import org.junit.rules.TestRule; |
| |
| /** |
| * The <tt>ContentDeploymentTest</tt> validates simple content deployment based on the resources changes in the |
| * workspace |
| * |
| */ |
| public class ContentDeploymentTest { |
| |
| private final LaunchpadConfig config = LaunchpadConfig.getInstance(); |
| |
| private final SlingWstServer wstServer = new SlingWstServer(config); |
| |
| @Rule |
| public TestRule chain = RuleChain.outerRule(new ExternalSlingLaunchpad(config)).around(wstServer); |
| |
| @Rule |
| public TemporaryProject projectRule = new TemporaryProject(); |
| |
| @Rule |
| public FailOnUnsuccessfulEventsRule failOnEventsRule = new FailOnUnsuccessfulEventsRule(); |
| |
| @Rule |
| public DisableDebugStatusHandlers disableDebugHandlers = new DisableDebugStatusHandlers(); |
| |
| @Test |
| public void deployFile() throws CoreException, InterruptedException, URIException, HttpException, IOException { |
| |
| wstServer.waitForServerToStart(); |
| |
| // create faceted project |
| IProject contentProject = projectRule.getProject(); |
| |
| ProjectAdapter project = new ProjectAdapter(contentProject); |
| project.addNatures(JavaCore.NATURE_ID, "org.eclipse.wst.common.project.facet.core.nature"); |
| |
| // install bundle facet |
| project.installFacet("sling.content", "1.0"); |
| |
| ServerAdapter server = new ServerAdapter(wstServer.getServer()); |
| server.installModule(contentProject); |
| |
| project.createOrUpdateFile(Path.fromPortableString("jcr_root/test/hello.txt"), new ByteArrayInputStream( |
| "hello, world".getBytes())); |
| |
| // verify that file is created |
| final RepositoryAccessor repo = new RepositoryAccessor(config); |
| Poller poller = new Poller(); |
| poller.pollUntil(new Callable<Void>() { |
| @Override |
| public Void call() throws HttpException, IOException { |
| repo.assertGetIsSuccessful("test/hello.txt", "hello, world"); |
| return null; |
| } |
| }, nullValue(Void.class)); |
| |
| project.createOrUpdateFile(Path.fromPortableString("jcr_root/test/hello.txt"), new ByteArrayInputStream( |
| "goodbye, world".getBytes())); |
| |
| // verify that file is updated |
| poller.pollUntil(new Callable<Void>() { |
| @Override |
| public Void call() throws HttpException, IOException { |
| repo.assertGetIsSuccessful("test/hello.txt", "goodbye, world"); |
| return null; |
| } |
| }, nullValue(Void.class)); |
| |
| |
| project.deleteMember(Path.fromPortableString("jcr_root/test/hello.txt")); |
| |
| // verify that file is deleted |
| poller.pollUntil(new Callable<Void>() { |
| @Override |
| public Void call() throws HttpException, IOException { |
| repo.assertGetReturns404("test/hello.txt"); |
| return null; |
| } |
| }, nullValue(Void.class)); |
| |
| } |
| |
| @Test |
| public void changeNodePrimaryType() throws Exception { |
| |
| wstServer.waitForServerToStart(); |
| |
| // create faceted project |
| IProject contentProject = projectRule.getProject(); |
| |
| ProjectAdapter project = new ProjectAdapter(contentProject); |
| project.addNatures("org.eclipse.wst.common.project.facet.core.nature"); |
| |
| // install bundle facet |
| project.installFacet("sling.content", "1.0"); |
| |
| ServerAdapter server = new ServerAdapter(wstServer.getServer()); |
| server.installModule(contentProject); |
| |
| project.createOrUpdateFile(Path.fromPortableString("jcr_root/test/hello.txt"), new ByteArrayInputStream( |
| "hello, world".getBytes())); |
| |
| // verifications |
| final RepositoryAccessor repo = new RepositoryAccessor(config); |
| Poller poller = new Poller(); |
| assertThatNode(repo, poller, "/test", allOf(hasPath("/test"), hasPrimaryType("nt:folder"), hasChildrenCount(1))); |
| |
| // change node type to sling:Folder |
| InputStream contentXml = getClass().getResourceAsStream("sling-folder-nodetype.xml"); |
| project.createOrUpdateFile(Path.fromPortableString("jcr_root/test/.content.xml"), contentXml); |
| |
| // verifications (2) |
| assertThatNode(repo, poller, "/test", |
| allOf(hasPath("/test"), hasPrimaryType("sling:Folder"), hasChildrenCount(1))); |
| } |
| |
| @Test |
| public void deployFileWithAttachedMetadata() throws Exception { |
| |
| wstServer.waitForServerToStart(); |
| |
| // create faceted project |
| IProject contentProject = projectRule.getProject(); |
| |
| ProjectAdapter project = new ProjectAdapter(contentProject); |
| project.addNatures(JavaCore.NATURE_ID, "org.eclipse.wst.common.project.facet.core.nature"); |
| |
| // install bundle facet |
| project.installFacet("sling.content", "1.0"); |
| |
| ServerAdapter server = new ServerAdapter(wstServer.getServer()); |
| server.installModule(contentProject); |
| |
| project.createOrUpdateFile(Path.fromPortableString("jcr_root/test/hello.esp"), new ByteArrayInputStream( |
| "// not really javascript".getBytes())); |
| |
| // verify that file is created |
| final RepositoryAccessor repo = new RepositoryAccessor(config); |
| Poller poller = new Poller(); |
| assertThatNode(repo, poller, "/test/hello.esp", hasPrimaryType("nt:file")); |
| |
| InputStream contentXml = getClass().getResourceAsStream("file-custom-mimetype.xml"); |
| project.createOrUpdateFile(Path.fromPortableString("jcr_root/test/hello.esp.dir/.content.xml"), contentXml); |
| |
| assertThatNode(repo, poller, "/test/hello.esp/jcr:content", hasPropertyValue("jcr:mimeType", "text/javascript")); |
| } |
| |
| @Test |
| public void fileDeployedBeforeAddingModuleToServerIsPublished() throws Throwable { |
| |
| wstServer.waitForServerToStart(); |
| |
| // create faceted project |
| IProject contentProject = projectRule.getProject(); |
| |
| ProjectAdapter project = new ProjectAdapter(contentProject); |
| project.addNatures(JavaCore.NATURE_ID, "org.eclipse.wst.common.project.facet.core.nature"); |
| |
| project.createOrUpdateFile(Path.fromPortableString("jcr_root/test/hello.txt"), new ByteArrayInputStream( |
| "hello, world".getBytes())); |
| |
| // install bundle facet |
| project.installFacet("sling.content", "1.0"); |
| |
| ServerAdapter server = new ServerAdapter(wstServer.getServer()); |
| server.installModule(contentProject); |
| |
| // verify that file is created |
| final RepositoryAccessor repo = new RepositoryAccessor(config); |
| Poller poller = new Poller(); |
| poller.pollUntil(new Callable<Node>() { |
| @Override |
| public Node call() throws RepositoryException { |
| return repo.getNode("/test/hello.txt"); |
| } |
| }, hasFileContent("hello, world")); |
| |
| } |
| |
| /** |
| * 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 |
| public void deployFileWithMissingParentFromRepository() throws Exception { |
| |
| wstServer.waitForServerToStart(); |
| |
| // create faceted project |
| IProject contentProject = projectRule.getProject(); |
| |
| ProjectAdapter project = new ProjectAdapter(contentProject); |
| project.addNatures(JavaCore.NATURE_ID, "org.eclipse.wst.common.project.facet.core.nature"); |
| |
| // install bundle facet |
| project.installFacet("sling.content", "1.0"); |
| |
| ServerAdapter server = new ServerAdapter(wstServer.getServer()); |
| server.installModule(contentProject); |
| |
| // create filter.xml |
| project.createVltFilterWithRoots("/test"); |
| // create file |
| project.createOrUpdateFile(Path.fromPortableString("jcr_root/test/demo/nested/structure/hello.txt"), |
| new ByteArrayInputStream("hello, world".getBytes())); |
| |
| // verify that file is created |
| final RepositoryAccessor repo = new RepositoryAccessor(config); |
| Poller poller = new Poller(); |
| poller.pollUntil(new Callable<Node>() { |
| @Override |
| public Node call() throws RepositoryException { |
| return repo.getNode("/test/demo/nested/structure/hello.txt"); |
| } |
| }, hasFileContent("hello, world")); |
| } |
| |
| @Test |
| public void filedDeployedWithFullCoverageSiblingDoesNotCauseSpuriousDeletion() throws Exception { |
| |
| wstServer.waitForServerToStart(); |
| |
| // create faceted project |
| IProject contentProject = projectRule.getProject(); |
| |
| ProjectAdapter project = new ProjectAdapter(contentProject); |
| project.addNatures(JavaCore.NATURE_ID, "org.eclipse.wst.common.project.facet.core.nature"); |
| |
| // install bundle facet |
| project.installFacet("sling.content", "1.0"); |
| |
| ServerAdapter server = new ServerAdapter(wstServer.getServer()); |
| server.installModule(contentProject); |
| |
| // create sling:Folder at /test/folder |
| project.createOrUpdateFile(Path.fromPortableString("jcr_root/test/folder/.content.xml"), getClass() |
| .getResourceAsStream("sling-folder-nodetype.xml")); |
| |
| // create nt:file at /test/folder/hello.esp |
| project.createOrUpdateFile(Path.fromPortableString("jcr_root/test/folder/hello.esp"), new ByteArrayInputStream( |
| "// not really javascript".getBytes())); |
| |
| // create sling:OsgiConfig at /test/folder/config.xml |
| project.createOrUpdateFile(Path.fromPortableString("jcr_root/test/folder/config.xml"), getClass() |
| .getResourceAsStream("com.example.some.Component.xml")); |
| |
| // verify that config node is created |
| final RepositoryAccessor repo = new RepositoryAccessor(config); |
| Poller poller = new Poller(); |
| |
| assertThatNode(repo, poller, "/test/folder/config", hasPrimaryType("sling:OsgiConfig")); |
| |
| // update file at /test/folder/hello.esp |
| project.createOrUpdateFile(Path.fromPortableString("jcr_root/test/folder/hello.esp"), new ByteArrayInputStream( |
| "// maybe javascript".getBytes())); |
| |
| // wait until the file is updated |
| assertThatNode(repo, poller, "/test/folder/hello.esp", hasFileContent("// maybe javascript")); |
| |
| // verify that the sling:OsgiConfig node is still present |
| assertThatNode(repo, poller, "/test/folder/config", hasPrimaryType("sling:OsgiConfig")); |
| } |
| |
| private void assertThatNode(final RepositoryAccessor repo, Poller poller, final String nodePath, Matcher<Node> matcher) |
| throws InterruptedException { |
| |
| poller.pollUntil(new Callable<Node>() { |
| @Override |
| public Node call() throws RepositoryException { |
| Node node = repo.getNode(nodePath); |
| return node; |
| |
| } |
| }, matcher); |
| } |
| |
| @After |
| public void cleanUp() throws Exception { |
| |
| new RepositoryAccessor(config).tryDeleteResource("/test"); |
| } |
| } |