Move Sling to new TLP location
git-svn-id: https://svn.eu.apache.org/repos/asf/sling/tags/org.apache.sling.launchpad.testing-5-incubator@785979 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed 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.
diff --git a/NOTICE b/NOTICE
new file mode 100644
index 0000000..861d0ce
--- /dev/null
+++ b/NOTICE
@@ -0,0 +1,8 @@
+Apache Sling Launchpad Testing
+Copyright 2008-2009 The Apache Software Foundation
+
+Apache Sling is based on source code originally developed
+by Day Software (http://www.day.com/).
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
diff --git a/README.txt b/README.txt
new file mode 100644
index 0000000..5ed48bf
--- /dev/null
+++ b/README.txt
@@ -0,0 +1,125 @@
+Apache Sling Launchpad Testing module
+
+This module builds a Sling webapp using bundles from the trunk, and
+runs integration tests (that were previously in the launchpad/webapp
+module) on them.
+
+
+Disclaimer
+==========
+Apache Sling is an effort undergoing incubation at The Apache Software Foundation (ASF),
+sponsored by the Apache Jackrabbit PMC. Incubation is required of all newly accepted
+projects until a further review indicates that the infrastructure, communications,
+and decision making process have stabilized in a manner consistent with other
+successful ASF projects. While incubation status is not necessarily a reflection of
+the completeness or stability of the code, it does indicate that the project has yet
+to be fully endorsed by the ASF.
+
+Getting Started
+===============
+
+This component uses a Maven 2 (http://maven.apache.org/) build
+environment. It requires a Java 5 JDK (or higher) and Maven (http://maven.apache.org/)
+2.0.7 or later. We recommend to use the latest Maven version.
+
+If you have Maven 2 installed, you can compile and
+package the jar using the following command:
+
+ mvn package
+
+See the Maven 2 documentation for other build features.
+
+The latest source code for this component is available in the
+Subversion (http://subversion.tigris.org/) source repository of
+the Apache Software Foundation. If you have Subversion installed,
+you can checkout the latest source using the following command:
+
+ svn checkout http://svn.apache.org/repos/asf/incubator/sling/trunk/launchpad/webapp
+
+See the Subversion documentation for other source control features.
+
+
+How to run this
+---------------
+ NOTE: "mvn clean" does not delete the "sling" work directory - make sure to
+ delete it manually if you want to start from a clean state.
+
+1) Build all Sling bundles
+
+ cd <top of the Sling source code tree>
+ mvn clean install
+
+2) Build and run this
+
+ cd launchpad/testing
+ mvn clean package jetty:run
+
+Once the webapp starts, http://localhost:8888/system/console should display the Felix
+OSGi console.
+
+4) Test node creation and display
+To create a node with curl:
+
+ curl -D - -Ftitle=something http://admin:admin@localhost:8888/testing/this
+
+Then, http://admin:admin@localhost:8888/testing/this should display a default HTML
+representation, including the value of the "title" property.
+
+Add a txt or json extension to see other output formats.
+
+Integration tests
+-----------------
+This module provides a number of integration tests, that run automatically when
+doing a full build, and test Sling via its client HTTP interfaces.
+
+These tests can also be run against another instance of Sling, for example to
+test it in another web container than the embedded Jetty that is used during the
+Maven build.
+
+See pom.xml for the parameters that control these integration tests. Here's an
+example of running them against a Sling instance running on host xyzzy, port 1234,
+with the Sling webapp mounted under /foo:
+
+ mvn -o -s /dev/null test \
+ -Dhttp.port=1234 \
+ -Dtest.host=xyzzy \
+ -Dhttp.base.path=foo \
+ -Dwebdav.workspace.path=foo/dav/default \
+ -Dtest=**/integrationtest/**/*Test.java
+
+The -s /dev/null parameter disables all your local Maven settings, to make sure
+they don't interfere. Feel free to remove that if you know what you're doing.
+
+To run a single test, other values can be used for the "-Dtest" parameter.
+
+This is very useful during development: you can leave a Sling webapp instance
+running, update bundles in it using the mvn autoInstallBundle profile, and run
+specific integration tests quickly from another terminal.
+
+JCR Install Integration tests
+-----------------------------
+
+This module also contains integration tests for the JCR Install module. These
+tests are disabled by default, since they may not be of general interest. To
+include the JCR Install tests in the integration tests run enable the
+jcrinstall-tests profile such as in
+
+ mvn -P jcrinstall-tests integration-test
+
+*** WARNING: the jcrinstall-tests do not work in revision 741168, due to changes
+in the start levels. They can be run according to the scenario below, if you
+change the default bundles start level to 30, after starting the Sling instance
+with mvn jetty:run, from http://localhost:8888/system/console/vmstat. ***
+
+To run the jcrinstall integration tests quickly, without having to start the
+webapp first:
+
+1. Run mvn clean package jetty:run -P jcrinstall-tests in a first console
+
+(1.5 see WARNING above - adjust the default bundles start level)
+
+2. In another console run
+
+ mvn test -Pjcrinstall-tests -Dtest=**/integrationtest/jcrinstall/**/*Test.java
+
+
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..dc9dd33
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,518 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+ 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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.apache.sling</groupId>
+ <artifactId>sling</artifactId>
+ <version>5-incubator</version>
+ <relativePath>../../parent/pom.xml</relativePath>
+ </parent>
+
+ <artifactId>org.apache.sling.launchpad.testing</artifactId>
+ <packaging>war</packaging>
+ <version>5-incubator</version>
+
+ <name>Apache Sling Launchpad Testing</name>
+ <description>
+ Sling Launchpad Testing module, contains integration tests that
+ were previously in the launchpad webapp module.
+ </description>
+
+ <scm>
+ <connection>scm:svn:http://svn.apache.org/repos/asf/incubator/sling/tags/org.apache.sling.launchpad.testing-5-incubator</connection>
+ <developerConnection>scm:svn:https://svn.apache.org/repos/asf/incubator/sling/tags/org.apache.sling.launchpad.testing-5-incubator</developerConnection>
+ <url>http://svn.apache.org/viewvc/incubator/sling/tags/org.apache.sling.launchpad.testing-5-incubator</url>
+ </scm>
+
+ <properties>
+ <!--
+ Jetty default port (override with -D)
+ -->
+ <http.port>8888</http.port>
+
+ <!-- path suffix for HTTP access to Sling -->
+ <http.base.path />
+
+ <!-- path suffix for WebDAV access to the repository -->
+ <webdav.workspace.path />
+
+ <!-- hostname for integration tests -->
+ <test.host>localhost</test.host>
+
+ <!--
+ Disable Jetty webapp rescan (override with -D)
+ -->
+ <jetty.scan.interval.seconds>0</jetty.scan.interval.seconds>
+
+ <!--
+ Sling home directory when starting with jetty:run
+ -->
+ <jetty.sling.home>target/sling</jetty.sling.home>
+
+ <!--
+ Defines which tests are for the "integration-testing" phase
+ -->
+ <integration.test.code.path>
+ **/launchpad/webapp/integrationtest
+ </integration.test.code.path>
+
+ <!--
+ Set this to true to stop mvn once the integration test Jetty instance is
+ started. Useful to manually test the integration testing webapp.
+ -->
+ <integration.test.wait>false</integration.test.wait>
+
+ <resources.bundles.path>${project.build.directory}/launchpad-bundles/resources/bundles</resources.bundles.path>
+ </properties>
+
+ <build>
+ <plugins>
+
+ <plugin>
+ <artifactId>maven-clean-plugin</artifactId>
+ <version>2.2</version>
+ <configuration>
+ <filesets>
+ <fileset>
+ <directory>${basedir}</directory>
+ <includes>
+ <include>derby.log</include>
+ <include>cachedir</include>
+ <include>sling</include>
+ </includes>
+ </fileset>
+ </filesets>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-antrun-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>delete-sling-folder</id>
+ <phase>package</phase>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ <configuration>
+ <tasks>
+ <echo>SLING-845 - delete parent sling folder before integration tests</echo>
+ <delete dir="../../sling" />
+ </tasks>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>maven-jetty-plugin</artifactId>
+ <configuration>
+ <contextPath>/</contextPath>
+ <scanIntervalSeconds>
+ ${jetty.scan.interval.seconds}
+ </scanIntervalSeconds>
+
+ <systemProperties>
+ <systemProperty>
+ <name>sling.home</name>
+ <value>${jetty.sling.home}</value>
+ </systemProperty>
+
+ </systemProperties>
+
+ <connectors>
+ <connector implementation="org.mortbay.jetty.nio.SelectChannelConnector">
+ <port>${http.port}</port>
+ <maxIdleTime>60000</maxIdleTime>
+ </connector>
+ </connectors>
+
+ <!--
+ Use target/... as the webapp source, as we unpack stuff there from the
+ Sling launcher modules
+ -->
+ <webAppSourceDirectory>
+ target/${artifactId}-${pom.version}
+ </webAppSourceDirectory>
+ </configuration>
+ </plugin>
+
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <executions>
+ <execution>
+ <!-- Unpack the sling-app launcher for inclusion in the web app -->
+ <id>unpack-dependencies</id>
+ <goals>
+ <goal>unpack-dependencies</goal>
+ </goals>
+ <configuration>
+ <includeArtifactIds>
+ org.apache.sling.launchpad.bundles
+ </includeArtifactIds>
+ <includes>
+ resources/**
+ </includes>
+ <excludeTransitive>true</excludeTransitive>
+ <outputDirectory>
+ ${project.build.directory}/launchpad-bundles
+ </outputDirectory>
+ <overWriteReleases>false</overWriteReleases>
+ <overWriteSnapshots>
+ true
+ </overWriteSnapshots>
+ </configuration>
+ </execution>
+ <!-- Launcher Jar -->
+ <execution>
+ <id>copy-launcher-jar</id>
+ <goals>
+ <goal>copy</goal>
+ </goals>
+ <configuration>
+ <artifactItems>
+ <artifactItem>
+ <groupId>org.apache.sling</groupId>
+ <artifactId>org.apache.sling.launchpad.base</artifactId>
+ <version>2.0.4-incubator</version>
+ </artifactItem>
+ </artifactItems>
+ <stripVersion>true</stripVersion>
+ <excludeTransitive>true</excludeTransitive>
+ <outputDirectory>
+ ${project.build.directory}/launchpad-bundles/resources
+ </outputDirectory>
+ </configuration>
+ </execution>
+
+ <execution>
+ <!--
+ Copy additional bundles that must be initially installed to
+ WEB-INF/resources/bundles/N where N = desired
+ start level
+ -->
+ <id>copy-bundles-dependencies</id>
+ <goals>
+ <goal>copy-dependencies</goal>
+ </goals>
+ <configuration>
+ <outputDirectory>
+ ${resources.bundles.path}/0
+ </outputDirectory>
+ <excludeTransitive>true</excludeTransitive>
+ <includeArtifactIds>
+ org.apache.sling.launchpad.test-services
+ </includeArtifactIds>
+ <includeScope>
+ provided
+ </includeScope>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+
+ <!--
+ Include sling-app launcher classes and resources, but no Sling
+ bundles (we want to specify our own versions)
+ -->
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-war-plugin</artifactId>
+ <configuration>
+ <webResources>
+ <!-- the configuration resources -->
+ <resource>
+ <directory>
+ ${project.build.directory}/launchpad-bundles
+ </directory>
+ <targetPath>WEB-INF</targetPath>
+ </resource>
+ <!-- Legal stuff -->
+ <resource>
+ <directory>${basedir}</directory>
+ <targetPath>META-INF</targetPath>
+ <includes>
+ <include>LICENSE*</include>
+ <include>NOTICE*</include>
+ <include>DISCLAIMER</include>
+ </includes>
+ </resource>
+ </webResources>
+ </configuration>
+ </plugin>
+
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <systemProperties>
+ <!--
+ WARNING: make sure these URLs are consistent with the
+ cargo-maven2-plugin settings: AFAIK Maven does not
+ expand variables in the <value> element.
+ And WARNING: these properties are duplicated somewhere in this
+ POM with slightly different values...there must be a better way.
+ -->
+ <property>
+ <name>launchpad.http.server.url</name>
+ <value>
+ http://${test.host}:${http.port}/${http.base.path}
+ </value>
+ </property>
+ <property>
+ <name>launchpad.webdav.server.url</name>
+ <value>
+ http://${test.host}:${http.port}/${webdav.workspace.path}
+ </value>
+ </property>
+ </systemProperties>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ <reporting>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-javadoc-plugin</artifactId>
+ <configuration>
+ <!-- No javadocs -->
+ <excludePackageNames>
+ org.apache.sling
+ </excludePackageNames>
+ </configuration>
+ </plugin>
+ </plugins>
+ </reporting>
+
+ <profiles>
+ <profile>
+ <!--
+ Run the cargo-based integration tests.
+ -->
+ <id>cargoIntegrationTesting</id>
+ <activation>
+ <property>
+ <name>!maven.test.skip</name>
+ </property>
+ </activation>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>surefire-integration-test</id>
+ <phase>integration-test</phase>
+ <goals>
+ <goal>test</goal>
+ </goals>
+ <configuration>
+ <excludes>
+ <exclude>none</exclude>
+ </excludes>
+ <includes>
+ <include>
+ ${integration.test.code.path}/**/*Test.java
+ </include>
+ </includes>
+ <systemProperties>
+ <!--
+ WARNING: make sure these URLs are consistent with the
+ cargo-maven2-plugin settings: AFAIK Maven does not
+ expand variables in the <value> element.
+ And WARNING: these properties are duplicated somewhere in this
+ POM with slightly different values...there must be a better way.
+ -->
+ <property>
+ <name>
+ launchpad.http.server.url
+ </name>
+ <value>
+ http://${test.host}:${http.port}/${project.build.finalName}
+ </value>
+ </property>
+ <property>
+ <name>
+ launchpad.webdav.server.url
+ </name>
+ <value>
+ http://${test.host}:${http.port}/${project.build.finalName}/${webdav.workspace.path}
+ </value>
+ </property>
+
+ </systemProperties>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.cargo</groupId>
+ <artifactId>cargo-maven2-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>start-container</id>
+ <phase>pre-integration-test</phase>
+ <goals>
+ <goal>start</goal>
+ </goals>
+ </execution>
+ <execution>
+ <id>stop-container</id>
+ <phase>post-integration-test</phase>
+ <goals>
+ <goal>stop</goal>
+ </goals>
+ </execution>
+ </executions>
+ <configuration>
+ <wait>${integration.test.wait}</wait>
+ <container>
+ <containerId>jetty6x</containerId>
+ <type>embedded</type>
+ <systemProperties>
+ <sling.home>
+ ${basedir}/target/it/sling
+ </sling.home>
+ </systemProperties>
+ </container>
+ <configuration>
+ <home>${project.build.directory}/cargo</home>
+ <properties>
+ <cargo.servlet.port>
+ ${http.port}
+ </cargo.servlet.port>
+ <!--
+ <cargo.jvmargs>-Xdebug -Xnoagent -Xrunjdwp:transport=dt_socket,address=30333,server=y,suspend=y</cargo.jvmargs>
+ -->
+ </properties>
+ </configuration>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ <profile>
+ <!--
+ By default, do not run the integration tests in the test phase, as they have
+ no Sling instance to talk to.
+ See README.txt for how to run the integration tests against a running instance
+ of Sling.
+ -->
+ <id>disableIntegrationTestsInTestPhase</id>
+ <activation>
+ <property>
+ <name>!maven.test.skip</name>
+ </property>
+ </activation>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <excludes>
+ <exclude>
+ ${integration.test.code.path}/**/*.java
+ </exclude>
+ </excludes>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ </profiles>
+
+ <dependencies>
+
+ <!-- The basic Sling WebApp -->
+ <dependency>
+ <groupId>org.apache.sling</groupId>
+ <artifactId>org.apache.sling.launchpad.base</artifactId>
+ <version>2.0.4-incubator</version>
+ <classifier>webapp</classifier>
+ <type>war</type>
+ <scope>runtime</scope>
+ </dependency>
+
+ <!-- The basic Sling Bundles -->
+ <dependency>
+ <groupId>org.apache.sling</groupId>
+ <artifactId>org.apache.sling.launchpad.bundles</artifactId>
+ <version>5-incubator</version>
+ <scope>provided</scope>
+ <optional>true</optional>
+ </dependency>
+
+ <!-- JCR Install - needs to be in a profile -->
+ <dependency>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>org.osgi.core</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>biz.aQute</groupId>
+ <artifactId>bnd</artifactId>
+ <version>0.0.169</version>
+ <scope>test</scope>
+ </dependency>
+
+ <!-- Dependencies for the Test Build and Run -->
+ <dependency>
+ <groupId>org.apache.sling</groupId>
+ <artifactId>org.apache.sling.commons.testing</artifactId>
+ <version>2.0.4-incubator</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.sling</groupId>
+ <artifactId>org.apache.sling.servlets.post</artifactId>
+ <version>2.0.2-incubator</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.sling</groupId>
+ <artifactId>org.apache.sling.launchpad.test-services</artifactId>
+ <version>2.0.6-incubator</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>jcl-over-slf4j</artifactId>
+ <version>1.5.2</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-simple</artifactId>
+ <version>1.5.2</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>servlet-api</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/src/main/resources/META-INF/DISCLAIMER b/src/main/resources/META-INF/DISCLAIMER
new file mode 100644
index 0000000..90850c2
--- /dev/null
+++ b/src/main/resources/META-INF/DISCLAIMER
@@ -0,0 +1,7 @@
+Apache Sling is an effort undergoing incubation at The Apache Software Foundation (ASF),
+sponsored by the Apache Jackrabbit PMC. Incubation is required of all newly accepted
+projects until a further review indicates that the infrastructure, communications,
+and decision making process have stabilized in a manner consistent with other
+successful ASF projects. While incubation status is not necessarily a reflection of
+the completeness or stability of the code, it does indicate that the project has yet
+to be fully endorsed by the ASF.
\ No newline at end of file
diff --git a/src/main/resources/META-INF/LICENSE b/src/main/resources/META-INF/LICENSE
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/src/main/resources/META-INF/LICENSE
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed 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.
diff --git a/src/main/resources/META-INF/NOTICE b/src/main/resources/META-INF/NOTICE
new file mode 100644
index 0000000..861d0ce
--- /dev/null
+++ b/src/main/resources/META-INF/NOTICE
@@ -0,0 +1,8 @@
+Apache Sling Launchpad Testing
+Copyright 2008-2009 The Apache Software Foundation
+
+Apache Sling is based on source code originally developed
+by Day Software (http://www.day.com/).
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
diff --git a/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/CreateNodeTest.java b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/CreateNodeTest.java
new file mode 100644
index 0000000..e2f024e
--- /dev/null
+++ b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/CreateNodeTest.java
@@ -0,0 +1,170 @@
+/*
+ * 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.launchpad.webapp.integrationtest;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.commons.httpclient.methods.GetMethod;
+import org.apache.sling.commons.testing.integration.HttpTestBase;
+
+/** Test creating a Node using the MicroslingIntegrationTestClient */
+public class CreateNodeTest extends HttpTestBase {
+
+ public void testCreateNode() throws IOException {
+ final String url = HTTP_BASE_URL + "/CreateNodeTest_1_" + System.currentTimeMillis();
+
+ // add some properties to the node
+ final Map<String,String> props = new HashMap<String,String>();
+ props.put("name1","value1");
+ props.put("name2","value2");
+
+ // POST and get URL of created node
+ String urlOfNewNode = null;
+ try {
+ urlOfNewNode = testClient.createNode(url, props);
+ } catch(IOException ioe) {
+ fail("createNode failed: " + ioe);
+ }
+
+ // get and check URL of created node
+ final GetMethod get = new GetMethod(urlOfNewNode + DEFAULT_EXT);
+ final int status = httpClient.executeMethod(get);
+ assertEquals(urlOfNewNode + " must be accessible after createNode",200,status);
+ final String responseBodyStr = get.getResponseBodyAsString();
+ assertTrue(responseBodyStr.contains("value1"));
+ assertTrue(responseBodyStr.contains("value2"));
+
+ // test default txt and html renderings
+ getContent(urlOfNewNode + DEFAULT_EXT, CONTENT_TYPE_PLAIN);
+ getContent(urlOfNewNode + ".txt", CONTENT_TYPE_PLAIN);
+ getContent(urlOfNewNode + ".html", CONTENT_TYPE_HTML);
+ getContent(urlOfNewNode + ".json", CONTENT_TYPE_JSON);
+ getContent(urlOfNewNode + ".xml", CONTENT_TYPE_XML);
+
+ // And extensions for which we have no renderer fail
+ assertHttpStatus(urlOfNewNode + ".pdf", 403);
+ assertHttpStatus(urlOfNewNode + ".someWeirdExtension", 403);
+ }
+
+ public void testCreateNodeMultipart() throws IOException {
+ final String url = HTTP_BASE_URL + "/CreateNodeTest_2_" + System.currentTimeMillis();
+
+ // add some properties to the node
+ final Map<String,String> props = new HashMap<String,String>();
+ props.put("name1","value1B");
+ props.put("name2","value2B");
+
+ // POST and get URL of created node
+ String urlOfNewNode = null;
+ try {
+ urlOfNewNode = testClient.createNode(url, props, null, true);
+ } catch(IOException ioe) {
+ fail("createNode failed: " + ioe);
+ }
+
+ // check node contents (not all renderings - those are tested above)
+ final GetMethod get = new GetMethod(urlOfNewNode + DEFAULT_EXT);
+ final int status = httpClient.executeMethod(get);
+ assertEquals(urlOfNewNode + " must be accessible after createNode",200,status);
+ final String responseBodyStr = get.getResponseBodyAsString();
+ assertTrue(responseBodyStr.contains("value1B"));
+ assertTrue(responseBodyStr.contains("value2B"));
+ }
+
+ public void testCreateNodeWithNodeType() throws IOException {
+ final String url = HTTP_BASE_URL + "/CreateNodeTest_3_" + System.currentTimeMillis();
+
+ // add node type param
+ final Map<String,String> props = new HashMap<String,String>();
+ props.put("jcr:primaryType","nt:folder");
+
+ // POST and get URL of created node
+ String urlOfNewNode = null;
+ try {
+ urlOfNewNode = testClient.createNode(url, props);
+ } catch(IOException ioe) {
+ fail("createNode failed: " + ioe);
+ }
+
+ String content = getContent(urlOfNewNode + ".json", CONTENT_TYPE_JSON);
+ assertJavascript("nt:folder", content, "out.println(data['jcr:primaryType'])");
+ }
+
+ public void testCreateNewNodeWithNodeType() throws IOException {
+ final String url = HTTP_BASE_URL + "/CreateNodeTest_4_" + System.currentTimeMillis() + "/*";
+
+ // add node type param
+ final Map<String,String> props = new HashMap<String,String>();
+ props.put("jcr:primaryType","nt:folder");
+
+ // POST and get URL of created node
+ String urlOfNewNode = null;
+ try {
+ urlOfNewNode = testClient.createNode(url, props);
+ } catch(IOException ioe) {
+ fail("createNode failed: " + ioe);
+ }
+
+ String content = getContent(urlOfNewNode + ".json", CONTENT_TYPE_JSON);
+ assertJavascript("nt:folder", content, "out.println(data['jcr:primaryType'])");
+ }
+
+ public void testDeepCreateNodeWithNodeType() throws IOException {
+ final String url = HTTP_BASE_URL + "/CreateNodeTest_5_" + System.currentTimeMillis();
+
+ // add node type param
+ final Map<String,String> props = new HashMap<String,String>();
+ props.put("jcr:primaryType","nt:folder");
+ props.put("foo/jcr:primaryType","nt:folder");
+ props.put("foo/bar/jcr:primaryType","nt:folder");
+
+ // POST and get URL of created node
+ String urlOfNewNode = null;
+ try {
+ urlOfNewNode = testClient.createNode(url, props);
+ } catch(IOException ioe) {
+ fail("createNode failed: " + ioe);
+ }
+
+ String content = getContent(urlOfNewNode + ".3.json", CONTENT_TYPE_JSON);
+ assertJavascript("nt:folder", content, "out.println(data['jcr:primaryType'])");
+ assertJavascript("nt:folder", content, "out.println(data.foo['jcr:primaryType'])");
+ assertJavascript("nt:folder", content, "out.println(data.foo.bar['jcr:primaryType'])");
+ }
+
+ public void testCreateEmptyNode() throws IOException {
+ final String url = HTTP_BASE_URL + "/CreateNodeTest_6_" + System.currentTimeMillis();
+
+ // add node type param
+ final Map<String,String> props = new HashMap<String,String>();
+
+ // POST and get URL of created node
+ String urlOfNewNode = null;
+ try {
+ urlOfNewNode = testClient.createNode(url, props);
+ } catch(IOException ioe) {
+ fail("createNode failed: " + ioe);
+ }
+
+ // get and check URL of created node
+ final GetMethod get = new GetMethod(urlOfNewNode + DEFAULT_EXT);
+ final int status = httpClient.executeMethod(get);
+ assertEquals(urlOfNewNode + " must be accessible after createNode",200,status);
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/EspLoadTest.java b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/EspLoadTest.java
new file mode 100644
index 0000000..9cd446d
--- /dev/null
+++ b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/EspLoadTest.java
@@ -0,0 +1,91 @@
+/*
+ * 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.launchpad.webapp.integrationtest;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.sling.commons.testing.integration.HttpTestBase;
+
+/** Test the SLING-428 esp load function */
+public class EspLoadTest extends HttpTestBase {
+
+ private String basePath;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ basePath = "/" + getClass().getSimpleName() + "_" + System.currentTimeMillis();
+ }
+
+ public void testNestedInclude() throws Exception {
+ final Map<String,String> props = new HashMap<String,String>();
+ props.put("scriptToInclude", "included-a.esp");
+ props.put(SLING_RESOURCE_TYPE, getClass().getSimpleName());
+ final TestNode tn = new TestNode(HTTP_BASE_URL + basePath, props);
+ final String subfolder = tn.scriptPath + "/subfolder";
+ testClient.mkdirs(WEBDAV_BASE_URL, subfolder);
+ final String [] toDelete = {
+ uploadTestScript(tn.scriptPath, "esp-load/main.esp", "html.esp"),
+ uploadTestScript(tn.scriptPath, "esp-load/included-a.esp", "included-a.esp"),
+ uploadTestScript(subfolder,
+ "esp-load/subfolder/included-b.esp", "included-b.esp")
+ };
+
+ try {
+ final String content = getContent(tn.nodeUrl + ".html", CONTENT_TYPE_HTML);
+
+ final String [] expectedStringsInOrder = {
+ "main.esp before load",
+ "included-a.esp before load",
+ "included-b.esp",
+ "included-a.esp after load",
+ "main.esp after load",
+ "Here's more from included-a"
+ };
+
+ int pos = 0;
+ for(String expected : expectedStringsInOrder) {
+ final int newPos = content.indexOf(expected);
+ assertTrue("Content (" + content + ") must contain '" + expected + "'", newPos >= 0);
+ assertTrue("String '" + expected + "' must come after previous expected string", newPos > pos);
+ pos = newPos;
+ }
+ } finally {
+ for(String s : toDelete) {
+ testClient.delete(s);
+ }
+ }
+ }
+
+ public void testNonExistentInclude() throws Exception {
+ final Map<String,String> props = new HashMap<String,String>();
+ final String badScript = "nonexistent.esp";
+ props.put("scriptToInclude", badScript);
+ props.put(SLING_RESOURCE_TYPE, getClass().getSimpleName());
+ final TestNode tn = new TestNode(HTTP_BASE_URL + basePath, props);
+ final String toDelete = uploadTestScript(tn.scriptPath, "esp-load/main.esp", "html.esp");
+ try {
+ assertHttpStatus(tn.nodeUrl + ".html", HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
+ "Including " + badScript + " must fail");
+ } finally {
+ testClient.delete(toDelete);
+ }
+ }
+}
diff --git a/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/FileUploadTest.java b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/FileUploadTest.java
new file mode 100644
index 0000000..836c1e9
--- /dev/null
+++ b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/FileUploadTest.java
@@ -0,0 +1,54 @@
+/*
+ * 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.launchpad.webapp.integrationtest;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.apache.sling.commons.testing.integration.HttpTestBase;
+
+/** Test uploading files to the Sling repository
+ * via WebDAV, as a first step towards testing the
+ * complete content creation and rendering scenario.
+ */
+public class FileUploadTest extends HttpTestBase {
+
+ /** This only tests the WebDAV interface. We know it works, so
+ * we're mostly testing our test code here ;-)
+ */
+ public void testUploadAndDelete() throws IOException {
+ final String testFile = "/integration-test/testfile.txt";
+ final InputStream data = getClass().getResourceAsStream(testFile);
+ try {
+ assertNotNull("Local test file " + testFile + " must be found",data);
+
+ final String webdavUrl = WEBDAV_BASE_URL + "/FileUploadTest." + System.currentTimeMillis() + ".txt";
+
+ // Upload a file via WebDAV, verify, delete and verify
+ assertHttpStatus(webdavUrl, 404, "Resource " + webdavUrl + " must not exist before test");
+ int status = testClient.upload(webdavUrl, data);
+ assertEquals("upload must return status code 201",201,status);
+ assertHttpStatus(webdavUrl, 200, "Resource " + webdavUrl + " must exist after upload");
+ testClient.delete(webdavUrl);
+ assertHttpStatus(webdavUrl, 404, "Resource " + webdavUrl + " must not exist anymore after deleting");
+ } finally {
+ if(data!=null) {
+ data.close();
+ }
+ }
+ }
+}
diff --git a/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/ForwardTest.java b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/ForwardTest.java
new file mode 100644
index 0000000..725e888
--- /dev/null
+++ b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/ForwardTest.java
@@ -0,0 +1,145 @@
+/*
+ * 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.launchpad.webapp.integrationtest;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.httpclient.methods.GetMethod;
+import org.apache.sling.commons.testing.integration.HttpTestBase;
+import org.apache.sling.servlets.post.SlingPostConstants;
+
+
+/** Test the {link ScriptHelper#forward) functionality */
+ public class ForwardTest extends HttpTestBase {
+
+ private String nodeUrlA;
+ private String testTextA;
+ private String nodeUrlB;
+ private String testTextB;
+ private String nodeUrlC;
+ private String nodeUrlD;
+ private String nodeUrlE;
+ private String scriptPath;
+ private String forcedResourceType;
+ private Set<String> toDelete = new HashSet<String>();
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ // Create the test nodes under a path that's specific to this class to
+ // allow collisions
+ final String url = HTTP_BASE_URL + "/" + getClass().getSimpleName() + "/" + System.currentTimeMillis() + SlingPostConstants.DEFAULT_CREATE_SUFFIX;
+ final Map<String,String> props = new HashMap<String,String>();
+
+ // Create two test nodes and store their paths
+ testTextA = "Text A " + System.currentTimeMillis();
+ props.put("text", testTextA);
+ nodeUrlA = testClient.createNode(url, props);
+ String pathToInclude = nodeUrlA.substring(HTTP_BASE_URL.length());
+
+ // Node B stores the path of A, so that the test script can
+ // forward A when rendering B
+ testTextB = "Text B " + System.currentTimeMillis();
+ props.put("text", testTextB);
+ props.put("pathToInclude", pathToInclude);
+ nodeUrlB = testClient.createNode(url, props);
+
+ // Node E is like B but with an extension on the forward path
+ props.put("pathToInclude", pathToInclude + ".html");
+ nodeUrlE = testClient.createNode(url, props);
+
+ // Node C is used for the infinite loop detection test
+ props.remove("pathToInclude");
+ props.put("testInfiniteLoop","true");
+ nodeUrlC = testClient.createNode(url, props);
+
+ // Node D is used for the "force resource type" test
+ forcedResourceType = getClass().getSimpleName() + "/" + System.currentTimeMillis();
+ props.remove("testInfiniteLoop");
+ props.put("forceResourceType", forcedResourceType);
+ props.put("pathToInclude", pathToInclude);
+ nodeUrlD = testClient.createNode(url, props);
+
+ // Script for forced resource type
+ scriptPath = "/apps/" + forcedResourceType;
+ testClient.mkdirs(WEBDAV_BASE_URL, scriptPath);
+ toDelete.add(uploadTestScript(scriptPath,"forward-forced.esp","html.esp"));
+
+ // The main rendering script goes under /apps in the repository
+ scriptPath = "/apps/nt/unstructured";
+ testClient.mkdirs(WEBDAV_BASE_URL, scriptPath);
+ toDelete.add(uploadTestScript(scriptPath,"forward-test.esp","html.esp"));
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ for(String script : toDelete) {
+ testClient.delete(script);
+ }
+ }
+
+ public void testWithoutForward() throws IOException {
+ final String content = getContent(nodeUrlA + ".html", CONTENT_TYPE_HTML);
+ assertTrue("Content includes ESP marker",content.contains("ESP template"));
+ assertTrue("Content contains formatted test text",content.contains("<p class=\"main\">" + testTextA + "</p>"));
+ }
+
+ public void testWithForward() throws IOException {
+ final String content = getContent(nodeUrlB + ".html", CONTENT_TYPE_HTML);
+ assertTrue("Content includes ESP marker",content.contains("ESP template"));
+ assertTrue("Content contains formatted test text",content.contains("<p class=\"main\">" + testTextA + "</p>"));
+ assertTrue("Text of node A is not included (" + content + ")",!content.contains(testTextB));
+ }
+
+ public void testWithForwardAndExtension() throws IOException {
+ final String content = getContent(nodeUrlE + ".html", CONTENT_TYPE_HTML);
+ assertTrue("Content includes ESP marker",content.contains("ESP template"));
+ assertTrue("Content contains formatted test text",content.contains("<p class=\"main\">" + testTextA + "</p>"));
+ assertTrue("Text of node A is not included (" + content + ")",!content.contains(testTextB));
+ }
+
+ public void testInfiniteLoopDetection() throws IOException {
+ // Node C has a property that causes an infinite include loop,
+ // Sling must indicate the problem in its response
+ final GetMethod get = new GetMethod(nodeUrlC + ".html");
+ httpClient.executeMethod(get);
+ final String content = get.getResponseBodyAsString();
+ assertTrue(
+ "Response contains infinite loop error message",
+ content.contains("org.apache.sling.api.request.RecursionTooDeepException"));
+
+ // TODO: SLING-515, status is 500 when running the tests as part of the maven build
+ // but 200 if running tests against a separate instance started with mvn jetty:run
+ // final int status = get.getStatusCode();
+ // assertEquals("Status is 500 for infinite loop",HttpServletResponse.SC_INTERNAL_SERVER_ERROR, status);
+ }
+
+ public void testForcedResourceType() throws IOException {
+ final String content = getContent(nodeUrlD + ".html", CONTENT_TYPE_HTML);
+ assertTrue("Content includes ESP marker",content.contains("ESP template"));
+ assertTrue("Content contains formatted test text",content.contains("<p class=\"main\">" + testTextA + "</p>"));
+ assertTrue("Text of node A is included (" + content + ")",!content.contains(testTextB));
+ assertTrue("Resource type has been forced (" + content + ")",content.contains("Forced resource type:" + forcedResourceType));
+ }
+}
diff --git a/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/GeneratedNodeNameTest.java b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/GeneratedNodeNameTest.java
new file mode 100644
index 0000000..03c8dd6
--- /dev/null
+++ b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/GeneratedNodeNameTest.java
@@ -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.launchpad.webapp.integrationtest;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.sling.commons.testing.integration.HttpTestBase;
+import org.apache.sling.servlets.post.SlingPostConstants;
+
+/** Test the generation of node names for POST requests to URLS
+ * ending in / *
+ */
+public class GeneratedNodeNameTest extends HttpTestBase {
+
+ private final String postUrl = HTTP_BASE_URL + "/" + getClass().getSimpleName() + "/" + System.currentTimeMillis() + SlingPostConstants.DEFAULT_CREATE_SUFFIX;
+
+ public void testTitle() throws IOException {
+ final Map<String,String> props = new HashMap<String,String>();
+ props.put("title", "Hello There");
+ final String location = testClient.createNode(postUrl, props);
+ final String expect = "hello_there";
+ assertTrue("Location " + location + " ends with " + expect,location.endsWith(expect));
+ }
+
+ public void testSlingPostNodeNameParam() throws IOException {
+ final Map<String,String> props = new HashMap<String,String>();
+ props.put(":name", "MyNodeName");
+ final String location = testClient.createNode(postUrl, props);
+ final String expect = "MyNodeName";
+ assertTrue("Location " + location + " ends with " + expect,location.endsWith(expect));
+ }
+
+ public void testSlingPostNodeNameHintParam() throws IOException {
+ final Map<String,String> props = new HashMap<String,String>();
+ props.put(":nameHint", "AnotherNodeName");
+ final String location = testClient.createNode(postUrl, props);
+ final String expect = "AnotherNodeName".toLowerCase();
+ assertTrue("Location " + location + " ends with " + expect,location.endsWith(expect));
+ }
+
+ public void testTitleWithSavePrefix() throws IOException {
+ final Map<String,String> props = new HashMap<String,String>();
+ props.put("./title", "Hello There 2");
+ props.put("title", "not this one");
+ final String location = testClient.createNode(postUrl, props);
+ final String expect = "hello_there_2";
+ assertTrue("Location " + location + " ends with " + expect,location.endsWith(expect));
+ }
+
+ public void testCollision() throws IOException {
+ final Map<String,String> props = new HashMap<String,String>();
+ props.put("title", "Hello There");
+
+ // posting twice with the same title must work, and return different locations
+ final String locationA = testClient.createNode(postUrl, props);
+ final String locationB = testClient.createNode(postUrl, props);
+
+ assertFalse("Locations A and B must be different (" + locationA + "," + locationB + ")",
+ locationA.equals(locationB));
+ }
+
+ public void testNoParams() throws IOException {
+ final String location = testClient.createNode(postUrl, null);
+ assertTrue("Location end with a digit",Character.isDigit(location.charAt(location.length() - 1)));
+ }
+}
diff --git a/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/GeneratedNodeNameTestStar.java b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/GeneratedNodeNameTestStar.java
new file mode 100644
index 0000000..ceecf7a
--- /dev/null
+++ b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/GeneratedNodeNameTestStar.java
@@ -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.launchpad.webapp.integrationtest;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.sling.commons.testing.integration.HttpTestBase;
+import org.apache.sling.servlets.post.SlingPostConstants;
+
+/** Test the generation of node names for POST requests to URLS
+ * ending in / *
+ */
+public class GeneratedNodeNameTestStar extends HttpTestBase {
+
+ private final String postUrl = HTTP_BASE_URL + "/" + getClass().getSimpleName() + "/" + System.currentTimeMillis() + SlingPostConstants.STAR_CREATE_SUFFIX;
+
+ public void testTitle() throws IOException {
+ final Map<String,String> props = new HashMap<String,String>();
+ props.put("title", "Hello There");
+ final String location = testClient.createNode(postUrl, props);
+ final String expect = "hello_there";
+ assertTrue("Location " + location + " ends with " + expect,location.endsWith(expect));
+ }
+
+ public void testSlingPostNodeNameParam() throws IOException {
+ final Map<String,String> props = new HashMap<String,String>();
+ props.put(":name", "MyNodeName");
+ final String location = testClient.createNode(postUrl, props);
+ final String expect = "MyNodeName";
+ assertTrue("Location " + location + " ends with " + expect,location.endsWith(expect));
+ }
+
+ public void testSlingPostNodeNameHintParam() throws IOException {
+ final Map<String,String> props = new HashMap<String,String>();
+ props.put(":nameHint", "AnotherNodeName");
+ final String location = testClient.createNode(postUrl, props);
+ final String expect = "AnotherNodeName".toLowerCase();
+ assertTrue("Location " + location + " ends with " + expect,location.endsWith(expect));
+ }
+
+ public void testTitleWithSavePrefix() throws IOException {
+ final Map<String,String> props = new HashMap<String,String>();
+ props.put("./title", "Hello There 2");
+ props.put("title", "not this one");
+ final String location = testClient.createNode(postUrl, props);
+ final String expect = "hello_there_2";
+ assertTrue("Location " + location + " ends with " + expect,location.endsWith(expect));
+ }
+
+ public void testCollision() throws IOException {
+ final Map<String,String> props = new HashMap<String,String>();
+ props.put("title", "Hello There");
+
+ // posting twice with the same title must work, and return different locations
+ final String locationA = testClient.createNode(postUrl, props);
+ final String locationB = testClient.createNode(postUrl, props);
+
+ assertFalse("Locations A and B must be different (" + locationA + "," + locationB + ")",
+ locationA.equals(locationB));
+ }
+
+ public void testNoParams() throws IOException {
+ final String location = testClient.createNode(postUrl, null);
+ assertTrue("Location end with a digit",Character.isDigit(location.charAt(location.length() - 1)));
+ }
+}
diff --git a/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/GetStarTest.java b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/GetStarTest.java
new file mode 100644
index 0000000..e8475e3
--- /dev/null
+++ b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/GetStarTest.java
@@ -0,0 +1,39 @@
+/*
+ * 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.launchpad.webapp.integrationtest;
+
+import java.io.IOException;
+
+/** A GET to *.html and *.json must work even if there is no Node
+ * at the specified path (SLING-344)
+ */
+public class GetStarTest extends RenderingTestBase {
+ private final String random = getClass().getSimpleName() + String.valueOf(System.currentTimeMillis());
+
+ public void testGetStarHtml() throws IOException {
+ getContent(HTTP_BASE_URL + "/*.html", CONTENT_TYPE_HTML);
+ getContent(HTTP_BASE_URL + "/" + random + "/*.html", CONTENT_TYPE_HTML);
+ getContent(HTTP_BASE_URL + "/" + random + "/" + random + "/*.html", CONTENT_TYPE_HTML);
+ getContent(HTTP_BASE_URL + "/" + random + "/*.someselector.html", CONTENT_TYPE_HTML);
+ }
+
+ public void testGetStarJson() throws IOException {
+ getContent(HTTP_BASE_URL + "/*.json", CONTENT_TYPE_JSON);
+ getContent(HTTP_BASE_URL + "/" + random + "/*.json", CONTENT_TYPE_JSON);
+ getContent(HTTP_BASE_URL + "/" + random + "/*.12.json", CONTENT_TYPE_JSON);
+ }
+}
diff --git a/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/GetWithSuffixTest.java b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/GetWithSuffixTest.java
new file mode 100644
index 0000000..3cd9e4d
--- /dev/null
+++ b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/GetWithSuffixTest.java
@@ -0,0 +1,99 @@
+/*
+ * 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.launchpad.webapp.integrationtest;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletResponse;
+
+/** GET requests with a suffix should fail with a 404, otherwise
+ * we get a lot of extra possible URLs which point to the same
+ * content.
+ */
+public class GetWithSuffixTest extends RenderingTestBase {
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ // set test values
+ testText = "This is a test " + System.currentTimeMillis();
+
+ // create the test node, under a path that's specific to this class to allow collisions
+ final String url = HTTP_BASE_URL + "/" + getClass().getSimpleName() + "_" + System.currentTimeMillis();
+ final Map<String,String> props = new HashMap<String,String>();
+ props.put("text", testText);
+ displayUrl = testClient.createNode(url, props);
+
+ // the rendering script goes under /apps in the repository
+ scriptPath = "/apps/nt/unstructured";
+ testClient.mkdirs(WEBDAV_BASE_URL, scriptPath);
+ }
+
+ public void testWithExactUrl() throws IOException {
+ final String toDelete = uploadTestScript("rendering-test.esp","html.esp");
+ try {
+ final String content = getContent(displayUrl + ".html", CONTENT_TYPE_HTML);
+ assertTrue("Content includes ESP marker",content.contains("ESP template"));
+ assertTrue("Content contains formatted test text",content.contains("<p>" + testText + "</p>"));
+ } finally {
+ testClient.delete(toDelete);
+ }
+ }
+
+ public void testGETScript() throws IOException {
+ final String toDelete = uploadTestScript("rendering-test.esp","GET.esp");
+ try {
+ final String content = getContent(displayUrl + ".html", CONTENT_TYPE_HTML);
+ assertTrue("Content includes ESP marker",content.contains("ESP template"));
+ assertTrue("Content contains formatted test text",content.contains("<p>" + testText + "</p>"));
+
+ final String content2 = getContent(displayUrl + ".txt", CONTENT_TYPE_PLAIN);
+ assertTrue("Content includes ESP marker",content2.contains("ESP template"));
+ assertTrue("Content contains formatted test text",content2.contains("<p>" + testText + "</p>"));
+ } finally {
+ testClient.delete(toDelete);
+ }
+ }
+
+ public void testWithExtraPathA() throws IOException {
+ final String toDelete = uploadTestScript("rendering-test.esp","txt.esp");
+ try {
+ // expected to be found as resource with ext .txt and suffix
+ final String content = getContent(displayUrl + ".txt/extra.html", CONTENT_TYPE_PLAIN);
+ assertTrue("Content includes ESP marker",content.contains("ESP template"));
+ assertTrue("Content contains formatted test text",content.contains("<p>" + testText + "</p>"));
+ } finally {
+ testClient.delete(toDelete);
+ }
+ }
+
+ /** behavior seems slightly different if using GET.esp vs. html.esp for the
+ * script name, verify that both give a 404
+ */
+ public void testWithExtraPathB() throws IOException {
+ final String toDelete = uploadTestScript("rendering-test.esp","GET.esp");
+ try {
+ // expected to not be found as dispalyUrl has no dots
+ assertHttpStatus(displayUrl + "/extra/more.a4.html", HttpServletResponse.SC_NOT_FOUND);
+ } finally {
+ testClient.delete(toDelete);
+ }
+ }
+}
diff --git a/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/HttpPingTest.java b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/HttpPingTest.java
new file mode 100644
index 0000000..6fc4059
--- /dev/null
+++ b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/HttpPingTest.java
@@ -0,0 +1,47 @@
+/*
+ * 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.launchpad.webapp.integrationtest;
+
+import org.apache.commons.httpclient.Header;
+import org.apache.commons.httpclient.methods.GetMethod;
+import org.apache.sling.commons.testing.integration.HttpTestBase;
+
+
+/** Ping the Sling server to verify that our integration test
+ * setup is ok.
+ */
+public class HttpPingTest extends HttpTestBase {
+
+ public void testWebServerRoot() throws Exception
+ {
+ // by default, the Launchpad default servlet redirects / to index.html
+ final String url = HTTP_BASE_URL + "/";
+ final GetMethod get = new GetMethod(url);
+ get.setFollowRedirects(false);
+ final int status = httpClient.executeMethod(get);
+ assertEquals("Status must be 302 for " + url, 302, status);
+ final Header h = get.getResponseHeader("Location");
+ assertNotNull("Location header must be provided",h);
+ assertTrue("Location header must end with index.html", h.getValue().endsWith("index.html"));
+ }
+
+ public void test404() throws Exception
+ {
+ assertHttpStatus(HTTP_BASE_URL + "/someNonExistentUrl", 404);
+ }
+
+}
diff --git a/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/IncludeTest.java b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/IncludeTest.java
new file mode 100644
index 0000000..7326dbf
--- /dev/null
+++ b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/IncludeTest.java
@@ -0,0 +1,148 @@
+/*
+ * 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.launchpad.webapp.integrationtest;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.httpclient.methods.GetMethod;
+import org.apache.sling.commons.testing.integration.HttpTestBase;
+import org.apache.sling.servlets.post.SlingPostConstants;
+
+
+/** Test the {link ScriptHelper#include) functionality */
+ public class IncludeTest extends HttpTestBase {
+
+ private String nodeUrlA;
+ private String testTextA;
+ private String nodeUrlB;
+ private String testTextB;
+ private String nodeUrlC;
+ private String nodeUrlD;
+ private String nodeUrlE;
+ private String scriptPath;
+ private Set<String> toDelete = new HashSet<String>();
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ // Create the test nodes under a path that's specific to this class to
+ // allow collisions
+ final String url = HTTP_BASE_URL + "/" + getClass().getSimpleName() + "/" + System.currentTimeMillis() + SlingPostConstants.DEFAULT_CREATE_SUFFIX;
+ final Map<String,String> props = new HashMap<String,String>();
+
+ // Create two test nodes and store their paths
+ testTextA = "Text A " + System.currentTimeMillis();
+ props.put("text", testTextA);
+ nodeUrlA = testClient.createNode(url, props);
+ String pathToInclude = nodeUrlA.substring(HTTP_BASE_URL.length());
+
+ // Node B stores the path of A, so that the test script can
+ // include A when rendering B
+ testTextB = "Text B " + System.currentTimeMillis();
+ props.put("text", testTextB);
+ props.put("pathToInclude", pathToInclude);
+ nodeUrlB = testClient.createNode(url, props);
+
+ // Node E is like B but with an extension on the include path
+ props.put("pathToInclude", pathToInclude + ".html");
+ nodeUrlE = testClient.createNode(url, props);
+
+ // Node C is used for the infinite loop detection test
+ props.remove("pathToInclude");
+ props.put("testInfiniteLoop","true");
+ nodeUrlC = testClient.createNode(url, props);
+
+ // Node D is used for the "force resource type" test
+ final String forcedResourceType = getClass().getSimpleName() + "/" + System.currentTimeMillis();
+ props.remove("testInfiniteLoop");
+ props.put("forceResourceType", forcedResourceType);
+ props.put("pathToInclude", pathToInclude);
+ nodeUrlD = testClient.createNode(url, props);
+
+ // Script for forced resource type
+ scriptPath = "/apps/" + forcedResourceType;
+ testClient.mkdirs(WEBDAV_BASE_URL, scriptPath);
+ toDelete.add(uploadTestScript(scriptPath,"include-forced.esp","html.esp"));
+
+ // The main rendering script goes under /apps in the repository
+ scriptPath = "/apps/nt/unstructured";
+ testClient.mkdirs(WEBDAV_BASE_URL, scriptPath);
+ toDelete.add(uploadTestScript(scriptPath,"include-test.esp","html.esp"));
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ for(String script : toDelete) {
+ testClient.delete(script);
+ }
+ }
+
+ public void testWithoutInclude() throws IOException {
+ final String content = getContent(nodeUrlA + ".html", CONTENT_TYPE_HTML);
+ assertTrue("Content includes ESP marker",content.contains("ESP template"));
+ assertTrue("Content contains formatted test text",content.contains("<p class=\"main\">" + testTextA + "</p>"));
+ assertFalse("Nothing has been included",content.contains("<p>Including"));
+ }
+
+ public void testWithInclude() throws IOException {
+ final String content = getContent(nodeUrlB + ".html", CONTENT_TYPE_HTML);
+ assertTrue("Content includes ESP marker",content.contains("ESP template"));
+ assertTrue("Content contains formatted test text",content.contains("<p class=\"main\">" + testTextB + "</p>"));
+ assertTrue("Include has been used",content.contains("<p>Including"));
+ assertTrue("Text of node A is included (" + content + ")",content.contains(testTextA));
+ }
+
+ public void testWithIncludeAndExtension() throws IOException {
+ final String content = getContent(nodeUrlE + ".html", CONTENT_TYPE_HTML);
+ assertTrue("Content includes ESP marker",content.contains("ESP template"));
+ assertTrue("Content contains formatted test text",content.contains("<p class=\"main\">" + testTextB + "</p>"));
+ assertTrue("Include has been used",content.contains("<p>Including"));
+ assertTrue("Text of node A is included (" + content + ")",content.contains(testTextA));
+ }
+
+ public void testInfiniteLoopDetection() throws IOException {
+ // Node C has a property that causes an infinite include loop,
+ // Sling must indicate the problem in its response
+ final GetMethod get = new GetMethod(nodeUrlC + ".html");
+ httpClient.executeMethod(get);
+ final String content = get.getResponseBodyAsString();
+ assertTrue(
+ "Response contains infinite loop error message",
+ content.contains("org.apache.sling.api.request.RecursionTooDeepException"));
+
+ // TODO: SLING-515, status is 500 when running the tests as part of the maven build
+ // but 200 if running tests against a separate instance started with mvn jetty:run
+ // final int status = get.getStatusCode();
+ // assertEquals("Status is 500 for infinite loop",HttpServletResponse.SC_INTERNAL_SERVER_ERROR, status);
+ }
+
+ public void testForcedResourceType() throws IOException {
+ final String content = getContent(nodeUrlD + ".html", CONTENT_TYPE_HTML);
+ assertTrue("Content includes ESP marker",content.contains("ESP template"));
+ assertTrue("Content contains formatted test text",content.contains("<p class=\"main\">" + testTextB + "</p>"));
+ assertTrue("Include has been used",content.contains("<p>Including"));
+ assertTrue("Text of node A is included (" + content + ")",content.contains(testTextA));
+ assertTrue("Resource type has been forced (" + content + ")",content.contains("Forced resource type:" + testTextA));
+ }
+}
diff --git a/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/InitialContentTest.java b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/InitialContentTest.java
new file mode 100644
index 0000000..a488b7d
--- /dev/null
+++ b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/InitialContentTest.java
@@ -0,0 +1,49 @@
+/* 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.launchpad.webapp.integrationtest;
+
+import java.io.IOException;
+
+import org.apache.sling.commons.testing.integration.HttpTestBase;
+
+public class InitialContentTest extends HttpTestBase {
+
+ public void testIndex() throws IOException {
+ final String expected = "Do not remove this comment, used for Launchpad integration tests";
+ final String content = getContent(HTTP_BASE_URL + "/index.html", CONTENT_TYPE_HTML);
+ assertTrue("Content contains expected marker (" + content + ")",content.contains(expected));
+ }
+
+ public void testRootRedirectProperty() throws IOException {
+ final String expected = "\"sling:resourceType\":\"sling:redirect\"";
+ final String content = getContent(HTTP_BASE_URL + "/.json", CONTENT_TYPE_JSON);
+ assertTrue("Content contains " + expected + " (" + content + ")", content.contains(expected));
+ }
+
+ public void testInitialContentA() throws IOException {
+ final String expected = "42";
+ final String content = getContent(
+ HTTP_BASE_URL + "/sling-test/sling/initial-content-test/marker.txt", CONTENT_TYPE_PLAIN);
+ assertTrue("Content contains " + expected + " (" + content + ")", content.contains(expected));
+ }
+
+ public void testInitialContentB() throws IOException {
+ final String expected = "46";
+ final String content = getContent(
+ HTTP_BASE_URL + "/sling-test/initial-content-folder/folder-content-test/marker.txt", CONTENT_TYPE_PLAIN);
+ assertTrue("Content contains " + expected + " (" + content + ")", content.contains(expected));
+ }
+}
diff --git a/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/JavascriptWrappersTest.java b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/JavascriptWrappersTest.java
new file mode 100644
index 0000000..00dc466
--- /dev/null
+++ b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/JavascriptWrappersTest.java
@@ -0,0 +1,76 @@
+/*
+ * 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.launchpad.webapp.integrationtest;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.sling.commons.testing.integration.HttpTestBase;
+
+/** Test Scriptable objects */
+public class JavascriptWrappersTest extends HttpTestBase {
+
+ private TestNode testRootNode;
+ private String basePath;
+
+ private void createNodes(TestNode n, String prefix, int levels) throws Exception {
+ String url = n.nodeUrl;
+ while(levels >= 1) {
+ url += "/" + prefix + levels;
+ testClient.createNode(url, null);
+ levels--;
+ }
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ basePath = "/" + getClass().getSimpleName() + "_" + System.currentTimeMillis();
+
+ final Map<String, String> props = new HashMap<String, String>();
+ props.put(SLING_RESOURCE_TYPE, getClass().getSimpleName());
+ props.put("title", "testnode");
+
+ testRootNode = new TestNode(HTTP_BASE_URL + basePath, props);
+ createNodes(testRootNode, "a", 3);
+ createNodes(testRootNode, "b", 1);
+ createNodes(testRootNode, "c", 2);
+ }
+
+ public void testRecursiveDump() throws IOException {
+ final String toDelete = uploadTestScript(testRootNode.scriptPath, "dump-resource.ecma", "html.ecma");
+ try {
+ final String content = getContent(testRootNode.nodeUrl + ".html", CONTENT_TYPE_HTML);
+
+ final String expected =
+ "1 " + basePath + "/testnode\n"
+ + "2 " + basePath + "/testnode/a3\n"
+ + "3 " + basePath + "/testnode/a3/a2\n"
+ + "4 " + basePath + "/testnode/a3/a2/a1\n"
+ + "2 " + basePath + "/testnode/b1\n"
+ + "2 " + basePath + "/testnode/c2\n"
+ + "3 " + basePath + "/testnode/c2/c1\n"
+ ;
+ assertEquals(expected, content);
+ } finally {
+ testClient.delete(toDelete);
+ }
+
+ }
+}
diff --git a/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/JsonQueryServletTest.java b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/JsonQueryServletTest.java
new file mode 100644
index 0000000..eb6c7ce
--- /dev/null
+++ b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/JsonQueryServletTest.java
@@ -0,0 +1,141 @@
+/*
+ * 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.launchpad.webapp.integrationtest;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.httpclient.NameValuePair;
+import org.apache.sling.commons.testing.integration.HttpTestBase;
+
+
+/** Test the {link JsonQueryServlet) functionality.
+ * We don't need to test the repository query feature, just
+ * make sure that the query servlet parameters are interpreted correctly.
+ */
+public class JsonQueryServletTest extends HttpTestBase {
+
+ private String testFolderUrl;
+ private final String testPath = "/" + getClass().getSimpleName() + "_" + System.currentTimeMillis();
+ private final static String counterCode = "out.print(data.length);";
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ testFolderUrl = testClient.createNode(HTTP_BASE_URL + testPath, null);
+
+ // create subfolders A..E with subnodes 0..4, each contains its name as a text property
+ for(char folder = 'A'; folder <= 'E'; folder++) {
+ final Map<String, String> props = new HashMap<String, String> ();
+ props.put("creator", getClass().getSimpleName());
+ props.put("text", "folder " + folder);
+ final String subfolderUrl = testClient.createNode(testFolderUrl + "/folder" + folder, props);
+ for(int i=0; i < 5; i++) {
+ props.put("text", "folder " + folder + " node "+ i);
+ testClient.createNode(subfolderUrl + "/node" + i, props);
+ }
+
+ }
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+
+ if(testFolderUrl != null) {
+ testClient.delete(WEBDAV_BASE_URL + testPath);
+ }
+ }
+
+ private void assertCount(int expectedCount, String statement, String queryType, int offset, int rows)
+ throws IOException {
+ final List<NameValuePair> params = new ArrayList<NameValuePair>();
+ params.add(new NameValuePair("statement", statement));
+ if(queryType != null) {
+ params.add(new NameValuePair("queryType", queryType));
+ }
+ if(offset > 0) {
+ params.add(new NameValuePair("offset", String.valueOf(offset)));
+ }
+ if(rows > 0) {
+ params.add(new NameValuePair("rows", String.valueOf(rows)));
+ }
+ final String json = getContent(testFolderUrl + ".query.json", CONTENT_TYPE_JSON, params);
+ assertJavascript(
+ expectedCount + ".0",
+ json,
+ counterCode,
+ "statement=" + statement + ", queryType=" + queryType
+ );
+ }
+
+ public void testFolderQuery() throws IOException {
+ assertCount(1, "/" + testPath + "/folderC", "xpath", 0, 0);
+ }
+
+ public void testSubFolderQuery() throws IOException {
+ assertCount(5, "/" + testPath + "/folderA/*", "xpath", 0, 0);
+ }
+
+ public void testDefaultQueryType() throws IOException {
+ assertCount(5, "/" + testPath + "/folderE/*", null, 0, 0);
+ }
+
+ public void testSql() throws IOException {
+ final String query = "select * from nt:unstructured where jcr:path like '" + testPath + "/folderB/%'";
+ assertCount(5, query, "sql", 0, 0);
+ }
+
+ public void testOffset() throws IOException {
+ assertCount(3, "/" + testPath + "/folderC/*", "xpath", 2, 0);
+ }
+
+ public void testRows() throws IOException {
+ assertCount(2, "/" + testPath + "/folderC/*", "xpath", 0, 2);
+ }
+
+ public void testPropertyParam() throws IOException {
+ final String url = testFolderUrl + ".query.json";
+ final String statement = "/" + testPath + "/folderB/node3";
+ final List<NameValuePair> params = new ArrayList<NameValuePair>();
+ params.add(new NameValuePair("statement", statement));
+
+ String json = getContent(url, CONTENT_TYPE_JSON, params);
+ assertJavascript("1.0", json, counterCode);
+ assertJavascript("ok", json, "if(!data[0].text) out.print('ok')");
+ assertJavascript("ok", json, "if(!data[0].creator) out.print('ok')");
+
+ params.add(new NameValuePair("property", "text"));
+ json = getContent(url, CONTENT_TYPE_JSON, params);
+ assertJavascript("1.0", json, counterCode);
+ assertJavascript("ok", json, "if(data[0].text) out.print('ok')");
+ assertJavascript("folder B node 3", json, "out.print(data[0].text)");
+ assertJavascript("ok", json, "if(!data[0].creator) out.print('ok')");
+
+ params.add(new NameValuePair("property", "creator"));
+ json = getContent(url, CONTENT_TYPE_JSON, params);
+ assertJavascript("1.0", json, counterCode);
+ assertJavascript("ok", json, "if(data[0].text) out.print('ok')");
+ assertJavascript("folder B node 3", json, "out.print(data[0].text)");
+ assertJavascript("ok", json, "if(data[0].creator) out.print('ok')");
+ assertJavascript(getClass().getSimpleName(), json, "out.print(data[0].creator)");
+ }
+}
diff --git a/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/JsonRenderingTest.java b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/JsonRenderingTest.java
new file mode 100644
index 0000000..d20e4a8
--- /dev/null
+++ b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/JsonRenderingTest.java
@@ -0,0 +1,228 @@
+/*
+ * 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.launchpad.webapp.integrationtest;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.sling.commons.testing.integration.HttpTestBase;
+import org.apache.sling.servlets.post.SlingPostConstants;
+
+/** Test creating Nodes and rendering them in JSON */
+public class JsonRenderingTest extends HttpTestBase {
+
+ private final String testPath = "/" + getClass().getSimpleName();
+ private String postUrl;
+
+ private String testText;
+
+ private String jsonUrl;
+
+ private String createdNodeUrl;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ // set test values
+ testText = "This is a test " + System.currentTimeMillis();
+
+ // create the test node, under a path that's specific to this class to
+ // allow collisions
+ postUrl = HTTP_BASE_URL + testPath + "_"
+ + System.currentTimeMillis()
+ + SlingPostConstants.DEFAULT_CREATE_SUFFIX;
+ final Map<String, String> props = new HashMap<String, String>();
+ props.put("text", testText);
+ createdNodeUrl = testClient.createNode(postUrl, props);
+ jsonUrl = createdNodeUrl + ".json";
+ }
+
+ /** test our assertJavascript method with static json */
+ public void testAssertJavascript() throws IOException {
+ final String json = "{ 'a' : '123', 'b' : '456' }";
+ assertJavascript("123456", json, "out.println(data.a + data.b)");
+ }
+
+ public void testNonRecursive() throws IOException {
+ final String json = getContent(jsonUrl, CONTENT_TYPE_JSON);
+ assertJavascript(testText, json, "out.println(data.text)");
+ }
+
+ /** Create a node with children, verify that we get them back in JSON format */
+ public void testRecursiveOneLevel() throws IOException {
+ final Map<String, String> props = new HashMap<String, String>();
+ props.put("text", testText);
+
+ final String parentNodeUrl = testClient.createNode(postUrl, props);
+ final String[] children = { "A", "B", "C" };
+ for (String child : children) {
+ props.put("child", child);
+ testClient.createNode(parentNodeUrl + "/" + child, props);
+ }
+
+ final String json = getContent(parentNodeUrl + ".1.json",
+ CONTENT_TYPE_JSON);
+ assertJavascript(testText, json, "out.print(data.text)");
+ for (String child : children) {
+ assertJavascript(child, json, "out.print(data['" + child
+ + "'].child)");
+ assertJavascript(testText, json, "out.print(data['" + child
+ + "'].text)");
+ }
+ }
+
+ /**
+ * Create a node with children, verify that we do not get them back in JSON
+ * format if using recursion level=0
+ */
+ public void testRecursiveZeroLevels() throws IOException {
+ final Map<String, String> props = new HashMap<String, String>();
+ props.put("text", testText);
+
+ final String parentNodeUrl = testClient.createNode(postUrl, props);
+ final String[] children = { "A", "B", "C" };
+ for (String child : children) {
+ props.put("child", child);
+ testClient.createNode(parentNodeUrl + "/" + child, props);
+ }
+
+ // .json and .0.json must both return 0 levels
+ final String[] extensions = { ".json", ".0.json" };
+ for (String extension : extensions) {
+ final String json = getContent(parentNodeUrl + extension,
+ CONTENT_TYPE_JSON);
+ assertJavascript(testText, json, "out.print(data.text)");
+ for (String child : children) {
+ final String testInfo = "extension: " + extension;
+ assertJavascript("undefined", json, "out.print(typeof data['"
+ + child + "'])", testInfo);
+ }
+ }
+
+ }
+
+ /** Test the "infinity" recursion level */
+ public void testRecursiveInfinity() throws IOException {
+ final Map<String, String> props = new HashMap<String, String>();
+ props.put("text", testText);
+ props.put("a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y", "yes");
+ final String url = testClient.createNode(postUrl, props);
+ final String json = getContent(url + ".infinity.json",
+ CONTENT_TYPE_JSON);
+ assertJavascript(testText, json, "out.print(data.text)");
+ assertJavascript("yes", json,
+ "out.print(data.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y)");
+ }
+
+ public void testInvalidLevel() throws IOException {
+ assertHttpStatus(createdNodeUrl + ".notAnIntegerOnPurpose.json",
+ HttpServletResponse.SC_BAD_REQUEST);
+ }
+
+ public void testEscapedStrings() throws IOException {
+ final Map<String, String> props = new HashMap<String, String>();
+ props.put("dq", "Some text with \"double quotes\"");
+ props.put("sq", "Some text with 'single quotes'");
+ props.put("cb", "Some text with {curly brackets}");
+ props.put("sb", "Some text with [square brackets]");
+ props.put("eol", "Some text with end\nof\nlines\nand\ttabs");
+ props.put("html",
+ "Some text with <body class=\"black\" mode=\'none yet\'/> html-like tags");
+ props.put("bs", "Some text with \\backslashes \\here and \\\"there\"");
+
+ final String location = testClient.createNode(postUrl, props);
+ final String json = getContent(location + ".json", CONTENT_TYPE_JSON);
+
+ int counter = 0;
+ for (String key : props.keySet()) {
+ counter++;
+ assertJavascript(props.get(key), json, "out.println(data." + key
+ + ")");
+ }
+ }
+
+ public void testAccentedStrings() throws IOException {
+ final Map<String, String> props = new HashMap<String, String>();
+ props.put("a", "Les amis en \u00E9t\u00E9 au ch\u00E2teau");
+ props.put("b", "The \u00B0 degree sign and \u00F1 ntilde");
+ props.put("c", "The \u0429 cyrillic capital letter shcha");
+ props.put("d", "The \u13C8 cherokee letter qui");
+
+ final String location = testClient.createNode(postUrl, props, null,
+ true);
+ final String json = getContent(location + ".json", CONTENT_TYPE_JSON);
+
+ for (String key : props.keySet()) {
+ assertJavascript(props.get(key), json, "out.println(data." + key
+ + ")");
+ }
+ }
+
+ protected static int countOccurences(String str, char toCount) {
+ int result = 0;
+ for(char c : str.toCharArray()) {
+ if(c == toCount) {
+ result++;
+ }
+ }
+ return result;
+ }
+
+ public void testTidyNonRecursive() throws IOException {
+ // Count end-of-line chars, there must be more in the tidy form
+ int noTidyCount = countOccurences(getContent(createdNodeUrl + ".json", CONTENT_TYPE_JSON), '\n');
+ int tidyCount = countOccurences(getContent(createdNodeUrl + ".tidy.json", CONTENT_TYPE_JSON), '\n');
+ int delta = tidyCount - noTidyCount;
+
+ // Output contains two properties so at least two EOL chars
+ int min = 2;
+
+ assertTrue("The .tidy selector should add at least 2 EOL chars to json output (delta=" + delta + ")", delta > min);
+ }
+
+ public void testTidyRecursive() throws IOException {
+ final Map<String, String> props = new HashMap<String, String>();
+ props.put("text", testText);
+ props.put("a/b", "yes");
+ final String url = testClient.createNode(postUrl, props);
+
+ int noTidyCount = countOccurences(getContent(url + ".infinity.json", CONTENT_TYPE_JSON), '\n');
+ int tidyCount = countOccurences(getContent(url + ".tidy.infinity.json", CONTENT_TYPE_JSON), '\n');
+ int delta = tidyCount - noTidyCount;
+
+ // Output contains 3 properties and a subnode with one, so at least 5 EOL chars
+ int min = 5;
+
+ assertTrue("The .tidy selector should add at least 2 EOL chars to json output (delta=" + delta + ")", delta > min);
+ }
+
+ public void testRootNoRecursion() throws IOException {
+ final String json = getContent(HTTP_BASE_URL + "/.json", CONTENT_TYPE_JSON);
+ assertJavascript("rep:root", json, "out.print(data['jcr:primaryType'])");
+ assertJavascript("undefined", json, "out.print(typeof data['jcr:system'])");
+ }
+
+ public void testRootWithRecursion() throws IOException {
+ final String json = getContent(HTTP_BASE_URL + "/.1.json", CONTENT_TYPE_JSON);
+ assertJavascript("rep:root", json, "out.print(data['jcr:primaryType'])");
+ assertJavascript("rep:system", json, "out.print(data['jcr:system']['jcr:primaryType'])");
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/JspForwardTest.java b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/JspForwardTest.java
new file mode 100644
index 0000000..4c1dc4d
--- /dev/null
+++ b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/JspForwardTest.java
@@ -0,0 +1,145 @@
+/*
+ * 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.launchpad.webapp.integrationtest;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.httpclient.methods.GetMethod;
+import org.apache.sling.commons.testing.integration.HttpTestBase;
+import org.apache.sling.servlets.post.SlingPostConstants;
+
+
+/** Test the {link ScriptHelper#forward) functionality */
+ public class JspForwardTest extends HttpTestBase {
+
+ private String nodeUrlA;
+ private String testTextA;
+ private String nodeUrlB;
+ private String testTextB;
+ private String nodeUrlC;
+ private String nodeUrlD;
+ private String nodeUrlE;
+ private String scriptPath;
+ private String forcedResourceType;
+ private Set<String> toDelete = new HashSet<String>();
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ // Create the test nodes under a path that's specific to this class to
+ // allow collisions
+ final String url = HTTP_BASE_URL + "/" + getClass().getSimpleName() + "/" + System.currentTimeMillis() + SlingPostConstants.DEFAULT_CREATE_SUFFIX;
+ final Map<String,String> props = new HashMap<String,String>();
+
+ // Create two test nodes and store their paths
+ testTextA = "Text A " + System.currentTimeMillis();
+ props.put("text", testTextA);
+ nodeUrlA = testClient.createNode(url, props);
+ String pathToInclude = nodeUrlA.substring(HTTP_BASE_URL.length());
+
+ // Node B stores the path of A, so that the test script can
+ // forward A when rendering B
+ testTextB = "Text B " + System.currentTimeMillis();
+ props.put("text", testTextB);
+ props.put("pathToInclude", pathToInclude);
+ nodeUrlB = testClient.createNode(url, props);
+
+ // Node E is like B but with an extension on the forward path
+ props.put("pathToInclude", pathToInclude + ".html");
+ nodeUrlE = testClient.createNode(url, props);
+
+ // Node C is used for the infinite loop detection test
+ props.remove("pathToInclude");
+ props.put("testInfiniteLoop","true");
+ nodeUrlC = testClient.createNode(url, props);
+
+ // Node D is used for the "force resource type" test
+ forcedResourceType = getClass().getSimpleName() + "/" + System.currentTimeMillis();
+ props.remove("testInfiniteLoop");
+ props.put("forceResourceType", forcedResourceType);
+ props.put("pathToInclude", pathToInclude);
+ nodeUrlD = testClient.createNode(url, props);
+
+ // Script for forced resource type
+ scriptPath = "/apps/" + forcedResourceType;
+ testClient.mkdirs(WEBDAV_BASE_URL, scriptPath);
+ toDelete.add(uploadTestScript(scriptPath,"forward-forced.jsp","html.jsp"));
+
+ // The main rendering script goes under /apps in the repository
+ scriptPath = "/apps/nt/unstructured";
+ testClient.mkdirs(WEBDAV_BASE_URL, scriptPath);
+ toDelete.add(uploadTestScript(scriptPath,"forward-test.jsp","html.jsp"));
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ for(String script : toDelete) {
+ testClient.delete(script);
+ }
+ }
+
+ public void testWithoutForward() throws IOException {
+ final String content = getContent(nodeUrlA + ".html", CONTENT_TYPE_HTML);
+ assertTrue("Content includes JSP marker",content.contains("JSP template"));
+ assertTrue("Content contains formatted test text",content.contains("<p class=\"main\">" + testTextA + "</p>"));
+ }
+
+ public void testWithForward() throws IOException {
+ final String content = getContent(nodeUrlB + ".html", CONTENT_TYPE_HTML);
+ assertTrue("Content includes JSP marker",content.contains("JSP template"));
+ assertTrue("Content contains formatted test text",content.contains("<p class=\"main\">" + testTextA + "</p>"));
+ assertTrue("Text of node A is not included (" + content + ")",!content.contains(testTextB));
+ }
+
+ public void testWithForwardAndExtension() throws IOException {
+ final String content = getContent(nodeUrlE + ".html", CONTENT_TYPE_HTML);
+ assertTrue("Content includes JSP marker",content.contains("JSP template"));
+ assertTrue("Content contains formatted test text",content.contains("<p class=\"main\">" + testTextA + "</p>"));
+ assertTrue("Text of node A is not included (" + content + ")",!content.contains(testTextB));
+ }
+
+ public void testInfiniteLoopDetection() throws IOException {
+ // Node C has a property that causes an infinite include loop,
+ // Sling must indicate the problem in its response
+ final GetMethod get = new GetMethod(nodeUrlC + ".html");
+ httpClient.executeMethod(get);
+ final String content = get.getResponseBodyAsString();
+ assertTrue(
+ "Response contains infinite loop error message",
+ content.contains("org.apache.sling.api.request.RecursionTooDeepException"));
+
+ // TODO: SLING-515, status is 500 when running the tests as part of the maven build
+ // but 200 if running tests against a separate instance started with mvn jetty:run
+ // final int status = get.getStatusCode();
+ // assertEquals("Status is 500 for infinite loop",HttpServletResponse.SC_INTERNAL_SERVER_ERROR, status);
+ }
+
+ public void testForcedResourceType() throws IOException {
+ final String content = getContent(nodeUrlD + ".html", CONTENT_TYPE_HTML);
+ assertTrue("Content includes JSP marker",content.contains("JSP template"));
+ assertTrue("Content contains formatted test text",content.contains("<p class=\"main\">" + testTextA + "</p>"));
+ assertTrue("Text of node A is included (" + content + ")",!content.contains(testTextB));
+ assertTrue("Resource type has been forced (" + content + ")",content.contains("Forced resource type:" + forcedResourceType));
+ }
+}
diff --git a/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/JspIncludeTest.java b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/JspIncludeTest.java
new file mode 100644
index 0000000..bce0225
--- /dev/null
+++ b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/JspIncludeTest.java
@@ -0,0 +1,171 @@
+/*
+ * 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.launchpad.webapp.integrationtest;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.httpclient.methods.GetMethod;
+import org.apache.sling.commons.testing.integration.HttpTestBase;
+import org.apache.sling.servlets.post.SlingPostConstants;
+
+
+/** Test the {link ScriptHelper#include) functionality */
+ public class JspIncludeTest extends HttpTestBase {
+
+ private String nodeUrlA;
+ private String testTextA;
+ private String nodeUrlB;
+ private String testTextB;
+ private String nodeUrlC;
+ private String nodeUrlD;
+ private String nodeUrlE;
+ private String nodeUrlF;
+ private String scriptPath;
+ private String forcedResourceType;
+ private Set<String> toDelete = new HashSet<String>();
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ // Create the test nodes under a path that's specific to this class to
+ // allow collisions
+ final String url = HTTP_BASE_URL + "/" + getClass().getSimpleName() + "/" + System.currentTimeMillis() + SlingPostConstants.DEFAULT_CREATE_SUFFIX;
+ final Map<String,String> props = new HashMap<String,String>();
+
+ // Create two test nodes and store their paths
+ testTextA = "Text A " + System.currentTimeMillis();
+ props.put("text", testTextA);
+ nodeUrlA = testClient.createNode(url, props);
+ String pathToInclude = nodeUrlA.substring(HTTP_BASE_URL.length());
+
+ // Node B stores the path of A, so that the test script can
+ // include A when rendering B
+ testTextB = "Text B " + System.currentTimeMillis();
+ props.put("text", testTextB);
+ props.put("pathToInclude", pathToInclude);
+ nodeUrlB = testClient.createNode(url, props);
+
+ // Node E is like B but with an extension on the include path
+ props.put("pathToInclude", pathToInclude + ".html");
+ nodeUrlE = testClient.createNode(url, props);
+
+ // Node F is used for the max calls detection test
+ props.put("testMaxCalls","true");
+ nodeUrlF = testClient.createNode(url, props);
+
+ // Node C is used for the infinite loop detection test
+ props.remove("pathToInclude");
+ props.remove("testMaxCalls");
+ props.put("testInfiniteLoop","true");
+ nodeUrlC = testClient.createNode(url, props);
+
+ // Node D is used for the "force resource type" test
+ forcedResourceType = getClass().getSimpleName() + "/" + System.currentTimeMillis();
+ props.remove("testInfiniteLoop");
+ props.put("forceResourceType", forcedResourceType);
+ props.put("pathToInclude", pathToInclude);
+ nodeUrlD = testClient.createNode(url, props);
+
+ // Script for forced resource type
+ scriptPath = "/apps/" + forcedResourceType;
+ testClient.mkdirs(WEBDAV_BASE_URL, scriptPath);
+ toDelete.add(uploadTestScript(scriptPath,"include-forced.jsp","html.jsp"));
+
+ // The main rendering script goes under /apps in the repository
+ scriptPath = "/apps/nt/unstructured";
+ testClient.mkdirs(WEBDAV_BASE_URL, scriptPath);
+ toDelete.add(uploadTestScript(scriptPath,"include-test.jsp","html.jsp"));
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ for(String script : toDelete) {
+ testClient.delete(script);
+ }
+ }
+
+ public void testWithoutInclude() throws IOException {
+ final String content = getContent(nodeUrlA + ".html", CONTENT_TYPE_HTML);
+ assertTrue("Content includes JSP marker",content.contains("JSP template"));
+ assertTrue("Content contains formatted test text",content.contains("<p class=\"main\">" + testTextA + "</p>"));
+ assertFalse("Nothing has been included",content.contains("<p>Including"));
+ }
+
+ public void testWithInclude() throws IOException {
+ final String content = getContent(nodeUrlB + ".html", CONTENT_TYPE_HTML);
+ assertTrue("Content includes JSP marker",content.contains("JSP template"));
+ assertTrue("Content contains formatted test text",content.contains("<p class=\"main\">" + testTextB + "</p>"));
+ assertTrue("Include has been used",content.contains("<p>Including"));
+ assertTrue("Text of node A is included (" + content + ")",content.contains(testTextA));
+ }
+
+ public void testWithIncludeAndExtension() throws IOException {
+ final String content = getContent(nodeUrlE + ".html", CONTENT_TYPE_HTML);
+ assertTrue("Content includes JSP marker",content.contains("JSP template"));
+ assertTrue("Content contains formatted test text",content.contains("<p class=\"main\">" + testTextB + "</p>"));
+ assertTrue("Include has been used",content.contains("<p>Including"));
+ assertTrue("Text of node A is included (" + content + ")",content.contains(testTextA));
+ }
+
+ public void testInfiniteLoopDetection() throws IOException {
+ // Node C has a property that causes an infinite include loop,
+ // Sling must indicate the problem in its response
+ final GetMethod get = new GetMethod(nodeUrlC + ".html");
+ httpClient.executeMethod(get);
+ final String content = get.getResponseBodyAsString();
+ assertTrue(
+ "Response contains infinite loop error message",
+ content.contains("org.apache.sling.api.request.RecursionTooDeepException"));
+
+ // TODO: SLING-515, status is 500 when running the tests as part of the maven build
+ // but 200 if running tests against a separate instance started with mvn jetty:run
+ // final int status = get.getStatusCode();
+ // assertEquals("Status is 500 for infinite loop",HttpServletResponse.SC_INTERNAL_SERVER_ERROR, status);
+ }
+
+ public void testMaxCallsDetection() throws IOException {
+ // Node F has a property that causes over 1000 includes
+ // Sling must indicate the problem in its response
+ final GetMethod get = new GetMethod(nodeUrlF + ".html");
+ httpClient.executeMethod(get);
+ final String content = get.getResponseBodyAsString();
+ assertTrue(
+ "Response contains infinite loop error message",
+ content.contains("org.apache.sling.api.request.TooManyCallsException"));
+
+ // TODO: SLING-515, status is 500 when running the tests as part of the maven build
+ // but 200 if running tests against a separate instance started with mvn jetty:run
+ // final int status = get.getStatusCode();
+ // assertEquals("Status is 500 for infinite loop",HttpServletResponse.SC_INTERNAL_SERVER_ERROR, status);
+ }
+
+ public void testForcedResourceType() throws IOException {
+ final String content = getContent(nodeUrlD + ".html", CONTENT_TYPE_HTML);
+ assertTrue("Content includes JSP marker",content.contains("JSP template"));
+ assertTrue("Content contains formatted test text",content.contains("<p class=\"main\">" + testTextB + "</p>"));
+ assertTrue("Include has been used",content.contains("<p>Including"));
+ assertTrue("Text of node A is included (" + content + ")",content.contains(testTextA));
+ assertTrue("Resource type has been forced (" + content + ")",content.contains("Forced resource type:" + forcedResourceType));
+ }
+}
diff --git a/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/JspScriptingTest.java b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/JspScriptingTest.java
new file mode 100644
index 0000000..449f11f
--- /dev/null
+++ b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/JspScriptingTest.java
@@ -0,0 +1,94 @@
+/*
+ * 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.launchpad.webapp.integrationtest;
+
+import org.apache.sling.commons.testing.integration.HttpTestBase;
+import org.apache.sling.servlets.post.SlingPostConstants;
+
+/** Test JSP scripting
+ * TODO this class can be generalized to be used for any scripting language,
+ * that would help in testing all scripting engines.
+ */
+public class JspScriptingTest extends HttpTestBase {
+
+ private String testRootUrl;
+ private TestNode rtNode;
+ private TestNode unstructuredNode;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ final String testRootPath = HTTP_BASE_URL + "/" + getClass().getSimpleName() + "/" + System.currentTimeMillis();
+ testRootUrl = testClient.createNode(testRootPath + SlingPostConstants.DEFAULT_CREATE_SUFFIX, null);
+ rtNode = new TestNode(testRootPath + "/rt", null);
+ unstructuredNode = new TestNode(testRootPath + "/unstructured", null);
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ testClient.delete(testRootUrl);
+ super.tearDown();
+ }
+
+ public void testRtNoScript() throws Exception {
+ final String content = getContent(rtNode.nodeUrl + ".txt", CONTENT_TYPE_PLAIN);
+ assertTrue(content.contains("PlainTextRendererServlet"));
+ assertTrue("Content contains " + rtNode.testText + " (" + content + ")", content.contains(rtNode.testText));
+ }
+
+ public void testUnstructuredNoScript() throws Exception {
+ final String content = getContent(unstructuredNode.nodeUrl + ".txt", CONTENT_TYPE_PLAIN);
+ assertTrue(content.contains("PlainTextRendererServlet"));
+ assertTrue("Content contains " + unstructuredNode.testText + " (" + content + ")", content.contains(unstructuredNode.testText));
+ }
+
+ public void testRtJsp() throws Exception {
+ final String toDelete = uploadTestScript(rtNode.scriptPath, "rendering-test.jsp", "html.jsp");
+ try {
+ checkContent(rtNode);
+ } finally {
+ if(toDelete != null) {
+ testClient.delete(toDelete);
+ }
+ }
+ }
+
+ public void testUnstructuredJsp() throws Exception {
+ final String toDelete = uploadTestScript(unstructuredNode.scriptPath, "rendering-test.jsp", "html.jsp");
+ try {
+ checkContent(unstructuredNode);
+ } finally {
+ if(toDelete != null) {
+ testClient.delete(toDelete);
+ }
+ }
+ }
+
+ private void checkContent(TestNode tn) throws Exception {
+ final String content = getContent(tn.nodeUrl + ".html", CONTENT_TYPE_HTML);
+ assertTrue("JSP script executed as expected (" + content + ")", content.contains("<h1>JSP rendering result</h1>"));
+
+ final String [] expected = {
+ "using resource.adaptTo:" + tn.testText,
+ "using currentNode:" + tn.testText,
+ };
+ for(String exp : expected) {
+ assertTrue("Content contains " + exp + "(" + content + ")", content.contains(exp));
+ }
+ }
+}
diff --git a/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/MkdirTest.java b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/MkdirTest.java
new file mode 100644
index 0000000..38ef6af
--- /dev/null
+++ b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/MkdirTest.java
@@ -0,0 +1,64 @@
+/*
+ * 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.launchpad.webapp.integrationtest;
+
+import java.io.IOException;
+
+import org.apache.sling.commons.testing.integration.HttpTestBase;
+
+/** Test the MicroslingIntegrationTestClient's mkdir functions */
+public class MkdirTest extends HttpTestBase {
+
+ /** Try creating a directory via WebDAV */
+ public void testMkdir() throws IOException {
+ final String testDirUrl = WEBDAV_BASE_URL + TEST_PATH + System.currentTimeMillis();
+
+ assertHttpStatus(testDirUrl, 404, testDirUrl);
+
+ try {
+ testClient.mkdir(testDirUrl);
+ } catch(IOException ioe) {
+ fail(ioe.getMessage());
+ }
+
+ assertHttpStatus(testDirUrl + DEFAULT_EXT, 200, testDirUrl);
+
+ try {
+ testClient.mkdir(testDirUrl);
+ } catch(IOException ioe) {
+ fail("mkdir must succeed on an existing directory, got IOException:" + ioe);
+ }
+
+ assertHttpStatus(testDirUrl + DEFAULT_EXT, 200, testDirUrl);
+
+ testClient.delete(testDirUrl);
+ assertHttpStatus(testDirUrl, 404, testDirUrl + " must be gone after DELETE");
+ }
+
+ /** Try creating a deep directory structure */
+ public void testMkdirDeep() throws IOException {
+ final String path = TEST_PATH + "/mkdir-test-" + System.currentTimeMillis() + "/something";
+ final String url = WEBDAV_BASE_URL + path;
+ assertHttpStatus(url,404,url + " must not exist before test");
+ try {
+ testClient.mkdirs(WEBDAV_BASE_URL, path);
+ } catch(IOException ioe) {
+ fail("mkdirs failed:" + ioe);
+ }
+ assertHttpStatus(url + DEFAULT_EXT,200,url + " must exist after test");
+ }
+}
diff --git a/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/NodetypeRenderingTest.java b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/NodetypeRenderingTest.java
new file mode 100644
index 0000000..7b81d22
--- /dev/null
+++ b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/NodetypeRenderingTest.java
@@ -0,0 +1,180 @@
+/*
+ * 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.launchpad.webapp.integrationtest;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.sling.servlets.post.SlingPostConstants;
+
+/** Test creating a Node and rendering it using scripts in
+ * various supported languages, using nodetype-based
+ * script resolution
+ */
+public class NodetypeRenderingTest extends RenderingTestBase {
+
+ private String secondFolderOfContentPath;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ // set test values
+ testText = "This is a test " + System.currentTimeMillis();
+
+ // create the test node, under a path that's specific to this class to allow collisions
+ secondFolderOfContentPath = "" + System.currentTimeMillis();
+ final String url = HTTP_BASE_URL + "/" + getClass().getSimpleName() + "/" + secondFolderOfContentPath + SlingPostConstants.DEFAULT_CREATE_SUFFIX;
+ final Map<String,String> props = new HashMap<String,String>();
+ props.put("text", testText);
+ displayUrl = testClient.createNode(url, props);
+
+ // the rendering script goes under /apps in the repository
+ scriptPath = "/apps/nt/unstructured";
+ testClient.mkdirs(WEBDAV_BASE_URL, scriptPath);
+ }
+
+ public void testWithoutScriptTxt() throws IOException {
+ final String content = getContent(displayUrl + ".txt", CONTENT_TYPE_PLAIN);
+ assertContains(content, "dumped by PlainTextRendererServlet");
+ }
+
+ public void testWithoutScriptHtml() throws IOException {
+ final String content = getContent(displayUrl + ".html", CONTENT_TYPE_HTML);
+ assertContains(content, "dumped by HtmlRendererServlet");
+ }
+
+ public void testMiniScriptHtml() throws IOException {
+ final String toDelete = uploadTestScript("no-code.esp","html.esp");
+ try {
+ final String content = getContent(displayUrl + ".html", CONTENT_TYPE_HTML);
+ assertEquals("There's no code in this script, just this constant string",content);
+ } finally {
+ testClient.delete(toDelete);
+ }
+ }
+
+ public void testPrint() throws IOException {
+ final String toDelete = uploadTestScript("print.esp","html.esp");
+ try {
+ final String content = getContent(displayUrl + ".html", CONTENT_TYPE_HTML);
+ final String expected = "print.esp ends";
+ assertContains(content, expected);
+ } finally {
+ testClient.delete(toDelete);
+ }
+ }
+
+ public void testEspHtml() throws IOException {
+ final String toDelete = uploadTestScript("rendering-test.esp","html.esp");
+ try {
+ final String content = getContent(displayUrl + ".html", CONTENT_TYPE_HTML);
+ assertContains(content, "ESP template");
+ assertContains(content, "<p>" + testText + "</p>");
+ } finally {
+ testClient.delete(toDelete);
+ }
+ }
+
+ public void testEspXml() throws IOException {
+ final String toDelete = uploadTestScript("rendering-test.esp","xml.esp");
+ try {
+ final String content = getContent(displayUrl + ".xml", CONTENT_TYPE_XML);
+ assertContains(content, "ESP template");
+ assertContains(content, "<p>" + testText + "</p>");
+ } finally {
+ testClient.delete(toDelete);
+ }
+ }
+
+ public void TODO_FAILS_testEspHtmlWithContentBasedPath() throws IOException {
+
+ // make sure there's no leftover rendering script
+ {
+ final String content = getContent(displayUrl + ".html", CONTENT_TYPE_HTML);
+ assertFalse("Content must not include ESP marker before test",content.contains("ESP template"));
+ }
+
+ // put our script in the /apps/<second folder level of content> (SLING-125)
+ final String path = "/apps/" + secondFolderOfContentPath;
+ testClient.mkdirs(WEBDAV_BASE_URL, path);
+ final String toDelete = uploadTestScript(path,"rendering-test.esp","html.esp");
+ try {
+ final String content = getContent(displayUrl + ".html", CONTENT_TYPE_HTML);
+ assertContains(content, "ESP template");
+ assertContains(content, "<p>" + testText + "</p>");
+ } finally {
+ testClient.delete(toDelete);
+ }
+ }
+
+ public void testEspPlain() throws IOException {
+ final String toDelete = uploadTestScript("rendering-test.esp","txt.esp");
+ try {
+ final String content = getContent(displayUrl + ".txt", CONTENT_TYPE_PLAIN);
+ assertContains(content, "ESP template");
+ assertContains(content, "<p>" + testText + "</p>");
+ } finally {
+ testClient.delete(toDelete);
+ }
+ }
+
+ public void TODO_FAILS_testVltHtml() throws IOException {
+ final String toDelete = uploadTestScript("rendering-test.vlt","html.vlt");
+ try {
+ final String content = getContent(displayUrl + ".html", CONTENT_TYPE_HTML);
+ assertTrue("Content includes VLT marker",content.contains("Velocity template"));
+ assertTrue("Content contains formatted test text",content.contains("<p><b>" + testText + "</b></p>"));
+ } finally {
+ testClient.delete(toDelete);
+ }
+ }
+
+ public void TODO_FAILS_testJsHtml() throws IOException {
+ final String toDelete = uploadTestScript("rendering-test.ecma","html.ecma");
+ try {
+ final String content = getContent(displayUrl + ".html", CONTENT_TYPE_HTML);
+ assertTrue("Content includes JS marker",content.contains("Raw javascript template"));
+ assertTrue("Content contains formatted test text",content.contains("<p><em>" + testText + "</em></p>"));
+ } finally {
+ testClient.delete(toDelete);
+ }
+ }
+
+ public void TODO_FAILS_testFtlHtml() throws IOException {
+ final String toDelete = uploadTestScript("rendering-test.ftl","html.ftl");
+ try {
+ final String content = getContent(displayUrl + ".html", CONTENT_TYPE_HTML);
+ assertTrue("Content includes FreeMarker marker",content.contains("FreeMarker template"));
+ assertTrue("Content contains formatted test text",content.contains("<p><span>" + testText + "</span></p>"));
+ } finally {
+ testClient.delete(toDelete);
+ }
+ }
+
+ public void TODO_FAILS_testErbHtml() throws IOException {
+ final String toDelete = uploadTestScript("rendering-test.erb","html.erb");
+ try {
+ final String content = getContent(displayUrl + ".html", CONTENT_TYPE_HTML);
+ assertTrue("Content includes Ruby marker",content.contains("Ruby template"));
+ assertTrue("Content contains formatted test text",content.contains("<p><span>" + testText + "</span></p>"));
+ } finally {
+ testClient.delete(toDelete);
+ }
+ }
+}
diff --git a/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/PostRedirectTest.java b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/PostRedirectTest.java
new file mode 100644
index 0000000..4c88a7d
--- /dev/null
+++ b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/PostRedirectTest.java
@@ -0,0 +1,106 @@
+/*
+ * 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.launchpad.webapp.integrationtest;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.sling.commons.testing.integration.HttpTestBase;
+import org.apache.sling.servlets.post.SlingPostConstants;
+
+/** Test the various redirect options for POST, SLING-126 */
+public class PostRedirectTest extends HttpTestBase {
+
+ private String postPath = "CreateNodeTest/" + System.currentTimeMillis();
+
+ private String postUrl = HTTP_BASE_URL + "/" + postPath
+ + SlingPostConstants.DEFAULT_CREATE_SUFFIX;
+
+ public void testForcedRedirect() throws IOException {
+ final Map<String, String> params = new HashMap<String, String>();
+ params.put(":redirect", "http://forced");
+ final Map<String, String> headers = new HashMap<String, String>();
+ headers.put("Referer", "http://referer/");
+
+ final String location = testClient.createNode(postUrl, params, headers,
+ false);
+ assertEquals(
+ "With forced redirect and Referer, redirect must be forced",
+ "http://forced", location);
+ }
+
+ public void testDefaultRedirect() throws IOException {
+ final Map<String, String> params = new HashMap<String, String>();
+ params.put(":redirect", null);
+ final String location = testClient.createNode(postUrl, null, null,
+ false);
+ assertTrue("With no headers or parameters, redirect (" + location
+ + ") must point to created node (path=" + postPath + ")",
+ location.contains(postPath));
+ }
+
+ public void testMagicStarRedirect() throws IOException {
+ final Map<String, String> params = new HashMap<String, String>();
+ params.put(":redirect", "*");
+ final Map<String, String> headers = new HashMap<String, String>();
+ headers.put("Referer", "http://referer/");
+ final String location = testClient.createNode(postUrl, params, headers,
+ false);
+ assertTrue("With magic star, redirect (" + location
+ + ") must point to created node (path=" + postPath + ")",
+ location.contains(postPath));
+ }
+
+ public void testMagicStarRedirectPrefix() throws IOException {
+ String prefix = "xyz/";
+ final Map<String, String> params = new HashMap<String, String>();
+ params.put(":redirect", prefix + "*");
+ final Map<String, String> headers = new HashMap<String, String>();
+ headers.put("Referer", "http://referer/");
+ final String location = testClient.createNode(postUrl, params, headers,
+ false);
+ assertTrue("With magic star, redirect (" + location
+ + ") must start with prefix " + prefix, location.contains(prefix));
+ }
+
+ public void testMagicStarRedirectSuffix() throws IOException {
+ String suffix = "/xyz.html";
+ final Map<String, String> params = new HashMap<String, String>();
+ params.put(":redirect", "*" + suffix);
+ final Map<String, String> headers = new HashMap<String, String>();
+ headers.put("Referer", "http://referer/");
+ final String location = testClient.createNode(postUrl, params, headers,
+ false);
+ assertTrue("With magic star, redirect (" + location
+ + ") must end with suffix " + suffix, location.endsWith(suffix));
+ }
+
+ public void testMagicStarRedirectPrefixSuffix() throws IOException {
+ String prefix = "xyz/";
+ String suffix = "/xyz.html";
+ final Map<String, String> params = new HashMap<String, String>();
+ params.put(":redirect", prefix + "*" + suffix);
+ final Map<String, String> headers = new HashMap<String, String>();
+ headers.put("Referer", "http://referer/");
+ final String location = testClient.createNode(postUrl, params, headers,
+ false);
+ assertTrue("With magic star, redirect (" + location
+ + ") must start with prefix " + prefix + " and end with suffix "
+ + suffix, location.contains(prefix) && location.endsWith(suffix));
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/PropertyRenderingTest.java b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/PropertyRenderingTest.java
new file mode 100644
index 0000000..438ff07
--- /dev/null
+++ b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/PropertyRenderingTest.java
@@ -0,0 +1,77 @@
+/*
+ * 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.launchpad.webapp.integrationtest;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.sling.servlets.post.SlingPostConstants;
+
+/** Test the rendering of JCR Properties, directly addressed by URLs.
+ * See SLING-133
+ */
+public class PropertyRenderingTest extends RenderingTestBase {
+
+ private String slingResourceType;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ // set test values
+ testText = "This is a test " + System.currentTimeMillis();
+ slingResourceType = getClass().getName();
+
+ // create the test node, under a path that's specific to this class to allow collisions
+ final String url = HTTP_BASE_URL + "/" + getClass().getSimpleName() + "/" + System.currentTimeMillis() + SlingPostConstants.DEFAULT_CREATE_SUFFIX;
+ final Map<String,String> props = new HashMap<String,String>();
+ props.put("sling:resourceType", slingResourceType);
+ props.put("text", testText);
+ displayUrl = testClient.createNode(url, props);
+ }
+
+ public void testNodeAccess() throws IOException {
+ final String json = getContent(displayUrl + ".json", CONTENT_TYPE_JSON);
+ assertJavascript(testText, json, "out.println(data.text)");
+ }
+
+ public void testTextJson() throws IOException {
+ final String json = getContent(displayUrl + "/text.json", CONTENT_TYPE_JSON);
+ assertEquals("{\"text\":\"" + testText + "\"}",json);
+ }
+
+ public void testTextHtml() throws IOException {
+ final String data = getContent(displayUrl + "/text.html", CONTENT_TYPE_HTML);
+ assertTrue(data.contains(testText));
+ }
+
+ public void testTextTxt() throws IOException {
+ final String data = getContent(displayUrl + "/text.txt", CONTENT_TYPE_PLAIN);
+ assertEquals(testText, data);
+ }
+
+ public void testTextNoExt() throws IOException {
+ final String data = getContent(displayUrl + "/text", null);
+ assertEquals(testText, data);
+ }
+
+ public void testResourceTypeNoExt() throws IOException {
+ final String data = getContent(displayUrl + "/sling:resourceType", null);
+ assertEquals(slingResourceType, data);
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/RedirectTest.java b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/RedirectTest.java
new file mode 100644
index 0000000..38d78cd
--- /dev/null
+++ b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/RedirectTest.java
@@ -0,0 +1,153 @@
+/*
+ * 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.launchpad.webapp.integrationtest;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.commons.httpclient.methods.GetMethod;
+import org.apache.sling.commons.json.JSONException;
+import org.apache.sling.commons.json.JSONObject;
+import org.apache.sling.commons.testing.integration.HttpTestBase;
+import org.apache.sling.servlets.post.SlingPostConstants;
+
+/** Test creating Nodes and rendering them in JSON */
+public class RedirectTest extends HttpTestBase {
+
+ private String postUrl;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ // create the test node, under a path that's specific to this class to
+ // allow collisions
+ postUrl = HTTP_BASE_URL + "/" + getClass().getSimpleName() + "_"
+ + System.currentTimeMillis()
+ + SlingPostConstants.DEFAULT_CREATE_SUFFIX;
+ }
+
+ /** test 302 response with existing sling:target */
+ public void testRedirect302() throws IOException {
+
+ // create a node redirecting to /index
+ Map<String, String> props = new HashMap<String, String>();
+ props.put("sling:resourceType", "sling:redirect");
+ props.put("sling:target", "/index.html");
+ String redirNodeUrl = testClient.createNode(postUrl, props);
+
+ // get the created node without following redirects
+ GetMethod get = new GetMethod(redirNodeUrl);
+ get.setFollowRedirects(false);
+ int status = httpClient.executeMethod(get);
+
+ // expect temporary redirect ...
+ assertEquals(302, status);
+
+ // ... to */index.html
+ String location = get.getResponseHeader("Location").getValue();
+ assertNotNull(location);
+ assertTrue(location.endsWith("/index.html"));
+
+ // get the created node without following redirects
+ get = new GetMethod(redirNodeUrl + ".html");
+ get.setFollowRedirects(false);
+ status = httpClient.executeMethod(get);
+
+ // expect temporary redirect ...
+ assertEquals(302, status);
+
+ // ... to */index.html
+ location = get.getResponseHeader("Location").getValue();
+ assertNotNull(location);
+ assertTrue(location.endsWith("/index.html.html"));
+ }
+
+ /** test 404 response when sling:target is missing */
+ public void testRedirect404() throws IOException {
+ // create a sling:redirect node without a target
+ Map<String, String> props = new HashMap<String, String>();
+ props.put("sling:resourceType", "sling:redirect");
+ String redirNodeUrl = testClient.createNode(postUrl, props);
+
+ // get the created node without following redirects
+ GetMethod get = new GetMethod(redirNodeUrl);
+ get.setFollowRedirects(false);
+ int status = httpClient.executeMethod(get);
+
+ // expect 404 not found
+ assertEquals(404, status);
+
+ // get the created node without following redirects
+ get = new GetMethod(redirNodeUrl + ".html");
+ get.setFollowRedirects(false);
+ status = httpClient.executeMethod(get);
+
+ // expect 404 not found
+ assertEquals(404, status);
+ }
+
+ /** test JSON result for .json requests with sling:target */
+ public void testRedirectJson() throws JSONException, IOException {
+ // create a sling:redirect node without a target
+ Map<String, String> props = new HashMap<String, String>();
+ props.put("sling:resourceType", "sling:redirect");
+ props.put("sling:target", "/index.html");
+ String redirNodeUrl = testClient.createNode(postUrl, props);
+
+ // get the created node without following redirects
+ final GetMethod get = new GetMethod(redirNodeUrl + ".json");
+ get.setFollowRedirects(false);
+ final int status = httpClient.executeMethod(get);
+
+ // expect 200 OK with the JSON data
+ assertEquals(200, status);
+ assertTrue(get.getResponseHeader("Content-Type").getValue().startsWith(CONTENT_TYPE_JSON));
+
+ // the json data
+ String jsonString = get.getResponseBodyAsString();
+ JSONObject json = new JSONObject(jsonString);
+
+ assertEquals("sling:redirect", json.get("sling:resourceType"));
+ assertEquals("/index.html", json.get("sling:target"));
+ }
+
+ /** test JSON result for .json requests with sling:target */
+ public void testRedirectJson2() throws JSONException, IOException {
+ // create a sling:redirect node without a target
+ Map<String, String> props = new HashMap<String, String>();
+ props.put("sling:resourceType", "sling:redirect");
+ String redirNodeUrl = testClient.createNode(postUrl, props);
+
+ // get the created node without following redirects
+ final GetMethod get = new GetMethod(redirNodeUrl + ".json");
+ get.setFollowRedirects(false);
+ final int status = httpClient.executeMethod(get);
+
+ // expect 200 OK with the JSON data
+ assertEquals(200, status);
+ assertTrue(get.getResponseHeader("Content-Type").getValue().startsWith(CONTENT_TYPE_JSON));
+
+ // the json data
+ String jsonString = get.getResponseBodyAsString();
+ JSONObject json = new JSONObject(jsonString);
+
+ assertEquals("sling:redirect", json.get("sling:resourceType"));
+ }
+
+}
\ No newline at end of file
diff --git a/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/RenderingTestBase.java b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/RenderingTestBase.java
new file mode 100644
index 0000000..6fa6ea8
--- /dev/null
+++ b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/RenderingTestBase.java
@@ -0,0 +1,39 @@
+/*
+ * 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.launchpad.webapp.integrationtest;
+
+import java.io.IOException;
+
+import org.apache.sling.commons.testing.integration.HttpTestBase;
+
+/** Base class for rendering tests
+ */
+class RenderingTestBase extends HttpTestBase {
+ protected String scriptPath;
+ protected String testText;
+ protected String displayUrl;
+
+ protected String uploadTestScript(String localFilename,String filenameOnServer) throws IOException {
+ return uploadTestScript(scriptPath, localFilename, filenameOnServer);
+ }
+
+ protected void assertContains(String content, String expected) {
+ if(!content.contains(expected)) {
+ fail("Content does not contain '" + expected + "' (content=" + content + ")");
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/RequestAttributeTest.java b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/RequestAttributeTest.java
new file mode 100644
index 0000000..41800f5
--- /dev/null
+++ b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/RequestAttributeTest.java
@@ -0,0 +1,124 @@
+/*
+ * 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.launchpad.webapp.integrationtest;
+
+import java.io.ByteArrayInputStream;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+
+import org.apache.sling.commons.testing.integration.HttpTestBase;
+import org.apache.sling.servlets.post.SlingPostConstants;
+
+/**
+ * Test the "org.apache.sling.api.include.servlet" and
+ * "org.apache.sling.api.include.resource" request attributes with the {link
+ * ScriptHelper#include) functionality
+ */
+public class RequestAttributeTest extends HttpTestBase {
+
+ private String nodeUrlA;
+
+ private String nodeUrlB;
+
+ private String scriptPath;
+
+ private Set<String> toDelete = new HashSet<String>();
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ // Create the test nodes under a path that's specific to this class to
+ // allow collisions
+ final String url = HTTP_BASE_URL + "/" + getClass().getSimpleName()
+ + "/" + System.currentTimeMillis()
+ + SlingPostConstants.DEFAULT_CREATE_SUFFIX;
+ final Map<String, String> props = new HashMap<String, String>();
+
+ // Create two test nodes and store their paths
+ props.put("text", "texta");
+ props.put("jcr:primaryType", "nt:unstructured");
+ nodeUrlA = testClient.createNode(url, props);
+
+ props.clear();
+ props.put("text", "textb");
+ props.put("jcr:primaryType", "nt:unstructured");
+ nodeUrlB = testClient.createNode(nodeUrlA + "/child", props);
+
+ // The main rendering script goes under /apps in the repository
+ scriptPath = "/apps/nt/unstructured";
+ testClient.mkdirs(WEBDAV_BASE_URL, scriptPath);
+ toDelete.add(uploadTestScript(scriptPath, "request-attribute-test.esp",
+ "txt.esp"));
+ toDelete.add(uploadTestScript(scriptPath,
+ "request-attribute-test-sel1.esp", "sel1.txt.esp"));
+ toDelete.add(uploadTestScript(scriptPath,
+ "request-attribute-test-sel2.esp", "sel2.txt.esp"));
+ toDelete.add(uploadTestScript(scriptPath,
+ "request-attribute-test-sel3.esp", "sel3.txt.esp"));
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ for (String script : toDelete) {
+ testClient.delete(script);
+ }
+ super.tearDown();
+ }
+
+ public void testRequestAttribute() throws Exception {
+ final String content = getContent(nodeUrlA + ".txt", CONTENT_TYPE_PLAIN);
+
+ final Properties props = new Properties();
+ props.load(new ByteArrayInputStream(content.getBytes("ISO-8859-1")));
+
+ final String pA = new URL(nodeUrlA).getPath();
+ final String pB = new URL(nodeUrlB).getPath();
+
+ // this is from txt.esp
+ assertEquals("Request Servlet 0 is null", "null",
+ props.get("servlet00"));
+ assertEquals("Request Resource 0 is null", "null",
+ props.get("resource00"));
+ assertEquals("Request Servlet 1 is null", "null",
+ props.get("servlet01"));
+ assertEquals("Request Resource 1 is null", "null",
+ props.get("resource01"));
+
+ // this is from sel1.txt.esp, included by txt.esp
+ assertEquals("Request Servlet 10", "/apps/nt/unstructured/txt.esp",
+ props.get("servlet10"));
+ assertEquals("Request Resource 10", pA, props.get("resource10"));
+ assertEquals("Request Servlet 11", "/apps/nt/unstructured/txt.esp",
+ props.get("servlet11"));
+ assertEquals("Request Resource 11", pA, props.get("resource11"));
+
+ // this is from sel2.txt.esp, included by txt.esp
+ assertEquals("Request Servlet 20", "/apps/nt/unstructured/txt.esp",
+ props.get("servlet20"));
+ assertEquals("Request Resource 20", pA, props.get("resource20"));
+
+ // this is from sel3.txt.esp, included by sel1.txt.esp
+ assertEquals("Request Servlet 30",
+ "/apps/nt/unstructured/sel1.txt.esp", props.get("servlet30"));
+ assertEquals("Request Resource 30", pB, props.get("resource30"));
+ }
+}
diff --git a/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/ScriptBuiltinObjectsTest.java b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/ScriptBuiltinObjectsTest.java
new file mode 100644
index 0000000..8651f57
--- /dev/null
+++ b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/ScriptBuiltinObjectsTest.java
@@ -0,0 +1,63 @@
+/*
+ * 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.launchpad.webapp.integrationtest;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.sling.servlets.post.SlingPostConstants;
+
+public class ScriptBuiltinObjectsTest extends RenderingTestBase {
+
+ private String slingResourceType;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ // set test values
+ slingResourceType = "integration-test/srt." + System.currentTimeMillis();
+ testText = "This is a test " + System.currentTimeMillis();
+
+ // create the test node, under a path that's specific to this class to allow collisions
+ final String url = HTTP_BASE_URL + "/" + getClass().getSimpleName() + "/" + System.currentTimeMillis() + SlingPostConstants.DEFAULT_CREATE_SUFFIX;
+ final Map<String,String> props = new HashMap<String,String>();
+ props.put("sling:resourceType", slingResourceType);
+ props.put("text", testText);
+ displayUrl = testClient.createNode(url, props);
+
+ // the rendering script goes under /apps in the repository
+ scriptPath = "/apps/" + slingResourceType;
+ testClient.mkdirs(WEBDAV_BASE_URL, scriptPath);
+ }
+
+ public void testEspBuiltinObjects() throws IOException {
+ final String toDelete = uploadTestScript("builtin-objects.esp","html.esp");
+ try {
+ final String content = getContent(displayUrl + ".html", CONTENT_TYPE_HTML);
+ assertTrue("Content includes ESP marker (" + content + ")",content.contains("ESP template"));
+ assertTrue("Content includes test text (" + content + ")", content.contains(testText));
+ assertTrue("Content includes currentNode text (" + content + ")", content.contains("currentNode.text:" + testText));
+ assertTrue("Content includes sc data (" + content + ")",content.contains("sc:null"));
+ assertTrue("Content includes response data (" + content + ")",content.contains("SlingHttpServletResponse:false"));
+ } finally {
+ testClient.delete(toDelete);
+ }
+ }
+
+}
diff --git a/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/SlingResourceTypeRenderingTest.java b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/SlingResourceTypeRenderingTest.java
new file mode 100644
index 0000000..73aeea3
--- /dev/null
+++ b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/SlingResourceTypeRenderingTest.java
@@ -0,0 +1,225 @@
+/*
+ * 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.launchpad.webapp.integrationtest;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.sling.servlets.post.SlingPostConstants;
+
+/** Test creating a Node and rendering it using scripts in
+ * various supported languages, using slingResourceType-based
+ * script resolution
+ */
+public class SlingResourceTypeRenderingTest extends RenderingTestBase {
+
+ private String slingResourceType;
+ private String secondFolderOfContentPath;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ // set test values
+ slingResourceType = "integration-test/srt." + System.currentTimeMillis();
+ testText = "This is a test " + System.currentTimeMillis();
+
+ // create the test node, under a path that's specific to this class to allow collisions
+ secondFolderOfContentPath = "" + System.currentTimeMillis();
+ final String url = HTTP_BASE_URL + "/" + getClass().getSimpleName() + "/" + secondFolderOfContentPath + SlingPostConstants.DEFAULT_CREATE_SUFFIX;
+ final Map<String,String> props = new HashMap<String,String>();
+ props.put("sling:resourceType", slingResourceType);
+ props.put("text", testText);
+ displayUrl = testClient.createNode(url, props);
+
+ // the rendering script goes under /apps in the repository
+ scriptPath = "/apps/" + slingResourceType;
+ testClient.mkdirs(WEBDAV_BASE_URL, scriptPath);
+ }
+
+ public void testWithoutScriptTxt() throws IOException {
+ final String content = getContent(displayUrl + ".txt", CONTENT_TYPE_PLAIN);
+ assertContains(content, "dumped by PlainTextRendererServlet");
+ }
+
+ public void testWithoutScriptHtml() throws IOException {
+ final String content = getContent(displayUrl + ".html", CONTENT_TYPE_HTML);
+ assertContains(content, "dumped by HtmlRendererServlet");
+ }
+
+ public void testEspHtml() throws IOException {
+ final String toDelete = uploadTestScript("rendering-test.esp","html.esp");
+ try {
+ final String content = getContent(displayUrl + ".html", CONTENT_TYPE_HTML);
+ assertContains(content, "ESP template");
+ assertContains(content, "<p>" + testText + "</p>");
+ assertContains(content, "<div class=\"SLING-142\" id=\"22\"/>");
+ } finally {
+ testClient.delete(toDelete);
+ }
+ }
+
+ public void testEspJavaCode() throws IOException {
+ final String toDelete = uploadTestScript("rendering-test.esp","html.esp");
+ try {
+ final String content = getContent(displayUrl + ".html", CONTENT_TYPE_HTML);
+ assertContains(content, "ESP template");
+ assertContains(content, "TestLinkedListTest");
+ } finally {
+ testClient.delete(toDelete);
+ }
+ }
+
+ public void testEspHtmlInAppsFolder() throws IOException {
+ // make sure there's no leftover rendering script
+ {
+ final String content = getContent(displayUrl + ".html", CONTENT_TYPE_HTML);
+ assertFalse("Content must not contain script marker before testing", content.contains("ESP template"));
+ }
+
+ // put our script under /apps/<resource type>
+ final String path = "/apps/" + slingResourceType;
+ testClient.mkdirs(WEBDAV_BASE_URL, path);
+ final String toDelete = uploadTestScript(path,"rendering-test.esp","html.esp");
+ try {
+ final String content = getContent(displayUrl + ".html", CONTENT_TYPE_HTML);
+ assertContains(content, "ESP template");
+ assertContains(content, "<p>" + testText + "</p>");
+ } finally {
+ testClient.delete(toDelete);
+ }
+ }
+
+ public void TODO_FAILS_testEspHtmlWithContentBasedPath() throws IOException {
+
+ // make sure there's no leftover rendering script
+ {
+ final String content = getContent(displayUrl + ".html", CONTENT_TYPE_HTML);
+ assertContains(content, "ESP template");
+ }
+
+ // put our script in the /apps/<second folder level of content> (SLING-125)
+ final String path = "/apps/" + secondFolderOfContentPath;
+ testClient.mkdirs(WEBDAV_BASE_URL, path);
+ final String toDelete = uploadTestScript(path,"rendering-test.esp","html.esp");
+ try {
+ final String content = getContent(displayUrl + ".html", CONTENT_TYPE_HTML);
+ assertContains(content, "ESP template");
+ assertContains(content, "<p>" + testText + "</p>");
+ } finally {
+ testClient.delete(toDelete);
+ }
+ }
+
+ public void testEspHtmlWithSelectors() throws IOException {
+ testClient.mkdirs(WEBDAV_BASE_URL, scriptPath + "/a4");
+ final String toDeleteA = uploadTestScript("rendering-test.esp","html.esp");
+ final String toDeleteB = uploadTestScript("rendering-test-2.esp","a4.esp");
+ final String toDeleteC = uploadTestScript("rendering-test-3.esp","a4/print.esp");
+
+ try {
+ String content = getContent(displayUrl + ".html", CONTENT_TYPE_HTML);
+ assertTrue("Without selectors, content includes standard marker",content.contains("ESP template"));
+ assertTrue("Without selectors, content contains formatted test text",content.contains("<p>" + testText + "</p>"));
+
+ content = getContent(displayUrl + ".a4.print.html", CONTENT_TYPE_HTML);
+ assertTrue("With a4.print selectors, content includes marker 3",content.contains("Template #3 for ESP tests"));
+ assertTrue("With a4.print selectors, content contains italic text",content.contains("<em>" + testText + "</em>"));
+
+ content = getContent(displayUrl + ".a4.html", CONTENT_TYPE_HTML);
+ assertTrue("With a4 selector, content includes marker 2",content.contains("Template #2 for ESP tests"));
+ assertTrue("With a4 selector, content contains bold text",content.contains("<b>" + testText + "</b>"));
+
+ content = getContent(displayUrl + ".different.html", CONTENT_TYPE_HTML);
+ assertTrue("With different selector only, content includes standard marker",content.contains("ESP template"));
+ assertTrue("With different selector only, content contains formatted test text",content.contains("<p>" + testText + "</p>"));
+ } finally {
+ testClient.delete(toDeleteA);
+ testClient.delete(toDeleteB);
+ testClient.delete(toDeleteC);
+ }
+ }
+
+ public void TODO_FAILS_testEspHtmlUppercase() throws IOException {
+ final String toDelete = uploadTestScript("rendering-test.esp","html.esp");
+ try {
+ final String content = getContent(displayUrl + ".HTML", CONTENT_TYPE_HTML);
+ assertTrue("Content includes ESP marker",content.contains("ESP template"));
+ assertTrue("Content contains formatted test text",content.contains("<p>" + testText + "</p>"));
+ } finally {
+ testClient.delete(toDelete);
+ }
+ }
+
+ public void TODO_FAILS_testEspNoExtension() throws IOException {
+ final String toDelete = uploadTestScript("rendering-test.esp","GET.esp");
+ try {
+ final String content = getContent(displayUrl, CONTENT_TYPE_PLAIN);
+ assertTrue("Content includes ESP marker",content.contains("ESP template"));
+ assertTrue("Content contains formatted test text",content.contains("<p>" + testText + "</p>"));
+ } finally {
+ testClient.delete(toDelete);
+ }
+ }
+
+ /** SLING-107, verify that extension is used instead of Content-Type for script name */
+ public void testEspJs() throws IOException {
+ final String toDelete = uploadTestScript("rendering-test.esp","js.esp");
+ try {
+ final String content = getContent(displayUrl + ".js", CONTENT_TYPE_JS);
+ // template makes no JS sense, that's not a problem for this test
+ assertContains(content, "ESP template");
+ assertContains(content, "<p>" + testText + "</p>");
+ } finally {
+ testClient.delete(toDelete);
+ }
+ }
+
+ public void testEspXml() throws IOException {
+ final String toDelete = uploadTestScript("rendering-test.esp","xml.esp");
+ try {
+ final String content = getContent(displayUrl + ".xml", CONTENT_TYPE_XML);
+ assertContains(content, "ESP template");
+ assertContains(content, "<p>" + testText + "</p>");
+ } finally {
+ testClient.delete(toDelete);
+ }
+ }
+
+ public void testEspPlain() throws IOException {
+ final String toDelete = uploadTestScript("rendering-test.esp","txt.esp");
+ try {
+ final String content = getContent(displayUrl + ".txt", CONTENT_TYPE_PLAIN);
+ assertContains(content, "ESP template");
+ assertContains(content, "<p>" + testText + "</p>");
+ } finally {
+ testClient.delete(toDelete);
+ }
+ }
+
+ public void TODO_FAILS_testJsHtml() throws IOException {
+ final String toDelete = uploadTestScript("rendering-test.ecma","html.ecma");
+ try {
+ final String content = getContent(displayUrl + ".html", CONTENT_TYPE_HTML);
+ assertTrue("Content includes JS marker",content.contains("Raw javascript template"));
+ assertTrue("Content contains formatted test text",content.contains("<p><em>" + testText + "</em></p>"));
+ } finally {
+ testClient.delete(toDelete);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/StaticContentTest.java b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/StaticContentTest.java
new file mode 100644
index 0000000..77adde7
--- /dev/null
+++ b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/StaticContentTest.java
@@ -0,0 +1,39 @@
+/*
+ * 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.launchpad.webapp.integrationtest;
+
+import java.io.IOException;
+
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.sling.commons.testing.integration.HttpTestBase;
+
+/** Some tests about static content */
+public class StaticContentTest extends HttpTestBase {
+
+ public void testWebInfForbidden() throws IOException {
+ // if DefaultSlingServlet handled this we'd get an SC_FORBIDDEN, but it looks
+ // like the servlet container blocks it already
+ assertHttpStatus(HTTP_BASE_URL + "/WEB-INF/web.xml", HttpServletResponse.SC_NOT_FOUND);
+ }
+
+ public void testMetaInfForbidden() throws IOException {
+ // if DefaultSlingServlet handled this we'd get an SC_FORBIDDEN, but it looks
+ // like the servlet container blocks it already
+ assertHttpStatus(HTTP_BASE_URL + "/META-INF/somefile.txt", HttpServletResponse.SC_NOT_FOUND);
+ }
+}
diff --git a/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/StreamServletTest.java b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/StreamServletTest.java
new file mode 100644
index 0000000..120f840
--- /dev/null
+++ b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/StreamServletTest.java
@@ -0,0 +1,57 @@
+/*
+ * 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.launchpad.webapp.integrationtest;
+
+
+/** Test the streaming of static files uploaded to the repository */
+public class StreamServletTest extends RenderingTestBase {
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ scriptPath = TEST_PATH + "/StreamServletTest." + System.currentTimeMillis();
+ displayUrl = HTTP_BASE_URL + scriptPath;
+ testClient.mkdirs(WEBDAV_BASE_URL, scriptPath);
+ }
+
+ private void runTest(String filename, String expectedContentType, String expectedContent) throws Exception {
+ final String toDelete = uploadTestScript(filename,filename);
+ try {
+ final String url = displayUrl + "/" + filename;
+ final String content = getContent(url, expectedContentType);
+ assertEquals(expectedContent, content);
+ } finally {
+ testClient.delete(toDelete);
+ }
+ }
+
+ public void testPlainTextFile() throws Exception {
+ runTest("testfile.txt", CONTENT_TYPE_PLAIN, "This is just some text in an ASCII file.");
+ }
+
+ public void testHtmlFile() throws Exception {
+ runTest("testfile.html", CONTENT_TYPE_HTML, "This is <em>testfile.html</em>");
+ }
+
+ public void testJavascriptFile() throws Exception {
+ runTest("testfile.js", CONTENT_TYPE_JS, "// This is testfile.js");
+ }
+
+ public void testJsonFile() throws Exception {
+ runTest("testfile.json", CONTENT_TYPE_JSON, "This is testfile.json");
+ }
+}
diff --git a/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/SyntheticResourceTest.java b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/SyntheticResourceTest.java
new file mode 100644
index 0000000..d46f2d7
--- /dev/null
+++ b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/SyntheticResourceTest.java
@@ -0,0 +1,98 @@
+/*
+ * 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.launchpad.webapp.integrationtest;
+
+import java.io.IOException;
+
+import org.apache.sling.commons.testing.integration.HttpTestBase;
+
+
+/** Test the SLING-129 {@link org.apache.sling.api.resource.SyntheticResource}, by requesting
+ * non-existent Nodes..
+ */
+public class SyntheticResourceTest extends HttpTestBase {
+
+ /** recurse random URLs under basePath, going nLevels deep,
+ * and check that we get the specified status for every URL
+ * @throws IOException
+ */
+ private void assertDeepGetStatus(String basePath, int nLevels, int expectedStatus, String urlSuffix) throws IOException {
+ String path = basePath;
+ for(int level=1; level <= nLevels; level++) {
+ final String url = HTTP_BASE_URL + path + urlSuffix;
+ assertHttpStatus(url, expectedStatus,"Unexpected status at URL=" + url);
+ basePath += "/level_" + level + "_" + (int)(Math.random() * Integer.MAX_VALUE);
+ }
+ }
+
+ public void TODO_FAILS_testSearchSyntheticResource() throws IOException {
+ // build a very random deep URL under /search and
+ // verify that we get a 200 every time
+ assertDeepGetStatus("/search",10,200,"");
+ }
+
+ public void TODO_FAILS_testSearchSyntheticResourceHtml() throws IOException {
+ // build a very random deep URL under /search and
+ // verify that we get a 200 every time
+ assertDeepGetStatus("/search",10,200,".html");
+ assertDeepGetStatus("/search",10,200,".a4.print.html");
+ }
+
+ public void TODO_FAILS_testSearchSyntheticResourceJson() throws IOException {
+ // build a very random deep URL under /search and
+ // verify that we get a 200 every time
+ assertDeepGetStatus("/search",10,200,".json");
+ assertDeepGetStatus("/search",10,200,".a4.print.json");
+ }
+
+ public void TODO_FAILS_testSearchSyntheticResourceTxt() throws IOException {
+ // build a very random deep URL under /search and
+ // verify that we get a 200 every time
+ assertDeepGetStatus("/search",10,200,".txt");
+ assertDeepGetStatus("/search",10,200,".a4.print.txt");
+ }
+
+ public void testNoSyntheticResourceTest() throws IOException {
+ // walk down a random path, verify that we
+ // get 404s all the time
+ final String basePath = "/" + getClass().getSimpleName() + "_" + System.currentTimeMillis() + "/" + (int)(Math.random() * Integer.MAX_VALUE);
+ assertDeepGetStatus(basePath,10,404,"");
+ }
+
+ public void TODO_FAILS_testSyntheticResourceWithJstTemplate() throws IOException {
+ final String synthResourceUrl = HTTP_BASE_URL + "/search/something.SyntheticResourceTest.html";
+ {
+ final String content = getContent(synthResourceUrl, CONTENT_TYPE_HTML);
+ assertFalse("Content must not include JST marker before test",content.contains("JST template"));
+ }
+
+ //final String scriptPath = "/apps/" + SyntheticResource.DEFAULT_RESOURCE_TYPE + "/SyntheticResourceTest";
+ final String scriptPath = "TODO";
+ testClient.mkdirs(WEBDAV_BASE_URL, scriptPath);
+ final String toDelete = uploadTestScript(scriptPath,"rendering-test.jst","html.jst");
+ try {
+ final String content = getContent(synthResourceUrl, CONTENT_TYPE_HTML);
+ assertTrue("Content includes JST marker: " + content,content.contains("JST template"));
+ } finally {
+ testClient.delete(toDelete);
+ }
+ }
+
+
+}
diff --git a/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/UploadFileTest.java b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/UploadFileTest.java
new file mode 100644
index 0000000..bb5dc74
--- /dev/null
+++ b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/UploadFileTest.java
@@ -0,0 +1,215 @@
+/*
+ * 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.launchpad.webapp.integrationtest;
+
+import java.io.File;
+import java.io.IOException;
+
+import org.apache.commons.httpclient.HttpException;
+import org.apache.commons.httpclient.methods.GetMethod;
+import org.apache.sling.commons.testing.integration.HttpTestBase;
+
+/**
+ * Test uploading files using the Sling post servlet (SLING-168)
+ */
+public class UploadFileTest extends HttpTestBase {
+
+ private static final String TEST_FILE = "src/test/resources/integration-test/file-to-upload.txt";
+
+ public void testDistinctResource() throws IOException {
+ String folderPath = "/UploadFileTest_1_" + System.currentTimeMillis();
+ final String url = HTTP_BASE_URL + folderPath;
+
+ // create new node
+ String urlOfNewNode = null;
+ try {
+ urlOfNewNode = testClient.createNode(url, null);
+ } catch(IOException ioe) {
+ fail("createNode failed: " + ioe);
+ }
+
+ // upload local file
+ File localFile = new File(TEST_FILE);
+ testClient.uploadToFileNode(urlOfNewNode, localFile, "./file", null);
+
+ // get and check URL of created file
+ String urlOfFileNode = urlOfNewNode + "/file";
+ final GetMethod get = new GetMethod(urlOfFileNode);
+ final int status = httpClient.executeMethod(get);
+ assertEquals(urlOfFileNode + " must be accessible after createNode",200,status);
+
+ /*
+ We should check the data, but nt:resources are not handled yet
+ // compare data with local file (just length)
+ final byte[] data = get.getResponseBody();
+ assertEquals("size of file must be same", localFile.length(), data.length);
+ */
+ String data = get.getResponseBodyAsString();
+ assertTrue("checking for content", data.contains("http://www.apache.org/licenses/LICENSE-2.0"));
+
+ // download structure
+ String json = getContent(urlOfFileNode + ".json", CONTENT_TYPE_JSON);
+ // just check for some strings
+ assertTrue("checking primary type", json.contains("\"jcr:primaryType\":\"nt:resource\""));
+ assertTrue("checking mime type", json.contains("\"jcr:mimeType\":\"text/plain\""));
+
+ }
+
+ public void testDistinctResourceWithType() throws IOException {
+ String folderPath = "/UploadFileTest_1_" + System.currentTimeMillis();
+ final String url = HTTP_BASE_URL + folderPath;
+
+ // create new node
+ String urlOfNewNode = null;
+ try {
+ urlOfNewNode = testClient.createNode(url, null);
+ } catch(IOException ioe) {
+ fail("createNode failed: " + ioe);
+ }
+
+ // upload local file
+ File localFile = new File(TEST_FILE);
+ testClient.uploadToFileNode(urlOfNewNode, localFile, "./file", "nt:unstructured");
+
+ // get and check URL of created file
+ String urlOfFileNode = urlOfNewNode + "/file";
+ final GetMethod get = new GetMethod(urlOfFileNode);
+ final int status = httpClient.executeMethod(get);
+ assertEquals(urlOfFileNode + " must be accessible after createNode",200,status);
+
+ /*
+ We should check the data, but nt:resources are not handled yet
+ // compare data with local file (just length)
+ final byte[] data = get.getResponseBody();
+ assertEquals("size of file must be same", localFile.length(), data.length);
+ */
+ String data = get.getResponseBodyAsString();
+ assertTrue("checking for content", data.contains("http://www.apache.org/licenses/LICENSE-2.0"));
+
+ // download structure
+ String json = getContent(urlOfFileNode + ".100.json", CONTENT_TYPE_JSON);
+
+ // just check for some strings
+ assertTrue("checking primary type", json.contains("\"jcr:primaryType\":\"nt:unstructured\""));
+ assertTrue("checking mime type", json.contains("\"jcr:mimeType\":\"text/plain\""));
+ }
+
+ public void testDistinctFile() throws IOException {
+ String folderPath = "/UploadFileTest_1_" + System.currentTimeMillis();
+ testClient.mkdirs(WEBDAV_BASE_URL, folderPath);
+ final String url = HTTP_BASE_URL + folderPath;
+
+
+ // upload local file
+ File localFile = new File(TEST_FILE);
+ testClient.uploadToFileNode(url, localFile, "./file", null);
+
+ // get and check URL of created file
+ String urlOfFileNode = url + "/file";
+
+ /*
+ TODO: does not work, since no nt:file resource type handler present ???
+
+ final GetMethod get = new GetMethod(urlOfFileNode);
+ final int status = httpClient.executeMethod(get);
+ assertEquals(urlOfFileNode + " must be accessible after createNode",200,status);
+
+ // compare data with local file (just length)
+ final byte[] data = get.getResponseBody();
+ assertEquals("size of file must be same", localFile.length(), data.length);
+ */
+
+ String webdavUrl = WEBDAV_BASE_URL + folderPath + "/file";
+ final GetMethod get = new GetMethod(webdavUrl);
+ final int status = httpClient.executeMethod(get);
+ assertEquals(urlOfFileNode + " must be accessible after createNode",200,status);
+
+ // compare data with local file (just length)
+ final byte[] data = get.getResponseBody();
+ assertEquals("size of file must be same", localFile.length(), data.length);
+
+ // download structure
+ String json = getContent(urlOfFileNode + ".json", CONTENT_TYPE_JSON);
+ // just check for some strings
+ assertTrue("checking primary type", json.contains("\"jcr:primaryType\":\"nt:file\""));
+ }
+
+
+ public void testMultiFileUpload() throws IOException {
+ String folderPath = "/UploadFileTest_1_" + System.currentTimeMillis();
+ final String url = HTTP_BASE_URL + folderPath;
+
+ // create new node
+ String urlOfNewNode = null;
+ try {
+ urlOfNewNode = testClient.createNode(url, null);
+ } catch(IOException ioe) {
+ fail("createNode failed: " + ioe);
+ }
+
+ // upload local file
+ File [] localFiles = new File[] {
+ new File(TEST_FILE),
+ new File(TEST_FILE),
+ new File(TEST_FILE)
+ };
+ String [] fieldNames = new String [] {
+ "./file1.txt",
+ "./file2.txt",
+ "./*"
+ };
+ testClient.uploadToFileNodes(urlOfNewNode, localFiles, fieldNames, null);
+
+ // get and check URL of created file1
+ String urlOfFileNode = urlOfNewNode + "/file1.txt";
+ checkUploadedFileState(urlOfFileNode);
+
+ // get and check URL of created file2
+ String urlOfFileNode2 = urlOfNewNode + "/file2.txt";
+ checkUploadedFileState(urlOfFileNode2);
+
+ // get and check URL of created file3
+ String urlOfFileNode3 = urlOfNewNode + "/file-to-upload.txt";
+ checkUploadedFileState(urlOfFileNode3);
+ }
+
+ private void checkUploadedFileState(String urlOfFileNode) throws IOException,
+ HttpException {
+ final GetMethod get = new GetMethod(urlOfFileNode);
+ final int status = httpClient.executeMethod(get);
+ assertEquals(urlOfFileNode + " must be accessible after createNode",200,status);
+
+ /*
+ We should check the data, but nt:resources are not handled yet
+ // compare data with local file (just length)
+ final byte[] data = get.getResponseBody();
+ assertEquals("size of file must be same", localFile.length(), data.length);
+ */
+ String data = get.getResponseBodyAsString();
+ assertTrue("checking for content", data.contains("http://www.apache.org/licenses/LICENSE-2.0"));
+
+ // download structure
+ String json = getContent(urlOfFileNode + ".json", CONTENT_TYPE_JSON);
+ // just check for some strings
+ assertTrue("checking primary type", json.contains("\"jcr:primaryType\":\"nt:file\""));
+
+ String content_json = getContent(urlOfFileNode + "/jcr:content.json", CONTENT_TYPE_JSON);
+ // just check for some strings
+ assertTrue("checking primary type", content_json.contains("\"jcr:primaryType\":\"nt:resource\""));
+ assertTrue("checking mime type", content_json.contains("\"jcr:mimeType\":\"text/plain\""));
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/ValueFromTest.java b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/ValueFromTest.java
new file mode 100644
index 0000000..3e68c6c
--- /dev/null
+++ b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/ValueFromTest.java
@@ -0,0 +1,80 @@
+/*
+ * 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.launchpad.webapp.integrationtest;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.sling.commons.testing.integration.HttpTestBase;
+import org.apache.sling.servlets.post.SlingPostConstants;
+
+/** Test the @ValueFrom field name suffix, SLING-130 */
+public class ValueFromTest extends HttpTestBase {
+
+ private String postUrl;
+ private String testText;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ // set test values
+ testText = "This is a test " + System.currentTimeMillis();
+
+ // create the test node, under a path that's specific to this class to allow collisions
+ postUrl = HTTP_BASE_URL + "/" + getClass().getSimpleName() + "/" + System.currentTimeMillis() + SlingPostConstants.DEFAULT_CREATE_SUFFIX;
+ final Map<String,String> props = new HashMap<String,String>();
+ props.put("text", testText);
+ }
+
+ public void testWithoutValueFrom() throws IOException {
+ final Map<String,String> props = new HashMap<String,String>();
+ props.put("./text", testText);
+ final String jsonUrl = testClient.createNode(postUrl, props) + ".json";
+ final String json = getContent(jsonUrl, CONTENT_TYPE_JSON);
+ assertJavascript(testText, json, "out.println(data.text)");
+
+ }
+
+ public void testWithValueFrom() throws IOException {
+ final Map<String,String> props = new HashMap<String,String>();
+ props.put("./text@ValueFrom", "fulltext");
+ props.put("fulltext", testText);
+ final String jsonUrl = testClient.createNode(postUrl, props) + ".json";
+ final String json = getContent(jsonUrl, CONTENT_TYPE_JSON);
+ assertJavascript("string", json, "out.println(typeof data.text)");
+ assertJavascript(testText, json, "out.println(data.text)");
+ assertJavascript("undefined", json, "out.println(typeof data.fulltext)");
+ }
+
+ public void testWithValueFromAndMissingField() throws IOException {
+ final Map<String,String> props = new HashMap<String,String>();
+ props.put("./jcr:created", "");
+ props.put("./text@ValueFrom", "fulltext");
+
+ // no fulltext field on purpose, field must be ignored
+
+ final String jsonUrl = testClient.createNode(postUrl, props) + ".json";
+ final String json = getContent(jsonUrl, CONTENT_TYPE_JSON);
+ assertJavascript("undefined", json, "out.println(typeof data.text)");
+ assertJavascript("undefined", json, "out.println(typeof data['text@ValueFrom'])");
+ }
+
+
+
+ }
\ No newline at end of file
diff --git a/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/WebdavUploadTest.java b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/WebdavUploadTest.java
new file mode 100644
index 0000000..4017874
--- /dev/null
+++ b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/WebdavUploadTest.java
@@ -0,0 +1,113 @@
+/*
+ * 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.launchpad.webapp.integrationtest;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.apache.commons.httpclient.methods.GetMethod;
+import org.apache.sling.commons.testing.integration.HttpTestBase;
+
+/** Test WebDAV upload of various file types */
+public class WebdavUploadTest extends HttpTestBase {
+
+ private final String testDir = "/sling-test/" + getClass().getSimpleName() + System.currentTimeMillis();
+ private final String testDirUrl = WEBDAV_BASE_URL + testDir;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ testClient.mkdirs(WEBDAV_BASE_URL, testDir);
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ testClient.delete(testDirUrl);
+ }
+
+ protected byte [] readStream(InputStream is) throws IOException {
+ if(is == null) {
+ fail("Null InputStream");
+ }
+ final ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ try {
+ final byte [] buffer = new byte[4096];
+ int n = 0;
+ while( (n = is.read(buffer, 0, buffer.length)) > 0) {
+ bos.write(buffer, 0, n);
+ }
+ } finally {
+ is.close();
+ bos.flush();
+ bos.close();
+ }
+ return bos.toByteArray();
+ }
+
+ protected void compareData(String slingDataUrl, String localResourcePath) throws IOException {
+
+ // Get Sling content as a binary stream
+ final GetMethod m = new GetMethod(slingDataUrl);
+ final int httpStatus = httpClient.executeMethod(m);
+ assertEquals("GET " + slingDataUrl + " must return status 200", 200, httpStatus);
+ final byte [] local = readStream(getClass().getResourceAsStream(localResourcePath));
+ final byte [] remote = readStream(m.getResponseBodyAsStream());
+
+ assertEquals("Local and remote files have the same length", local.length, remote.length);
+
+ for(int i=0 ; i < local.length; i++) {
+ assertEquals("Content must match at index " + i, local[i], remote[i]);
+ }
+ }
+
+ protected void uploadAndCheck(String localResourcePath) throws IOException {
+ final InputStream data = getClass().getResourceAsStream(localResourcePath);
+ if(data==null) {
+ fail("Local resource not found: " + localResourcePath);
+ }
+
+ try {
+ final String url = testDirUrl + "/" + new File(localResourcePath).getName();
+ testClient.upload(url, data);
+ compareData(url, localResourcePath);
+ } finally {
+ if(data!=null) {
+ data.close();
+ }
+ }
+
+ }
+
+ public void testTextUpload() throws IOException {
+ uploadAndCheck("/integration-test/testfile.txt");
+ }
+
+ public void testXmlUpload() throws IOException {
+ uploadAndCheck("/integration-test/testfile.xml");
+ }
+
+ public void testZipUpload() throws IOException {
+ uploadAndCheck("/integration-test/testfile.zip");
+ }
+
+ public void testPngUpload() throws IOException {
+ uploadAndCheck("/integration-test/sling-logo.png");
+ }
+}
diff --git a/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/accessManager/AbstractAccessManagerTest.java b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/accessManager/AbstractAccessManagerTest.java
new file mode 100644
index 0000000..2ce7106
--- /dev/null
+++ b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/accessManager/AbstractAccessManagerTest.java
@@ -0,0 +1,196 @@
+/*
+ * 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.launchpad.webapp.integrationtest.accessManager;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.httpclient.Credentials;
+import org.apache.commons.httpclient.Header;
+import org.apache.commons.httpclient.HttpException;
+import org.apache.commons.httpclient.NameValuePair;
+import org.apache.commons.httpclient.UsernamePasswordCredentials;
+import org.apache.commons.httpclient.auth.AuthScope;
+import org.apache.commons.httpclient.methods.GetMethod;
+import org.apache.commons.httpclient.methods.PostMethod;
+import org.apache.sling.commons.testing.integration.HttpTestBase;
+import org.apache.sling.servlets.post.SlingPostConstants;
+
+/**
+ * Base class for AccessManager tests.
+ */
+public abstract class AbstractAccessManagerTest extends HttpTestBase {
+
+ public static final String TEST_BASE_PATH = "/sling-tests";
+
+ /** Execute a POST request and check status */
+ protected void assertAuthenticatedPostStatus(Credentials creds, String url, int expectedStatusCode, List<NameValuePair> postParams, String assertMessage)
+ throws IOException {
+ final PostMethod post = new PostMethod(url);
+ post.setFollowRedirects(false);
+
+ URL baseUrl = new URL(HTTP_BASE_URL);
+ AuthScope authScope = new AuthScope(baseUrl.getHost(), baseUrl.getPort(), AuthScope.ANY_REALM);
+ post.setDoAuthentication(true);
+ Credentials oldCredentials = httpClient.getState().getCredentials(authScope);
+ try {
+ httpClient.getState().setCredentials(authScope, creds);
+
+ if(postParams!=null) {
+ final NameValuePair [] nvp = {};
+ post.setRequestBody(postParams.toArray(nvp));
+ }
+
+ final int status = httpClient.executeMethod(post);
+ if(assertMessage == null) {
+ assertEquals(expectedStatusCode, status);
+ } else {
+ assertEquals(assertMessage, expectedStatusCode, status);
+ }
+ } finally {
+ httpClient.getState().setCredentials(authScope, oldCredentials);
+ }
+ }
+
+ /** Verify that given URL returns expectedStatusCode
+ * @throws IOException */
+ protected void assertAuthenticatedHttpStatus(Credentials creds, String urlString, int expectedStatusCode, String assertMessage) throws IOException {
+ URL baseUrl = new URL(HTTP_BASE_URL);
+ AuthScope authScope = new AuthScope(baseUrl.getHost(), baseUrl.getPort(), AuthScope.ANY_REALM);
+ GetMethod getMethod = new GetMethod(urlString);
+ getMethod.setDoAuthentication(true);
+
+ Credentials oldCredentials = httpClient.getState().getCredentials(authScope);
+ try {
+ httpClient.getState().setCredentials(authScope, creds);
+
+ final int status = httpClient.executeMethod(getMethod);
+ if(assertMessage == null) {
+ assertEquals(urlString,expectedStatusCode, status);
+ } else {
+ assertEquals(assertMessage, expectedStatusCode, status);
+ }
+ } finally {
+ httpClient.getState().setCredentials(authScope, oldCredentials);
+ }
+ }
+
+
+ /** retrieve the contents of given URL and assert its content type
+ * @param expectedContentType use CONTENT_TYPE_DONTCARE if must not be checked
+ * @throws IOException
+ * @throws HttpException */
+ protected String getAuthenticatedContent(Credentials creds, String url, String expectedContentType, List<NameValuePair> params, int expectedStatusCode) throws IOException {
+ final GetMethod get = new GetMethod(url);
+
+ URL baseUrl = new URL(HTTP_BASE_URL);
+ AuthScope authScope = new AuthScope(baseUrl.getHost(), baseUrl.getPort(), AuthScope.ANY_REALM);
+ get.setDoAuthentication(true);
+ Credentials oldCredentials = httpClient.getState().getCredentials(authScope);
+ try {
+ httpClient.getState().setCredentials(authScope, creds);
+
+ if(params != null) {
+ final NameValuePair [] nvp = new NameValuePair[0];
+ get.setQueryString(params.toArray(nvp));
+ }
+ final int status = httpClient.executeMethod(get);
+ final InputStream is = get.getResponseBodyAsStream();
+ final StringBuffer content = new StringBuffer();
+ final String charset = get.getResponseCharSet();
+ final byte [] buffer = new byte[16384];
+ int n = 0;
+ while( (n = is.read(buffer, 0, buffer.length)) > 0) {
+ content.append(new String(buffer, 0, n, charset));
+ }
+ assertEquals("Expected status " + expectedStatusCode + " for " + url + " (content=" + content + ")",
+ expectedStatusCode,status);
+ final Header h = get.getResponseHeader("Content-Type");
+ if(expectedContentType == null) {
+ if(h!=null) {
+ fail("Expected null Content-Type, got " + h.getValue());
+ }
+ } else if(CONTENT_TYPE_DONTCARE.equals(expectedContentType)) {
+ // no check
+ } else if(h==null) {
+ fail(
+ "Expected Content-Type that starts with '" + expectedContentType
+ +" but got no Content-Type header at " + url
+ );
+ } else {
+ assertTrue(
+ "Expected Content-Type that starts with '" + expectedContentType
+ + "' for " + url + ", got '" + h.getValue() + "'",
+ h.getValue().startsWith(expectedContentType)
+ );
+ }
+ return content.toString();
+
+ } finally {
+ httpClient.getState().setCredentials(authScope, oldCredentials);
+ }
+ }
+
+
+ protected static int counter = 1;
+
+ protected String createTestUser() throws IOException {
+ String postUrl = HTTP_BASE_URL + "/system/userManager/user.create.html";
+
+ String testUserId = "testUser" + (counter++);
+ List<NameValuePair> postParams = new ArrayList<NameValuePair>();
+ postParams.add(new NameValuePair(":name", testUserId));
+ postParams.add(new NameValuePair("pwd", "testPwd"));
+ postParams.add(new NameValuePair("pwdConfirm", "testPwd"));
+ assertPostStatus(postUrl, HttpServletResponse.SC_OK, postParams, null);
+
+ return testUserId;
+ }
+
+ protected String createTestGroup() throws IOException {
+ String postUrl = HTTP_BASE_URL + "/system/userManager/group.create.html";
+
+ String testGroupId = "testGroup" + (counter++);
+ List<NameValuePair> postParams = new ArrayList<NameValuePair>();
+ postParams.add(new NameValuePair(":name", testGroupId));
+
+ //success would be a redirect to the welcome page of the webapp
+ Credentials creds = new UsernamePasswordCredentials("admin", "admin");
+ assertAuthenticatedPostStatus(creds, postUrl, HttpServletResponse.SC_OK, postParams, null);
+
+ return testGroupId;
+ }
+
+ protected String createTestFolder() throws IOException {
+ String postUrl = HTTP_BASE_URL + TEST_BASE_PATH + "/" + "testFolder" + (counter++);
+
+ final String location = testClient.createNode(postUrl + SlingPostConstants.DEFAULT_CREATE_SUFFIX, null);
+ assertHttpStatus(location + DEFAULT_EXT, HttpServletResponse.SC_OK,
+ "POST must redirect to created resource (" + location + ")");
+ assertTrue("Node (" + location + ") must have generated name",
+ !location.endsWith("/*"));
+ assertTrue("Node (" + location + ") must created be under POST URL (" + postUrl + ")",
+ location.contains(postUrl + "/"));
+
+ return location;
+ }
+}
diff --git a/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/accessManager/ModifyAceTest.java b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/accessManager/ModifyAceTest.java
new file mode 100644
index 0000000..87dd33c
--- /dev/null
+++ b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/accessManager/ModifyAceTest.java
@@ -0,0 +1,140 @@
+/*
+ * 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.launchpad.webapp.integrationtest.accessManager;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.httpclient.Credentials;
+import org.apache.commons.httpclient.NameValuePair;
+import org.apache.commons.httpclient.UsernamePasswordCredentials;
+import org.apache.sling.commons.json.JSONArray;
+import org.apache.sling.commons.json.JSONException;
+import org.apache.sling.commons.json.JSONObject;
+
+/**
+ * Tests for the 'modifyAce' Sling Post Operation
+ */
+public class ModifyAceTest extends AbstractAccessManagerTest {
+
+ String testUserId = null;
+ String testGroupId = null;
+ String testFolderUrl = null;
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+
+ Credentials creds = new UsernamePasswordCredentials("admin", "admin");
+
+ if (testFolderUrl != null) {
+ //remove the test user if it exists.
+ String postUrl = testFolderUrl;
+ List<NameValuePair> postParams = new ArrayList<NameValuePair>();
+ postParams.add(new NameValuePair(":operation", "delete"));
+ assertAuthenticatedPostStatus(creds, postUrl, HttpServletResponse.SC_OK, postParams, null);
+ }
+ if (testGroupId != null) {
+ //remove the test user if it exists.
+ String postUrl = HTTP_BASE_URL + "/system/userManager/group/" + testGroupId + ".delete.html";
+ List<NameValuePair> postParams = new ArrayList<NameValuePair>();
+ assertAuthenticatedPostStatus(creds, postUrl, HttpServletResponse.SC_OK, postParams, null);
+ }
+ if (testUserId != null) {
+ //remove the test user if it exists.
+ String postUrl = HTTP_BASE_URL + "/system/userManager/user/" + testUserId + ".delete.html";
+ List<NameValuePair> postParams = new ArrayList<NameValuePair>();
+ assertAuthenticatedPostStatus(creds, postUrl, HttpServletResponse.SC_OK, postParams, null);
+ }
+ }
+
+ public void testModifyAceForUser() throws IOException, JSONException {
+ testUserId = createTestUser();
+
+ testFolderUrl = createTestFolder();
+
+ String postUrl = testFolderUrl + ".modifyAce.html";
+
+ List<NameValuePair> postParams = new ArrayList<NameValuePair>();
+ postParams.add(new NameValuePair("principalId", testUserId));
+ postParams.add(new NameValuePair("privilege@jcr:read", "granted"));
+ postParams.add(new NameValuePair("privilege@jcr:write", "denied"));
+
+ Credentials creds = new UsernamePasswordCredentials("admin", "admin");
+ assertAuthenticatedPostStatus(creds, postUrl, HttpServletResponse.SC_OK, postParams, null);
+
+
+ //fetch the JSON for the acl to verify the settings.
+ String getUrl = testFolderUrl + ".acl.json";
+
+ String json = getAuthenticatedContent(creds, getUrl, CONTENT_TYPE_JSON, null, HttpServletResponse.SC_OK);
+ assertNotNull(json);
+ JSONObject jsonObj = new JSONObject(json);
+ String aceString = jsonObj.getString(testUserId);
+ assertNotNull(aceString);
+
+ JSONObject aceObject = new JSONObject(aceString);
+ assertNotNull(aceObject);
+
+ JSONArray grantedArray = aceObject.getJSONArray("granted");
+ assertNotNull(grantedArray);
+ assertEquals("jcr:read", grantedArray.getString(0));
+
+ JSONArray deniedArray = aceObject.getJSONArray("denied");
+ assertNotNull(deniedArray);
+ assertEquals("jcr:write", deniedArray.getString(0));
+ }
+
+ public void testModifyAceForGroup() throws IOException, JSONException {
+ testGroupId = createTestGroup();
+
+ testFolderUrl = createTestFolder();
+
+ String postUrl = testFolderUrl + ".modifyAce.html";
+
+ List<NameValuePair> postParams = new ArrayList<NameValuePair>();
+ postParams.add(new NameValuePair("principalId", testGroupId));
+ postParams.add(new NameValuePair("privilege@jcr:read", "granted"));
+ postParams.add(new NameValuePair("privilege@jcr:write", "denied"));
+
+ Credentials creds = new UsernamePasswordCredentials("admin", "admin");
+ assertAuthenticatedPostStatus(creds, postUrl, HttpServletResponse.SC_OK, postParams, null);
+
+
+ //fetch the JSON for the acl to verify the settings.
+ String getUrl = testFolderUrl + ".acl.json";
+
+ String json = getAuthenticatedContent(creds, getUrl, CONTENT_TYPE_JSON, null, HttpServletResponse.SC_OK);
+ assertNotNull(json);
+ JSONObject jsonObj = new JSONObject(json);
+ String aceString = jsonObj.getString(testGroupId);
+ assertNotNull(aceString);
+
+ JSONObject aceObject = new JSONObject(aceString);
+ assertNotNull(aceObject);
+
+ JSONArray grantedArray = aceObject.getJSONArray("granted");
+ assertNotNull(grantedArray);
+ assertEquals("jcr:read", grantedArray.getString(0));
+
+ //denied rights are not applied for groups, so make sure it is not there
+ assertTrue(aceObject.isNull("denied"));
+ }
+}
diff --git a/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/accessManager/RemoveAcesTest.java b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/accessManager/RemoveAcesTest.java
new file mode 100644
index 0000000..5049c44
--- /dev/null
+++ b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/accessManager/RemoveAcesTest.java
@@ -0,0 +1,171 @@
+/*
+ * 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.launchpad.webapp.integrationtest.accessManager;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.httpclient.Credentials;
+import org.apache.commons.httpclient.NameValuePair;
+import org.apache.commons.httpclient.UsernamePasswordCredentials;
+import org.apache.sling.commons.json.JSONArray;
+import org.apache.sling.commons.json.JSONException;
+import org.apache.sling.commons.json.JSONObject;
+
+/**
+ * Tests for the 'removeAce' Sling POST operation
+ */
+public class RemoveAcesTest extends AbstractAccessManagerTest {
+ String testUserId = null;
+ String testGroupId = null;
+ String testFolderUrl = null;
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+
+ Credentials creds = new UsernamePasswordCredentials("admin", "admin");
+
+ if (testFolderUrl != null) {
+ //remove the test user if it exists.
+ String postUrl = testFolderUrl;
+ List<NameValuePair> postParams = new ArrayList<NameValuePair>();
+ postParams.add(new NameValuePair(":operation", "delete"));
+ assertAuthenticatedPostStatus(creds, postUrl, HttpServletResponse.SC_OK, postParams, null);
+ }
+ if (testGroupId != null) {
+ //remove the test user if it exists.
+ String postUrl = HTTP_BASE_URL + "/system/userManager/group/" + testGroupId + ".delete.html";
+ List<NameValuePair> postParams = new ArrayList<NameValuePair>();
+ assertAuthenticatedPostStatus(creds, postUrl, HttpServletResponse.SC_OK, postParams, null);
+ }
+ if (testUserId != null) {
+ //remove the test user if it exists.
+ String postUrl = HTTP_BASE_URL + "/system/userManager/user/" + testUserId + ".delete.html";
+ List<NameValuePair> postParams = new ArrayList<NameValuePair>();
+ assertAuthenticatedPostStatus(creds, postUrl, HttpServletResponse.SC_OK, postParams, null);
+ }
+ //todo delete test folder
+ }
+
+ private String createFolderWithAces(boolean addGroupAce) throws IOException, JSONException {
+ testUserId = createTestUser();
+ testFolderUrl = createTestFolder();
+
+ String postUrl = testFolderUrl + ".modifyAce.html";
+
+ List<NameValuePair> postParams = new ArrayList<NameValuePair>();
+ postParams.add(new NameValuePair("principalId", testUserId));
+ postParams.add(new NameValuePair("privilege@jcr:read", "granted"));
+ postParams.add(new NameValuePair("privilege@jcr:write", "denied"));
+
+ Credentials creds = new UsernamePasswordCredentials("admin", "admin");
+ assertAuthenticatedPostStatus(creds, postUrl, HttpServletResponse.SC_OK, postParams, null);
+
+ if (addGroupAce) {
+ testGroupId = createTestGroup();
+
+ postParams = new ArrayList<NameValuePair>();
+ postParams.add(new NameValuePair("principalId", testGroupId));
+ postParams.add(new NameValuePair("privilege@jcr:read", "granted"));
+
+ assertAuthenticatedPostStatus(creds, postUrl, HttpServletResponse.SC_OK, postParams, null);
+ }
+
+ //fetch the JSON for the acl to verify the settings.
+ String getUrl = testFolderUrl + ".acl.json";
+
+ String json = getAuthenticatedContent(creds, getUrl, CONTENT_TYPE_JSON, null, HttpServletResponse.SC_OK);
+ assertNotNull(json);
+
+ JSONObject jsonObj = new JSONObject(json);
+ String aceString = jsonObj.getString(testUserId);
+ assertNotNull(aceString);
+
+ JSONObject aceObject = new JSONObject(aceString);
+ assertNotNull(aceObject);
+
+ JSONArray grantedArray = aceObject.getJSONArray("granted");
+ assertNotNull(grantedArray);
+ assertEquals("jcr:read", grantedArray.getString(0));
+
+ JSONArray deniedArray = aceObject.getJSONArray("denied");
+ assertNotNull(deniedArray);
+ assertEquals("jcr:write", deniedArray.getString(0));
+
+ if (addGroupAce) {
+ aceString = jsonObj.getString(testGroupId);
+ assertNotNull(aceString);
+
+ aceObject = new JSONObject(aceString);
+ assertNotNull(aceObject);
+
+ grantedArray = aceObject.getJSONArray("granted");
+ assertNotNull(grantedArray);
+ assertEquals("jcr:read", grantedArray.getString(0));
+ }
+
+ return testFolderUrl;
+ }
+
+ //test removing a single ace
+ public void testRemoveAce() throws IOException, JSONException {
+ String folderUrl = createFolderWithAces(false);
+
+ //remove the ace for the testUser principal
+ String postUrl = folderUrl + ".deleteAce.html";
+ List<NameValuePair> postParams = new ArrayList<NameValuePair>();
+ postParams.add(new NameValuePair(":applyTo", testUserId));
+ Credentials creds = new UsernamePasswordCredentials("admin", "admin");
+ assertAuthenticatedPostStatus(creds, postUrl, HttpServletResponse.SC_OK, postParams, null);
+
+ //fetch the JSON for the acl to verify the settings.
+ String getUrl = folderUrl + ".acl.json";
+
+ String json = getAuthenticatedContent(creds, getUrl, CONTENT_TYPE_JSON, null, HttpServletResponse.SC_OK);
+ assertNotNull(json);
+
+ JSONObject jsonObj = new JSONObject(json);
+ assertTrue(jsonObj.isNull(testUserId));
+ }
+
+ //test removing multiple aces
+ public void testRemoveAces() throws IOException, JSONException {
+ String folderUrl = createFolderWithAces(true);
+
+ //remove the ace for the testUser principal
+ String postUrl = folderUrl + ".deleteAce.html";
+ List<NameValuePair> postParams = new ArrayList<NameValuePair>();
+ postParams.add(new NameValuePair(":applyTo", testUserId));
+ postParams.add(new NameValuePair(":applyTo", testGroupId));
+ Credentials creds = new UsernamePasswordCredentials("admin", "admin");
+ assertAuthenticatedPostStatus(creds, postUrl, HttpServletResponse.SC_OK, postParams, null);
+
+ //fetch the JSON for the acl to verify the settings.
+ String getUrl = folderUrl + ".acl.json";
+
+ String json = getAuthenticatedContent(creds, getUrl, CONTENT_TYPE_JSON, null, HttpServletResponse.SC_OK);
+ assertNotNull(json);
+
+ JSONObject jsonObj = new JSONObject(json);
+ assertTrue(jsonObj.isNull(testUserId));
+ assertTrue(jsonObj.isNull(testGroupId));
+ }
+}
diff --git a/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/issues/SLING457Test.java b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/issues/SLING457Test.java
new file mode 100644
index 0000000..5c352c2
--- /dev/null
+++ b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/issues/SLING457Test.java
@@ -0,0 +1,89 @@
+/*
+ * 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.launchpad.webapp.integrationtest.issues;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.sling.commons.testing.integration.HttpTestBase;
+
+public class SLING457Test extends HttpTestBase {
+
+ private String testRootUrl;
+
+ private String contentUrl;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ final String testRootPathBare = "/" + getClass().getSimpleName() + "/"
+ + System.currentTimeMillis();
+ final String testRootPath = HTTP_BASE_URL + testRootPathBare;
+
+ // the root for our tests
+ testRootUrl = testClient.createNode(testRootPath, null);
+
+ // create the Resource Type "a" location
+ String rtA = testRootPathBare + "/a";
+ testClient.createNode(HTTP_BASE_URL + rtA, null);
+
+ // create the Resource Type "b" location
+ String rtB = testRootPathBare + "/b";
+ Map<String, String> props = new HashMap<String, String>();
+ props.put("sling:resourceSuperType", rtA);
+ testClient.createNode(HTTP_BASE_URL + rtB, props);
+
+ // create content node "x" of type rtB
+ String rtX = testRootPathBare + "/x";
+ props.clear();
+ props.put("sling:resourceType", rtB);
+ contentUrl = testClient.createNode(HTTP_BASE_URL + rtX, props);
+
+ // create content node "x/image" of type rtB
+ String rtXImage = rtX + "/image";
+ props.clear();
+ props.put("sling:resourceType", "nt:unstructured");
+ testClient.createNode(HTTP_BASE_URL + rtXImage, props);
+
+ uploadTestScript(rtA, "issues/sling457/a-foo.html.jsp", "foo.html.jsp");
+ uploadTestScript(rtB, "issues/sling457/b-b.jsp", "b.jsp");
+
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ testClient.delete(testRootUrl);
+ super.tearDown();
+ }
+
+ public void testCallFooHtml() throws Exception {
+ String url = contentUrl + ".foo.html";
+ String content = getContent(url, CONTENT_TYPE_HTML);
+ assertTrue("Expected 'foo.html.jsp' in content",
+ content.indexOf("foo.html.jsp") >= 0);
+ }
+
+ public void testCallHtml() throws Exception {
+ String url = contentUrl + ".html";
+ String content = getContent(url, CONTENT_TYPE_HTML);
+ assertTrue("Expected 'foo.html.jsp' in content",
+ content.indexOf("foo.html.jsp") >= 0);
+ }
+}
diff --git a/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/issues/SLING760Test.java b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/issues/SLING760Test.java
new file mode 100644
index 0000000..e558fc4
--- /dev/null
+++ b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/issues/SLING760Test.java
@@ -0,0 +1,56 @@
+/*
+ * 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.launchpad.webapp.integrationtest.issues;
+
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.sling.commons.testing.integration.HttpTestBase;
+
+public class SLING760Test extends HttpTestBase {
+ public static final String TEST_PATH = "/" + SLING760Test.class.getSimpleName();
+
+ /** Verify that all instances of our error message are escaped in response, which
+ * is generated by the default Sling error handler */
+ public void testEscapedErrorMessages() throws Exception {
+ final String [] mustContain = { "<characters/>", "filtered & escaped" };
+ final String [] mustNotContain = { "<characters/>", "filtered & escaped" };
+
+ final TestNode tn = new TestNode(HTTP_BASE_URL + TEST_PATH, null);
+
+ String toDelete = null;
+ try {
+ toDelete = uploadTestScript(tn.scriptPath, "issues/sling760/throw-with-markup.esp", "html.esp");
+ final String content = getContent(tn.nodeUrl + ".html", CONTENT_TYPE_HTML,
+ null, HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+
+ for(String str : mustContain) {
+ assertTrue("Content must contain " + str + " (" + content + ")", content.contains(str));
+ }
+
+ for(String str : mustNotContain) {
+ assertFalse("Content must NOT contain " + str + " (" + content + ")", content.contains(str));
+ }
+ } finally {
+ if (toDelete != null) {
+ testClient.delete(toDelete);
+ }
+ tn.delete();
+ }
+ }
+}
diff --git a/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/package.html b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/package.html
new file mode 100644
index 0000000..b4c0c84
--- /dev/null
+++ b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/package.html
@@ -0,0 +1,20 @@
+<html>
+<body>
+ <p>
+ The tests found in and under this package are used in the
+ "integration-test" build phase (SLING-82), they are not run
+ as part of the normal "test" build phase.
+ </p>
+ <p>
+ To debug the integration tests, however, it is useful to run
+ them as part of the normal test phase, after starting a separate
+ Sling instance that they can talk to.
+ </p>
+ <p>
+ This is implemented using Maven profiles: to run the integration
+ tests during the normal test phase, disable the "disableIntegrationTestsInTestPhase"
+ Maven profile, for example using <code>mvn -P nullUslingProfile test</code>.
+ See pom.xml for more details.
+ </p>
+</body>
+</html>
\ No newline at end of file
diff --git a/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/post/PostServletAtCopyTest.java b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/post/PostServletAtCopyTest.java
new file mode 100644
index 0000000..d1bfcfc
--- /dev/null
+++ b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/post/PostServletAtCopyTest.java
@@ -0,0 +1,199 @@
+/*
+ * 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.launchpad.webapp.integrationtest.servlets.post;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.sling.commons.testing.integration.HttpTestBase;
+
+/** Test item copy support by @CopyFrom suffix (SLING-455) */
+public class PostServletAtCopyTest extends HttpTestBase {
+
+ public static final String TEST_BASE_PATH = "/sling-at-copy-tests";
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
+ public void testCopyNodeAbsolute() throws IOException {
+ final String testPath = TEST_BASE_PATH + "/abs/" + System.currentTimeMillis();
+ Map<String, String> props = new HashMap<String, String>();
+ props.put("text", "Hello");
+ testClient.createNode(HTTP_BASE_URL + testPath + "/src", props);
+
+ // assert content at source location
+ final String oldContent = getContent(HTTP_BASE_URL + testPath + "/src.json", CONTENT_TYPE_JSON);
+ assertJavascript("Hello", oldContent, "out.println(data.text)");
+
+ // create dest with text set from src/text
+ props.clear();
+ props.put("src@CopyFrom", testPath + "/src");
+ testClient.createNode(HTTP_BASE_URL + testPath + "/dest", props);
+
+ // assert content at new location
+ String content = getContent(HTTP_BASE_URL + testPath + "/dest.-1.json", CONTENT_TYPE_JSON);
+ assertJavascript("Hello", content, "out.println(data.src.text)");
+
+ // assert content at old location
+ String contentOld = getContent(HTTP_BASE_URL + testPath + "/src.-1.json", CONTENT_TYPE_JSON);
+ assertJavascript("Hello", contentOld, "out.println(data.text)");
+ }
+
+ public void testCopyNodeRelative() throws IOException {
+ final String testPath = TEST_BASE_PATH + "/rel/" + System.currentTimeMillis();
+ Map<String, String> props = new HashMap<String, String>();
+ props.put("text", "Hello");
+ testClient.createNode(HTTP_BASE_URL + testPath + "/src", props);
+
+ // assert content at source location
+ final String oldContent = getContent(HTTP_BASE_URL + testPath + "/src.json", CONTENT_TYPE_JSON);
+ assertJavascript("Hello", oldContent, "out.println(data.text)");
+
+ // create dest with text set from src/text
+ props.clear();
+ props.put("src@CopyFrom", "../src");
+ testClient.createNode(HTTP_BASE_URL + testPath + "/dest", props);
+
+ // assert content at new location
+ String content = getContent(HTTP_BASE_URL + testPath + "/dest.-1.json", CONTENT_TYPE_JSON);
+ assertJavascript("Hello", content, "out.println(data.src.text)");
+
+ // assert content at old location
+ String contentOld = getContent(HTTP_BASE_URL + testPath + "/src.-1.json", CONTENT_TYPE_JSON);
+ assertJavascript("Hello", contentOld, "out.println(data.text)");
+ }
+
+ public void testCopyPropertyAbsolute() throws IOException {
+ final String testPath = TEST_BASE_PATH + "/abs/" + System.currentTimeMillis();
+ Map<String, String> props = new HashMap<String, String>();
+ props.put("text", "Hello");
+ testClient.createNode(HTTP_BASE_URL + testPath + "/src", props);
+
+ // assert content at source location
+ final String oldContent = getContent(HTTP_BASE_URL + testPath + "/src.json", CONTENT_TYPE_JSON);
+ assertJavascript("Hello", oldContent, "out.println(data.text)");
+
+ // create dest with text set from src/text
+ props.clear();
+ props.put("text@CopyFrom", testPath + "/src/text");
+ testClient.createNode(HTTP_BASE_URL + testPath + "/dest", props);
+
+ // assert content at new location
+ String content = getContent(HTTP_BASE_URL + testPath + "/dest.json", CONTENT_TYPE_JSON);
+ assertJavascript("Hello", content, "out.println(data.text)");
+
+ // assert content at old location
+ String contentOld = getContent(HTTP_BASE_URL + testPath + "/src.json", CONTENT_TYPE_JSON);
+ assertJavascript("Hello", contentOld, "out.println(data.text)");
+ }
+
+ public void testCopyPropertyRelative() throws IOException {
+ final String testPath = TEST_BASE_PATH + "/rel/" + System.currentTimeMillis();
+ Map<String, String> props = new HashMap<String, String>();
+ props.put("text", "Hello");
+ testClient.createNode(HTTP_BASE_URL + testPath + "/src", props);
+
+ // assert content at source location
+ final String oldContent = getContent(HTTP_BASE_URL + testPath + "/src.json", CONTENT_TYPE_JSON);
+ assertJavascript("Hello", oldContent, "out.println(data.text)");
+
+ // create dest with text set from src/text
+ props.clear();
+ props.put("text@CopyFrom", "../src/text");
+ testClient.createNode(HTTP_BASE_URL + testPath + "/dest", props);
+
+ // assert content at new location
+ String content = getContent(HTTP_BASE_URL + testPath + "/dest.json", CONTENT_TYPE_JSON);
+ assertJavascript("Hello", content, "out.println(data.text)");
+
+ // assert content at old location
+ String contentOld = getContent(HTTP_BASE_URL + testPath + "/src.json", CONTENT_TYPE_JSON);
+ assertJavascript("Hello", contentOld, "out.println(data.text)");
+ }
+
+ public void testCopyNodeSourceMissing() throws IOException {
+ final String testPath = TEST_BASE_PATH + "/exist/" + System.currentTimeMillis();
+ Map<String, String> props = new HashMap<String, String>();
+
+ // create dest node
+ props.clear();
+ props.put("text", "Hello Destination");
+ testClient.createNode(HTTP_BASE_URL + testPath + "/dest/src", props);
+
+ props.clear();
+ props.put("src@CopyFrom", testPath + "/non_existing_source");
+ testClient.createNode(HTTP_BASE_URL + testPath + "/dest", props);
+
+ // expect unmodified dest
+ String content = getContent(HTTP_BASE_URL + testPath + "/dest.-1.json", CONTENT_TYPE_JSON);
+ assertJavascript("Hello Destination", content, "out.println(data.src.text)");
+ }
+
+ public void testCopyNodeExistingReplace() throws IOException {
+ final String testPath = TEST_BASE_PATH + "/replace/" + System.currentTimeMillis();
+ Map<String, String> props = new HashMap<String, String>();
+ props.put("text", "Hello");
+ testClient.createNode(HTTP_BASE_URL + testPath + "/src", props);
+
+ // create dest node
+ props.clear();
+ props.put("text", "Hello Destination");
+ testClient.createNode(HTTP_BASE_URL + testPath + "/dest/src", props);
+
+ props.clear();
+ props.put("src@CopyFrom", "../src");
+ testClient.createNode(HTTP_BASE_URL + testPath + "/dest", props);
+
+ // expect unmodified dest
+ String content = getContent(HTTP_BASE_URL + testPath + "/dest.-1.json", CONTENT_TYPE_JSON);
+ assertJavascript("Hello", content, "out.println(data.src.text)");
+ }
+
+ public void testCopyNodeDeepRelative() throws IOException {
+ final String testPath = TEST_BASE_PATH + "/new/" + System.currentTimeMillis();
+ Map<String, String> props = new HashMap<String, String>();
+ props.put("text", "Hello");
+ testClient.createNode(HTTP_BASE_URL + testPath + "/src", props);
+
+ props.clear();
+ props.put("deep/new@CopyFrom", "../../src");
+ testClient.createNode(HTTP_BASE_URL + testPath + "/dest", props);
+
+ // expect new data
+ String content = getContent(HTTP_BASE_URL + testPath + "/dest.-1.json", CONTENT_TYPE_JSON);
+ assertJavascript("Hello", content, "out.println(data.deep['new'].text)");
+ }
+
+ public void testCopyNodeDeepAbsolute() throws IOException {
+ final String testPath = TEST_BASE_PATH + "/new_fail/" + System.currentTimeMillis();
+ Map<String, String> props = new HashMap<String, String>();
+ props.put("text", "Hello");
+ testClient.createNode(HTTP_BASE_URL + testPath + "/src", props);
+
+ props.clear();
+ props.put(testPath + "/some/not/existing/structure@CopyFrom", testPath + "/src");
+ testClient.createNode(HTTP_BASE_URL + testPath + "/*", props);
+
+ // expect new data
+ String content = getContent(HTTP_BASE_URL + testPath + "/some/not/existing/structure.json", CONTENT_TYPE_JSON);
+ assertJavascript("Hello", content, "out.println(data.text)");
+ }
+
+ }
\ No newline at end of file
diff --git a/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/post/PostServletAtDeleteTest.java b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/post/PostServletAtDeleteTest.java
new file mode 100644
index 0000000..f497602
--- /dev/null
+++ b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/post/PostServletAtDeleteTest.java
@@ -0,0 +1,111 @@
+/*
+ * 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.launchpad.webapp.integrationtest.servlets.post;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.httpclient.NameValuePair;
+import org.apache.sling.commons.json.JSONObject;
+import org.apache.sling.commons.testing.integration.HttpTestBase;
+import org.apache.sling.servlets.post.SlingPostConstants;
+
+/** Test support of @Delete suffix of SLING-458 */
+public class PostServletAtDeleteTest extends HttpTestBase {
+ public static final String TEST_BASE_PATH = "/sling-tests";
+
+ private static final String PROP_NAME = "text";
+ private static final String PROP_NAME2 = "title";
+
+ private static final String PROP_VALUE = "some value";
+ private static final String PROP_VALUE2 = "title value";
+
+ private String postUrl;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ postUrl = HTTP_BASE_URL + TEST_BASE_PATH + "/" + getClass().getSimpleName() + "/" + System.currentTimeMillis();
+
+ assertHttpStatus(postUrl, HttpServletResponse.SC_NOT_FOUND,
+ "Path must not exist before test: " + postUrl);
+ }
+
+ public void testDeleteOnly() throws Exception {
+ final Map<String, String> props = new HashMap<String, String>();
+ props.put(PROP_NAME, PROP_VALUE);
+ final String contentURL = testClient.createNode(postUrl + SlingPostConstants.DEFAULT_CREATE_SUFFIX, props);
+
+ try {
+ // assert property is set correctly
+ final String propURL = contentURL + "/" + PROP_NAME;
+ final String data = getContent(propURL + ".json", CONTENT_TYPE_JSON);
+ final JSONObject json = new JSONObject(data);
+ assertEquals(PROP_VALUE, json.get(PROP_NAME));
+
+ final List <NameValuePair> params = new LinkedList<NameValuePair> ();
+ params.add(new NameValuePair(PROP_NAME + SlingPostConstants.SUFFIX_DELETE, "don't care"));
+
+ assertPostStatus(contentURL, HttpServletResponse.SC_OK, params, PROP_NAME + " must be deleted");
+ assertHttpStatus(propURL, HttpServletResponse.SC_NOT_FOUND, PROP_NAME + " must be deleted");
+ } finally {
+ deleteNode(contentURL);
+ }
+ }
+
+ public void testDeleteWithModify() throws Exception {
+ final Map<String, String> props = new HashMap<String, String>();
+ props.put(PROP_NAME, PROP_VALUE);
+ final String contentURL = testClient.createNode(postUrl + SlingPostConstants.DEFAULT_CREATE_SUFFIX, props);
+
+ try {
+ // assert property is set correctly
+ final String propURL = contentURL + "/" + PROP_NAME;
+ final String data = getContent(propURL + ".json", CONTENT_TYPE_JSON);
+ final JSONObject json = new JSONObject(data);
+ assertEquals(PROP_VALUE, json.get(PROP_NAME));
+
+ final List <NameValuePair> params = new LinkedList<NameValuePair> ();
+ params.add(new NameValuePair(PROP_NAME + SlingPostConstants.SUFFIX_DELETE, "don't care"));
+ params.add(new NameValuePair(PROP_NAME2, PROP_VALUE2));
+
+ assertPostStatus(contentURL, HttpServletResponse.SC_OK, params, PROP_NAME + " must be deleted");
+ assertHttpStatus(propURL, HttpServletResponse.SC_NOT_FOUND, PROP_NAME + " must be deleted");
+ assertHttpStatus(contentURL + "/" + PROP_NAME2, HttpServletResponse.SC_OK, PROP_NAME2 + " must exist");
+
+ final String data2 = getContent(contentURL + ".json", CONTENT_TYPE_JSON);
+ final JSONObject json2 = new JSONObject(data2);
+ assertFalse(json2.has(PROP_VALUE));
+ assertEquals(PROP_VALUE2, json2.get(PROP_NAME2));
+
+ } finally {
+ deleteNode(contentURL);
+ }
+ }
+
+ protected void deleteNode(String nodeURL) throws IOException {
+ // delete one and check
+ final List <NameValuePair> params = new LinkedList<NameValuePair> ();
+ params.add(new NameValuePair(SlingPostConstants.RP_OPERATION, SlingPostConstants.OPERATION_DELETE));
+ assertPostStatus(nodeURL, HttpServletResponse.SC_OK, params, nodeURL + " must be deleted");
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/post/PostServletAtMoveTest.java b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/post/PostServletAtMoveTest.java
new file mode 100644
index 0000000..61e53d2
--- /dev/null
+++ b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/post/PostServletAtMoveTest.java
@@ -0,0 +1,209 @@
+/*
+ * 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.launchpad.webapp.integrationtest.servlets.post;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.sling.commons.testing.integration.HttpTestBase;
+
+/** Test item move support by @MoveFrom suffix (SLING-455) */
+public class PostServletAtMoveTest extends HttpTestBase {
+
+ public static final String TEST_BASE_PATH = "/sling-at-move-tests";
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
+ public void testMoveNodeAbsolute() throws IOException {
+ final String testPath = TEST_BASE_PATH + "/abs/" + System.currentTimeMillis();
+ Map<String, String> props = new HashMap<String, String>();
+ props.put("text", "Hello");
+ testClient.createNode(HTTP_BASE_URL + testPath + "/src", props);
+
+ // assert content at source location
+ final String oldContent = getContent(HTTP_BASE_URL + testPath + "/src.json", CONTENT_TYPE_JSON);
+ assertJavascript("Hello", oldContent, "out.println(data.text)");
+
+ // create dest with text set from src/text
+ props.clear();
+ props.put("src@MoveFrom", testPath + "/src");
+ testClient.createNode(HTTP_BASE_URL + testPath + "/dest", props);
+
+ // assert content at new location
+ String content = getContent(HTTP_BASE_URL + testPath + "/dest.-1.json", CONTENT_TYPE_JSON);
+ assertJavascript("Hello", content, "out.println(data.src.text)");
+
+ // assert no content at old location
+ assertHttpStatus(HTTP_BASE_URL + testPath + "/src.json",
+ HttpServletResponse.SC_NOT_FOUND,
+ "Expected Not_Found for old content");
+ }
+
+ public void testMoveNodeRelative() throws IOException {
+ final String testPath = TEST_BASE_PATH + "/rel/" + System.currentTimeMillis();
+ Map<String, String> props = new HashMap<String, String>();
+ props.put("text", "Hello");
+ testClient.createNode(HTTP_BASE_URL + testPath + "/src", props);
+
+ // assert content at source location
+ final String oldContent = getContent(HTTP_BASE_URL + testPath + "/src.json", CONTENT_TYPE_JSON);
+ assertJavascript("Hello", oldContent, "out.println(data.text)");
+
+ // create dest with text set from src/text
+ props.clear();
+ props.put("src@MoveFrom", "../src");
+ testClient.createNode(HTTP_BASE_URL + testPath + "/dest", props);
+
+ // assert content at new location
+ String content = getContent(HTTP_BASE_URL + testPath + "/dest.-1.json", CONTENT_TYPE_JSON);
+ assertJavascript("Hello", content, "out.println(data.src.text)");
+
+ // assert no content at old location
+ assertHttpStatus(HTTP_BASE_URL + testPath + "/src.json",
+ HttpServletResponse.SC_NOT_FOUND,
+ "Expected Not_Found for old content");
+ }
+
+ public void testMovePropertyAbsolute() throws IOException {
+ final String testPath = TEST_BASE_PATH + "/abs/" + System.currentTimeMillis();
+ Map<String, String> props = new HashMap<String, String>();
+ props.put("text", "Hello");
+ testClient.createNode(HTTP_BASE_URL + testPath + "/src", props);
+
+ // assert content at source location
+ final String oldContent = getContent(HTTP_BASE_URL + testPath + "/src.json", CONTENT_TYPE_JSON);
+ assertJavascript("Hello", oldContent, "out.println(data.text)");
+
+ // create dest with text set from src/text
+ props.clear();
+ props.put("text@MoveFrom", testPath + "/src/text");
+ testClient.createNode(HTTP_BASE_URL + testPath + "/dest", props);
+
+ // assert content at new location
+ String content = getContent(HTTP_BASE_URL + testPath + "/dest.json", CONTENT_TYPE_JSON);
+ assertJavascript("Hello", content, "out.println(data.text)");
+
+ // assert no content at old location
+ assertHttpStatus(HTTP_BASE_URL + testPath + "/src.json",
+ HttpServletResponse.SC_OK, "Expected source parent existing");
+ assertHttpStatus(HTTP_BASE_URL + testPath + "/src/text.json",
+ HttpServletResponse.SC_NOT_FOUND,
+ "Expected Not_Found for old content");
+ }
+
+ public void testMovePropertyRelative() throws IOException {
+ final String testPath = TEST_BASE_PATH + "/rel/" + System.currentTimeMillis();
+ Map<String, String> props = new HashMap<String, String>();
+ props.put("text", "Hello");
+ testClient.createNode(HTTP_BASE_URL + testPath + "/src", props);
+
+ // assert content at source location
+ final String oldContent = getContent(HTTP_BASE_URL + testPath + "/src.json", CONTENT_TYPE_JSON);
+ assertJavascript("Hello", oldContent, "out.println(data.text)");
+
+ // create dest with text set from src/text
+ props.clear();
+ props.put("text@MoveFrom", "../src/text");
+ testClient.createNode(HTTP_BASE_URL + testPath + "/dest", props);
+
+ // assert content at new location
+ String content = getContent(HTTP_BASE_URL + testPath + "/dest.json", CONTENT_TYPE_JSON);
+ assertJavascript("Hello", content, "out.println(data.text)");
+
+ // assert no content at old location
+ assertHttpStatus(HTTP_BASE_URL + testPath + "/src.json",
+ HttpServletResponse.SC_OK, "Expected source parent existing");
+ assertHttpStatus(HTTP_BASE_URL + testPath + "/src/text.json",
+ HttpServletResponse.SC_NOT_FOUND,
+ "Expected Not_Found for old content");
+ }
+
+ public void testMoveNodeSourceMissing() throws IOException {
+ final String testPath = TEST_BASE_PATH + "/exist/" + System.currentTimeMillis();
+ Map<String, String> props = new HashMap<String, String>();
+
+ // create dest node
+ props.clear();
+ props.put("text", "Hello Destination");
+ testClient.createNode(HTTP_BASE_URL + testPath + "/dest/src", props);
+
+ props.clear();
+ props.put("src@MoveFrom", testPath + "/non_existing_source");
+ testClient.createNode(HTTP_BASE_URL + testPath + "/dest", props);
+
+ // expect unmodified dest
+ String content = getContent(HTTP_BASE_URL + testPath + "/dest.-1.json", CONTENT_TYPE_JSON);
+ assertJavascript("Hello Destination", content, "out.println(data.src.text)");
+ }
+
+ public void testMoveNodeExistingReplace() throws IOException {
+ final String testPath = TEST_BASE_PATH + "/replace/" + System.currentTimeMillis();
+ Map<String, String> props = new HashMap<String, String>();
+ props.put("text", "Hello");
+ testClient.createNode(HTTP_BASE_URL + testPath + "/src", props);
+
+ // create dest node
+ props.clear();
+ props.put("text", "Hello Destination");
+ testClient.createNode(HTTP_BASE_URL + testPath + "/dest/src", props);
+
+ props.clear();
+ props.put("src@MoveFrom", "../src");
+ testClient.createNode(HTTP_BASE_URL + testPath + "/dest", props);
+
+ // expect unmodified dest
+ String content = getContent(HTTP_BASE_URL + testPath + "/dest.-1.json", CONTENT_TYPE_JSON);
+ assertJavascript("Hello", content, "out.println(data.src.text)");
+ }
+
+ public void testMoveNodeDeepRelative() throws IOException {
+ final String testPath = TEST_BASE_PATH + "/new/" + System.currentTimeMillis();
+ Map<String, String> props = new HashMap<String, String>();
+ props.put("text", "Hello");
+ testClient.createNode(HTTP_BASE_URL + testPath + "/src", props);
+
+ props.clear();
+ props.put("deep/new@MoveFrom", "../../src");
+ testClient.createNode(HTTP_BASE_URL + testPath + "/dest", props);
+
+ // expect new data
+ String content = getContent(HTTP_BASE_URL + testPath + "/dest.-1.json", CONTENT_TYPE_JSON);
+ assertJavascript("Hello", content, "out.println(data.deep['new'].text)");
+ }
+
+ public void testMoveNodeDeepAbsolute() throws IOException {
+ final String testPath = TEST_BASE_PATH + "/new_fail/" + System.currentTimeMillis();
+ Map<String, String> props = new HashMap<String, String>();
+ props.put("text", "Hello");
+ testClient.createNode(HTTP_BASE_URL + testPath + "/src", props);
+
+ props.clear();
+ props.put(testPath + "/some/not/existing/structure@MoveFrom", testPath + "/src");
+ testClient.createNode(HTTP_BASE_URL + testPath + "/*", props);
+
+ // expect new data
+ String content = getContent(HTTP_BASE_URL + testPath + "/some/not/existing/structure.json", CONTENT_TYPE_JSON);
+ assertJavascript("Hello", content, "out.println(data.text)");
+ }
+
+ }
\ No newline at end of file
diff --git a/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/post/PostServletCopyTest.java b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/post/PostServletCopyTest.java
new file mode 100644
index 0000000..c4cff8a
--- /dev/null
+++ b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/post/PostServletCopyTest.java
@@ -0,0 +1,445 @@
+/*
+ * 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.launchpad.webapp.integrationtest.servlets.post;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.httpclient.NameValuePair;
+import org.apache.sling.commons.json.JSONObject;
+import org.apache.sling.commons.testing.integration.HttpStatusCodeException;
+import org.apache.sling.commons.testing.integration.HttpTestBase;
+import org.apache.sling.servlets.post.SlingPostConstants;
+
+/** Test node copy via the MicrojaxPostServlet */
+public class PostServletCopyTest extends HttpTestBase {
+
+ public static final String TEST_BASE_PATH = "/sling-copy-tests";
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
+ public void testCopyNodeAbsolute() throws IOException {
+ final String testPath = TEST_BASE_PATH + "/abs/"
+ + System.currentTimeMillis();
+ Map<String, String> props = new HashMap<String, String>();
+ props.put("text", "Hello");
+ testClient.createNode(HTTP_BASE_URL + testPath + "/src", props);
+
+ props.clear();
+ props.put(SlingPostConstants.RP_OPERATION,
+ SlingPostConstants.OPERATION_COPY);
+ props.put(SlingPostConstants.RP_DEST, testPath + "/dest");
+ testClient.createNode(HTTP_BASE_URL + testPath + "/src", props);
+
+ // assert content at new location
+ String content = getContent(HTTP_BASE_URL + testPath + "/dest.json",
+ CONTENT_TYPE_JSON);
+ assertJavascript("Hello", content, "out.println(data.text)");
+
+ // assert content at old location
+ content = getContent(HTTP_BASE_URL + testPath + "/src.json",
+ CONTENT_TYPE_JSON);
+ assertJavascript("Hello", content, "out.println(data.text)");
+ }
+
+ public void testCopyNodeAbsoluteBelowDest() throws IOException {
+ final String testPath = TEST_BASE_PATH + "/abs/"
+ + System.currentTimeMillis();
+ Map<String, String> props = new HashMap<String, String>();
+ props.put("text", "Hello");
+ testClient.createNode(HTTP_BASE_URL + testPath + "/src", props);
+
+ // first test: failure because dest (parent) does not exist
+ 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/"));
+ assertPostStatus(HTTP_BASE_URL + testPath + "/src",
+ HttpServletResponse.SC_PRECONDITION_FAILED, nvPairs,
+ "Expecting Copy Failure (dest must exist)");
+
+ // create dest as parent
+ testClient.createNode(HTTP_BASE_URL + testPath + "/dest", null);
+
+ // copy now succeeds to below dest
+ assertPostStatus(HTTP_BASE_URL + testPath + "/src",
+ HttpServletResponse.SC_CREATED, nvPairs, "Expecting Copy Success");
+
+ // assert content at new location
+ String content = getContent(HTTP_BASE_URL + testPath + "/dest.-1.json",
+ CONTENT_TYPE_JSON);
+ assertJavascript("Hello", content, "out.println(data.src.text)");
+
+ // assert content at old location
+ content = getContent(HTTP_BASE_URL + testPath + "/src.json",
+ CONTENT_TYPE_JSON);
+ assertJavascript("Hello", content, "out.println(data.text)");
+ }
+
+ public void testCopyNodeRelative() throws IOException {
+ final String testPath = TEST_BASE_PATH + "/rel/"
+ + System.currentTimeMillis();
+ Map<String, String> props = new HashMap<String, String>();
+ props.put("text", "Hello");
+ testClient.createNode(HTTP_BASE_URL + testPath + "/src", props);
+
+ props.clear();
+ props.put(SlingPostConstants.RP_OPERATION,
+ SlingPostConstants.OPERATION_COPY);
+ props.put(SlingPostConstants.RP_DEST, "dest");
+ testClient.createNode(HTTP_BASE_URL + testPath + "/src", props);
+ String content = getContent(HTTP_BASE_URL + testPath + "/dest.json",
+ CONTENT_TYPE_JSON);
+ assertJavascript("Hello", content, "out.println(data.text)");
+ }
+
+ public void testCopyNodeExistingFail() throws IOException {
+ final String testPath = TEST_BASE_PATH + "/exist/"
+ + System.currentTimeMillis();
+ Map<String, String> props = new HashMap<String, String>();
+ props.put("text", "Hello");
+ testClient.createNode(HTTP_BASE_URL + testPath + "/src", props);
+
+ // create dest node
+ props.put("text", "Hello Destination");
+ testClient.createNode(HTTP_BASE_URL + testPath + "/dest", props);
+
+ props.clear();
+ props.put(SlingPostConstants.RP_OPERATION,
+ SlingPostConstants.OPERATION_COPY);
+ props.put(SlingPostConstants.RP_DEST, testPath + "/dest");
+ try {
+ testClient.createNode(HTTP_BASE_URL + testPath, props);
+ } catch (HttpStatusCodeException hsce) {
+ // if we do not get the status code 302 message, fail
+ if (hsce.getActualStatus() == 302) {
+ throw hsce;
+ }
+ }
+
+ // expect unmodified dest
+ String content = getContent(HTTP_BASE_URL + testPath + "/dest.json",
+ CONTENT_TYPE_JSON);
+ assertJavascript("Hello Destination", content, "out.println(data.text)");
+ }
+
+ public void testCopyNodeExistingReplace() throws IOException {
+ final String testPath = TEST_BASE_PATH + "/replace/"
+ + System.currentTimeMillis();
+ Map<String, String> props = new HashMap<String, String>();
+ props.put("text", "Hello");
+ testClient.createNode(HTTP_BASE_URL + testPath + "/src", props);
+
+ // create dest node
+ props.put("text", "Hello Destination");
+ testClient.createNode(HTTP_BASE_URL + testPath + "/dest", props);
+
+ props.clear();
+ props.put(SlingPostConstants.RP_OPERATION,
+ SlingPostConstants.OPERATION_COPY);
+ props.put(SlingPostConstants.RP_DEST, testPath + "/dest");
+ props.put(SlingPostConstants.RP_REPLACE, "true");
+ testClient.createNode(HTTP_BASE_URL + testPath + "/src", props);
+ String content = getContent(HTTP_BASE_URL + testPath + "/dest.json",
+ CONTENT_TYPE_JSON);
+ assertJavascript("Hello", content, "out.println(data.text)");
+ }
+
+ public void testCopyNodeDeepRelative() throws IOException {
+ final String testPath = TEST_BASE_PATH + "/new/"
+ + System.currentTimeMillis();
+ Map<String, String> props = new HashMap<String, String>();
+ props.put("text", "Hello");
+ testClient.createNode(HTTP_BASE_URL + testPath + "/src", props);
+
+ props.clear();
+ props.put(SlingPostConstants.RP_OPERATION,
+ SlingPostConstants.OPERATION_COPY);
+ props.put(SlingPostConstants.RP_DEST, "deep/new");
+
+ try {
+ testClient.createNode(HTTP_BASE_URL + testPath + "/src", props);
+ fail("Moving node to non existing parent location should fail.");
+ } catch (HttpStatusCodeException hsce) {
+ // actually the status is not 200, but we get "browser" clear stati
+ if (hsce.getActualStatus() != 200) {
+ throw hsce;
+ }
+ }
+ }
+
+ public void testCopyNodeDeepAbsolute() throws IOException {
+ final String testPath = TEST_BASE_PATH + "/new_fail/"
+ + System.currentTimeMillis();
+ Map<String, String> props = new HashMap<String, String>();
+ props.put("text", "Hello");
+ testClient.createNode(HTTP_BASE_URL + testPath + "/src", props);
+
+ props.clear();
+ props.put(SlingPostConstants.RP_OPERATION,
+ SlingPostConstants.OPERATION_COPY);
+ props.put(SlingPostConstants.RP_DEST, "/some/not/existing/structure");
+ try {
+ testClient.createNode(HTTP_BASE_URL + testPath + "/*", props);
+ // not quite correct. should check status response
+ fail("Moving node to non existing parent location should fail.");
+ } catch (HttpStatusCodeException hsce) {
+ // actually the status is not 200, but we get "browser" clear stati
+ if (hsce.getActualStatus() != 200) {
+ throw hsce;
+ }
+ }
+ }
+
+ public void testCopyNodeMultipleSourceValid() throws IOException {
+ final String testPath = TEST_BASE_PATH + "/cpmult/"
+ + 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 + "/src1", props);
+ testClient.createNode(HTTP_BASE_URL + testPath + "/src2", props);
+ testClient.createNode(HTTP_BASE_URL + testPath + "/src3", props);
+ testClient.createNode(HTTP_BASE_URL + testPath + "/src4", 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, testPath
+ + "/src1"));
+ nvPairs.add(new NameValuePair(SlingPostConstants.RP_APPLY_TO, testPath
+ + "/src2"));
+ nvPairs.add(new NameValuePair(SlingPostConstants.RP_APPLY_TO, testPath
+ + "/src3"));
+ nvPairs.add(new NameValuePair(SlingPostConstants.RP_APPLY_TO, testPath
+ + "/src4"));
+ assertPostStatus(testRoot, HttpServletResponse.SC_PRECONDITION_FAILED,
+ nvPairs, "Expecting Copy Failure: dest parent does not exist");
+
+ // create destination parent
+ testClient.createNode(HTTP_BASE_URL + testPath + "/dest", props);
+
+ // now dest exists, so 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);
+ }
+
+ public void testCopyNodeMultipleSourceInValid() throws IOException {
+ final String testPath = TEST_BASE_PATH + "/cpmult/"
+ + 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 + "/src1", props);
+ testClient.createNode(HTTP_BASE_URL + testPath + "/src2", props);
+ testClient.createNode(HTTP_BASE_URL + testPath + "/src3", props);
+ testClient.createNode(HTTP_BASE_URL + testPath + "/src4", 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, testPath
+ + "/src1"));
+ nvPairs.add(new NameValuePair(SlingPostConstants.RP_APPLY_TO, testPath
+ + "/src2"));
+ nvPairs.add(new NameValuePair(SlingPostConstants.RP_APPLY_TO, testPath
+ + "/src3"));
+ nvPairs.add(new NameValuePair(SlingPostConstants.RP_APPLY_TO, testPath
+ + "/src4"));
+ assertPostStatus(testRoot,
+ HttpServletResponse.SC_INTERNAL_SERVER_ERROR, nvPairs,
+ "Expecting Copy Failure (dest must have trailing slash)");
+
+ // create destination parent
+ testClient.createNode(HTTP_BASE_URL + testPath + "/dest", props);
+
+ // retest after creating test
+ assertPostStatus(testRoot, HttpServletResponse.SC_PRECONDITION_FAILED,
+ nvPairs, "Expecting Copy Failure (dest already exists)");
+
+ // assert non-existence of the src?/text properties
+ assertHttpStatus(HTTP_BASE_URL + testPath + "/dest/src1/text",
+ HttpServletResponse.SC_NOT_FOUND);
+ assertHttpStatus(HTTP_BASE_URL + testPath + "/dest/src2/text",
+ HttpServletResponse.SC_NOT_FOUND);
+ assertHttpStatus(HTTP_BASE_URL + testPath + "/dest/src3/text",
+ HttpServletResponse.SC_NOT_FOUND);
+ assertHttpStatus(HTTP_BASE_URL + testPath + "/dest/src4/text",
+ HttpServletResponse.SC_NOT_FOUND);
+
+ testClient.delete(testRoot);
+ }
+
+ public void testCopyNodeMultipleSourcePartial() throws IOException {
+ final String testPath = TEST_BASE_PATH + "/cpmult/"
+ + 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 + "/src1", props);
+ testClient.createNode(HTTP_BASE_URL + testPath + "/src3", 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, testPath
+ + "/src1"));
+ nvPairs.add(new NameValuePair(SlingPostConstants.RP_APPLY_TO, testPath
+ + "/src2"));
+ nvPairs.add(new NameValuePair(SlingPostConstants.RP_APPLY_TO, testPath
+ + "/src3"));
+ nvPairs.add(new NameValuePair(SlingPostConstants.RP_APPLY_TO, testPath
+ + "/src4"));
+ assertPostStatus(testRoot, HttpServletResponse.SC_PRECONDITION_FAILED,
+ nvPairs, "Expecting Copy Failure: dest parent does not exist");
+
+ // create destination parent
+ testClient.createNode(HTTP_BASE_URL + testPath + "/dest", props);
+
+ // now dest exists, so we expect success
+ assertPostStatus(testRoot, HttpServletResponse.SC_OK, nvPairs,
+ "Expecting Copy Success");
+
+ // assert partial 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_NOT_FOUND);
+ assertHttpStatus(HTTP_BASE_URL + testPath + "/dest/src3/text",
+ HttpServletResponse.SC_OK);
+ assertHttpStatus(HTTP_BASE_URL + testPath + "/dest/src4/text",
+ HttpServletResponse.SC_NOT_FOUND);
+
+ testClient.delete(testRoot);
+ }
+
+ public void testCopyNodeMultipleSourceReplace() throws Exception {
+ final String testPath = TEST_BASE_PATH + "/cpmult/"
+ + 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 + "/src1", props);
+ testClient.createNode(HTTP_BASE_URL + testPath + "/src2", 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, testPath
+ + "/src1"));
+ nvPairs.add(new NameValuePair(SlingPostConstants.RP_APPLY_TO, testPath
+ + "/src2"));
+ assertPostStatus(testRoot, HttpServletResponse.SC_PRECONDITION_FAILED,
+ nvPairs, "Expecting Copy Failure: dest parent does not exist");
+
+ // create destination parent
+ testClient.createNode(HTTP_BASE_URL + testPath + "/dest", null);
+
+ // now dest exists, so we expect success
+ assertPostStatus(testRoot, HttpServletResponse.SC_OK, nvPairs,
+ "Expecting Copy Success");
+
+ // assert partial 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_NOT_FOUND);
+ assertHttpStatus(HTTP_BASE_URL + testPath + "/dest/src4/text",
+ HttpServletResponse.SC_NOT_FOUND);
+
+ // assert content test
+ String content = getContent(HTTP_BASE_URL + testPath
+ + "/dest/src1.json", CONTENT_TYPE_JSON);
+ JSONObject json = new JSONObject(content);
+ assertEquals("Hello", json.get("text"));
+
+ // modify src1 content
+ nvPairs.clear();
+ nvPairs.add(new NameValuePair("text", "Modified Hello"));
+ assertPostStatus(HTTP_BASE_URL + testPath + "/src1",
+ HttpServletResponse.SC_OK, nvPairs, "Expect Content Update Success");
+
+ // copy the src? nodes
+ nvPairs.clear();
+ 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, testPath
+ + "/src1"));
+ nvPairs.add(new NameValuePair(SlingPostConstants.RP_APPLY_TO, testPath
+ + "/src2"));
+ assertPostStatus(testRoot, HttpServletResponse.SC_OK, nvPairs,
+ "Expecting Copy Success");
+
+ // assert content test
+ String content2 = getContent(HTTP_BASE_URL + testPath
+ + "/dest/src1.json", CONTENT_TYPE_JSON);
+ JSONObject json2 = new JSONObject(content2);
+ assertEquals("Modified Hello", json2.get("text"));
+
+ // clean up
+ testClient.delete(testRoot);
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/post/PostServletCreateTest.java b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/post/PostServletCreateTest.java
new file mode 100644
index 0000000..b6ed3aa
--- /dev/null
+++ b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/post/PostServletCreateTest.java
@@ -0,0 +1,139 @@
+/*
+ * 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.launchpad.webapp.integrationtest.servlets.post;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.sling.commons.testing.integration.HttpTestBase;
+import org.apache.sling.servlets.post.SlingPostConstants;
+
+/** Test node creation via the MicrojaxPostServlet */
+public class PostServletCreateTest extends HttpTestBase {
+ public static final String TEST_BASE_PATH = "/sling-tests";
+ private String postUrl;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ postUrl = HTTP_BASE_URL + TEST_BASE_PATH + "/" + System.currentTimeMillis();
+ }
+
+ public void testPostPathIsUnique() throws IOException {
+ assertHttpStatus(postUrl, HttpServletResponse.SC_NOT_FOUND,
+ "Path must not exist before test: " + postUrl);
+ }
+
+ public void testCreateNode() throws IOException {
+ final String location = testClient.createNode(postUrl + SlingPostConstants.DEFAULT_CREATE_SUFFIX, null);
+ assertHttpStatus(location + DEFAULT_EXT, HttpServletResponse.SC_OK,
+ "POST must redirect to created resource (" + location + ")");
+ assertTrue("Node (" + location + ") must have generated name",
+ !location.endsWith("/*"));
+ assertTrue("Node (" + location + ") must created be under POST URL (" + postUrl + ")",
+ location.contains(postUrl + "/"));
+ }
+
+ public void testCreateNodeWithExtension() throws IOException {
+ final String location = testClient.createNode(postUrl + SlingPostConstants.DEFAULT_CREATE_SUFFIX + ".html", null);
+ assertHttpStatus(location + DEFAULT_EXT, HttpServletResponse.SC_OK,
+ "POST must redirect to created resource (" + location + ")");
+ assertTrue("Node (" + location + ") must have generated name",
+ !location.endsWith("/*"));
+ assertTrue("Node (" + location + ") must created be under POST URL (" + postUrl + ")",
+ location.contains(postUrl + "/"));
+ }
+
+ public void testCreateNodeAtSpecificUrl() throws IOException {
+ final String specifiedLocation = postUrl + "/specified-location";
+ final String location = testClient.createNode(specifiedLocation, null);
+ assertHttpStatus(location + DEFAULT_EXT, HttpServletResponse.SC_OK,
+ "POST must redirect to created resource (" + location + ")");
+ assertTrue("Node (" + location + ") must be created at given URL (" + specifiedLocation + ")",
+ location.equals(specifiedLocation));
+ }
+
+ public void testCreateNodeAtDeepUrl() throws IOException {
+ final long id = System.currentTimeMillis();
+ final String specifiedLocation = postUrl + "/specified-location" + id + "/deepA/deepB/" + id;
+ final String location = testClient.createNode(specifiedLocation, null);
+ assertHttpStatus(location + DEFAULT_EXT, HttpServletResponse.SC_OK,
+ "POST must redirect to created resource (" + location + ")");
+ assertTrue("Node (" + location + ") must be created (deep) at given URL (" + specifiedLocation + ")",
+ location.equals(specifiedLocation));
+ }
+
+ /** Create a node with some data, and check that data */
+ public void testCreateWithData() throws IOException {
+ final Map <String, String> props = new HashMap <String, String> ();
+ props.put("a","123");
+ props.put("b","456");
+ props.put("c","some words");
+ final String createdNodeUrl = testClient.createNode(postUrl + SlingPostConstants.DEFAULT_CREATE_SUFFIX, props);
+ final String content = getContent(createdNodeUrl + ".json", CONTENT_TYPE_JSON);
+ assertJavascript("123456", content, "out.println(data.a + data.b)");
+ assertJavascript("some words", content, "out.println(data.c)");
+ }
+
+ /** Create a node with a propery in a subnode, and check (SLING-223) */
+ public void testCreateSubnodeProperty() throws IOException {
+ final Map <String, String> props = new HashMap <String, String> ();
+ props.put("a","123");
+ props.put("subnode/b","456");
+ props.put("c","some words");
+ final String createdNodeUrl = testClient.createNode(postUrl + SlingPostConstants.DEFAULT_CREATE_SUFFIX, props);
+ final String content = getContent(createdNodeUrl + ".2.json", CONTENT_TYPE_JSON);
+ assertJavascript("123", content, "out.println(data.a)");
+ assertJavascript("456", content, "out.println(data.subnode.b)");
+ assertJavascript("some words", content, "out.println(data.c)");
+ }
+
+ /** Use the default "save prefix" on some parameters, and check that only those
+ * who have the prefix are saved.
+ */
+ public void testDefaultSavePrefix() throws IOException {
+ final Map <String, String> props = new HashMap <String, String> ();
+ props.put("./a","123");
+ props.put("./b","456");
+ props.put("c","not saved");
+ final String createdNodeUrl = testClient.createNode(postUrl + SlingPostConstants.DEFAULT_CREATE_SUFFIX, props);
+ final String content = getContent(createdNodeUrl + ".json", CONTENT_TYPE_JSON);
+ assertJavascript("123456", content, "out.println(data.a + data.b)");
+ assertJavascript("undefined", content, "out.println(typeof data.c)");
+ }
+
+ /** SLING-394 removed :saveParamPrefix support. We check whether this is
+ * really ignored
+ */
+ public void testCustomSavePrefix() throws IOException {
+ final Map <String, String> props = new HashMap <String, String> ();
+ props.put("STUFF_a","123");
+ props.put("STUFF_b","456");
+ props.put("c","not saved");
+ props.put(":saveParamPrefix","STUFF_");
+ final String createdNodeUrl = testClient.createNode(postUrl + SlingPostConstants.DEFAULT_CREATE_SUFFIX, props,null,false);
+ final String content = getContent(createdNodeUrl + ".json", CONTENT_TYPE_JSON);
+ assertJavascript("undefined", content, "out.println(typeof data.a)");
+ assertJavascript("undefined", content, "out.println(typeof data.b)");
+ assertJavascript("123456", content, "out.println(data.STUFF_a + data.STUFF_b)");
+ assertJavascript("string", content, "out.println(typeof data.c)");
+ }
+
+ }
\ No newline at end of file
diff --git a/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/post/PostServletDeleteTest.java b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/post/PostServletDeleteTest.java
new file mode 100644
index 0000000..b627886
--- /dev/null
+++ b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/post/PostServletDeleteTest.java
@@ -0,0 +1,113 @@
+/*
+ * 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.launchpad.webapp.integrationtest.servlets.post;
+
+import java.io.IOException;
+import java.util.LinkedList;
+import java.util.List;
+
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.httpclient.NameValuePair;
+import org.apache.sling.commons.testing.integration.HttpTestBase;
+import org.apache.sling.servlets.post.SlingPostConstants;
+
+/** Test node deletion via the MicrojaxPostServlet */
+public class PostServletDeleteTest extends HttpTestBase {
+ public static final String TEST_BASE_PATH = "/sling-tests";
+ private String postUrl;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ postUrl = HTTP_BASE_URL + TEST_BASE_PATH + "/" + getClass().getSimpleName() + "/" + System.currentTimeMillis();
+
+ assertHttpStatus(postUrl, HttpServletResponse.SC_NOT_FOUND,
+ "Path must not exist before test: " + postUrl);
+ }
+
+ public void testDelete() 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 one and check
+ final List <NameValuePair> params = new LinkedList<NameValuePair> ();
+ params.add(new NameValuePair(SlingPostConstants.RP_OPERATION, SlingPostConstants.OPERATION_DELETE));
+ assertPostStatus(urlA,HttpServletResponse.SC_OK,params,"Delete must return expected status (3)");
+ assertHttpStatus(urlA + DEFAULT_EXT, HttpServletResponse.SC_NOT_FOUND, "A must be deleted (1)");
+ assertHttpStatus(urlB + DEFAULT_EXT, HttpServletResponse.SC_OK, "B must still exist");
+ assertHttpStatus(urlC + DEFAULT_EXT, HttpServletResponse.SC_OK, "C must still exist");
+ assertHttpStatus(urlD + DEFAULT_EXT, HttpServletResponse.SC_OK, "D must still exist");
+
+ // delete the others with successive requests
+ assertPostStatus(urlB,HttpServletResponse.SC_OK,params,"Delete must return expected status (2)");
+ assertPostStatus(urlC,HttpServletResponse.SC_OK,params,"Delete must return expected status (2)");
+ assertPostStatus(urlD,HttpServletResponse.SC_OK,params,"Delete must return expected status (2)");
+ assertHttpStatus(urlA + DEFAULT_EXT, HttpServletResponse.SC_NOT_FOUND, "A must be deleted (2)");
+ assertHttpStatus(urlB + DEFAULT_EXT, HttpServletResponse.SC_NOT_FOUND, "B must be deleted (2)");
+ 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)");
+
+ // attempting to delete non-existing nodes is ok
+ assertPostStatus(postUrl,HttpServletResponse.SC_OK,params,"Delete must return expected status (2)");
+ }
+
+ public void testDeleteMultiple() 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 one 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, urlA.substring(HTTP_BASE_URL.length())));
+ params.add(new NameValuePair(SlingPostConstants.RP_APPLY_TO, urlB.substring(HTTP_BASE_URL.length())));
+ assertPostStatus(urlC,HttpServletResponse.SC_OK,params,"Delete must return expected status (3)");
+ assertHttpStatus(urlA + DEFAULT_EXT, HttpServletResponse.SC_NOT_FOUND, "A must be deleted (1)");
+ assertHttpStatus(urlB + DEFAULT_EXT, HttpServletResponse.SC_NOT_FOUND, "B must be deleted (1)");
+ assertHttpStatus(urlC + DEFAULT_EXT, HttpServletResponse.SC_OK, "C must still exist");
+ assertHttpStatus(urlD + DEFAULT_EXT, HttpServletResponse.SC_OK, "D must still exist");
+
+ // delete the others with successive requests
+ params.clear();
+ params.add(new NameValuePair(SlingPostConstants.RP_OPERATION, SlingPostConstants.OPERATION_DELETE));
+ params.add(new NameValuePair(SlingPostConstants.RP_APPLY_TO, urlA.substring(HTTP_BASE_URL.length())));
+ params.add(new NameValuePair(SlingPostConstants.RP_APPLY_TO, urlB.substring(HTTP_BASE_URL.length())));
+ params.add(new NameValuePair(SlingPostConstants.RP_APPLY_TO, urlC.substring(HTTP_BASE_URL.length())));
+ params.add(new NameValuePair(SlingPostConstants.RP_APPLY_TO, urlD.substring(HTTP_BASE_URL.length())));
+ assertPostStatus(urlC,HttpServletResponse.SC_OK,params,"Delete must return expected status (3)");
+ assertHttpStatus(urlA + DEFAULT_EXT, HttpServletResponse.SC_NOT_FOUND, "A must be deleted (2)");
+ assertHttpStatus(urlB + DEFAULT_EXT, HttpServletResponse.SC_NOT_FOUND, "B must be deleted (2)");
+ 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)");
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/post/PostServletMoveTest.java b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/post/PostServletMoveTest.java
new file mode 100644
index 0000000..be993ef
--- /dev/null
+++ b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/post/PostServletMoveTest.java
@@ -0,0 +1,476 @@
+/*
+ * 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.launchpad.webapp.integrationtest.servlets.post;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.httpclient.NameValuePair;
+import org.apache.sling.commons.json.JSONObject;
+import org.apache.sling.commons.testing.integration.HttpStatusCodeException;
+import org.apache.sling.commons.testing.integration.HttpTestBase;
+import org.apache.sling.servlets.post.SlingPostConstants;
+
+/** Test node move via the MicrojaxPostServlet */
+public class PostServletMoveTest extends HttpTestBase {
+
+ public static final String TEST_BASE_PATH = "/sling-move-tests";
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
+ public void testMoveNodeAbsolute() throws IOException {
+ final String testPath = TEST_BASE_PATH + "/abs/"
+ + System.currentTimeMillis();
+ Map<String, String> props = new HashMap<String, String>();
+ props.put("text", "Hello");
+ testClient.createNode(HTTP_BASE_URL + testPath + "/src", props);
+
+ props.clear();
+ props.put(SlingPostConstants.RP_OPERATION,
+ SlingPostConstants.OPERATION_MOVE);
+ props.put(SlingPostConstants.RP_DEST, testPath + "/dest");
+ testClient.createNode(HTTP_BASE_URL + testPath + "/src", props);
+
+ // assert content at new location
+ String content = getContent(HTTP_BASE_URL + testPath + "/dest.json",
+ CONTENT_TYPE_JSON);
+ assertJavascript("Hello", content, "out.println(data.text)");
+
+ // assert no content at old location
+ assertHttpStatus(HTTP_BASE_URL + testPath + "/src.json",
+ HttpServletResponse.SC_NOT_FOUND,
+ "Expected Not_Found for old content");
+ }
+
+ public void testMoveNodeAbsoluteBelowDest() throws IOException {
+ final String testPath = TEST_BASE_PATH + "/abs/"
+ + System.currentTimeMillis();
+ Map<String, String> props = new HashMap<String, String>();
+ props.put("text", "Hello");
+ testClient.createNode(HTTP_BASE_URL + testPath + "/src", props);
+
+ // first test: failure because dest (parent) does not exist
+ 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/"));
+ assertPostStatus(HTTP_BASE_URL + testPath + "/src",
+ HttpServletResponse.SC_PRECONDITION_FAILED, nvPairs,
+ "Expecting Move Failure (dest must exist)");
+
+ // create dest as parent
+ testClient.createNode(HTTP_BASE_URL + testPath + "/dest", null);
+
+ // move now succeeds to below dest
+ assertPostStatus(HTTP_BASE_URL + testPath + "/src",
+ HttpServletResponse.SC_CREATED, nvPairs, "Expecting Move Success");
+
+ // assert content at new location
+ String content = getContent(HTTP_BASE_URL + testPath + "/dest.-1.json",
+ CONTENT_TYPE_JSON);
+ assertJavascript("Hello", content, "out.println(data.src.text)");
+
+ // assert content at old location
+ assertHttpStatus(HTTP_BASE_URL + testPath + "/src.json",
+ HttpServletResponse.SC_NOT_FOUND);
+ }
+
+ public void testMoveNodeRelative() throws IOException {
+ final String testPath = TEST_BASE_PATH + "/rel/"
+ + System.currentTimeMillis();
+ Map<String, String> props = new HashMap<String, String>();
+ props.put("text", "Hello");
+ testClient.createNode(HTTP_BASE_URL + testPath + "/src", props);
+
+ props.clear();
+ props.put(SlingPostConstants.RP_OPERATION,
+ SlingPostConstants.OPERATION_MOVE);
+ props.put(SlingPostConstants.RP_DEST, "dest");
+ testClient.createNode(HTTP_BASE_URL + testPath + "/src", props);
+ String content = getContent(HTTP_BASE_URL + testPath + "/dest.json",
+ CONTENT_TYPE_JSON);
+ assertJavascript("Hello", content, "out.println(data.text)");
+ }
+
+ public void testMoveNodeExistingFail() throws IOException {
+ final String testPath = TEST_BASE_PATH + "/exist/"
+ + System.currentTimeMillis();
+ Map<String, String> props = new HashMap<String, String>();
+ props.put("text", "Hello");
+ testClient.createNode(HTTP_BASE_URL + testPath + "/src", props);
+
+ // create dest node
+ props.put("text", "Hello Destination");
+ testClient.createNode(HTTP_BASE_URL + testPath + "/dest", props);
+
+ props.clear();
+ props.put(SlingPostConstants.RP_OPERATION,
+ SlingPostConstants.OPERATION_MOVE);
+ props.put(SlingPostConstants.RP_DEST, testPath + "/dest");
+ try {
+ testClient.createNode(HTTP_BASE_URL + testPath, props);
+ } catch (HttpStatusCodeException hsce) {
+ // if we do not get the status code 302 message, fail
+ if (hsce.getActualStatus() == 302) {
+ throw hsce;
+ }
+ }
+
+ // expect unmodified dest
+ String content = getContent(HTTP_BASE_URL + testPath + "/dest.json",
+ CONTENT_TYPE_JSON);
+ assertJavascript("Hello Destination", content, "out.println(data.text)");
+ }
+
+ public void testMoveNodeExistingReplace() throws IOException {
+ final String testPath = TEST_BASE_PATH + "/replace/"
+ + System.currentTimeMillis();
+ Map<String, String> props = new HashMap<String, String>();
+ props.put("text", "Hello");
+ testClient.createNode(HTTP_BASE_URL + testPath + "/src", props);
+
+ // create dest node
+ props.put("text", "Hello Destination");
+ testClient.createNode(HTTP_BASE_URL + testPath + "/dest", props);
+
+ props.clear();
+ props.put(SlingPostConstants.RP_OPERATION,
+ SlingPostConstants.OPERATION_MOVE);
+ props.put(SlingPostConstants.RP_DEST, testPath + "/dest");
+ props.put(SlingPostConstants.RP_REPLACE, "true");
+ testClient.createNode(HTTP_BASE_URL + testPath + "/src", props);
+ String content = getContent(HTTP_BASE_URL + testPath + "/dest.json",
+ CONTENT_TYPE_JSON);
+ assertJavascript("Hello", content, "out.println(data.text)");
+ }
+
+ public void testMoveNodeDeepRelative() throws IOException {
+ final String testPath = TEST_BASE_PATH + "/new/"
+ + System.currentTimeMillis();
+ Map<String, String> props = new HashMap<String, String>();
+ props.put("text", "Hello");
+ testClient.createNode(HTTP_BASE_URL + testPath + "/src", props);
+
+ props.clear();
+ props.put(SlingPostConstants.RP_OPERATION,
+ SlingPostConstants.OPERATION_MOVE);
+ props.put(SlingPostConstants.RP_DEST, "deep/new");
+
+ try {
+ testClient.createNode(HTTP_BASE_URL + testPath + "/src", props);
+ fail("Moving node to non existing parent location should fail.");
+ } catch (HttpStatusCodeException hsce) {
+ // actually the status is not 200, but we get "browser" clear stati
+ if (hsce.getActualStatus() != 200) {
+ throw hsce;
+ }
+ }
+ }
+
+ public void testMoveNodeDeepAbsolute() throws IOException {
+ final String testPath = TEST_BASE_PATH + "/new_fail/"
+ + System.currentTimeMillis();
+ Map<String, String> props = new HashMap<String, String>();
+ props.put("text", "Hello");
+ testClient.createNode(HTTP_BASE_URL + testPath + "/src", props);
+
+ props.clear();
+ props.put(SlingPostConstants.RP_OPERATION,
+ SlingPostConstants.OPERATION_MOVE);
+ props.put(SlingPostConstants.RP_DEST, "/some/not/existing/structure");
+ try {
+ testClient.createNode(HTTP_BASE_URL + testPath + "/*", props);
+ // not quite correct. should check status response
+ fail("Moving node to non existing parent location should fail.");
+ } catch (HttpStatusCodeException hsce) {
+ // actually the status is not 200, but we get "browser" clear stati
+ if (hsce.getActualStatus() != 200) {
+ throw hsce;
+ }
+ }
+ }
+
+ public void testMoveNodeMultipleSourceValid() throws IOException {
+ final String testPath = TEST_BASE_PATH + "/mvmult/"
+ + 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 + "/src1", props);
+ testClient.createNode(HTTP_BASE_URL + testPath + "/src2", props);
+ testClient.createNode(HTTP_BASE_URL + testPath + "/src3", props);
+ testClient.createNode(HTTP_BASE_URL + testPath + "/src4", 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, testPath
+ + "/src1"));
+ nvPairs.add(new NameValuePair(SlingPostConstants.RP_APPLY_TO, testPath
+ + "/src2"));
+ nvPairs.add(new NameValuePair(SlingPostConstants.RP_APPLY_TO, testPath
+ + "/src3"));
+ nvPairs.add(new NameValuePair(SlingPostConstants.RP_APPLY_TO, testPath
+ + "/src4"));
+ assertPostStatus(testRoot, HttpServletResponse.SC_PRECONDITION_FAILED,
+ nvPairs, "Expecting Move Failure: dest parent does not exist");
+
+ // create destination parent
+ testClient.createNode(HTTP_BASE_URL + testPath + "/dest", props);
+
+ // now dest exists, so 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 + "/src1.html",
+ HttpServletResponse.SC_NOT_FOUND);
+ assertHttpStatus(HTTP_BASE_URL + testPath + "/src2.html",
+ HttpServletResponse.SC_NOT_FOUND);
+ assertHttpStatus(HTTP_BASE_URL + testPath + "/src3.html",
+ HttpServletResponse.SC_NOT_FOUND);
+ assertHttpStatus(HTTP_BASE_URL + testPath + "/src4.html",
+ HttpServletResponse.SC_NOT_FOUND);
+
+ testClient.delete(testRoot);
+ }
+
+ public void testMoveNodeMultipleSourceInValid() throws IOException {
+ final String testPath = TEST_BASE_PATH + "/mvmult/"
+ + 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 + "/src1", props);
+ testClient.createNode(HTTP_BASE_URL + testPath + "/src2", props);
+ testClient.createNode(HTTP_BASE_URL + testPath + "/src3", props);
+ testClient.createNode(HTTP_BASE_URL + testPath + "/src4", 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, testPath
+ + "/src1"));
+ nvPairs.add(new NameValuePair(SlingPostConstants.RP_APPLY_TO, testPath
+ + "/src2"));
+ nvPairs.add(new NameValuePair(SlingPostConstants.RP_APPLY_TO, testPath
+ + "/src3"));
+ nvPairs.add(new NameValuePair(SlingPostConstants.RP_APPLY_TO, testPath
+ + "/src4"));
+ assertPostStatus(testRoot,
+ HttpServletResponse.SC_INTERNAL_SERVER_ERROR, nvPairs,
+ "Expecting Move Failure (dest must have trailing slash)");
+
+ // create destination parent
+ testClient.createNode(HTTP_BASE_URL + testPath + "/dest", props);
+
+ // retest after creating test
+ assertPostStatus(testRoot, HttpServletResponse.SC_PRECONDITION_FAILED,
+ nvPairs, "Expecting Move Failure (dest already exists)");
+
+ // assert non-existence of the src?/text properties
+ assertHttpStatus(HTTP_BASE_URL + testPath + "/dest/src1/text",
+ HttpServletResponse.SC_NOT_FOUND);
+ assertHttpStatus(HTTP_BASE_URL + testPath + "/dest/src2/text",
+ HttpServletResponse.SC_NOT_FOUND);
+ assertHttpStatus(HTTP_BASE_URL + testPath + "/dest/src3/text",
+ HttpServletResponse.SC_NOT_FOUND);
+ assertHttpStatus(HTTP_BASE_URL + testPath + "/dest/src4/text",
+ HttpServletResponse.SC_NOT_FOUND);
+
+ // assert non-existence of src?
+ assertHttpStatus(HTTP_BASE_URL + testPath + "/src1.html",
+ HttpServletResponse.SC_OK);
+ assertHttpStatus(HTTP_BASE_URL + testPath + "/src2.html",
+ HttpServletResponse.SC_OK);
+ assertHttpStatus(HTTP_BASE_URL + testPath + "/src3.html",
+ HttpServletResponse.SC_OK);
+ assertHttpStatus(HTTP_BASE_URL + testPath + "/src4.html",
+ HttpServletResponse.SC_OK);
+
+ testClient.delete(testRoot);
+ }
+
+ public void testMoveNodeMultipleSourcePartial() throws IOException {
+ final String testPath = TEST_BASE_PATH + "/mvmult/"
+ + 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 + "/src1", props);
+ testClient.createNode(HTTP_BASE_URL + testPath + "/src3", 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, testPath
+ + "/src1"));
+ nvPairs.add(new NameValuePair(SlingPostConstants.RP_APPLY_TO, testPath
+ + "/src2"));
+ nvPairs.add(new NameValuePair(SlingPostConstants.RP_APPLY_TO, testPath
+ + "/src3"));
+ nvPairs.add(new NameValuePair(SlingPostConstants.RP_APPLY_TO, testPath
+ + "/src4"));
+ assertPostStatus(testRoot, HttpServletResponse.SC_PRECONDITION_FAILED,
+ nvPairs, "Expecting Move Failure: dest parent does not exist");
+
+ // create destination parent
+ testClient.createNode(HTTP_BASE_URL + testPath + "/dest", props);
+
+ // now dest exists, so we expect success
+ assertPostStatus(testRoot, HttpServletResponse.SC_OK, nvPairs,
+ "Expecting Move Success");
+
+ // assert partial 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_NOT_FOUND);
+ assertHttpStatus(HTTP_BASE_URL + testPath + "/dest/src3/text",
+ HttpServletResponse.SC_OK);
+ assertHttpStatus(HTTP_BASE_URL + testPath + "/dest/src4/text",
+ HttpServletResponse.SC_NOT_FOUND);
+
+ // assert non-existence of src?
+ assertHttpStatus(HTTP_BASE_URL + testPath + "/src1.html",
+ HttpServletResponse.SC_NOT_FOUND);
+ assertHttpStatus(HTTP_BASE_URL + testPath + "/src2.html",
+ HttpServletResponse.SC_NOT_FOUND);
+ assertHttpStatus(HTTP_BASE_URL + testPath + "/src3.html",
+ HttpServletResponse.SC_NOT_FOUND);
+ assertHttpStatus(HTTP_BASE_URL + testPath + "/src4.html",
+ HttpServletResponse.SC_NOT_FOUND);
+
+ testClient.delete(testRoot);
+ }
+
+ public void testMoveNodeMultipleSourceReplace() throws Exception {
+ final String testPath = TEST_BASE_PATH + "/mvmult/"
+ + 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 + "/src1", props);
+ testClient.createNode(HTTP_BASE_URL + testPath + "/src2", 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, testPath
+ + "/src1"));
+ nvPairs.add(new NameValuePair(SlingPostConstants.RP_APPLY_TO, testPath
+ + "/src2"));
+ assertPostStatus(testRoot, HttpServletResponse.SC_PRECONDITION_FAILED,
+ nvPairs, "Expecting Move Failure: dest parent does not exist");
+
+ // create destination parent
+ testClient.createNode(HTTP_BASE_URL + testPath + "/dest", null);
+
+ // now dest exists, so we expect success
+ assertPostStatus(testRoot, HttpServletResponse.SC_OK, nvPairs,
+ "Expecting Move Success");
+
+ // assert partial 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_NOT_FOUND);
+ assertHttpStatus(HTTP_BASE_URL + testPath + "/dest/src4/text",
+ HttpServletResponse.SC_NOT_FOUND);
+
+ // assert content test
+ String content = getContent(HTTP_BASE_URL + testPath
+ + "/dest/src1.json", CONTENT_TYPE_JSON);
+ JSONObject json = new JSONObject(content);
+ assertEquals("Hello", json.get("text"));
+
+ // modify src1 content
+ nvPairs.clear();
+ nvPairs.add(new NameValuePair("text", "Modified Hello"));
+ assertPostStatus(HTTP_BASE_URL + testPath + "/src1",
+ HttpServletResponse.SC_CREATED, nvPairs,
+ "Expect Content Create Success");
+
+ // move the src? nodes
+ nvPairs.clear();
+ 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, testPath
+ + "/src1"));
+ nvPairs.add(new NameValuePair(SlingPostConstants.RP_APPLY_TO, testPath
+ + "/src2"));
+ assertPostStatus(testRoot, HttpServletResponse.SC_OK, nvPairs,
+ "Expecting Move Success");
+
+ // assert content test
+ String content2 = getContent(HTTP_BASE_URL + testPath
+ + "/dest/src1.json", CONTENT_TYPE_JSON);
+ JSONObject json2 = new JSONObject(content2);
+ assertEquals("Modified Hello", json2.get("text"));
+
+ // clean up
+ testClient.delete(testRoot);
+ }
+
+}
\ No newline at end of file
diff --git a/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/post/PostServletNopTest.java b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/post/PostServletNopTest.java
new file mode 100644
index 0000000..ac13581
--- /dev/null
+++ b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/post/PostServletNopTest.java
@@ -0,0 +1,75 @@
+/*
+ * 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.launchpad.webapp.integrationtest.servlets.post;
+
+import java.io.IOException;
+
+import org.apache.commons.httpclient.methods.PostMethod;
+import org.apache.sling.commons.testing.integration.HttpTestBase;
+
+
+public class PostServletNopTest extends HttpTestBase {
+
+ private static final String TEST_URL = HTTP_BASE_URL + "/"
+ + System.currentTimeMillis();
+
+ public void testDefault() throws IOException {
+ post(TEST_URL, null, 200);
+ }
+
+ public void testStatus200() throws IOException {
+ post(TEST_URL, 200);
+ }
+
+ public void testStatus708() throws IOException {
+ post(TEST_URL, 708);
+ }
+
+ // request status <100, expect default 200
+ public void testStatus88() throws IOException {
+ post(TEST_URL, "88", 200);
+ }
+
+ // request status >999, expect default 200
+ public void testStatus1234() throws IOException {
+ post(TEST_URL, "1234", 200);
+ }
+
+ // request non-numeric status, expect default 200
+ public void testStatusNonNumeric() throws IOException {
+ post(TEST_URL, "nonumber", 200);
+ }
+
+ private void post(String url, int status) throws IOException {
+ post(url, String.valueOf(status), status);
+ }
+
+ private void post(String url, String code, int expectedStatus)
+ throws IOException {
+ final PostMethod post = new PostMethod(url);
+ post.setFollowRedirects(false);
+
+ post.addParameter(":operation", "nop");
+
+ if (code != null) {
+ post.addParameter(":nopstatus", code);
+ }
+
+ int actualStatus = httpClient.executeMethod(post);
+ assertEquals(expectedStatus, actualStatus);
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/post/PostServletOrderTest.java b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/post/PostServletOrderTest.java
new file mode 100644
index 0000000..e875619
--- /dev/null
+++ b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/post/PostServletOrderTest.java
@@ -0,0 +1,209 @@
+/*
+ * 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.launchpad.webapp.integrationtest.servlets.post;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.sling.commons.json.JSONArray;
+import org.apache.sling.commons.json.JSONException;
+import org.apache.sling.commons.json.JSONObject;
+import org.apache.sling.commons.testing.integration.HttpTestBase;
+
+/** Test the order option for node creation via the MicrojaxPostServlet */
+public class PostServletOrderTest extends HttpTestBase {
+
+ public static final String TEST_BASE_PATH = "/sling-tests-order";
+
+ private static final String[] DEFAULT_ORDER = new String[]{"a","b","c","d"};
+
+ /*
+ does not work (yet) since rhino does not preserve order of
+ object elements.
+
+ private static final String TEST_SCRIPT =
+ "var s=''; " +
+ "for (var a in data) {" +
+ " var n = data[a];" +
+ " if (typeof(n) == 'object') s += a + ',';" +
+ "}" +
+ "out.println(s);";
+ */
+
+ /**
+ * Create nodes and check if they are in default order
+ */
+ public void testStandardOrder() throws IOException {
+ final String postUrl = HTTP_BASE_URL + TEST_BASE_PATH + "/" + System.currentTimeMillis();
+ createNodes(postUrl, DEFAULT_ORDER);
+ verifyOrder(postUrl, DEFAULT_ORDER);
+ }
+
+ /**
+ * Create nodes and check if they are in correct order after a
+ * :order="first" request
+ */
+ public void testOrderFirst() throws IOException {
+ final String postUrl = HTTP_BASE_URL + TEST_BASE_PATH + "/" + System.currentTimeMillis();
+ createNodes(postUrl, DEFAULT_ORDER);
+
+ final Map <String, String> props = new HashMap <String, String> ();
+ props.put(":order","first");
+ testClient.createNode(postUrl + "/c", props);
+ verifyOrder(postUrl, new String[]{"c", "a", "b", "d"});
+ }
+
+ /**
+ * Create nodes and check if they are in correct order after a
+ * :order="last" request
+ */
+ public void testOrderLast() throws IOException {
+ final String postUrl = HTTP_BASE_URL + TEST_BASE_PATH + "/" + System.currentTimeMillis();
+ createNodes(postUrl, DEFAULT_ORDER);
+
+ final Map <String, String> props = new HashMap <String, String> ();
+ props.put(":order","last");
+ testClient.createNode(postUrl + "/c", props);
+ verifyOrder(postUrl, new String[]{"a", "b", "d", "c"});
+ }
+
+ /**
+ * Create nodes and check if they are in correct order after a
+ * :order="before" request
+ */
+ public void testOrderBefore() throws IOException {
+ final String postUrl = HTTP_BASE_URL + TEST_BASE_PATH + "/" + System.currentTimeMillis();
+ createNodes(postUrl, DEFAULT_ORDER);
+
+ final Map <String, String> props = new HashMap <String, String> ();
+ props.put(":order","before b");
+ testClient.createNode(postUrl + "/c", props);
+ verifyOrder(postUrl, new String[]{"a", "c", "b", "d"});
+ }
+
+ /**
+ * Create nodes and check if they are in correct order after a
+ * :order="after" request
+ */
+ public void testOrderAfter() throws IOException {
+ final String postUrl = HTTP_BASE_URL + TEST_BASE_PATH + "/" + System.currentTimeMillis();
+ createNodes(postUrl, DEFAULT_ORDER);
+
+ final Map <String, String> props = new HashMap <String, String> ();
+ props.put(":order","after c");
+ testClient.createNode(postUrl + "/b", props);
+ verifyOrder(postUrl, new String[]{"a", "c", "b", "d"});
+ }
+
+ /**
+ * Create nodes and check if they are in correct order after a
+ * :order="N" request, where new position is greater than old one.
+ */
+ public void testOrderIntToBack() throws IOException {
+ final String postUrl = HTTP_BASE_URL + TEST_BASE_PATH + "/" + System.currentTimeMillis();
+ createNodes(postUrl, DEFAULT_ORDER);
+
+ final Map <String, String> props = new HashMap <String, String> ();
+ props.put(":order","2");
+ testClient.createNode(postUrl + "/a", props);
+ verifyOrder(postUrl, new String[]{"b", "c", "a", "d"});
+ }
+
+ /**
+ * Create nodes and check if they are in correct order after a
+ * :order="N" request, where new position is less than old one.
+ */
+ public void testOrderIntToFront() throws IOException {
+ final String postUrl = HTTP_BASE_URL + TEST_BASE_PATH + "/" + System.currentTimeMillis();
+ createNodes(postUrl, DEFAULT_ORDER);
+
+ final Map <String, String> props = new HashMap <String, String> ();
+ props.put(":order","1");
+ testClient.createNode(postUrl + "/d", props);
+ verifyOrder(postUrl, new String[]{"a", "d", "b", "c"});
+ }
+
+ /**
+ * Create nodes and check if they are in correct order after a
+ * :order="0" request
+ */
+ public void testOrderIntZero() throws IOException {
+ final String postUrl = HTTP_BASE_URL + TEST_BASE_PATH + "/" + System.currentTimeMillis();
+ createNodes(postUrl, DEFAULT_ORDER);
+
+ final Map <String, String> props = new HashMap <String, String> ();
+ props.put(":order","0");
+ testClient.createNode(postUrl + "/d", props);
+ verifyOrder(postUrl, new String[]{"d", "a", "b", "c"});
+ }
+
+ /**
+ * Create nodes and check if they are in correct order after a
+ * :order="N" request, where new position is out of bounds
+ */
+ public void testOrderIntOOB() throws IOException {
+ final String postUrl = HTTP_BASE_URL + TEST_BASE_PATH + "/" + System.currentTimeMillis();
+ createNodes(postUrl, DEFAULT_ORDER);
+
+ final Map <String, String> props = new HashMap <String, String> ();
+ props.put(":order","100");
+ testClient.createNode(postUrl + "/a", props);
+ verifyOrder(postUrl, new String[]{"b", "c", "d", "a"});
+ }
+
+ /**
+ * Create test nodes
+ */
+ private String[] createNodes(String parentUrl, String[] names)
+ throws IOException {
+ String[] urls = new String[names.length];
+ for (int i=0; i<names.length; i++) {
+ urls[i] = testClient.createNode(parentUrl + "/" + names[i], null);
+ }
+ return urls;
+ }
+
+ /**
+ * Verify node order
+ */
+ private void verifyOrder(String parentUrl, String[] names)
+ throws IOException {
+ // check that nodes appear in creation order in their parent's list of children
+ final String content = getContent(parentUrl + ".1.json", CONTENT_TYPE_JSON);
+ String expected = "";
+ for (String n: names) {
+ expected +=n + ",";
+ }
+ //assertJavascript(expected, content, TEST_SCRIPT);
+ try {
+ String actual = "";
+ JSONObject obj = new JSONObject(content);
+ JSONArray n = obj.names();
+ for (int i=0; i<n.length(); i++) {
+ String name = n.getString(i);
+ Object o = obj.get(name);
+ if (o instanceof JSONObject) {
+ actual += name + ",";
+ }
+ }
+ assertEquals(expected, actual);
+ } catch (JSONException e) {
+ throw new IOException(e.toString());
+ }
+ }
+ }
\ No newline at end of file
diff --git a/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/post/PostServletUpdateTest.java b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/post/PostServletUpdateTest.java
new file mode 100644
index 0000000..146a86d
--- /dev/null
+++ b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/post/PostServletUpdateTest.java
@@ -0,0 +1,154 @@
+/*
+ * 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.launchpad.webapp.integrationtest.servlets.post;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.sling.commons.json.JSONArray;
+import org.apache.sling.commons.json.JSONException;
+import org.apache.sling.commons.json.JSONObject;
+import org.apache.sling.commons.testing.integration.HttpTestBase;
+import org.apache.sling.servlets.post.SlingPostConstants;
+
+/** Test node updates via the MicrojaxPostServlet */
+public class PostServletUpdateTest extends HttpTestBase {
+ public static final String TEST_BASE_PATH = "/sling-tests";
+ private String postUrl;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ postUrl = HTTP_BASE_URL + TEST_BASE_PATH + "/" + System.currentTimeMillis();
+ }
+
+ public void testPostPathIsUnique() throws IOException {
+ assertHttpStatus(postUrl, HttpServletResponse.SC_NOT_FOUND,
+ "Path must not exist before test: " + postUrl);
+ }
+
+ public void testUpdateWithChanges() throws IOException {
+ final Map <String, String> props = new HashMap <String, String> ();
+ props.put("./a","123");
+ props.put("./b","456");
+
+ final String location = testClient.createNode(postUrl + SlingPostConstants.DEFAULT_CREATE_SUFFIX, props);
+ String content = getContent(location + ".json", CONTENT_TYPE_JSON);
+ assertJavascript("123456", content, "out.println(data.a + data.b)");
+
+ props.put("./a","789");
+ // the testClient method is called createNode but all it does is a POST,
+ // so it can be used for updates as well
+ final String newLocation = testClient.createNode(location, props);
+ assertEquals("Location must not changed after POST to existing node",location,newLocation);
+ content = getContent(location + ".json", CONTENT_TYPE_JSON);
+ assertJavascript("789456", content, "out.println(data.a + data.b)");
+ }
+
+ public void testUpdateNoChanges() throws IOException {
+ final Map <String, String> props = new HashMap <String, String> ();
+ props.put("./a","123");
+ props.put("./b","456");
+
+ final String location = testClient.createNode(postUrl + SlingPostConstants.DEFAULT_CREATE_SUFFIX, props);
+ String content = getContent(location + ".json", CONTENT_TYPE_JSON);
+ assertJavascript("123456", content, "out.println(data.a + data.b)");
+
+ props.clear();
+ // the testClient method is called createNode but all it does is a POST,
+ // so it can be used for updates as well
+ final String newLocation = testClient.createNode(location, props);
+ assertEquals("Location must not changed after POST to existing node",location,newLocation);
+ content = getContent(location + ".json", CONTENT_TYPE_JSON);
+ assertJavascript("123456", content, "out.println(data.a + data.b)");
+ }
+
+ public void testUpdateSomeChanges() throws IOException {
+ final Map <String, String> props = new HashMap <String, String> ();
+ props.put("./a","123");
+ props.put("./b","456");
+ props.put("C","not stored");
+
+ final String location = testClient.createNode(postUrl + SlingPostConstants.DEFAULT_CREATE_SUFFIX, props);
+ String content = getContent(location + ".json", CONTENT_TYPE_JSON);
+ assertJavascript("123456", content, "out.println(data.a + data.b)");
+
+ props.clear();
+ props.put("./b","457");
+ props.put("C","still not stored");
+
+ // the testClient method is called createNode but all it does is a POST,
+ // so it can be used for updates as well
+ final String newLocation = testClient.createNode(location, props);
+ assertEquals("Location must not changed after POST to existing node",location,newLocation);
+ content = getContent(location + ".json", CONTENT_TYPE_JSON);
+ assertJavascript("123457", content, "out.println(data.a + data.b)");
+ }
+
+ public void testMultivalueHint() throws IOException {
+ final Map <String, String> props = new HashMap <String, String> ();
+ props.put("./f","123");
+ props.put("./f@TypeHint", "String[]");
+ props.put("./g","456");
+
+ final String location = testClient.createNode(postUrl + SlingPostConstants.DEFAULT_CREATE_SUFFIX, props);
+ String content = getContent(location + ".json", CONTENT_TYPE_JSON);
+ assertTrue(content.indexOf("\"f\":[\"123\"]") > 0);
+ assertTrue(content.indexOf("\"g\":\"456\"") > 0);
+ }
+
+ public void testMixinTypes() throws IOException, JSONException {
+
+ // create a node without mixin node types
+ final Map <String, String> props = new HashMap <String, String> ();
+ props.put("jcr:primaryType","nt:unstructured");
+ final String location = testClient.createNode(postUrl + SlingPostConstants.DEFAULT_CREATE_SUFFIX, props);
+
+ // assert no mixins
+ String content = getContent(location + ".json", CONTENT_TYPE_JSON);
+ JSONObject json = new JSONObject(content);
+ assertFalse("jcr:mixinTypes not expected to be set", json.has("jcr:mixinTypes"));
+
+ // add mixin
+ props.clear();
+ props.put("jcr:mixinTypes", "mix:versionable");
+ testClient.createNode(location, props);
+
+ content = getContent(location + ".json", CONTENT_TYPE_JSON);
+ json = new JSONObject(content);
+ assertTrue("jcr:mixinTypes expected after setting them", json.has("jcr:mixinTypes"));
+
+ Object mixObject = json.get("jcr:mixinTypes");
+ assertTrue("jcr:mixinTypes must be an array", mixObject instanceof JSONArray);
+
+ JSONArray mix = (JSONArray) mixObject;
+ assertTrue("jcr:mixinTypes must have a single entry", mix.length() == 1);
+ assertEquals("jcr:mixinTypes must have correct value", "mix:versionable", mix.get(0));
+
+ // remove mixin
+ props.clear();
+ props.put("jcr:mixinTypes@Delete", "-");
+ testClient.createNode(location, props);
+
+ content = getContent(location + ".json", CONTENT_TYPE_JSON);
+ json = new JSONObject(content);
+ assertTrue("no jcr:mixinTypes expected after clearing it", !json.has("jcr:mixinTypes"));
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/post/PostStatusTest.java b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/post/PostStatusTest.java
new file mode 100644
index 0000000..a8304a5
--- /dev/null
+++ b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/post/PostStatusTest.java
@@ -0,0 +1,77 @@
+/*
+ * 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.launchpad.webapp.integrationtest.servlets.post;
+
+import java.io.IOException;
+
+import org.apache.commons.httpclient.methods.PostMethod;
+import org.apache.sling.commons.testing.integration.HttpTestBase;
+import org.apache.sling.servlets.post.SlingPostConstants;
+
+/** Test the various status options for POST, SLING-422 */
+public class PostStatusTest extends HttpTestBase {
+
+ private String postPath = "PostStatusTest/" + System.currentTimeMillis();
+
+ public void testStandardStatusNull() throws IOException {
+ final String resPath = "/" + postPath + "/StandardNull";
+ final String postUrl = HTTP_BASE_URL + resPath;
+ simplePost(postUrl, null, 201, resPath);
+ }
+
+ public void testStandardStatusStandard() throws IOException {
+ final String resPath = "/" + postPath + "/StandardStandard";
+ final String postUrl = HTTP_BASE_URL + resPath;
+ simplePost(postUrl, SlingPostConstants.STATUS_VALUE_STANDARD, 201, resPath);
+ }
+
+ public void testStandardStatusUnknown() throws IOException {
+ final String resPath = "/" + postPath + "/StandardUnknown";
+ final String postUrl = HTTP_BASE_URL + resPath;
+ simplePost(postUrl, "Unknown Value", 201, resPath);
+ }
+
+ public void testStatusBrowser() throws IOException {
+ final String resPath = "/" + postPath + "/Browser";
+ final String postUrl = HTTP_BASE_URL + resPath;
+ simplePost(postUrl, SlingPostConstants.STATUS_VALUE_BROWSER, 200, null);
+ }
+
+ private void simplePost(String url, String statusParam, int expectStatus,
+ String expectLocation) throws IOException {
+
+ final PostMethod post = new PostMethod(url);
+ post.setFollowRedirects(false);
+
+ if (statusParam != null) {
+ post.addParameter(SlingPostConstants.RP_STATUS, statusParam);
+ }
+
+ final int status = httpClient.executeMethod(post);
+ assertEquals("Unexpected status response", expectStatus, status);
+
+ if (expectLocation != null) {
+ String location = post.getResponseHeader("Location").getValue();
+
+ assertNotNull("Expected location header", location);
+ assertTrue(location.endsWith(expectLocation));
+ }
+
+ post.releaseConnection();
+ }
+
+}
\ No newline at end of file
diff --git a/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/post/PostToRootTest.java b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/post/PostToRootTest.java
new file mode 100644
index 0000000..6945c1e
--- /dev/null
+++ b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/post/PostToRootTest.java
@@ -0,0 +1,41 @@
+/*
+ * 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.launchpad.webapp.integrationtest.servlets.post;
+
+import org.apache.commons.httpclient.methods.PostMethod;
+import org.apache.sling.commons.testing.integration.HttpTestBase;
+
+/** Test POSTing to root node (SLING-668) */
+public class PostToRootTest extends HttpTestBase {
+
+ public void testSetRootProperty() throws Exception {
+ String url = HTTP_BASE_URL;
+ if(!url.endsWith("/")) {
+ url += "/";
+ }
+ final PostMethod post = new PostMethod(url);
+ final String name = getClass().getSimpleName();
+ final String value = getClass().getSimpleName() + System.currentTimeMillis();
+ post.addParameter(name, value);
+
+ final int status = httpClient.executeMethod(post);
+ assertEquals(200, status);
+
+ final String json = getContent(url + ".json", CONTENT_TYPE_JSON);
+ assertJavascript(value, json, "out.print(data." + name + ")");
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/post/SlingAutoPropertiesTest.java b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/post/SlingAutoPropertiesTest.java
new file mode 100644
index 0000000..86a6a9f
--- /dev/null
+++ b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/post/SlingAutoPropertiesTest.java
@@ -0,0 +1,103 @@
+/*
+ * 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.launchpad.webapp.integrationtest.servlets.post;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.sling.commons.testing.integration.HttpTestBase;
+import org.apache.sling.servlets.post.SlingPostConstants;
+
+/** {#link MicrojaxPropertyValueSetter} sets the value of some properties
+ * automatically if they are empty. This is tested here with various cases.
+ */
+
+public class SlingAutoPropertiesTest extends HttpTestBase {
+
+ public static final String TEST_BASE_PATH = "/sling-tests";
+ private String postUrl;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ postUrl = HTTP_BASE_URL + TEST_BASE_PATH + "/" + System.currentTimeMillis();
+ }
+
+ public void testPostPathIsUnique() throws IOException {
+ assertHttpStatus(postUrl, HttpServletResponse.SC_NOT_FOUND,
+ "Path must not exist before test: " + postUrl);
+ }
+
+ public void testCreatedAndModified() throws IOException {
+ final Map <String, String> props = new HashMap <String, String> ();
+ props.put("a","123");
+
+ props.put("created","");
+ props.put("createdBy","");
+ props.put("lastModified","");
+ props.put("lastModifiedBy","");
+
+ final String createdNodeUrl = testClient.createNode(postUrl + SlingPostConstants.DEFAULT_CREATE_SUFFIX, props);
+ String content = getContent(createdNodeUrl + ".json", CONTENT_TYPE_JSON);
+
+ assertJavascript("123", content, "out.println(data.a)");
+ assertJavascript("admin", content, "out.println(data.createdBy)");
+ assertJavascript("admin", content, "out.println(data.lastModifiedBy)");
+ assertJavascript("true", content, "out.println(data.created.length > 0)");
+ assertJavascript("true", content, "out.println(data.lastModified.length > 0)");
+ assertJavascript("true", content, "out.println(data.lastModified == data.created)");
+
+ // update node and check that "last modified" has changed
+ try {
+ Thread.sleep(1000L);
+ } catch(InterruptedException ignored) {
+ // ignore
+ }
+
+ testClient.createNode(createdNodeUrl, props);
+ content = getContent(createdNodeUrl + ".json", CONTENT_TYPE_JSON);
+
+ assertJavascript("123", content, "out.println(data.a)");
+ assertJavascript("admin", content, "out.println(data.createdBy)");
+ assertJavascript("admin", content, "out.println(data.lastModifiedBy)");
+ assertJavascript("true", content, "out.println(data.created.length > 0)");
+ assertJavascript("true", content, "out.println(data.lastModified.length > 0)");
+ assertJavascript("true", content, "out.println(data.lastModified > data.created)");
+ }
+
+ public void testWithSpecificValues() throws IOException {
+ final Map <String, String> props = new HashMap <String, String> ();
+ props.put("a","123");
+
+ props.put("created","a");
+ props.put("createdBy","b");
+ props.put("lastModified","c");
+ props.put("lastModifiedBy","d");
+
+ final String createdNodeUrl = testClient.createNode(postUrl + SlingPostConstants.DEFAULT_CREATE_SUFFIX, props);
+ final String content = getContent(createdNodeUrl + ".json", CONTENT_TYPE_JSON);
+
+ assertJavascript("123", content, "out.println(data.a)");
+ assertJavascript("a", content, "out.println(data.created)");
+ assertJavascript("b", content, "out.println(data.createdBy)");
+ assertJavascript("c", content, "out.println(data.lastModified)");
+ assertJavascript("d", content, "out.println(data.lastModifiedBy)");
+ }
+}
diff --git a/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/post/SlingDateValuesTest.java b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/post/SlingDateValuesTest.java
new file mode 100644
index 0000000..fdb8bd6
--- /dev/null
+++ b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/post/SlingDateValuesTest.java
@@ -0,0 +1,78 @@
+/*
+ * 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.launchpad.webapp.integrationtest.servlets.post;
+
+import java.io.IOException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+
+import org.apache.sling.commons.testing.integration.HttpTestBase;
+import org.apache.sling.servlets.post.SlingPostConstants;
+
+/**
+ * checks if the date parsing for non jcr-dates works.
+ */
+
+public class SlingDateValuesTest extends HttpTestBase {
+
+ public static final String TEST_BASE_PATH = "/sling-tests";
+
+ // TODO: the commented formats do not work beacuse of SLING-242
+ // the + of the timezone offset is stripped by sling
+
+ private final SimpleDateFormat[] testFormats = new SimpleDateFormat[]{
+ new SimpleDateFormat("EEE MMM dd yyyy HH:mm:ss 'GMT'Z", Locale.US),
+ new SimpleDateFormat("dd.MM.yyyy HH:mm:ss", Locale.US),
+ new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ", Locale.US),
+ new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.US)
+ };
+
+ private String postUrl;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ postUrl = HTTP_BASE_URL + TEST_BASE_PATH + "/" + System.currentTimeMillis();
+ }
+
+ private void doDateTest(String expected, String input)
+ throws IOException {
+ final Map<String, String> props = new HashMap<String, String>();
+ props.put("someDate", input);
+ props.put("someDate@TypeHint", "Date");
+
+ final String createdNodeUrl = testClient.createNode(postUrl + SlingPostConstants.DEFAULT_CREATE_SUFFIX, props);
+ String content = getContent(createdNodeUrl + ".json", CONTENT_TYPE_JSON);
+
+ // default behaviour writes empty string
+ assertJavascript(expected, content, "out.println(data.someDate)");
+ }
+
+ public void testDateValues() throws IOException {
+ SimpleDateFormat ecmaFmt = new SimpleDateFormat("EEE MMM dd yyyy HH:mm:ss 'GMT'Z", Locale.US);
+ Date now = new Date();
+ String nowStr = ecmaFmt.format(now);
+ for (SimpleDateFormat fmt: testFormats) {
+ String testStr = fmt.format(now);
+ doDateTest(nowStr, testStr);
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/post/SlingDefaultValuesTest.java b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/post/SlingDefaultValuesTest.java
new file mode 100644
index 0000000..af84982
--- /dev/null
+++ b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/post/SlingDefaultValuesTest.java
@@ -0,0 +1,105 @@
+/*
+ * 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.launchpad.webapp.integrationtest.servlets.post;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.sling.commons.testing.integration.HttpTestBase;
+import org.apache.sling.servlets.post.SlingPostConstants;
+
+/** {#link SlingPropertyValueSetter} sets the value of some properties
+ * with default values if they are empty. This is tested here with various cases.
+ */
+
+public class SlingDefaultValuesTest extends HttpTestBase {
+
+ public static final String TEST_BASE_PATH = "/sling-tests";
+ private String postUrl;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ postUrl = HTTP_BASE_URL + TEST_BASE_PATH + "/" + System.currentTimeMillis();
+ }
+
+ public void testDefaultBehaviour() throws IOException {
+ final Map<String, String> props = new HashMap<String, String>();
+ props.put("a","");
+
+ final String createdNodeUrl = testClient.createNode(postUrl + SlingPostConstants.DEFAULT_CREATE_SUFFIX, props);
+ String content = getContent(createdNodeUrl + ".json", CONTENT_TYPE_JSON);
+
+ // default behaviour writes empty string
+ assertJavascript("undefined", content, "out.println(\"\" + data.a)");
+
+ // overwrite with "123"
+ props.put("a", "123");
+ testClient.createNode(createdNodeUrl, props);
+ content = getContent(createdNodeUrl + ".json", CONTENT_TYPE_JSON);
+
+ assertJavascript("123", content, "out.println(data.a)");
+
+ // and clear again
+ props.put("a", "");
+ testClient.createNode(createdNodeUrl, props);
+ content = getContent(createdNodeUrl + ".json", CONTENT_TYPE_JSON);
+
+ assertJavascript("undefined", content, "out.println(\"\" + data.a)");
+ }
+
+ public void testWithSpecificDefault() throws IOException {
+ final Map <String, String> props = new HashMap <String, String> ();
+ props.put("a","");
+ props.put("a@DefaultValue","123");
+
+ final String createdNodeUrl = testClient.createNode(postUrl + SlingPostConstants.DEFAULT_CREATE_SUFFIX, props);
+ final String content = getContent(createdNodeUrl + ".json", CONTENT_TYPE_JSON);
+
+ assertJavascript("123", content, "out.println(data.a)");
+ }
+
+ public void testWithIgnore() throws IOException {
+ final Map <String, String> props = new HashMap <String, String> ();
+ props.put("a","");
+ props.put("a@DefaultValue",":ignore");
+
+ final String createdNodeUrl = testClient.createNode(postUrl + SlingPostConstants.DEFAULT_CREATE_SUFFIX, props);
+ final String content = getContent(createdNodeUrl + ".json", CONTENT_TYPE_JSON);
+
+ assertJavascript("undefined", content, "out.println(typeof(data.a))");
+ }
+
+ public void testWithNull() throws IOException {
+ final Map <String, String> props = new HashMap <String, String> ();
+ props.put("a","123");
+
+ final String createdNodeUrl = testClient.createNode(postUrl + SlingPostConstants.DEFAULT_CREATE_SUFFIX, props);
+ String content = getContent(createdNodeUrl + ".json", CONTENT_TYPE_JSON);
+
+ assertJavascript("123", content, "out.println(data.a)");
+
+ // now try to delete prop by sending empty string
+ props.put("a","");
+ props.put("a@DefaultValue",":null");
+ testClient.createNode(createdNodeUrl, props);
+ content = getContent(createdNodeUrl + ".json", CONTENT_TYPE_JSON);
+
+ assertJavascript("undefined", content, "out.println(typeof(data.a))");
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/post/SlingSessionInfoTest.java b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/post/SlingSessionInfoTest.java
new file mode 100644
index 0000000..2cb6738
--- /dev/null
+++ b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/post/SlingSessionInfoTest.java
@@ -0,0 +1,41 @@
+/*
+ * 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.launchpad.webapp.integrationtest.servlets.post;
+
+import java.io.IOException;
+
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.sling.commons.testing.integration.HttpTestBase;
+
+/** Test the sling:sessionInfo resource */
+
+public class SlingSessionInfoTest extends HttpTestBase {
+
+ public void testSessionInfo() throws IOException {
+ final String content = getContent(HTTP_BASE_URL + "/system/sling/info.sessionInfo.json", CONTENT_TYPE_JSON);
+
+ // assume workspace name contains "default", might not
+ // always be the case as the default workspace is selected
+ // by the JCR implementation due to SLING-256
+ assertJavascript("admin.true", content, "out.println(data.userID + '.' + (data.workspace.indexOf('default') >= 0) )");
+ }
+
+ public void testNonexistentSlingUrl() throws IOException {
+ assertHttpStatus(HTTP_BASE_URL + "/sling.nothing", HttpServletResponse.SC_NOT_FOUND);
+ }
+}
diff --git a/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/resolution/ExtensionServletTest.java b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/resolution/ExtensionServletTest.java
new file mode 100644
index 0000000..66ca149
--- /dev/null
+++ b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/resolution/ExtensionServletTest.java
@@ -0,0 +1,38 @@
+/*
+ * 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.launchpad.webapp.integrationtest.servlets.resolution;
+
+/** Test the ExtensionServlet */
+public class ExtensionServletTest extends ResolutionTestBase {
+
+ public void testExtensionOne() throws Exception {
+ assertServlet(
+ getContent(testNodeNORT.nodeUrl + ".TEST_EXT_1", CONTENT_TYPE_PLAIN),
+ EXT_SERVLET_SUFFIX);
+ }
+
+ public void testExtensionTwo() throws Exception {
+ assertServlet(
+ getContent(testNodeNORT.nodeUrl + ".TEST_EXT_2", CONTENT_TYPE_PLAIN),
+ EXT_SERVLET_SUFFIX);
+ }
+
+ public void testExtensionOther() throws Exception {
+ assertNotTestServlet(
+ getContent(testNodeNORT.nodeUrl + ".txt", CONTENT_TYPE_PLAIN));
+ }
+}
diff --git a/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/resolution/PrefixTest.java b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/resolution/PrefixTest.java
new file mode 100644
index 0000000..0d60e1d
--- /dev/null
+++ b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/resolution/PrefixTest.java
@@ -0,0 +1,39 @@
+/*
+ * 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.launchpad.webapp.integrationtest.servlets.resolution;
+
+/** Verify that PrefixServletZero overrides PrefixServletMinusOne */
+public class PrefixTest extends ResolutionTestBase {
+
+ public void testPrefixServletZeroPresent() throws Exception {
+ assertServlet(
+ getContent(testNodeNORT.nodeUrl + ".TEST_EXT_5", CONTENT_TYPE_PLAIN),
+ PREFIX_0_SERVLET_SUFFIX);
+ }
+
+ public void testPrefixServletMinusOnePresent() throws Exception {
+ assertServlet(
+ getContent(testNodeNORT.nodeUrl + ".TEST_EXT_4", CONTENT_TYPE_PLAIN),
+ PREFIX_M1_SERVLET_SUFFIX);
+ }
+
+ public void testPrefixServletZeroWins() throws Exception {
+ assertServlet(
+ getContent(testNodeNORT.nodeUrl + ".TEST_EXT_3", CONTENT_TYPE_PLAIN),
+ PREFIX_0_SERVLET_SUFFIX);
+ }
+}
diff --git a/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/resolution/PrioritiesTest.java b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/resolution/PrioritiesTest.java
new file mode 100644
index 0000000..1797a71
--- /dev/null
+++ b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/resolution/PrioritiesTest.java
@@ -0,0 +1,27 @@
+/*
+ * 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.launchpad.webapp.integrationtest.servlets.resolution;
+
+/** Test the priority of servlet selection mechanisms */
+public class PrioritiesTest extends ResolutionTestBase {
+
+ public void testExtensionWinsOverSelector() throws Exception {
+ assertServlet(
+ getContent(testNodeNORT.nodeUrl + ".TEST_SEL_2.TEST_EXT_1", CONTENT_TYPE_PLAIN),
+ EXT_SERVLET_SUFFIX);
+ }
+}
diff --git a/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/resolution/PutMethodServletTest.java b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/resolution/PutMethodServletTest.java
new file mode 100644
index 0000000..9c98f40
--- /dev/null
+++ b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/resolution/PutMethodServletTest.java
@@ -0,0 +1,37 @@
+/*
+ * 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.launchpad.webapp.integrationtest.servlets.resolution;
+
+import org.apache.commons.httpclient.methods.PutMethod;
+
+/** Test the PutMethodServlet resolution */
+public class PutMethodServletTest extends ResolutionTestBase {
+
+ public void testPutMethodServletSpecificRT() throws Exception {
+ final PutMethod put = new PutMethod(testNodeRT.nodeUrl);
+ final int status = httpClient.executeMethod(put);
+ assertEquals("PUT to testNodeRT should return 200", 200, status);
+ final String content = put.getResponseBodyAsString();
+ assertServlet(content, PUT_SERVLET_SUFFIX);
+ }
+
+ public void testPutMethodServletDefaultRT() throws Exception {
+ final PutMethod put = new PutMethod(testNodeNORT.nodeUrl);
+ final int status = httpClient.executeMethod(put);
+ assertFalse("PUT to testNodeRT should not return 200", 200 == status);
+ }
+}
diff --git a/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/resolution/ResolutionTestBase.java b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/resolution/ResolutionTestBase.java
new file mode 100644
index 0000000..426f28e
--- /dev/null
+++ b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/resolution/ResolutionTestBase.java
@@ -0,0 +1,87 @@
+/*
+ * 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.launchpad.webapp.integrationtest.servlets.resolution;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+
+import org.apache.sling.commons.testing.integration.HttpTestBase;
+
+/** Base class for servlet resolution tests */
+class ResolutionTestBase extends HttpTestBase {
+ public static final String CLASS_PROP = "servlet.class.name";
+ public static final String TEST_SERVLET_MARKER = "created by org.apache.sling.launchpad.testservices.servlets";
+ public static final String TEST_RESOURCE_TYPE = "LAUNCHPAD_TEST_ResourceType";
+ public static final String TEST_PATH = "/servlet-resolution-tests/" + System.currentTimeMillis();
+
+ public static final String EXT_SERVLET_SUFFIX = "testservices.servlets.ExtensionServlet";
+ public static final String SEL_SERVLET_SUFFIX = "testservices.servlets.SelectorServlet";
+ public static final String PREFIX_0_SERVLET_SUFFIX = "testservices.servlets.PrefixServletZero";
+ public static final String PREFIX_M1_SERVLET_SUFFIX = "testservices.servlets.PrefixServletMinusOne";
+ public static final String PUT_SERVLET_SUFFIX = "testservices.servlets.PutMethodServlet";
+
+ protected TestNode testNodeNORT;
+ protected TestNode testNodeRT;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ testNodeNORT = new TestNode(HTTP_BASE_URL + TEST_PATH, null);
+ final Map<String, String> properties = new HashMap<String, String>();
+ properties.put("sling:resourceType", TEST_RESOURCE_TYPE);
+ testNodeRT = new TestNode(HTTP_BASE_URL + TEST_PATH, properties);
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ testNodeNORT.delete();
+ testNodeRT.delete();
+ }
+
+ /** Asserts that the given content is in Properties format and
+ * contains a property named CLASS_PROP that ends with
+ * expected suffix
+ */
+ protected void assertServlet(String content, String expectedSuffix) throws IOException {
+ final Properties props = new Properties();
+ final InputStream is = new ByteArrayInputStream(content.getBytes());
+ props.load(is);
+ assertTrue(
+ "Content represents a non-empty Properties object (" + content + ")",
+ props.size() > 0);
+ final String clazz = props.getProperty(CLASS_PROP);
+ assertNotNull(
+ "Content contains " + CLASS_PROP + " property (" + content + ")",
+ clazz);
+ assertTrue(
+ CLASS_PROP + " property value (" + clazz + ") ends with " + expectedSuffix,
+ clazz.endsWith(expectedSuffix));
+ }
+
+ /** Assert that content does not contain TEST_SERVLET_MARKER
+ */
+ protected void assertNotTestServlet(String content) {
+ if(content.contains(TEST_SERVLET_MARKER)) {
+ fail("Content should not contain " + TEST_SERVLET_MARKER + " marker (" + content + ")");
+ }
+ }
+}
diff --git a/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/resolution/SelectorServletTest.java b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/resolution/SelectorServletTest.java
new file mode 100644
index 0000000..04d392e
--- /dev/null
+++ b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/resolution/SelectorServletTest.java
@@ -0,0 +1,38 @@
+/*
+ * 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.launchpad.webapp.integrationtest.servlets.resolution;
+
+/** Test the SelectorServlet */
+public class SelectorServletTest extends ResolutionTestBase {
+
+ public void testSelectorOne() throws Exception {
+ assertServlet(
+ getContent(testNodeNORT.nodeUrl + ".TEST_SEL_1.txt", CONTENT_TYPE_PLAIN),
+ SEL_SERVLET_SUFFIX);
+ }
+
+ public void testSelectorTwo() throws Exception {
+ assertServlet(
+ getContent(testNodeNORT.nodeUrl + ".TEST_SEL_2.txt", CONTENT_TYPE_PLAIN),
+ SEL_SERVLET_SUFFIX);
+ }
+
+ public void testSelectorOther() throws Exception {
+ assertNotTestServlet(
+ getContent(testNodeNORT.nodeUrl + ".TEST_SEL_3.txt", CONTENT_TYPE_PLAIN));
+ }
+}
diff --git a/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/userManager/AbstractUserManagerTest.java b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/userManager/AbstractUserManagerTest.java
new file mode 100644
index 0000000..0dd0ce5
--- /dev/null
+++ b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/userManager/AbstractUserManagerTest.java
@@ -0,0 +1,185 @@
+/*
+ * 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.launchpad.webapp.integrationtest.userManager;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.httpclient.Credentials;
+import org.apache.commons.httpclient.Header;
+import org.apache.commons.httpclient.HttpException;
+import org.apache.commons.httpclient.NameValuePair;
+import org.apache.commons.httpclient.UsernamePasswordCredentials;
+import org.apache.commons.httpclient.auth.AuthScope;
+import org.apache.commons.httpclient.methods.GetMethod;
+import org.apache.commons.httpclient.methods.PostMethod;
+import org.apache.sling.commons.testing.integration.HttpTestBase;
+
+/**
+ * Base class for UserManager tests.
+ */
+public abstract class AbstractUserManagerTest extends HttpTestBase {
+
+ /** Execute a POST request and check status */
+ protected void assertAuthenticatedAdminPostStatus(String url, int expectedStatusCode, List<NameValuePair> postParams, String assertMessage)
+ throws IOException {
+ Credentials defaultcreds = new UsernamePasswordCredentials("admin", "admin");
+ assertAuthenticatedPostStatus(defaultcreds, url, expectedStatusCode, postParams, assertMessage);
+ }
+
+ /** Execute a POST request and check status */
+ protected void assertAuthenticatedPostStatus(Credentials creds, String url, int expectedStatusCode, List<NameValuePair> postParams, String assertMessage)
+ throws IOException {
+ final PostMethod post = new PostMethod(url);
+ post.setFollowRedirects(false);
+
+ URL baseUrl = new URL(HTTP_BASE_URL);
+ AuthScope authScope = new AuthScope(baseUrl.getHost(), baseUrl.getPort(), AuthScope.ANY_REALM);
+ post.setDoAuthentication(true);
+ Credentials oldCredentials = httpClient.getState().getCredentials(authScope);
+ try {
+ httpClient.getState().setCredentials(authScope, creds);
+
+ if(postParams!=null) {
+ final NameValuePair [] nvp = {};
+ post.setRequestBody(postParams.toArray(nvp));
+ }
+
+ final int status = httpClient.executeMethod(post);
+ if(assertMessage == null) {
+ assertEquals(expectedStatusCode, status);
+ } else {
+ assertEquals(assertMessage, expectedStatusCode, status);
+ }
+ } finally {
+ httpClient.getState().setCredentials(authScope, oldCredentials);
+ }
+ }
+
+ /** Verify that given URL returns expectedStatusCode
+ * @throws IOException */
+ protected void assertAuthenticatedHttpStatus(Credentials creds, String urlString, int expectedStatusCode, String assertMessage) throws IOException {
+ URL baseUrl = new URL(HTTP_BASE_URL);
+ AuthScope authScope = new AuthScope(baseUrl.getHost(), baseUrl.getPort(), AuthScope.ANY_REALM);
+ GetMethod getMethod = new GetMethod(urlString);
+ getMethod.setDoAuthentication(true);
+ Credentials oldCredentials = httpClient.getState().getCredentials(authScope);
+ try {
+ httpClient.getState().setCredentials(authScope, creds);
+
+ final int status = httpClient.executeMethod(getMethod);
+ if(assertMessage == null) {
+ assertEquals(urlString,expectedStatusCode, status);
+ } else {
+ assertEquals(assertMessage, expectedStatusCode, status);
+ }
+ } finally {
+ httpClient.getState().setCredentials(authScope, oldCredentials);
+ }
+ }
+
+
+ /** retrieve the contents of given URL and assert its content type
+ * @param expectedContentType use CONTENT_TYPE_DONTCARE if must not be checked
+ * @throws IOException
+ * @throws HttpException */
+ protected String getAuthenticatedContent(Credentials creds, String url, String expectedContentType, List<NameValuePair> params, int expectedStatusCode) throws IOException {
+ final GetMethod get = new GetMethod(url);
+
+ URL baseUrl = new URL(HTTP_BASE_URL);
+ AuthScope authScope = new AuthScope(baseUrl.getHost(), baseUrl.getPort(), AuthScope.ANY_REALM);
+ get.setDoAuthentication(true);
+ Credentials oldCredentials = httpClient.getState().getCredentials(authScope);
+ try {
+ httpClient.getState().setCredentials(authScope, creds);
+
+ if(params != null) {
+ final NameValuePair [] nvp = new NameValuePair[0];
+ get.setQueryString(params.toArray(nvp));
+ }
+ final int status = httpClient.executeMethod(get);
+ final InputStream is = get.getResponseBodyAsStream();
+ final StringBuffer content = new StringBuffer();
+ final String charset = get.getResponseCharSet();
+ final byte [] buffer = new byte[16384];
+ int n = 0;
+ while( (n = is.read(buffer, 0, buffer.length)) > 0) {
+ content.append(new String(buffer, 0, n, charset));
+ }
+ assertEquals("Expected status " + expectedStatusCode + " for " + url + " (content=" + content + ")",
+ expectedStatusCode,status);
+ final Header h = get.getResponseHeader("Content-Type");
+ if(expectedContentType == null) {
+ if(h!=null) {
+ fail("Expected null Content-Type, got " + h.getValue());
+ }
+ } else if(CONTENT_TYPE_DONTCARE.equals(expectedContentType)) {
+ // no check
+ } else if(h==null) {
+ fail(
+ "Expected Content-Type that starts with '" + expectedContentType
+ +" but got no Content-Type header at " + url
+ );
+ } else {
+ assertTrue(
+ "Expected Content-Type that starts with '" + expectedContentType
+ + "' for " + url + ", got '" + h.getValue() + "'",
+ h.getValue().startsWith(expectedContentType)
+ );
+ }
+ return content.toString();
+
+ } finally {
+ httpClient.getState().setCredentials(authScope, oldCredentials);
+ }
+ }
+
+
+ protected static int counter = 1;
+
+ protected String createTestUser() throws IOException {
+ String postUrl = HTTP_BASE_URL + "/system/userManager/user.create.html";
+
+ String testUserId = "testUser" + (counter++);
+ List<NameValuePair> postParams = new ArrayList<NameValuePair>();
+ postParams.add(new NameValuePair(":name", testUserId));
+ postParams.add(new NameValuePair("pwd", "testPwd"));
+ postParams.add(new NameValuePair("pwdConfirm", "testPwd"));
+ assertPostStatus(postUrl, HttpServletResponse.SC_OK, postParams, null);
+
+ return testUserId;
+ }
+
+ protected String createTestGroup() throws IOException {
+ String postUrl = HTTP_BASE_URL + "/system/userManager/group.create.html";
+
+ String testGroupId = "testGroup" + (counter++);
+ List<NameValuePair> postParams = new ArrayList<NameValuePair>();
+ postParams.add(new NameValuePair(":name", testGroupId));
+
+ //success would be a redirect to the welcome page of the webapp
+ assertAuthenticatedAdminPostStatus(postUrl, HttpServletResponse.SC_OK, postParams, null);
+
+ return testGroupId;
+ }
+
+}
diff --git a/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/userManager/CreateGroupTest.java b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/userManager/CreateGroupTest.java
new file mode 100644
index 0000000..3075211
--- /dev/null
+++ b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/userManager/CreateGroupTest.java
@@ -0,0 +1,106 @@
+/*
+ * 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.launchpad.webapp.integrationtest.userManager;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.httpclient.Credentials;
+import org.apache.commons.httpclient.NameValuePair;
+import org.apache.commons.httpclient.UsernamePasswordCredentials;
+import org.apache.sling.commons.json.JSONException;
+import org.apache.sling.commons.json.JSONObject;
+
+/**
+ * Tests for the 'createGroup' Sling Post Operation
+ */
+public class CreateGroupTest extends AbstractUserManagerTest {
+
+ String testGroupId = null;
+
+ @Override
+ protected void tearDown() throws Exception {
+ if (testGroupId != null) {
+ //remove the test group if it exists.
+ String postUrl = HTTP_BASE_URL + "/system/userManager/group/" + testGroupId + ".delete.html";
+ List<NameValuePair> postParams = new ArrayList<NameValuePair>();
+ assertAuthenticatedAdminPostStatus(postUrl, HttpServletResponse.SC_OK, postParams, null);
+ }
+
+ super.tearDown();
+ }
+
+ public void testCreateGroup() throws IOException, JSONException {
+ String postUrl = HTTP_BASE_URL + "/system/userManager/group.create.html";
+
+ testGroupId = "testGroup" + (counter++);
+ List<NameValuePair> postParams = new ArrayList<NameValuePair>();
+ postParams.add(new NameValuePair(":name", testGroupId));
+ assertAuthenticatedAdminPostStatus(postUrl, HttpServletResponse.SC_OK, postParams, null);
+
+ //fetch the group profile json to verify the settings
+ String getUrl = HTTP_BASE_URL + "/system/userManager/group/" + testGroupId + ".json";
+ Credentials creds = new UsernamePasswordCredentials("admin", "admin");
+ String json = getAuthenticatedContent(creds, getUrl, CONTENT_TYPE_JSON, null, HttpServletResponse.SC_OK);
+ assertNotNull(json);
+ JSONObject jsonObj = new JSONObject(json);
+ assertEquals(testGroupId, jsonObj.getString("rep:principalName"));
+ }
+
+ public void testCreateGroupMissingGroupId() throws IOException {
+ String postUrl = HTTP_BASE_URL + "/system/userManager/group.create.html";
+
+ List<NameValuePair> postParams = new ArrayList<NameValuePair>();
+ assertAuthenticatedAdminPostStatus(postUrl, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, postParams, null);
+ }
+
+ public void testCreateGroupAlreadyExists() throws IOException {
+ String postUrl = HTTP_BASE_URL + "/system/userManager/group.create.html";
+
+ testGroupId = "testGroup" + (counter++);
+ List<NameValuePair> postParams = new ArrayList<NameValuePair>();
+ postParams.add(new NameValuePair(":name", testGroupId));
+ assertAuthenticatedAdminPostStatus(postUrl, HttpServletResponse.SC_OK, postParams, null);
+
+ //post the same info again, should fail
+ assertAuthenticatedAdminPostStatus(postUrl, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, postParams, null);
+ }
+
+ public void testCreateGroupWithExtraProperties() throws IOException, JSONException {
+ String postUrl = HTTP_BASE_URL + "/system/userManager/group.create.html";
+
+ testGroupId = "testGroup" + (counter++);
+ List<NameValuePair> postParams = new ArrayList<NameValuePair>();
+ postParams.add(new NameValuePair(":name", testGroupId));
+ postParams.add(new NameValuePair("displayName", "My Test Group"));
+ postParams.add(new NameValuePair("url", "http://www.apache.org"));
+ assertAuthenticatedAdminPostStatus(postUrl, HttpServletResponse.SC_OK, postParams, null);
+
+ //fetch the group profile json to verify the settings
+ String getUrl = HTTP_BASE_URL + "/system/userManager/group/" + testGroupId + ".json";
+ Credentials creds = new UsernamePasswordCredentials("admin", "admin");
+ String json = getAuthenticatedContent(creds, getUrl, CONTENT_TYPE_JSON, null, HttpServletResponse.SC_OK);
+ assertNotNull(json);
+ JSONObject jsonObj = new JSONObject(json);
+ assertEquals(testGroupId, jsonObj.getString("rep:principalName"));
+ assertEquals("My Test Group", jsonObj.getString("displayName"));
+ assertEquals("http://www.apache.org", jsonObj.getString("url"));
+ }
+}
diff --git a/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/userManager/CreateUserTest.java b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/userManager/CreateUserTest.java
new file mode 100644
index 0000000..2fcdc93
--- /dev/null
+++ b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/userManager/CreateUserTest.java
@@ -0,0 +1,155 @@
+/*
+ * 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.launchpad.webapp.integrationtest.userManager;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.httpclient.Credentials;
+import org.apache.commons.httpclient.NameValuePair;
+import org.apache.commons.httpclient.UsernamePasswordCredentials;
+import org.apache.sling.commons.json.JSONException;
+import org.apache.sling.commons.json.JSONObject;
+
+/**
+ * Tests for the 'createUser' Sling Post Operation
+ */
+public class CreateUserTest extends AbstractUserManagerTest {
+
+ String testUserId = null;
+
+ @Override
+ protected void tearDown() throws Exception {
+ if (testUserId != null) {
+ //remove the test user if it exists.
+ String postUrl = HTTP_BASE_URL + "/system/userManager/user/" + testUserId + ".delete.html";
+ List<NameValuePair> postParams = new ArrayList<NameValuePair>();
+ assertAuthenticatedAdminPostStatus(postUrl, HttpServletResponse.SC_OK, postParams, null);
+ }
+ super.tearDown();
+ }
+
+ /*
+ <form action="/system/userManager/user.create.html" method="POST">
+ <div>Name: <input type="text" name=":name" value="testUser" /></div>
+ <div>Password: <input type="text" name="pwd" value="testUser" /></div>
+ <div>Password Confirm: <input type="text" name="pwdConfirm" value="testUser" /></div>
+ <input type="submit" value="Submit" />
+ </form>
+ */
+ public void testCreateUser() throws IOException, JSONException {
+ String postUrl = HTTP_BASE_URL + "/system/userManager/user.create.html";
+
+ testUserId = "testUser" + (counter++);
+ List<NameValuePair> postParams = new ArrayList<NameValuePair>();
+ postParams.add(new NameValuePair(":name", testUserId));
+ postParams.add(new NameValuePair("pwd", "testPwd"));
+ postParams.add(new NameValuePair("pwdConfirm", "testPwd"));
+ assertPostStatus(postUrl, HttpServletResponse.SC_OK, postParams, null);
+
+ //fetch the user profile json to verify the settings
+ String getUrl = HTTP_BASE_URL + "/system/userManager/user/" + testUserId + ".json";
+ Credentials creds = new UsernamePasswordCredentials("admin", "admin");
+ String json = getAuthenticatedContent(creds, getUrl, CONTENT_TYPE_JSON, null, HttpServletResponse.SC_OK);
+ assertNotNull(json);
+ JSONObject jsonObj = new JSONObject(json);
+ assertEquals(testUserId, jsonObj.getString("rep:principalName"));
+ assertFalse(jsonObj.has(":name"));
+ assertFalse(jsonObj.has("pwd"));
+ assertFalse(jsonObj.has("pwdConfirm"));
+ }
+
+ public void testCreateUserMissingUserId() throws IOException {
+ String postUrl = HTTP_BASE_URL + "/system/userManager/user.create.html";
+
+ List<NameValuePair> postParams = new ArrayList<NameValuePair>();
+ assertPostStatus(postUrl, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, postParams, null);
+ }
+
+ public void testCreateUserMissingPwd() throws IOException {
+ String postUrl = HTTP_BASE_URL + "/system/userManager/user.create.html";
+
+ String userId = "testUser" + (counter++);
+ List<NameValuePair> postParams = new ArrayList<NameValuePair>();
+ postParams.add(new NameValuePair(":name", userId));
+ assertPostStatus(postUrl, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, postParams, null);
+ }
+
+ public void testCreateUserWrongConfirmPwd() throws IOException {
+ String postUrl = HTTP_BASE_URL + "/system/userManager/user.create.html";
+
+ String userId = "testUser" + (counter++);
+ List<NameValuePair> postParams = new ArrayList<NameValuePair>();
+ postParams.add(new NameValuePair(":name", userId));
+ postParams.add(new NameValuePair("pwd", "testPwd"));
+ postParams.add(new NameValuePair("pwdConfirm", "testPwd2"));
+ assertPostStatus(postUrl, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, postParams, null);
+ }
+
+ public void testCreateUserUserAlreadyExists() throws IOException {
+ String postUrl = HTTP_BASE_URL + "/system/userManager/user.create.html";
+
+ testUserId = "testUser" + (counter++);
+ List<NameValuePair> postParams = new ArrayList<NameValuePair>();
+ postParams.add(new NameValuePair(":name", testUserId));
+ postParams.add(new NameValuePair("pwd", "testPwd"));
+ postParams.add(new NameValuePair("pwdConfirm", "testPwd"));
+ assertPostStatus(postUrl, HttpServletResponse.SC_OK, postParams, null);
+
+ //post the same info again, should fail
+ assertPostStatus(postUrl, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, postParams, null);
+ }
+
+ /*
+ <form action="/system/userManager/user.create.html" method="POST">
+ <div>Name: <input type="text" name=":name" value="testUser" /></div>
+ <div>Password: <input type="text" name="pwd" value="testUser" /></div>
+ <div>Password Confirm: <input type="text" name="pwdConfirm" value="testUser" /></div>
+ <div>Extra Property #1: <input type="text" name="displayName" value="My Test User" /></div>
+ <div>Extra Property #2: <input type="text" name="url" value="http://www.apache.org" /></div>
+ <input type="submit" value="Submit" />
+ </form>
+ */
+ public void testCreateUserWithExtraProperties() throws IOException, JSONException {
+ String postUrl = HTTP_BASE_URL + "/system/userManager/user.create.html";
+
+ testUserId = "testUser" + (counter++);
+ List<NameValuePair> postParams = new ArrayList<NameValuePair>();
+ postParams.add(new NameValuePair(":name", testUserId));
+ postParams.add(new NameValuePair("pwd", "testPwd"));
+ postParams.add(new NameValuePair("pwdConfirm", "testPwd"));
+ postParams.add(new NameValuePair("displayName", "My Test User"));
+ postParams.add(new NameValuePair("url", "http://www.apache.org"));
+ assertPostStatus(postUrl, HttpServletResponse.SC_OK, postParams, null);
+
+ //fetch the user profile json to verify the settings
+ String getUrl = HTTP_BASE_URL + "/system/userManager/user/" + testUserId + ".json";
+ Credentials creds = new UsernamePasswordCredentials("admin", "admin");
+ String json = getAuthenticatedContent(creds, getUrl, CONTENT_TYPE_JSON, null, HttpServletResponse.SC_OK);
+ assertNotNull(json);
+ JSONObject jsonObj = new JSONObject(json);
+ assertEquals(testUserId, jsonObj.getString("rep:principalName"));
+ assertEquals("My Test User", jsonObj.getString("displayName"));
+ assertEquals("http://www.apache.org", jsonObj.getString("url"));
+ assertFalse(jsonObj.has(":name"));
+ assertFalse(jsonObj.has("pwd"));
+ assertFalse(jsonObj.has("pwdConfirm"));
+ }
+}
diff --git a/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/userManager/RemoveAuthorizablesTest.java b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/userManager/RemoveAuthorizablesTest.java
new file mode 100644
index 0000000..35b7172
--- /dev/null
+++ b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/userManager/RemoveAuthorizablesTest.java
@@ -0,0 +1,90 @@
+/*
+ * 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.launchpad.webapp.integrationtest.userManager;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.httpclient.Credentials;
+import org.apache.commons.httpclient.NameValuePair;
+import org.apache.commons.httpclient.UsernamePasswordCredentials;
+
+/**
+ * Tests for the 'removeAuthorizable' Sling Post Operation
+ */
+public class RemoveAuthorizablesTest extends AbstractUserManagerTest {
+
+ public void testRemoveUser() throws IOException {
+ String userId = createTestUser();
+
+ Credentials creds = new UsernamePasswordCredentials("admin", "admin");
+
+ String getUrl = HTTP_BASE_URL + "/system/userManager/user/" + userId + ".json";
+ assertAuthenticatedHttpStatus(creds, getUrl, HttpServletResponse.SC_OK, null); //make sure the profile request returns some data
+
+ String postUrl = HTTP_BASE_URL + "/system/userManager/user/" + userId + ".delete.html";
+ List<NameValuePair> postParams = new ArrayList<NameValuePair>();
+ assertAuthenticatedPostStatus(creds, postUrl, HttpServletResponse.SC_OK, postParams, null);
+
+ getUrl = HTTP_BASE_URL + "/system/userManager/user/" + userId + ".json";
+ assertAuthenticatedHttpStatus(creds, getUrl, HttpServletResponse.SC_NOT_FOUND, null); //make sure the profile request returns some data
+ }
+
+ public void testRemoveGroup() throws IOException {
+ String groupId = createTestGroup();
+
+ Credentials creds = new UsernamePasswordCredentials("admin", "admin");
+
+ String getUrl = HTTP_BASE_URL + "/system/userManager/group/" + groupId + ".json";
+ assertAuthenticatedHttpStatus(creds, getUrl, HttpServletResponse.SC_OK, null); //make sure the profile request returns some data
+
+ String postUrl = HTTP_BASE_URL + "/system/userManager/group/" + groupId + ".delete.html";
+ List<NameValuePair> postParams = new ArrayList<NameValuePair>();
+ assertAuthenticatedPostStatus(creds, postUrl, HttpServletResponse.SC_OK, postParams, null);
+
+ getUrl = HTTP_BASE_URL + "/system/userManager/group/" + groupId + ".json";
+ assertAuthenticatedHttpStatus(creds, getUrl, HttpServletResponse.SC_NOT_FOUND, null); //make sure the profile request returns some data
+ }
+
+ public void testRemoveAuthorizables() throws IOException {
+ String userId = createTestUser();
+ String groupId = createTestGroup();
+
+ Credentials creds = new UsernamePasswordCredentials("admin", "admin");
+
+ String getUrl = HTTP_BASE_URL + "/system/userManager/user/" + userId + ".json";
+ assertAuthenticatedHttpStatus(creds, getUrl, HttpServletResponse.SC_OK, null); //make sure the profile request returns some data
+
+ getUrl = HTTP_BASE_URL + "/system/userManager/group/" + groupId + ".json";
+ assertAuthenticatedHttpStatus(creds, getUrl, HttpServletResponse.SC_OK, null); //make sure the profile request returns some data
+
+ String postUrl = HTTP_BASE_URL + "/system/userManager.delete.html";
+ List<NameValuePair> postParams = new ArrayList<NameValuePair>();
+ postParams.add(new NameValuePair(":applyTo", "group/" + groupId));
+ postParams.add(new NameValuePair(":applyTo", "user/" + userId));
+ assertAuthenticatedPostStatus(creds, postUrl, HttpServletResponse.SC_OK, postParams, null);
+
+ getUrl = HTTP_BASE_URL + "/system/userManager/user/" + userId + ".json";
+ assertAuthenticatedHttpStatus(creds, getUrl, HttpServletResponse.SC_NOT_FOUND, null); //make sure the profile request returns some data
+
+ getUrl = HTTP_BASE_URL + "/system/userManager/group/" + groupId + ".json";
+ assertAuthenticatedHttpStatus(creds, getUrl, HttpServletResponse.SC_NOT_FOUND, null); //make sure the profile request returns some data
+ }
+}
diff --git a/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/userManager/UpdateGroupTest.java b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/userManager/UpdateGroupTest.java
new file mode 100644
index 0000000..41f9d71
--- /dev/null
+++ b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/userManager/UpdateGroupTest.java
@@ -0,0 +1,90 @@
+/*
+ * 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.launchpad.webapp.integrationtest.userManager;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.httpclient.Credentials;
+import org.apache.commons.httpclient.NameValuePair;
+import org.apache.commons.httpclient.UsernamePasswordCredentials;
+import org.apache.sling.commons.json.JSONException;
+import org.apache.sling.commons.json.JSONObject;
+
+/**
+ * Tests for the 'updateAuthorizable' Sling Post Operation on
+ * a group resource.
+ */
+public class UpdateGroupTest extends AbstractUserManagerTest {
+
+ String testGroupId = null;
+
+ @Override
+ protected void tearDown() throws Exception {
+ if (testGroupId != null) {
+ //remove the test user if it exists.
+ String postUrl = HTTP_BASE_URL + "/system/userManager/group/" + testGroupId + ".delete.html";
+ List<NameValuePair> postParams = new ArrayList<NameValuePair>();
+ assertAuthenticatedAdminPostStatus(postUrl, HttpServletResponse.SC_OK, postParams, null);
+ }
+
+ super.tearDown();
+ }
+
+ public void testUpdateGroup() throws IOException, JSONException {
+ testGroupId = createTestGroup();
+
+ String postUrl = HTTP_BASE_URL + "/system/userManager/group/" + testGroupId + ".update.html";
+
+ List<NameValuePair> postParams = new ArrayList<NameValuePair>();
+ postParams.add(new NameValuePair("displayName", "My Updated Test Group"));
+ postParams.add(new NameValuePair("url", "http://www.apache.org/updated"));
+
+ Credentials creds = new UsernamePasswordCredentials("admin", "admin");
+ assertAuthenticatedPostStatus(creds, postUrl, HttpServletResponse.SC_OK, postParams, null);
+
+ //fetch the user profile json to verify the settings
+ String getUrl = HTTP_BASE_URL + "/system/userManager/group/" + testGroupId + ".json";
+ assertAuthenticatedHttpStatus(creds, getUrl, HttpServletResponse.SC_OK, null); //make sure the profile request returns some data
+ String json = getAuthenticatedContent(creds, getUrl, CONTENT_TYPE_JSON, null, HttpServletResponse.SC_OK);
+ assertNotNull(json);
+ JSONObject jsonObj = new JSONObject(json);
+ assertEquals("My Updated Test Group", jsonObj.getString("displayName"));
+ assertEquals("http://www.apache.org/updated", jsonObj.getString("url"));
+ }
+
+ public void testUpdateGroupMembers() throws IOException, JSONException {
+ testGroupId = createTestGroup();
+
+ String postUrl = HTTP_BASE_URL + "/system/userManager/group/" + testGroupId + ".update.html";
+
+ //TODO: verify this works....
+ List<NameValuePair> postParams = new ArrayList<NameValuePair>();
+ postParams.add(new NameValuePair(":member", "../user/testUser"));
+ postParams.add(new NameValuePair(":member@Delete", "testGroup"));
+
+ Credentials creds = new UsernamePasswordCredentials("admin", "admin");
+ assertAuthenticatedPostStatus(creds, postUrl, HttpServletResponse.SC_OK, postParams, null);
+
+ //TODO: verify the group membership is correct....
+ }
+
+}
+
diff --git a/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/userManager/UpdateUserTest.java b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/userManager/UpdateUserTest.java
new file mode 100644
index 0000000..cd40386
--- /dev/null
+++ b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/userManager/UpdateUserTest.java
@@ -0,0 +1,116 @@
+/*
+ * 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.launchpad.webapp.integrationtest.userManager;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.httpclient.Credentials;
+import org.apache.commons.httpclient.NameValuePair;
+import org.apache.commons.httpclient.UsernamePasswordCredentials;
+import org.apache.sling.commons.json.JSONException;
+import org.apache.sling.commons.json.JSONObject;
+
+/**
+ * Tests for the 'updateAuthorizable' and 'changePassword' Sling Post
+ * Operations on a user resource.
+ */
+public class UpdateUserTest extends AbstractUserManagerTest {
+
+ String testUserId = null;
+
+ @Override
+ protected void tearDown() throws Exception {
+ if (testUserId != null) {
+ //remove the test user if it exists.
+ String postUrl = HTTP_BASE_URL + "/system/userManager/user/" + testUserId + ".delete.html";
+ List<NameValuePair> postParams = new ArrayList<NameValuePair>();
+ assertAuthenticatedAdminPostStatus(postUrl, HttpServletResponse.SC_OK, postParams, null);
+ }
+
+ super.tearDown();
+ }
+
+ public void testUpdateUser() throws IOException, JSONException {
+ testUserId = createTestUser();
+
+ String postUrl = HTTP_BASE_URL + "/system/userManager/user/" + testUserId + ".update.html";
+
+ List<NameValuePair> postParams = new ArrayList<NameValuePair>();
+ postParams.add(new NameValuePair("displayName", "My Updated Test User"));
+ postParams.add(new NameValuePair("url", "http://www.apache.org/updated"));
+ Credentials creds = new UsernamePasswordCredentials(testUserId, "testPwd");
+ assertAuthenticatedPostStatus(creds, postUrl, HttpServletResponse.SC_OK, postParams, null);
+
+ //fetch the user profile json to verify the settings
+ String getUrl = HTTP_BASE_URL + "/system/userManager/user/" + testUserId + ".json";
+ assertAuthenticatedHttpStatus(creds, getUrl, HttpServletResponse.SC_OK, null); //make sure the profile request returns some data
+ String json = getAuthenticatedContent(creds, getUrl, CONTENT_TYPE_JSON, null, HttpServletResponse.SC_OK);
+ assertNotNull(json);
+ JSONObject jsonObj = new JSONObject(json);
+ assertEquals("My Updated Test User", jsonObj.getString("displayName"));
+ assertEquals("http://www.apache.org/updated", jsonObj.getString("url"));
+ }
+
+ public void testChangeUserPassword() throws IOException {
+ testUserId = createTestUser();
+
+ String postUrl = HTTP_BASE_URL + "/system/userManager/user/" + testUserId + ".changePassword.html";
+
+ List<NameValuePair> postParams = new ArrayList<NameValuePair>();
+ postParams.add(new NameValuePair("oldPwd", "testPwd"));
+ postParams.add(new NameValuePair("newPwd", "testNewPwd"));
+ postParams.add(new NameValuePair("newPwdConfirm", "testNewPwd"));
+
+ Credentials creds = new UsernamePasswordCredentials(testUserId, "testPwd");
+ assertAuthenticatedPostStatus(creds, postUrl, HttpServletResponse.SC_OK, postParams, null);
+ }
+
+ public void testChangeUserPasswordWrongOldPwd() throws IOException {
+ testUserId = createTestUser();
+
+ String postUrl = HTTP_BASE_URL + "/system/userManager/user/" + testUserId + ".changePassword.html";
+
+ List<NameValuePair> postParams = new ArrayList<NameValuePair>();
+ postParams.add(new NameValuePair("oldPwd", "wrongTestPwd"));
+ postParams.add(new NameValuePair("newPwd", "testNewPwd"));
+ postParams.add(new NameValuePair("newPwdConfirm", "testNewPwd"));
+
+ //Credentials creds = new UsernamePasswordCredentials(testUserId, "testPwd");
+ Credentials creds = new UsernamePasswordCredentials("admin", "admin");
+ assertAuthenticatedPostStatus(creds, postUrl, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, postParams, null);
+ }
+
+ public void testChangeUserPasswordWrongConfirmPwd() throws IOException {
+ testUserId = createTestUser();
+
+ String postUrl = HTTP_BASE_URL + "/system/userManager/user/" + testUserId + ".changePassword.html";
+
+ List<NameValuePair> postParams = new ArrayList<NameValuePair>();
+ postParams.add(new NameValuePair("oldPwd", "testPwd"));
+ postParams.add(new NameValuePair("newPwd", "testNewPwd"));
+ postParams.add(new NameValuePair("newPwdConfirm", "wrongTestNewPwd"));
+
+ //Credentials creds = new UsernamePasswordCredentials(testUserId, "testPwd");
+ Credentials creds = new UsernamePasswordCredentials("admin", "admin");
+ assertAuthenticatedPostStatus(creds, postUrl, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, postParams, null);
+ }
+
+}
diff --git a/src/test/resources/integration-test/builtin-objects.esp b/src/test/resources/integration-test/builtin-objects.esp
new file mode 100644
index 0000000..a14cd05
--- /dev/null
+++ b/src/test/resources/integration-test/builtin-objects.esp
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+
+<%-- used by ScriptBuiltinObjectsTest --%>
+<html>
+ <body>
+ <h1>ESP template</h1>
+ <p>currentNode.text:<%= currentNode.text %></p>
+ </body>
+
+ <!--
+ TODO we should test access to a well-known service
+ via the ServiceLocator - for now just check that it's
+ available
+ -->
+ <%
+ var sc = sling.getService(Packages.java.lang.String);
+ %>
+ <p>sc:<%= sc %></p>
+
+ <!-- test access to Response -->
+ <p>SlingHttpServletResponse:<%= response.containsHeader('NOT_A_HEADER') %></p>
+
+ <!-- sling object is tested elsewhere (IncludeTest) -->
+
+</html>
diff --git a/src/test/resources/integration-test/dump-resource.ecma b/src/test/resources/integration-test/dump-resource.ecma
new file mode 100644
index 0000000..9000dd2
--- /dev/null
+++ b/src/test/resources/integration-test/dump-resource.ecma
@@ -0,0 +1,31 @@
+/*
+ * 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.
+ */
+
+// recursive dump of a Resource in server-side javascript
+
+function dumpResource(r, level) {
+ out.print(level + " " + r + '\n');
+
+ var iterator = r.resourceResolver.listChildren(r);
+ while(iterator.hasNext()) {
+ dumpResource(iterator.next(), level + 1);
+ }
+}
+
+dumpResource(resource, 1);
diff --git a/src/test/resources/integration-test/esp-load/included-a.esp b/src/test/resources/integration-test/esp-load/included-a.esp
new file mode 100644
index 0000000..56f05f9
--- /dev/null
+++ b/src/test/resources/integration-test/esp-load/included-a.esp
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ */
+
+// Test SLING-428
+included-a.esp before load.
+
+<% load("subfolder/included-b.esp"); %>
+
+included-a.esp after load
+
+<%
+// esp is templating, so one needs to enclose functions
+// in the appropriate markers
+function functionFromIncludedA() {
+ %>Here's more from included-a<%
+}
+%>
\ No newline at end of file
diff --git a/src/test/resources/integration-test/esp-load/main.esp b/src/test/resources/integration-test/esp-load/main.esp
new file mode 100644
index 0000000..5bd09b9
--- /dev/null
+++ b/src/test/resources/integration-test/esp-load/main.esp
@@ -0,0 +1,27 @@
+/*
+ * 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.
+ */
+
+// Test SLING-428
+main.esp before load.
+
+<% load(currentNode.scriptToInclude); %>
+
+main.esp after load
+
+<% functionFromIncludedA() %>
\ No newline at end of file
diff --git a/src/test/resources/integration-test/esp-load/subfolder/included-b.esp b/src/test/resources/integration-test/esp-load/subfolder/included-b.esp
new file mode 100644
index 0000000..a1342f4
--- /dev/null
+++ b/src/test/resources/integration-test/esp-load/subfolder/included-b.esp
@@ -0,0 +1,21 @@
+/*
+ * 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.
+ */
+
+// Test SLING-428
+included-b.esp
\ No newline at end of file
diff --git a/src/test/resources/integration-test/file-to-upload.txt b/src/test/resources/integration-test/file-to-upload.txt
new file mode 100644
index 0000000..367f23d
--- /dev/null
+++ b/src/test/resources/integration-test/file-to-upload.txt
@@ -0,0 +1,12 @@
+This file is used by UploadFileTest.java.
+
+In must contain http://www.apache.org/licenses/LICENSE-2.0 for tests.
+
+Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Fusce semper ipsum et lorem. In hac habitasse
+platea dictumst. Donec dictum tincidunt purus. Aenean quis nunc. Aliquam rhoncus. Proin sed risus.
+Maecenas porta arcu in nisi. Pellentesque quis sapien quis lectus vehicula aliquet. Cras ornare elit
+eget massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Sed
+ut justo. Integer porttitor quam. Aliquam aliquet. Nulla interdum arcu vitae nibh. Morbi dapibus odio
+a sem. Integer dictum. Praesent vel eros nec ipsum venenatis malesuada. Vestibulum rutrum mi ac ligula.
+Ut nisl ligula, vehicula dignissim, accumsan quis, faucibus sed, sapien. Quisque purus tellus, euismod
+id, auctor quis, rutrum non, augue.
\ No newline at end of file
diff --git a/src/test/resources/integration-test/forward-forced.esp b/src/test/resources/integration-test/forward-forced.esp
new file mode 100644
index 0000000..90670f5
--- /dev/null
+++ b/src/test/resources/integration-test/forward-forced.esp
@@ -0,0 +1,31 @@
+<%
+
+/*
+ * 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.
+ */
+
+// used by ForwardTest
+%><html>
+ <body>
+ <h1>ESP template</h1>
+ <p class="main"><%= currentNode.text %></p>
+ <div>
+ Forced resource type:<%= resource.resourceType %></p>.
+ </div>
+ </body>
+</html>
\ No newline at end of file
diff --git a/src/test/resources/integration-test/forward-forced.jsp b/src/test/resources/integration-test/forward-forced.jsp
new file mode 100644
index 0000000..aa1d247
--- /dev/null
+++ b/src/test/resources/integration-test/forward-forced.jsp
@@ -0,0 +1,31 @@
+<%--
+/*
+ * 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.
+--%><%@page session="false"%><%
+%><%@taglib prefix="sling" uri="http://sling.apache.org/taglibs/sling/1.0"%><%
+%><sling:defineObjects/><%
+// used by ForwardTest
+%><html>
+ <body>
+ <h1>JSP template</h1>
+ <p class="main"><%= currentNode.getProperty("text").getString() %></p>
+ <div>
+ Forced resource type:<%= resource.getResourceType() %></p>.
+ </div>
+ </body>
+</html>
\ No newline at end of file
diff --git a/src/test/resources/integration-test/forward-test.esp b/src/test/resources/integration-test/forward-test.esp
new file mode 100644
index 0000000..fcf29d6
--- /dev/null
+++ b/src/test/resources/integration-test/forward-test.esp
@@ -0,0 +1,53 @@
+<%
+
+/*
+ * 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.
+ */
+
+// used by ForwardTest
+
+// Test 3: Forced Resource Type
+if(currentNode.pathToInclude && currentNode.forceResourceType) {
+ sling.forward(currentNode.pathToInclude, currentNode.forceResourceType);
+}
+
+else
+
+// Test 1: Simple Forward
+if(currentNode.pathToInclude) {
+ sling.forward(currentNode.pathToInclude);
+}
+
+else
+
+// Test 2: Infinite Loop
+if(currentNode.testInfiniteLoop) {
+ // try to include the item itself, to cause an infinite loop
+ sling.forward(resource.getPath());
+} else {
+
+// Test 0: No Forward
+%><html>
+ <body>
+ <h1>ESP template</h1>
+ <p class="main"><%= currentNode.text %></p>
+ </body>
+</html><%
+
+}
+%>
\ No newline at end of file
diff --git a/src/test/resources/integration-test/forward-test.jsp b/src/test/resources/integration-test/forward-test.jsp
new file mode 100644
index 0000000..012449b
--- /dev/null
+++ b/src/test/resources/integration-test/forward-test.jsp
@@ -0,0 +1,76 @@
+<%--
+/*
+ * 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.
+--%><%@page session="false"%><%
+%><%@taglib prefix="sling" uri="http://sling.apache.org/taglibs/sling/1.0"%><%
+%><sling:defineObjects/><%
+
+// used by JspForwardTest
+%><%!
+
+private String getProperty(javax.jcr.Node node, String propertyName) {
+ try {
+ if (node.hasProperty(propertyName)) {
+ return node.getProperty(propertyName).getString();
+ }
+ } catch (Throwable t) {
+ // don't care
+ }
+ return null;
+}
+
+%><%
+
+String pathToInclude = getProperty(currentNode, "pathToInclude");
+String forceResourceType = getProperty(currentNode, "forceResourceType");
+String testInfiniteLoop = getProperty(currentNode, "testInfiniteLoop");
+
+// Test 3: Forced Resource Type
+if(pathToInclude != null && forceResourceType != null) {
+ %><sling:forward path="<%= pathToInclude %>" resourceType="<%= forceResourceType %>"/><%
+}
+
+else
+
+// Test 1: Simple Forward
+if(pathToInclude != null) {
+ %><sling:forward path="<%= pathToInclude %>"/><%
+}
+
+else
+
+// Test 2: Infinite Loop
+if(testInfiniteLoop != null) {
+ // try to include the item itself, to cause an infinite loop
+ %><sling:forward path="<%= resource.getPath() %>"/><%
+}
+
+else
+
+{
+
+// Test 0: No Forward
+%><html>
+ <body>
+ <h1>JSP template</h1>
+ <p class="main"><%= currentNode.getProperty("text").getString() %></p>
+ </body>
+</html><%
+
+}
+%>
\ No newline at end of file
diff --git a/src/test/resources/integration-test/include-forced.esp b/src/test/resources/integration-test/include-forced.esp
new file mode 100644
index 0000000..a3deb82
--- /dev/null
+++ b/src/test/resources/integration-test/include-forced.esp
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ */
+
+<%-- used by IncludeTest --%>
+<div>
+ Forced resource type:<%= currentNode.text %></p>.
+</div>
\ No newline at end of file
diff --git a/src/test/resources/integration-test/include-forced.jsp b/src/test/resources/integration-test/include-forced.jsp
new file mode 100644
index 0000000..5e756d7
--- /dev/null
+++ b/src/test/resources/integration-test/include-forced.jsp
@@ -0,0 +1,26 @@
+<%--
+/*
+ * 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.
+ */
+--%><%@page session="false"%><%
+%><%@taglib prefix="sling" uri="http://sling.apache.org/taglibs/sling/1.0"%><%
+%><sling:defineObjects/><%
+// used by ForwardTest
+%><div>
+ Forced resource type:<%= resource.getResourceType() %></p>.
+</div>
diff --git a/src/test/resources/integration-test/include-test.esp b/src/test/resources/integration-test/include-test.esp
new file mode 100644
index 0000000..15095b6
--- /dev/null
+++ b/src/test/resources/integration-test/include-test.esp
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ */
+
+<%-- used by IncludeTest --%>
+<html>
+ <body>
+ <h1>ESP template</h1>
+ <p class="main"><%= currentNode.text %></p>
+
+ <h2>Test 1</h2>
+ <%
+ if(currentNode.pathToInclude) {
+ %>
+ <p>pathToInclude = <%= currentNode.pathToInclude %></p>
+ <p>Including <%= currentNode.pathToInclude %></p>
+ <%
+ sling.include(currentNode.pathToInclude);
+ }
+ %>
+
+ <h2>Test 2</h2>
+ <%
+ if(currentNode.testInfiniteLoop) {
+ %>
+ <p>testInfiniteLoop = <%= currentNode.testInfiniteLoop %></p>
+ <%
+ // try to include the item itself, to cause an infinite loop
+ sling.include(resource.getPath());
+ }
+ %>
+
+ <h2>Test 3</h2>
+ <%
+ if(currentNode.pathToInclude && currentNode.forceResourceType) {
+ %>
+ <p>pathToInclude = <%= currentNode.pathToInclude %></p>
+ <p>Including <%= currentNode.pathToInclude %></p>
+ <%
+ sling.include(currentNode.pathToInclude, currentNode.forceResourceType);
+ }
+ %>
+ </body>
+</html>
diff --git a/src/test/resources/integration-test/include-test.jsp b/src/test/resources/integration-test/include-test.jsp
new file mode 100644
index 0000000..75a3f2b
--- /dev/null
+++ b/src/test/resources/integration-test/include-test.jsp
@@ -0,0 +1,103 @@
+<%--
+/*
+ * 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.
+--%><%@page session="false"%><%
+%><%@taglib prefix="sling" uri="http://sling.apache.org/taglibs/sling/1.0"%><%
+%><sling:defineObjects/><%
+
+// used by IncludeTest
+%><%!
+
+private String getProperty(javax.jcr.Node node, String propertyName) {
+ try {
+ if (node.hasProperty(propertyName)) {
+ return node.getProperty(propertyName).getString();
+ }
+ } catch (Throwable t) {
+ // don't care
+ }
+ return null;
+}
+
+%><%
+
+String text = getProperty(currentNode, "text");
+String pathToInclude = getProperty(currentNode, "pathToInclude");
+String forceResourceType = getProperty(currentNode, "forceResourceType");
+String testInfiniteLoop = getProperty(currentNode, "testInfiniteLoop");
+String testMaxCalls = getProperty(currentNode, "testMaxCalls");
+
+%><html>
+ <body>
+ <h1>JSP template</h1>
+ <p class="main"><%= text %></p>
+
+ <h2>Test 1</h2>
+ <%
+ if(pathToInclude != null) {
+ %>
+ <p>pathToInclude = <%= pathToInclude %></p>
+ <p>Including <%= pathToInclude %></p>
+ <sling:include path="<%= pathToInclude %>"/>
+ <%
+ }
+ %>
+
+ <h2>Test 2</h2>
+ <%
+ if(testInfiniteLoop != null) {
+ %>
+ <p>testInfiniteLoop = <%= testInfiniteLoop %></p>
+ <%
+ // try to include the item itself, to cause an infinite loop
+ %>
+ <sling:include path="<%= resource.getPath() %>"/>
+ <%
+ }
+ %>
+
+ <h2>Test 3</h2>
+ <%
+ if(pathToInclude != null && forceResourceType != null) {
+ %>
+ <p>pathToInclude = <%= pathToInclude %></p>
+ <p>Including <%= pathToInclude %></p>
+ <sling:include path="<%= pathToInclude %>" resourceType="<%= forceResourceType %>"/>
+ <%
+ }
+ %>
+
+ <h2>Test 4</h2>
+ <%
+ if(pathToInclude != null && testMaxCalls != null) {
+ %>
+ <p>pathToInclude = <%= pathToInclude %></p>
+ <p>Including <%= pathToInclude %></p>
+ <%
+ for (int i=0; i < 1200; i++) {
+ %>
+ <%= i %><br />
+ <hr />
+ <sling:include path="<%= pathToInclude %>" />
+ <hr />
+ <%
+ }
+ }
+ %>
+ </body>
+</html>
diff --git a/src/test/resources/integration-test/issues/sling457/a-foo.html.jsp b/src/test/resources/integration-test/issues/sling457/a-foo.html.jsp
new file mode 100644
index 0000000..ef434b8
--- /dev/null
+++ b/src/test/resources/integration-test/issues/sling457/a-foo.html.jsp
@@ -0,0 +1,21 @@
+<!--
+/*
+ * 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.
+-->
+<%@page session="false"%>
+foo.html.jsp
\ No newline at end of file
diff --git a/src/test/resources/integration-test/issues/sling457/b-b.jsp b/src/test/resources/integration-test/issues/sling457/b-b.jsp
new file mode 100644
index 0000000..f1c4ac7
--- /dev/null
+++ b/src/test/resources/integration-test/issues/sling457/b-b.jsp
@@ -0,0 +1,27 @@
+<!--
+/*
+ * 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.
+-->
+<%@page session="false"%>
+<%@page import="org.apache.sling.api.SlingHttpServletRequest"%>
+<%@taglib prefix="sling" uri="http://sling.apache.org/taglibs/sling/1.0"%>
+<%
+ SlingHttpServletRequest req = (SlingHttpServletRequest) request;
+ String resType = req.getResource().getResourceType();
+%>
+<sling:include path="./image.foo.html" resourceType="<%= resType %>" />
\ No newline at end of file
diff --git a/src/test/resources/integration-test/issues/sling760/throw-with-markup.esp b/src/test/resources/integration-test/issues/sling760/throw-with-markup.esp
new file mode 100644
index 0000000..f600bcf
--- /dev/null
+++ b/src/test/resources/integration-test/issues/sling760/throw-with-markup.esp
@@ -0,0 +1,5 @@
+<%
+// SLING-760: test an error message with characters that must
+// be escaped
+throw("This string contains <characters/> that must be filtered & escaped");
+%>
\ No newline at end of file
diff --git a/src/test/resources/integration-test/no-code.esp b/src/test/resources/integration-test/no-code.esp
new file mode 100644
index 0000000..cb9db23
--- /dev/null
+++ b/src/test/resources/integration-test/no-code.esp
@@ -0,0 +1 @@
+There's no code in this script, just this constant string
\ No newline at end of file
diff --git a/src/test/resources/integration-test/post-test.esp b/src/test/resources/integration-test/post-test.esp
new file mode 100644
index 0000000..c7cffe9
--- /dev/null
+++ b/src/test/resources/integration-test/post-test.esp
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+
+<%
+var length = 0;
+if (request.getRequestParameter("file") != null) {
+ var file = null;
+ // store file
+ var reqPara = request.getRequestParameter("file");
+ var is = reqPara.getInputStream();
+ file = Packages.java.io.File.createTempFile("posttest", ".txt");
+ var fout = new Packages.java.io.FileOutputStream(file);
+ var c;
+ while ((c = is.read()) != -1) {
+ fout.write(c);
+ }
+ fout.close();
+
+ // read length
+ length = file.length();
+}
+%><%= Packages.java.lang.String.valueOf(length) %>
\ No newline at end of file
diff --git a/src/test/resources/integration-test/print.esp b/src/test/resources/integration-test/print.esp
new file mode 100644
index 0000000..dc584ad
--- /dev/null
+++ b/src/test/resources/integration-test/print.esp
@@ -0,0 +1,22 @@
+/*
+ * 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.
+ */
+
+// Verify that the print() method compiles
+<% print("something from print.esp"); %>
+print.esp ends
\ No newline at end of file
diff --git a/src/test/resources/integration-test/rendering-test-2.esp b/src/test/resources/integration-test/rendering-test-2.esp
new file mode 100644
index 0000000..b469c20
--- /dev/null
+++ b/src/test/resources/integration-test/rendering-test-2.esp
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ */
+
+<%-- used by ScriptedRenderingTest --%>
+<html>
+ <body>
+ Template #2 for ESP tests
+ <p><b><%= currentNode.text %></b></p>
+ </body>
+</html>
diff --git a/src/test/resources/integration-test/rendering-test-3.esp b/src/test/resources/integration-test/rendering-test-3.esp
new file mode 100644
index 0000000..f96eebf
--- /dev/null
+++ b/src/test/resources/integration-test/rendering-test-3.esp
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ */
+
+<%-- used by ScriptedRenderingTest --%>
+<html>
+ <body>
+ Template #3 for ESP tests
+ <p><em><%= currentNode.text %></em></p>
+ </body>
+</html>
diff --git a/src/test/resources/integration-test/rendering-test.ecma b/src/test/resources/integration-test/rendering-test.ecma
new file mode 100644
index 0000000..3c989a3
--- /dev/null
+++ b/src/test/resources/integration-test/rendering-test.ecma
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+// Used by ScriptedRenderingTest
+out.println("<html><body>");
+out.println("Raw javascript template");
+out.println("<p><em>" + currentNode.text + "</em></p>");
+out.print("</body></html>");
diff --git a/src/test/resources/integration-test/rendering-test.esp b/src/test/resources/integration-test/rendering-test.esp
new file mode 100644
index 0000000..63ba195
--- /dev/null
+++ b/src/test/resources/integration-test/rendering-test.esp
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+
+<%-- used by ScriptedRenderingTest --%>
+<html>
+ <body>
+ ESP template
+ <p><%= currentNode.text %></p>
+
+ <!-- test SLING-142, compact syntax -->
+ <div class="SLING-142" id="${'2' + '2'}"/>
+
+ <!-- test access to microsling java classes -->
+ <%
+ var list = new Packages.java.util.LinkedList();
+ list.add("LinkedListTest");
+ %>
+ <p>Test<%= list.get(0) %></p>
+
+ </body>
+</html>
diff --git a/src/test/resources/integration-test/rendering-test.jsp b/src/test/resources/integration-test/rendering-test.jsp
new file mode 100644
index 0000000..0b92d29
--- /dev/null
+++ b/src/test/resources/integration-test/rendering-test.jsp
@@ -0,0 +1,31 @@
+<!--
+/*
+ * 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.
+-->
+<!-- simple JSP rendering test -->
+<%@page session="false"%>
+<%@taglib prefix="sling" uri="http://sling.apache.org/taglibs/sling/1.0"%>
+<sling:defineObjects/>
+
+<h1>JSP rendering result</h1>
+<p>
+ text value using resource.adaptTo:<%= resource.adaptTo(javax.jcr.Node.class).getProperty("text").getValue().getString() %>
+</p>
+<p>
+ text value using currentNode:<%= currentNode.getProperty("text").getValue().getString() %>
+</p>
diff --git a/src/test/resources/integration-test/request-attribute-test-sel1.esp b/src/test/resources/integration-test/request-attribute-test-sel1.esp
new file mode 100644
index 0000000..7de0ad1
--- /dev/null
+++ b/src/test/resources/integration-test/request-attribute-test-sel1.esp
@@ -0,0 +1,34 @@
+<%--
+ * 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.
+-->
+<%-- used by RequestAttributeTest --%>
+<%
+ function /* String */ getServlet() {
+ var servlet = request.getAttribute( "org.apache.sling.api.include.servlet" );
+ if (servlet) {
+ return servlet.servletConfig.servletName;
+ } else {
+ return "null";
+ }
+ }
+%>
+servlet10=<%= getServlet() %>
+resource10=<%= request.getContextPath() + request.getAttribute( "org.apache.sling.api.include.resource" ) %>
+<% sling.include(resource.path, "replaceSelectors=sel3"); %>
+servlet11=<%= getServlet() %>
+resource11=<%= request.getContextPath() + request.getAttribute( "org.apache.sling.api.include.resource" ) %>
diff --git a/src/test/resources/integration-test/request-attribute-test-sel2.esp b/src/test/resources/integration-test/request-attribute-test-sel2.esp
new file mode 100644
index 0000000..359c121
--- /dev/null
+++ b/src/test/resources/integration-test/request-attribute-test-sel2.esp
@@ -0,0 +1,31 @@
+<%--
+ * 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.
+-->
+<%-- used by RequestAttributeTest --%>
+<%
+ function /* String */ getServlet() {
+ var servlet = request.getAttribute( "org.apache.sling.api.include.servlet" );
+ if (servlet) {
+ return servlet.servletConfig.servletName;
+ } else {
+ return "null";
+ }
+ }
+%>
+servlet20=<%= getServlet() %>
+resource20=<%= request.getContextPath() + request.getAttribute( "org.apache.sling.api.include.resource" ) %>
diff --git a/src/test/resources/integration-test/request-attribute-test-sel3.esp b/src/test/resources/integration-test/request-attribute-test-sel3.esp
new file mode 100644
index 0000000..cefcb6d
--- /dev/null
+++ b/src/test/resources/integration-test/request-attribute-test-sel3.esp
@@ -0,0 +1,31 @@
+<%--
+ * 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.
+-->
+<%-- used by RequestAttributeTest --%>
+<%
+ function /* String */ getServlet() {
+ var servlet = request.getAttribute( "org.apache.sling.api.include.servlet" );
+ if (servlet) {
+ return servlet.servletConfig.servletName;
+ } else {
+ return "null";
+ }
+ }
+%>
+servlet30=<%= getServlet() %>
+resource30=<%= request.getContextPath() + request.getAttribute( "org.apache.sling.api.include.resource" ) %>
diff --git a/src/test/resources/integration-test/request-attribute-test.esp b/src/test/resources/integration-test/request-attribute-test.esp
new file mode 100644
index 0000000..4c3c15a
--- /dev/null
+++ b/src/test/resources/integration-test/request-attribute-test.esp
@@ -0,0 +1,38 @@
+<%--
+ * 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.
+-->
+<%-- used by RequestAttributeTest --%>
+<%
+ response.setContentType("text/plain");
+ response.setCharacterEncoding("UTF-8");
+
+ function /* String */ getServlet() {
+ var servlet = request.getAttribute( "org.apache.sling.api.include.servlet" );
+ if (servlet) {
+ return servlet.servletConfig.servletName;
+ } else {
+ return "null";
+ }
+ }
+%>
+servlet00=<%= getServlet() %>
+resource00=<%= request.getAttribute( "org.apache.sling.api.include.resource" ) %>
+<% sling.include(resource.path + "/child", "replaceSelectors=sel1"); %>
+<% sling.include(resource.path, "replaceSelectors=sel2"); %>
+servlet01=<%= getServlet() %>
+resource01=<%= request.getAttribute( "org.apache.sling.api.include.resource" ) %>
diff --git a/src/test/resources/integration-test/sling-logo.png b/src/test/resources/integration-test/sling-logo.png
new file mode 100644
index 0000000..0de4b3a
--- /dev/null
+++ b/src/test/resources/integration-test/sling-logo.png
Binary files differ
diff --git a/src/test/resources/integration-test/testfile.html b/src/test/resources/integration-test/testfile.html
new file mode 100644
index 0000000..e95ba6a
--- /dev/null
+++ b/src/test/resources/integration-test/testfile.html
@@ -0,0 +1 @@
+This is <em>testfile.html</em>
\ No newline at end of file
diff --git a/src/test/resources/integration-test/testfile.js b/src/test/resources/integration-test/testfile.js
new file mode 100644
index 0000000..bc9ede4
--- /dev/null
+++ b/src/test/resources/integration-test/testfile.js
@@ -0,0 +1 @@
+// This is testfile.js
\ No newline at end of file
diff --git a/src/test/resources/integration-test/testfile.json b/src/test/resources/integration-test/testfile.json
new file mode 100644
index 0000000..40487f3
--- /dev/null
+++ b/src/test/resources/integration-test/testfile.json
@@ -0,0 +1 @@
+This is testfile.json
\ No newline at end of file
diff --git a/src/test/resources/integration-test/testfile.txt b/src/test/resources/integration-test/testfile.txt
new file mode 100644
index 0000000..6a61609
--- /dev/null
+++ b/src/test/resources/integration-test/testfile.txt
@@ -0,0 +1 @@
+This is just some text in an ASCII file.
\ No newline at end of file
diff --git a/src/test/resources/integration-test/testfile.xml b/src/test/resources/integration-test/testfile.xml
new file mode 100644
index 0000000..728448a
--- /dev/null
+++ b/src/test/resources/integration-test/testfile.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+/*
+ * 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.
+ */
+ -->
+
+<testfile id="42">
+ <some-element>
+ <child-element id="1"/>
+ <child-element id="2"/>
+ </some-element>
+</testfile>
diff --git a/src/test/resources/integration-test/testfile.zip b/src/test/resources/integration-test/testfile.zip
new file mode 100644
index 0000000..46cfd31
--- /dev/null
+++ b/src/test/resources/integration-test/testfile.zip
Binary files differ