SLING-576 - launchpad/webapp integration tests moved to new launchpad/testing module

git-svn-id: https://svn.apache.org/repos/asf/incubator/sling/trunk@680946 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..7ae398f
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,511 @@
+<?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>4-incubator-SNAPSHOT</version>
+        <relativePath>../../parent/pom.xml</relativePath>
+    </parent>
+
+    <artifactId>org.apache.sling.launchpad.testing</artifactId>
+    <packaging>war</packaging>
+    <version>4-incubator-SNAPSHOT</version>
+
+    <name>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/trunk/launchpad/testing</connection>
+        <developerConnection>scm:svn:https://svn.apache.org/repos/asf/incubator/sling/trunk/launchpad/testing</developerConnection>
+        <url>http://svn.apache.org/viewvc/incubator/sling/trunk/launchpad/testing</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>
+    </properties>
+
+    <build>
+        <plugins>
+
+            <plugin>
+                <groupId>org.mortbay.jetty</groupId>
+                <artifactId>maven-jetty-plugin</artifactId>
+                <version>6.1.5</version>
+                <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.app,servlet
+                            </includeArtifactIds>
+                            <excludeTransitive>true</excludeTransitive>
+                            <outputDirectory>
+                                ${project.build.directory}/launchpad-app
+                            </outputDirectory>
+                            <overWriteReleases>false</overWriteReleases>
+                            <overWriteSnapshots>
+                                true
+                            </overWriteSnapshots>
+                        </configuration>
+                    </execution>
+                    <execution>
+                        <!-- Copy bundles that must be initially installed to WEB-INF/resources/bundles -->
+                        <id>copy-dependencies</id>
+                        <goals>
+                            <goal>copy-dependencies</goal>
+                        </goals>
+                        <configuration>
+                            <outputDirectory>
+                                ${project.build.directory}/${project.build.finalName}/WEB-INF/resources/bundles
+                            </outputDirectory>
+                            <excludeTransitive>true</excludeTransitive>
+                            <includeGroupIds>
+                                org.apache.felix,org.apache.sling,org.apache.jackrabbit
+                            </includeGroupIds>
+                            <excludeArtifactIds>
+                              <!-- the app bundle is not needed, we only depend on it to get the same dependencies,
+                                   same is try for the base bundle -->
+                              org.apache.sling.launchpad.app,org.apache.sling.launchpad.base
+                            </excludeArtifactIds>
+                            <includeScope>
+                                provided
+                            </includeScope>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+
+            <!-- Include sling-app launcher classes and resources -->
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-war-plugin</artifactId>
+                <configuration>
+                    <webResources>
+                        <!-- the classes (except unneeded Main) -->
+                        <resource>
+                            <directory>
+                                ${basedir}/target/launchpad-app
+                            </directory>
+                            <targetPath>WEB-INF/classes</targetPath>
+                            <excludes>
+                                <exclude>
+                                    org/apache/sling/launcher/app/main/**
+                                </exclude>
+                                <exclude>
+                                    resources/bundles/org.apache.felix.http.jetty*.jar
+                                </exclude>
+                                <exclude>
+                                    resources/bundles/pax-web-service*.jar
+                                </exclude>
+                                <exclude>
+                                    resources/bundles/org.apache.felix.commons.servlet-api*.jar
+                                </exclude>
+                            </excludes>
+                            <includes>
+                                <include>org/**</include>
+                            </includes>
+                        </resource>
+                        <!-- the configuration resources -->
+                        <resource>
+                            <directory>
+                                ${basedir}/target/launchpad-app
+                            </directory>
+                            <targetPath>WEB-INF</targetPath>
+                            <includes>
+                                <include>resources/**</include>
+                                <include>sling.properties</include>
+                                <include>sling_install.properties</include>
+                                <include>jre-*.properties</include>
+                            </includes>
+                            <excludes>
+                                <exclude>
+                                    resources/bundles/org.apache.felix.http.jetty*.jar
+                                </exclude>
+                                <exclude>
+                                    resources/bundles/pax-web-service*.jar
+                                </exclude>
+                                <exclude>
+                                    resources/bundles/org.apache.felix.commons.servlet-api*.jar
+                                </exclude>
+                            </excludes>
+                        </resource>
+                        <!-- selected WEB-INF resources -->
+                        <resource>
+                            <directory>
+                                ${basedir}/target/launchpad-app
+                            </directory>
+                            <targetPath>/</targetPath>
+                            <includes>
+                                <include>WEB-INF/jcr-client.properties</include>
+                            </includes>
+                        </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>
+
+            <plugin>
+                <artifactId>maven-assembly-plugin</artifactId>
+                <configuration>
+                    <descriptors>
+                        <descriptor>src/main/assembly/bin.xml</descriptor>
+                    </descriptors>
+                </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>
+                        <version>0.3.1</version>
+                        <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>
+                                <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>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.launchpad.app</artifactId>
+            <version>4-incubator-SNAPSHOT</version>
+            <scope>provided</scope>
+            <optional>true</optional>
+        </dependency>
+
+        <dependency>
+            <groupId>org.eclipse.equinox.http</groupId>
+            <artifactId>servlet</artifactId>
+            <scope>provided</scope>
+            <optional>true</optional>
+        </dependency>
+
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.commons.testing</artifactId>
+            <version>2.0.2-incubator</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.commons.json</artifactId>
+            <version>2.0.2-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>
+            <optional>true</optional>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.scripting.javascript</artifactId>
+            <version>2.0.2-incubator</version>
+            <scope>test</scope>
+            <optional>true</optional>
+        </dependency>
+        <dependency>
+            <groupId>commons-httpclient</groupId>
+            <artifactId>commons-httpclient</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-log4j12</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>jcl-over-slf4j</artifactId>
+            <scope>test</scope>
+        </dependency>
+
+        <!-- The servlet container will have to provide these API classes -->
+        <dependency>
+            <groupId>javax.servlet</groupId>
+            <artifactId>servlet-api</artifactId>
+        </dependency>
+    </dependencies>
+</project>
diff --git a/src/main/webapp/WEB-INF/DISCLAIMER b/src/main/webapp/WEB-INF/DISCLAIMER
new file mode 100644
index 0000000..90850c2
--- /dev/null
+++ b/src/main/webapp/WEB-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/webapp/WEB-INF/LICENSE b/src/main/webapp/WEB-INF/LICENSE
new file mode 100644
index 0000000..86c3f2f
--- /dev/null
+++ b/src/main/webapp/WEB-INF/LICENSE
@@ -0,0 +1,1291 @@
+
+                                 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.
+
+
+APACHE SLING SUBCOMPONENTS:
+
+Apache Sling includes subcomponents with separate copyright notices and
+license terms. Your use of these subcomponents is subject to the terms
+and conditions of the following licenses.
+
+JSON in Java
+
+   Copyright (c) 2002 JSON.org
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   "Software"), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   The Software shall be used for Good, not Evil.
+
+   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+
+SLF4J logging libraries
+
+   Copyright (c) 2004-2007 QOS.ch
+   All rights reserved.
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   "Software"), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be
+   included in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+   LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+   OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+   WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+JCR 1.0 API
+
+   Day Management AG ("Licensor") is willing to license this specification
+   to you ONLY UPON THE CONDITION THAT YOU ACCEPT ALL OF THE TERMS CONTAINED
+   IN THIS LICENSE AGREEMENT ("Agreement"). Please read the terms and
+   conditions of this Agreement carefully.
+
+   Content Repository for JavaTM Technology API Specification ("Specification")
+   Version: 1.0
+   Status: FCS
+   Release: 11 May 2005
+
+   Copyright 2005 Day Management AG
+   Barfusserplatz 6, 4001 Basel, Switzerland.
+   All rights reserved.
+
+   NOTICE; LIMITED LICENSE GRANTS
+
+   1. License for Purposes of Evaluation and Developing Applications. Licensor
+   hereby grants you a fully-paid, non-exclusive, non-transferable, worldwide,
+   limited license (without the right to sublicense), under Licensor's
+   applicable intellectual property rights to view, download, use and
+   reproduce the Specification only for the purpose of internal evaluation.
+   This includes developing applications intended to run on an implementation
+   of the Specification provided that such applications do not themselves
+   implement any portion(s) of the Specification.
+
+   2. License for the Distribution of Compliant Implementations. Licensor also
+   grants you a perpetual, non-exclusive, non-transferable, worldwide, fully
+   paid-up, royalty free, limited license (without the right to sublicense)
+   under any applicable copyrights or, subject to the provisions of subsection
+   4 below, patent rights it may have covering the Specification to create
+   and/or distribute an Independent Implementation of the Specification that:
+   (a) fully implements the Specification including all its required
+   interfaces and functionality; (b) does not modify, subset, superset or
+   otherwise extend the Licensor Name Space, or include any public or
+   protected packages, classes, Java interfaces, fields or methods within
+   the Licensor Name Space other than those required/authorized by the
+   Specification or Specifications being implemented; and (c) passes the
+   Technology Compatibility Kit (including satisfying the requirements of the
+   applicable TCK Users Guide) for such Specification ("Compliant
+   Implementation"). In addition, the foregoing license is expressly
+   conditioned on your not acting outside its scope. No license is granted
+   hereunder for any other purpose (including, for example, modifying the
+   Specification, other than to the extent of your fair use rights, or
+   distributing the Specification to third parties).
+
+   3. Pass-through Conditions. You need not include limitations (a)-(c) from
+   the previous paragraph or any other particular "pass through" requirements
+   in any license You grant concerning the use of your Independent
+   Implementation or products derived from it. However, except with respect
+   to Independent Implementations (and products derived from them) that
+   satisfy limitations (a)-(c) from the previous paragraph, You may neither:
+   (a) grant or otherwise pass through to your licensees any licenses under
+   Licensor's applicable intellectual property rights; nor (b) authorize your
+   licensees to make any claims concerning their implementation's compliance
+   with the Specification.
+
+   4. Reciprocity Concerning Patent Licenses. With respect to any patent
+   claims covered by the license granted under subparagraph 2 above that
+   would be infringed by all technically feasible implementations of the
+   Specification, such license is conditioned upon your offering on fair,
+   reasonable and non-discriminatory terms, to any party seeking it from You,
+   a perpetual, non-exclusive, non-transferable, worldwide license under Your
+   patent rights that are or would be infringed by all technically feasible
+   implementations of the Specification to develop, distribute and use a
+   Compliant Implementation.
+
+   5. Definitions. For the purposes of this Agreement: "Independent
+   Implementation" shall mean an implementation of the Specification that
+   neither derives from any of Licensor's source code or binary code materials
+   nor, except with an appropriate and separate license from Licensor,
+   includes any of Licensor's source code or binary code materials; "Licensor
+   Name Space" shall mean the public class or interface declarations whose
+   names begin with "java", "javax", "javax.jcr" or their equivalents in any
+   subsequent naming convention adopted by Licensor through the Java Community
+   Process, or any recognized successors or replacements thereof; and
+   "Technology Compatibility Kit" or "TCK" shall mean the test suite and
+   accompanying TCK User's Guide provided by Licensor which corresponds to
+   the particular version of the Specification being tested.
+
+   6. Termination. This Agreement will terminate immediately without notice
+   from Licensor if you fail to comply with any material provision of or act
+   outside the scope of the licenses granted above.
+
+   7. Trademarks. No right, title, or interest in or to any trademarks,
+   service marks, or trade names of Licensor is granted hereunder. Java is
+   a registered trademark of Sun Microsystems, Inc. in the United States and
+   other countries.
+
+   8. Disclaimer of Warranties. The Specification is provided "AS IS".
+   LICENSOR MAKES NO REPRESENTATIONS OR WARRANTIES, EITHER EXPRESS OR
+   IMPLIED, INCLUDING BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY,
+   FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT (INCLUDING AS A
+   CONSEQUENCE OF ANY PRACTICE OR IMPLEMENTATION OF THE SPECIFICATION),
+   OR THAT THE CONTENTS OF THE SPECIFICATION ARE SUITABLE FOR ANY PURPOSE.
+   This document does not represent any commitment to release or implement
+   any portion of the Specification in any product.
+
+   The Specification could include technical inaccuracies or typographical
+   errors. Changes are periodically added to the information therein; these
+   changes will be incorporated into new versions of the Specification, if
+   any. Licensor may make improvements and/or changes to the product(s)
+   and/or the program(s) described in the Specification at any time. Any use
+   of such changes in the Specification will be governed by the then-current
+   license for the applicable version of the Specification.
+
+   9. Limitation of Liability. TO THE EXTENT NOT PROHIBITED BY LAW, IN NO
+   EVENT WILL LICENSOR BE LIABLE FOR ANY DAMAGES, INCLUDING WITHOUT
+   LIMITATION, LOST REVENUE, PROFITS OR DATA, OR FOR SPECIAL, INDIRECT,
+   CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND
+   REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF OR RELATED TO ANY
+   FURNISHING, PRACTICING, MODIFYING OR ANY USE OF THE SPECIFICATION, EVEN
+   IF LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+   10. Report. If you provide Licensor with any comments or suggestions in
+   connection with your use of the Specification ("Feedback"), you hereby:
+   (i) agree that such Feedback is provided on a non-proprietary and
+   non-confidential basis, and (ii) grant Licensor a perpetual, non-exclusive,
+   worldwide, fully paid-up, irrevocable license, with the right to sublicense
+   through multiple levels of sublicensees, to incorporate, disclose, and use
+   without limitation the Feedback for any purpose related to the
+   Specification and future versions, implementations, and test suites thereof.
+
+kXML parser
+
+   Copyright (c) 2002,2003, Stefan Haustein, Oberhausen, Rhld., Germany
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   "Software"), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to permit
+   persons to whom the Software is furnished to do so, subject to the
+   following conditions:
+
+   The above copyright notice and this permission notice shall be included in
+   all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+   IN THE SOFTWARE. 
+
+Rhino
+
+                          MOZILLA PUBLIC LICENSE
+                                Version 1.1
+
+                              ---------------
+
+   1. Definitions.
+
+     1.0.1. "Commercial Use" means distribution or otherwise making the
+     Covered Code available to a third party.
+
+     1.1. "Contributor" means each entity that creates or contributes to
+     the creation of Modifications.
+
+     1.2. "Contributor Version" means the combination of the Original
+     Code, prior Modifications used by a Contributor, and the Modifications
+     made by that particular Contributor.
+
+     1.3. "Covered Code" means the Original Code or Modifications or the
+     combination of the Original Code and Modifications, in each case
+     including portions thereof.
+
+     1.4. "Electronic Distribution Mechanism" means a mechanism generally
+     accepted in the software development community for the electronic
+     transfer of data.
+
+     1.5. "Executable" means Covered Code in any form other than Source
+     Code.
+
+     1.6. "Initial Developer" means the individual or entity identified
+     as the Initial Developer in the Source Code notice required by Exhibit
+     A.
+
+     1.7. "Larger Work" means a work which combines Covered Code or
+     portions thereof with code not governed by the terms of this License.
+
+     1.8. "License" means this document.
+
+     1.8.1. "Licensable" means having the right to grant, to the maximum
+     extent possible, whether at the time of the initial grant or
+     subsequently acquired, any and all of the rights conveyed herein.
+
+     1.9. "Modifications" means any addition to or deletion from the
+     substance or structure of either the Original Code or any previous
+     Modifications. When Covered Code is released as a series of files, a
+     Modification is:
+          A. Any addition to or deletion from the contents of a file
+          containing Original Code or previous Modifications.
+
+          B. Any new file that contains any part of the Original Code or
+          previous Modifications.
+
+     1.10. "Original Code" means Source Code of computer software code
+     which is described in the Source Code notice required by Exhibit A as
+     Original Code, and which, at the time of its release under this
+     License is not already Covered Code governed by this License.
+
+     1.10.1. "Patent Claims" means any patent claim(s), now owned or
+     hereafter acquired, including without limitation,  method, process,
+     and apparatus claims, in any patent Licensable by grantor.
+
+     1.11. "Source Code" means the preferred form of the Covered Code for
+     making modifications to it, including all modules it contains, plus
+     any associated interface definition files, scripts used to control
+     compilation and installation of an Executable, or source code
+     differential comparisons against either the Original Code or another
+     well known, available Covered Code of the Contributor's choice. The
+     Source Code can be in a compressed or archival form, provided the
+     appropriate decompression or de-archiving software is widely available
+     for no charge.
+
+     1.12. "You" (or "Your")  means an individual or a legal entity
+     exercising rights under, and complying with all of the terms of, this
+     License or a future version of this License issued under Section 6.1.
+     For legal entities, "You" includes any entity which controls, is
+     controlled by, or is under common control with You. For purposes of
+     this definition, "control" means (a) the power, direct or indirect,
+     to cause the direction or management of such entity, whether by
+     contract or otherwise, or (b) ownership of more than fifty percent
+     (50%) of the outstanding shares or beneficial ownership of such
+     entity.
+
+   2. Source Code License.
+
+     2.1. The Initial Developer Grant.
+     The Initial Developer hereby grants You a world-wide, royalty-free,
+     non-exclusive license, subject to third party intellectual property
+     claims:
+          (a)  under intellectual property rights (other than patent or
+          trademark) Licensable by Initial Developer to use, reproduce,
+          modify, display, perform, sublicense and distribute the Original
+          Code (or portions thereof) with or without Modifications, and/or
+          as part of a Larger Work; and
+
+          (b) under Patents Claims infringed by the making, using or
+          selling of Original Code, to make, have made, use, practice,
+          sell, and offer for sale, and/or otherwise dispose of the
+          Original Code (or portions thereof).
+
+          (c) the licenses granted in this Section 2.1(a) and (b) are
+          effective on the date Initial Developer first distributes
+          Original Code under the terms of this License.
+
+          (d) Notwithstanding Section 2.1(b) above, no patent license is
+          granted: 1) for code that You delete from the Original Code; 2)
+          separate from the Original Code;  or 3) for infringements caused
+          by: i) the modification of the Original Code or ii) the
+          combination of the Original Code with other software or devices.
+
+     2.2. Contributor Grant.
+     Subject to third party intellectual property claims, each Contributor
+     hereby grants You a world-wide, royalty-free, non-exclusive license
+
+          (a)  under intellectual property rights (other than patent or
+          trademark) Licensable by Contributor, to use, reproduce, modify,
+          display, perform, sublicense and distribute the Modifications
+          created by such Contributor (or portions thereof) either on an
+          unmodified basis, with other Modifications, as Covered Code
+          and/or as part of a Larger Work; and
+
+          (b) under Patent Claims infringed by the making, using, or
+          selling of  Modifications made by that Contributor either alone
+          and/or in combination with its Contributor Version (or portions
+          of such combination), to make, use, sell, offer for sale, have
+          made, and/or otherwise dispose of: 1) Modifications made by that
+          Contributor (or portions thereof); and 2) the combination of
+          Modifications made by that Contributor with its Contributor
+          Version (or portions of such combination).
+
+          (c) the licenses granted in Sections 2.2(a) and 2.2(b) are
+          effective on the date Contributor first makes Commercial Use of
+          the Covered Code.
+
+          (d)    Notwithstanding Section 2.2(b) above, no patent license is
+          granted: 1) for any code that Contributor has deleted from the
+          Contributor Version; 2)  separate from the Contributor Version;
+          3)  for infringements caused by: i) third party modifications of
+          Contributor Version or ii)  the combination of Modifications made
+          by that Contributor with other software  (except as part of the
+          Contributor Version) or other devices; or 4) under Patent Claims
+          infringed by Covered Code in the absence of Modifications made by
+          that Contributor.
+
+   3. Distribution Obligations.
+
+     3.1. Application of License.
+     The Modifications which You create or to which You contribute are
+     governed by the terms of this License, including without limitation
+     Section 2.2. The Source Code version of Covered Code may be
+     distributed only under the terms of this License or a future version
+     of this License released under Section 6.1, and You must include a
+     copy of this License with every copy of the Source Code You
+     distribute. You may not offer or impose any terms on any Source Code
+     version that alters or restricts the applicable version of this
+     License or the recipients' rights hereunder. However, You may include
+     an additional document offering the additional rights described in
+     Section 3.5.
+
+     3.2. Availability of Source Code.
+     Any Modification which You create or to which You contribute must be
+     made available in Source Code form under the terms of this License
+     either on the same media as an Executable version or via an accepted
+     Electronic Distribution Mechanism to anyone to whom you made an
+     Executable version available; and if made available via Electronic
+     Distribution Mechanism, must remain available for at least twelve (12)
+     months after the date it initially became available, or at least six
+     (6) months after a subsequent version of that particular Modification
+     has been made available to such recipients. You are responsible for
+     ensuring that the Source Code version remains available even if the
+     Electronic Distribution Mechanism is maintained by a third party.
+
+     3.3. Description of Modifications.
+     You must cause all Covered Code to which You contribute to contain a
+     file documenting the changes You made to create that Covered Code and
+     the date of any change. You must include a prominent statement that
+     the Modification is derived, directly or indirectly, from Original
+     Code provided by the Initial Developer and including the name of the
+     Initial Developer in (a) the Source Code, and (b) in any notice in an
+     Executable version or related documentation in which You describe the
+     origin or ownership of the Covered Code.
+
+     3.4. Intellectual Property Matters
+          (a) Third Party Claims.
+          If Contributor has knowledge that a license under a third party's
+          intellectual property rights is required to exercise the rights
+          granted by such Contributor under Sections 2.1 or 2.2,
+          Contributor must include a text file with the Source Code
+          distribution titled "LEGAL" which describes the claim and the
+          party making the claim in sufficient detail that a recipient will
+          know whom to contact. If Contributor obtains such knowledge after
+          the Modification is made available as described in Section 3.2,
+          Contributor shall promptly modify the LEGAL file in all copies
+          Contributor makes available thereafter and shall take other steps
+          (such as notifying appropriate mailing lists or newsgroups)
+          reasonably calculated to inform those who received the Covered
+          Code that new knowledge has been obtained.
+
+          (b) Contributor APIs.
+          If Contributor's Modifications include an application programming
+          interface and Contributor has knowledge of patent licenses which
+          are reasonably necessary to implement that API, Contributor must
+          also include this information in the LEGAL file.
+
+               (c)    Representations.
+          Contributor represents that, except as disclosed pursuant to
+          Section 3.4(a) above, Contributor believes that Contributor's
+          Modifications are Contributor's original creation(s) and/or
+          Contributor has sufficient rights to grant the rights conveyed by
+          this License.
+
+     3.5. Required Notices.
+     You must duplicate the notice in Exhibit A in each file of the Source
+     Code.  If it is not possible to put such notice in a particular Source
+     Code file due to its structure, then You must include such notice in a
+     location (such as a relevant directory) where a user would be likely
+     to look for such a notice.  If You created one or more Modification(s)
+     You may add your name as a Contributor to the notice described in
+     Exhibit A.  You must also duplicate this License in any documentation
+     for the Source Code where You describe recipients' rights or ownership
+     rights relating to Covered Code.  You may choose to offer, and to
+     charge a fee for, warranty, support, indemnity or liability
+     obligations to one or more recipients of Covered Code. However, You
+     may do so only on Your own behalf, and not on behalf of the Initial
+     Developer or any Contributor. You must make it absolutely clear than
+     any such warranty, support, indemnity or liability obligation is
+     offered by You alone, and You hereby agree to indemnify the Initial
+     Developer and every Contributor for any liability incurred by the
+     Initial Developer or such Contributor as a result of warranty,
+     support, indemnity or liability terms You offer.
+
+     3.6. Distribution of Executable Versions.
+     You may distribute Covered Code in Executable form only if the
+     requirements of Section 3.1-3.5 have been met for that Covered Code,
+     and if You include a notice stating that the Source Code version of
+     the Covered Code is available under the terms of this License,
+     including a description of how and where You have fulfilled the
+     obligations of Section 3.2. The notice must be conspicuously included
+     in any notice in an Executable version, related documentation or
+     collateral in which You describe recipients' rights relating to the
+     Covered Code. You may distribute the Executable version of Covered
+     Code or ownership rights under a license of Your choice, which may
+     contain terms different from this License, provided that You are in
+     compliance with the terms of this License and that the license for the
+     Executable version does not attempt to limit or alter the recipient's
+     rights in the Source Code version from the rights set forth in this
+     License. If You distribute the Executable version under a different
+     license You must make it absolutely clear that any terms which differ
+     from this License are offered by You alone, not by the Initial
+     Developer or any Contributor. You hereby agree to indemnify the
+     Initial Developer and every Contributor for any liability incurred by
+     the Initial Developer or such Contributor as a result of any such
+     terms You offer.
+
+     3.7. Larger Works.
+     You may create a Larger Work by combining Covered Code with other code
+     not governed by the terms of this License and distribute the Larger
+     Work as a single product. In such a case, You must make sure the
+     requirements of this License are fulfilled for the Covered Code.
+
+   4. Inability to Comply Due to Statute or Regulation.
+
+     If it is impossible for You to comply with any of the terms of this
+     License with respect to some or all of the Covered Code due to
+     statute, judicial order, or regulation then You must: (a) comply with
+     the terms of this License to the maximum extent possible; and (b)
+     describe the limitations and the code they affect. Such description
+     must be included in the LEGAL file described in Section 3.4 and must
+     be included with all distributions of the Source Code. Except to the
+     extent prohibited by statute or regulation, such description must be
+     sufficiently detailed for a recipient of ordinary skill to be able to
+     understand it.
+
+   5. Application of this License.
+
+     This License applies to code to which the Initial Developer has
+     attached the notice in Exhibit A and to related Covered Code.
+
+   6. Versions of the License.
+
+     6.1. New Versions.
+     Netscape Communications Corporation ("Netscape") may publish revised
+     and/or new versions of the License from time to time. Each version
+     will be given a distinguishing version number.
+
+     6.2. Effect of New Versions.
+     Once Covered Code has been published under a particular version of the
+     License, You may always continue to use it under the terms of that
+     version. You may also choose to use such Covered Code under the terms
+     of any subsequent version of the License published by Netscape. No one
+     other than Netscape has the right to modify the terms applicable to
+     Covered Code created under this License.
+
+     6.3. Derivative Works.
+     If You create or use a modified version of this License (which you may
+     only do in order to apply it to code which is not already Covered Code
+     governed by this License), You must (a) rename Your license so that
+     the phrases "Mozilla", "MOZILLAPL", "MOZPL", "Netscape",
+     "MPL", "NPL" or any confusingly similar phrase do not appear in your
+     license (except to note that your license differs from this License)
+     and (b) otherwise make it clear that Your version of the license
+     contains terms which differ from the Mozilla Public License and
+     Netscape Public License. (Filling in the name of the Initial
+     Developer, Original Code or Contributor in the notice described in
+     Exhibit A shall not of themselves be deemed to be modifications of
+     this License.)
+
+   7. DISCLAIMER OF WARRANTY.
+
+     COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS,
+     WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+     WITHOUT LIMITATION, WARRANTIES THAT THE COVERED CODE IS FREE OF
+     DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING.
+     THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED CODE
+     IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT,
+     YOU (NOT THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE
+     COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER
+     OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF
+     ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER.
+
+   8. TERMINATION.
+
+     8.1.  This License and the rights granted hereunder will terminate
+     automatically if You fail to comply with terms herein and fail to cure
+     such breach within 30 days of becoming aware of the breach. All
+     sublicenses to the Covered Code which are properly granted shall
+     survive any termination of this License. Provisions which, by their
+     nature, must remain in effect beyond the termination of this License
+     shall survive.
+
+     8.2.  If You initiate litigation by asserting a patent infringement
+     claim (excluding declatory judgment actions) against Initial Developer
+     or a Contributor (the Initial Developer or Contributor against whom
+     You file such action is referred to as "Participant")  alleging that:
+
+     (a)  such Participant's Contributor Version directly or indirectly
+     infringes any patent, then any and all rights granted by such
+     Participant to You under Sections 2.1 and/or 2.2 of this License
+     shall, upon 60 days notice from Participant terminate prospectively,
+     unless if within 60 days after receipt of notice You either: (i)
+     agree in writing to pay Participant a mutually agreeable reasonable
+     royalty for Your past and future use of Modifications made by such
+     Participant, or (ii) withdraw Your litigation claim with respect to
+     the Contributor Version against such Participant.  If within 60 days
+     of notice, a reasonable royalty and payment arrangement are not
+     mutually agreed upon in writing by the parties or the litigation claim
+     is not withdrawn, the rights granted by Participant to You under
+     Sections 2.1 and/or 2.2 automatically terminate at the expiration of
+     the 60 day notice period specified above.
+
+     (b)  any software, hardware, or device, other than such Participant's
+     Contributor Version, directly or indirectly infringes any patent, then
+     any rights granted to You by such Participant under Sections 2.1(b)
+     and 2.2(b) are revoked effective as of the date You first made, used,
+     sold, distributed, or had made, Modifications made by that
+     Participant.
+
+     8.3.  If You assert a patent infringement claim against Participant
+     alleging that such Participant's Contributor Version directly or
+     indirectly infringes any patent where such claim is resolved (such as
+     by license or settlement) prior to the initiation of patent
+     infringement litigation, then the reasonable value of the licenses
+     granted by such Participant under Sections 2.1 or 2.2 shall be taken
+     into account in determining the amount or value of any payment or
+     license.
+
+     8.4.  In the event of termination under Sections 8.1 or 8.2 above,
+     all end user license agreements (excluding distributors and resellers)
+     which have been validly granted by You or any distributor hereunder
+     prior to termination shall survive termination.
+
+   9. LIMITATION OF LIABILITY.
+
+     UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT
+     (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL YOU, THE INITIAL
+     DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF COVERED CODE,
+     OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO ANY PERSON FOR
+     ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY
+     CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL,
+     WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER
+     COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN
+     INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF
+     LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY
+     RESULTING FROM SUCH PARTY'S NEGLIGENCE TO THE EXTENT APPLICABLE LAW
+     PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE
+     EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO
+     THIS EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU.
+
+   10. U.S. GOVERNMENT END USERS.
+
+     The Covered Code is a "commercial item," as that term is defined in
+     48 C.F.R. 2.101 (Oct. 1995), consisting of "commercial computer
+     software" and "commercial computer software documentation," as such
+     terms are used in 48 C.F.R. 12.212 (Sept. 1995). Consistent with 48
+     C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995),
+     all U.S. Government End Users acquire Covered Code with only those
+     rights set forth herein.
+
+   11. MISCELLANEOUS.
+
+     This License represents the complete agreement concerning subject
+     matter hereof. If any provision of this License is held to be
+     unenforceable, such provision shall be reformed only to the extent
+     necessary to make it enforceable. This License shall be governed by
+     California law provisions (except to the extent applicable law, if
+     any, provides otherwise), excluding its conflict-of-law provisions.
+     With respect to disputes in which at least one party is a citizen of,
+     or an entity chartered or registered to do business in the United
+     States of America, any litigation relating to this License shall be
+     subject to the jurisdiction of the Federal Courts of the Northern
+     District of California, with venue lying in Santa Clara County,
+     California, with the losing party responsible for costs, including
+     without limitation, court costs and reasonable attorneys' fees and
+     expenses. The application of the United Nations Convention on
+     Contracts for the International Sale of Goods is expressly excluded.
+     Any law or regulation which provides that the language of a contract
+     shall be construed against the drafter shall not apply to this
+     License.
+
+   12. RESPONSIBILITY FOR CLAIMS.
+
+     As between Initial Developer and the Contributors, each party is
+     responsible for claims and damages arising, directly or indirectly,
+     out of its utilization of rights under this License and You agree to
+     work with Initial Developer and Contributors to distribute such
+     responsibility on an equitable basis. Nothing herein is intended or
+     shall be deemed to constitute any admission of liability.
+
+   13. MULTIPLE-LICENSED CODE.
+
+     Initial Developer may designate portions of the Covered Code as
+     "Multiple-Licensed".  "Multiple-Licensed" means that the Initial
+     Developer permits you to utilize portions of the Covered Code under
+     Your choice of the NPL or the alternative licenses, if any, specified
+     by the Initial Developer in the file described in Exhibit A.
+
+   EXHIBIT A -Mozilla Public License.
+
+     ``The contents of this file are subject to the Mozilla Public License
+     Version 1.1 (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.mozilla.org/MPL/
+
+     Software distributed under the License is distributed on an "AS IS"
+     basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+     License for the specific language governing rights and limitations
+     under the License.
+
+     The Original Code is ______________________________________.
+
+     The Initial Developer of the Original Code is ________________________.
+     Portions created by ______________________ are Copyright (C) ______
+     _______________________. All Rights Reserved.
+
+     Contributor(s): ______________________________________.
+
+     Alternatively, the contents of this file may be used under the terms
+     of the _____ license (the  "[___] License"), in which case the
+     provisions of [______] License are applicable instead of those
+     above.  If you wish to allow use of your version of this file only
+     under the terms of the [____] License and not to allow others to use
+     your version of this file under the MPL, indicate your decision by
+     deleting  the provisions above and replace  them with the notice and
+     other provisions required by the [___] License.  If you do not delete
+     the provisions above, a recipient may use your version of this file
+     under either the MPL or the [___] License."
+
+     [NOTE: The text of this Exhibit A may differ slightly from the text of
+     the notices in the Source Code files of the Original Code. You should
+     use the text of this Exhibit A rather than the text found in the
+     Original Code Source Code for Your Modifications.]
+
+W3C XPath parser
+
+   XPath 2.0/XQuery 1.0 Parser:
+   http://www.w3.org/2002/11/xquery-xpath-applets/xgrammar.zip
+
+   Copyright (C) 2002 World Wide Web Consortium, (Massachusetts Institute of
+   Technology, European Research Consortium for Informatics and Mathematics,
+   Keio University). All Rights Reserved.
+
+   This work is distributed under the W3C(R) Software License in the hope
+   that it will be useful, but WITHOUT ANY WARRANTY; without even the
+   implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+   W3C(R) SOFTWARE NOTICE AND LICENSE
+   http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231
+
+   This work (and included software, documentation such as READMEs, or
+   other related items) is being provided by the copyright holders under
+   the following license. By obtaining, using and/or copying this work,
+   you (the licensee) agree that you have read, understood, and will comply
+   with the following terms and conditions.
+
+   Permission to copy, modify, and distribute this software and its
+   documentation, with or without modification, for any purpose and
+   without fee or royalty is hereby granted, provided that you include
+   the following on ALL copies of the software and documentation or
+   portions thereof, including modifications:
+
+      1. The full text of this NOTICE in a location viewable to users
+         of the redistributed or derivative work.
+
+      2. Any pre-existing intellectual property disclaimers, notices,
+         or terms and conditions. If none exist, the W3C Software Short
+         Notice should be included (hypertext is preferred, text is
+         permitted) within the body of any redistributed or derivative code.
+
+      3. Notice of any changes or modifications to the files, including
+         the date changes were made. (We recommend you provide URIs to the
+         location from which the code is derived.)
+
+   THIS SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS," AND COPYRIGHT
+   HOLDERS MAKE NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED,
+   INCLUDING BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS
+   FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE SOFTWARE OR
+   DOCUMENTATION WILL NOT INFRINGE ANY THIRD PARTY PATENTS, COPYRIGHTS,
+   TRADEMARKS OR OTHER RIGHTS.
+
+   COPYRIGHT HOLDERS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL
+   OR CONSEQUENTIAL DAMAGES ARISING OUT OF ANY USE OF THE SOFTWARE OR
+   DOCUMENTATION.
+
+   The name and trademarks of copyright holders may NOT be used in
+   advertising or publicity pertaining to the software without specific,
+   written prior permission. Title to copyright in this software and
+   any associated documentation will at all times remain with
+   copyright holders.
+
+Concurrent
+
+   http://g.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/intro.html
+
+   All classes are released to the public domain and may be used for any
+   purpose whatsoever without permission or acknowledgment. Portions of
+   the CopyOnWriteArrayList and ConcurrentReaderHashMap classes are adapted
+   from Sun JDK source code. These are copyright of Sun Microsystems, Inc,
+   and are used with their kind permission, as described in this license:
+
+   TECHNOLOGY LICENSE FROM SUN MICROSYSTEMS, INC. TO DOUG LEA
+
+   Whereas Doug Lea desires to utlized certain Java Software technologies
+   in the util.concurrent technology; and Whereas Sun Microsystems, Inc.
+   ("Sun") desires that Doug Lea utilize certain Java Software technologies
+   in the util.concurrent technology;
+
+   Therefore the parties agree as follows, effective May 31, 2002:
+
+   "Java Software technologies" means
+
+       classes/java/util/ArrayList.java, and
+       classes/java/util/HashMap.java.
+
+   The Java Software technologies are Copyright (c) 1994-2000 Sun
+   Microsystems, Inc. All rights reserved.
+
+   Sun hereby grants Doug Lea a non-exclusive, worldwide, non-transferrable
+   license to use, reproduce, create derivate works of, and distribute the
+   Java Software and derivative works thereof in source and binary forms
+   as part of a larger work, and to sublicense the right to use, reproduce
+   and distribute the Java Software and Doug Lea's derivative works as the
+   part of larger works through multiple tiers of sublicensees provided that
+   the following conditions are met:
+
+   -Neither the name of or trademarks of Sun may be used to endorse or
+   promote products including or derived from the Java Software technology
+   without specific prior written permission; and
+   -Redistributions of source or binary code must contain the above
+   copyright notice, this notice and and the following disclaimers:
+
+   This software is provided "AS IS," without a warranty of any kind.
+   ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+   INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+   PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
+   MICROSYSTEMS, INC. AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES
+   SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
+   THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN MICROSYSTEMS, INC.
+   OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
+   DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES,
+   HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF
+   THE USE OF OR INABILITY TO USE SOFTWARE, EVEN IF SUN MICROSYSTEMS, INC.
+   HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+   You acknowledge that Software is not designed,licensed or intended for
+   use in the design, construction, operation or maintenance of any nuclear
+   facility.
+
+PDFBox
+
+   Copyright (c) 2003-2005, www.pdfbox.org
+   All rights reserved.
+
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are met:
+
+   1. Redistributions of source code must retain the above copyright notice,
+      this list of conditions and the following disclaimer.
+
+   2. Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+
+   3. Neither the name of pdfbox; nor the names of its contributors may be
+      used to endorse or promote products derived from this software without
+      specific prior written permission.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+   ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+   FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+   OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+   HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+   LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+   OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+   OF SUCH DAMAGE.
+
+CyberNeko HTML Parser
+
+   The CyberNeko Software License, Version 1.0
+
+   (C) Copyright 2002-2005, Andy Clark.  All rights reserved.
+
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   1. Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+   2. Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in
+      the documentation and/or other materials provided with the
+      distribution.
+
+   3. The end-user documentation included with the redistribution,
+      if any, must include the following acknowledgment:
+        "This product includes software developed by Andy Clark."
+      Alternately, this acknowledgment may appear in the software itself,
+      if and wherever such third-party acknowledgments normally appear.
+
+   4. The names "CyberNeko" and "NekoHTML" must not be used to endorse
+      or promote products derived from this software without prior
+      written permission. For written permission, please contact
+      andyc@cyberneko.net.
+
+   5. Products derived from this software may not be called "CyberNeko",
+      nor may "CyberNeko" appear in their name, without prior written
+      permission of the author.
+
+   THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+   WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+   OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+   DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS
+   BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+   OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+   OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+   BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+   OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+   EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+   ====================================================================
+
+   This license is based on the Apache Software License, version 1.1.
+
+Equinox
+
+   Eclipse Public License - v 1.0
+
+   THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE PUBLIC
+   LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM
+   CONSTITUTES RECIPIENTÕS ACCEPTANCE OF THIS AGREEMENT.
+
+   1. DEFINITIONS
+
+   "Contribution" means:
+
+      a) in the case of the initial Contributor, the initial code and
+         documentation distributed under this Agreement, and
+      b) in the case of each subsequent Contributor:
+      i) changes to the Program, and
+      ii) additions to the Program;
+      where such changes and/or additions to the Program originate from and
+      are distributed by that particular Contributor. A Contribution
+      'originates' from a Contributor if it was added to the Program by such
+      Contributor itself or anyone acting on such Contributor's behalf.
+      Contributions do not include additions to the Program which: (i) are
+      separate modules of software distributed in conjunction with the Program
+      under their own license agreement, and (ii) are not derivative works of
+      the Program.
+
+   "Contributor" means any person or entity that distributes the Program.
+
+   "Licensed Patents " mean patent claims licensable by a Contributor which
+   are necessarily infringed by the use or sale of its Contribution alone or
+   when combined with the Program.
+
+   "Program" means the Contributions distributed in accordance with this
+   Agreement.
+
+   "Recipient" means anyone who receives the Program under this Agreement,
+   including all Contributors.
+
+   2. GRANT OF RIGHTS
+
+      a) Subject to the terms of this Agreement, each Contributor hereby
+      grants Recipient a non-exclusive, worldwide, royalty-free copyright
+      license to reproduce, prepare derivative works of, publicly display,
+      publicly perform, distribute and sublicense the Contribution of such
+      Contributor, if any, and such derivative works, in source code and
+      object code form.
+
+      b) Subject to the terms of this Agreement, each Contributor hereby
+      grants Recipient a non-exclusive, worldwide, royalty-free patent license
+      under Licensed Patents to make, use, sell, offer to sell, import and
+      otherwise transfer the Contribution of such Contributor, if any, in
+      source code and object code form. This patent license shall apply to the
+      combination of the Contribution and the Program if, at the time the
+      Contribution is added by the Contributor, such addition of the
+      Contribution causes such combination to be covered by the Licensed
+      Patents. The patent license shall not apply to any other combinations
+      which include the Contribution. No hardware per se is licensed hereunder.
+
+      c) Recipient understands that although each Contributor grants the
+      licenses to its Contributions set forth herein, no assurances are
+      provided by any Contributor that the Program does not infringe the
+      patent or other intellectual property rights of any other entity. Each
+      Contributor disclaims any liability to Recipient for claims brought by
+      any other entity based on infringement of intellectual property rights
+      or otherwise. As a condition to exercising the rights and licenses
+      granted hereunder, each Recipient hereby assumes sole responsibility to
+      secure any other intellectual property rights needed, if any. For
+      example, if a third party patent license is required to allow Recipient
+      to distribute the Program, it is Recipient's responsibility to acquire
+      that license before distributing the Program.
+
+      d) Each Contributor represents that to its knowledge it has sufficient
+      copyright rights in its Contribution, if any, to grant the copyright
+      license set forth in this Agreement.
+
+   3. REQUIREMENTS
+
+   A Contributor may choose to distribute the Program in object code form
+   under its own license agreement, provided that:
+
+      a) it complies with the terms and conditions of this Agreement; and
+
+      b) its license agreement:
+
+      i) effectively disclaims on behalf of all Contributors all warranties
+      and conditions, express and implied, including warranties or conditions
+      of title and non-infringement, and implied warranties or conditions of
+      merchantability and fitness for a particular purpose;
+
+      ii) effectively excludes on behalf of all Contributors all liability
+      for damages, including direct, indirect, special, incidental and
+      consequential damages, such as lost profits;
+
+      iii) states that any provisions which differ from this Agreement are
+      offered by that Contributor alone and not by any other party; and
+
+      iv) states that source code for the Program is available from such
+      Contributor, and informs licensees how to obtain it in a reasonable
+      manner on or through a medium customarily used for software exchange.
+
+   When the Program is made available in source code form:
+
+      a) it must be made available under this Agreement; and
+
+      b) a copy of this Agreement must be included with each copy of the
+      Program.
+
+   Contributors may not remove or alter any copyright notices contained within
+   the Program.
+
+   Each Contributor must identify itself as the originator of its
+   Contribution, if any, in a manner that reasonably allows subsequent
+   Recipients to identify the originator of the Contribution.
+
+   4. COMMERCIAL DISTRIBUTION
+
+   Commercial distributors of software may accept certain responsibilities
+   with respect to end users, business partners and the like. While this
+   license is intended to facilitate the commercial use of the Program, the
+   Contributor who includes the Program in a commercial product offering
+   should do so in a manner which does not create potential liability for
+   other Contributors. Therefore, if a Contributor includes the Program in
+   a commercial product offering, such Contributor ("Commercial Contributor")
+   hereby agrees to defend and indemnify every other Contributor ("Indemnified
+   Contributor") against any losses, damages and costs (collectively "Losses")
+   arising from claims, lawsuits and other legal actions brought by a third
+   party against the Indemnified Contributor to the extent caused by the acts
+   or omissions of such Commercial Contributor in connection with its
+   distribution of the Program in a commercial product offering. The
+   obligations in this section do not apply to any claims or Losses relating
+   to any actual or alleged intellectual property infringement. In order to
+   qualify, an Indemnified Contributor must: a) promptly notify the Commercial
+   Contributor in writing of such claim, and b) allow the Commercial
+   Contributor to control, and cooperate with the Commercial Contributor in,
+   the defense and any related settlement negotiations. The Indemnified
+   Contributor may participate in any such claim at its own expense.
+
+   For example, a Contributor might include the Program in a commercial
+   product offering, Product X. That Contributor is then a Commercial
+   Contributor. If that Commercial Contributor then makes performance claims,
+   or offers warranties related to Product X, those performance claims and
+   warranties are such Commercial ContributorÕs responsibility alone. Under
+   this section, the Commercial Contributor would have to defend claims
+   against the other Contributors related to those performance claims and
+   warranties, and if a court requires any other Contributor to pay any
+   damages as a result, the Commercial Contributor must pay those damages.
+
+   5. NO WARRANTY
+
+   EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED
+   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. Each Recipient is solely responsible for determining
+   the appropriateness of using and distributing the Program and assumes all
+   risks associated with its exercise of rights under this Agreement,
+   including but not limited to the risks and costs of program errors,
+   compliance with applicable laws, damage to or loss of data, programs or
+   equipment, and unavailability or interruption of operations.
+
+   6. DISCLAIMER OF LIABILITY
+
+   EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY
+   CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION
+   LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+   ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE
+   EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE
+   POSSIBILITY OF SUCH DAMAGES.
+
+   7. GENERAL
+
+   If any provision of this Agreement is invalid or unenforceable under
+   applicable law, it shall not affect the validity or enforceability of the
+   remainder of the terms of this Agreement, and without further action by the
+   parties hereto, such provision shall be reformed to the minimum extent
+   necessary to make such provision valid and enforceable.
+
+   If Recipient institutes patent litigation against any entity (including a
+   cross-claim or counterclaim in a lawsuit) alleging that the Program itself
+   (excluding combinations of the Program with other software or hardware)
+   infringes such RecipientÕs patent(s), then such RecipientÕs rights granted
+   under Section 2(b) shall terminate as of the date such litigation is filed.
+
+   All RecipientÕs rights under this Agreement shall terminate if it fails to
+   comply with any of the material terms or conditions of this Agreement and
+   does not cure such failure in a reasonable period of time after becoming
+   aware of such noncompliance. If all RecipientÕs rights under this Agreement
+   terminate, Recipient agrees to cease use and distribution of the Program as
+   soon as reasonably practicable. However, Recipient's obligations under this
+   Agreement and any licenses granted by Recipient relating to the Program
+   shall continue and survive.
+
+   Everyone is permitted to copy and distribute copies of this Agreement, but
+   in order to avoid inconsistency the Agreement is copyrighted and may only
+   be modified in the following manner. The Agreement Steward reserves the
+   right to publish new versions (including revisions) of this Agreement from
+   time to time. No one other than the Agreement Steward has the right to
+   modify this Agreement. The Eclipse Foundation is the initial Agreement
+   Steward. The Eclipse Foundation may assign the responsibility to serve as
+   the Agreement Steward to a suitable separate entity. Each new version of
+   the Agreement will be given a distinguishing version number. The Program
+   (including Contributions) may always be distributed subject to the version
+   of the Agreement under which it was received. In addition, after a new
+   version of the Agreement is published, Contributor may elect to distribute
+   the Program (including its Contributions) under the new version. Except as
+   expressly stated in Sections 2(a) and 2(b) above, Recipient receives no
+   rights or licenses to the intellectual property of any Contributor under
+   this Agreement, whether expressly, by implication, estoppel or otherwise.
+   All rights in the Program not expressly granted under this Agreement are
+   reserved.
+
+   This Agreement is governed by the laws of the State of New York and the
+   intellectual property laws of the United States of America. No party to
+   this Agreement will bring a legal action under this Agreement more than one
+   year after the cause of action arose. Each party waives its rights to a
+   jury trial in any resulting litigation. 
diff --git a/src/main/webapp/WEB-INF/NOTICE b/src/main/webapp/WEB-INF/NOTICE
new file mode 100644
index 0000000..e19857e
--- /dev/null
+++ b/src/main/webapp/WEB-INF/NOTICE
@@ -0,0 +1,61 @@
+Apache Sling Launchpad Testing
+Copyright 2008 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/).
+
+This product contains code derived from JSON in Java code from JSON.org.
+Copyright (c) 2002 JSON.org
+
+This product includes SLF4J logging libraries (http://www.slf4j.org/).
+Copyright (c) 2004-2007 QOS.ch.
+
+This product uses software developed at
+The OSGi Alliance (http://www.osgi.org/).
+Copyright 2006 The OSGi Alliance.
+Licensed under the Apache License 2.0.
+
+This product includes software from http://kxml.sourceforge.net.
+Copyright (c) 2002,2003, Stefan Haustein, Oberhausen, Rhld., Germany.
+Licensed under BSD License.
+
+This product includes software developed under the JCP from http://www.jcp.org.
+Copyright 2005 Day Management AG
+
+This product contains an XPath parser from the World Wide Web Consortium.
+Copyright (c) 2002 World Wide Web Consortium, (Massachusetts Institute of
+Technology, European Research Consortium for Informatics and Mathematics,
+Keio University).
+
+This product includes software developed at pdfbox.org.
+Copyright (c) 2003-2005, www.pdfbox.org
+
+This product includes the CyberNeko HTML Parser
+(C) Copyright 2002-2005, Andy Clark.
+
+This software contains code written by Ryan Ackley.
+Please go to http://www.textmining.org for the latest version.
+
+This product includes software developed at
+mozilla.org (http://www.mozilla.org/).
+
+This product includes software developed at
+eclipse.org (http://www.eclipse.org/equinox).
+Licensed under the Eclipse Public License (EPL).
+
+This product includes Apache Xerces, portions of which were
+originally based on the following:
+- software copyright (c) 1999, IBM Corporation., http://www.ibm.com.
+- software copyright (c) 1999, Sun Microsystems., http://www.sun.com.
+- voluntary contributions made by Paul Eng on behalf of the
+  Apache Software Foundation that were originally developed at iClick, Inc.,
+  software copyright (c) 1999.
+
+This product includes Apache Derby, which is based on source code originally
+developed at the International Business Machines Corporation.
+(C) Copyright 1997,2004 International Business Machines Corporation.
+All rights reserved.
+(C) Copyright IBM Corp. 2003.
diff --git a/src/main/webapp/WEB-INF/web.xml b/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..c04be60
--- /dev/null
+++ b/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,167 @@
+<?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.
+-->
+<web-app version="2.4"
+         xmlns="http://java.sun.com/xml/ns/j2ee"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
+    <display-name>Sling Launchpad Testing Module</display-name>
+
+    <servlet>
+        <display-name>Sling Servlet</display-name>
+        <servlet-name>sling</servlet-name>
+        <servlet-class>
+            org.apache.sling.launcher.webapp.SlingServlet
+        </servlet-class>
+        <load-on-startup>100</load-on-startup>
+    </servlet>
+
+    <!-- Default Mapping for the Context -->
+    <servlet-mapping>
+        <servlet-name>sling</servlet-name>
+        <url-pattern>/*</url-pattern>
+    </servlet-mapping>
+
+    <!-- Overwrite Mappings which may be present in default web.xml files -->
+    <servlet-mapping>
+        <servlet-name>sling</servlet-name>
+        <url-pattern>*.jsp</url-pattern>
+    </servlet-mapping>
+    
+      <!-- ====================================================================== -->
+  <!-- M I M E T Y P E   M A P P I N G                                          -->
+  <!-- ====================================================================== -->
+  <mime-mapping>
+    <extension>doc</extension>
+    <mime-type>application/msword</mime-type>
+  </mime-mapping>
+  <mime-mapping>
+    <extension>bin</extension>
+    <mime-type>application/octet-stream</mime-type>
+  </mime-mapping>
+  <mime-mapping>
+    <extension>pdf</extension>
+    <mime-type>application/pdf</mime-type>
+  </mime-mapping>
+  <mime-mapping>
+    <extension>ai</extension>
+    <mime-type>application/postscript</mime-type>
+  </mime-mapping>
+  <mime-mapping>
+    <extension>eps</extension>
+    <mime-type>application/postscript</mime-type>
+  </mime-mapping>
+  <mime-mapping>
+    <extension>ps</extension>
+    <mime-type>application/postscript</mime-type>
+  </mime-mapping>
+  <mime-mapping>
+    <extension>rtf</extension>
+    <mime-type>application/rtf</mime-type>
+  </mime-mapping>
+  <mime-mapping>
+    <extension>mif</extension>
+    <mime-type>application/vnd.mif</mime-type>
+  </mime-mapping>
+  <mime-mapping>
+    <extension>ppt</extension>
+    <mime-type>application/vnd.ms-powerpoint</mime-type>
+  </mime-mapping>
+  <mime-mapping>
+    <extension>xls</extension>
+    <mime-type>application/vnd.ms-excel</mime-type>
+  </mime-mapping>  
+  <mime-mapping>
+    <extension>vcd</extension>
+    <mime-type>application/x-cdlink</mime-type>
+  </mime-mapping>
+    <mime-mapping>
+    <extension>js</extension>
+    <mime-type>application/x-javascript</mime-type>
+  </mime-mapping>
+  <mime-mapping>
+    <extension>mp3</extension>
+    <mime-type>audio/mpeg</mime-type>
+  </mime-mapping>
+  <mime-mapping>
+    <extension>ram</extension>
+    <mime-type>audio/x-pn-realaudio</mime-type>
+  </mime-mapping>
+  <mime-mapping>
+    <extension>rm</extension>
+    <mime-type>audio/x-pn-realaudio</mime-type>
+  </mime-mapping>
+  <mime-mapping>
+    <extension>ra</extension>
+    <mime-type>audio/x-realaudio</mime-type>
+  </mime-mapping>
+  <mime-mapping>
+    <extension>gif</extension>
+    <mime-type>image/gif</mime-type>
+  </mime-mapping>
+  <mime-mapping>
+    <extension>jpeg</extension>
+    <mime-type>image/jpeg</mime-type>
+  </mime-mapping>
+  <mime-mapping>
+    <extension>jpg</extension>
+    <mime-type>image/jpeg</mime-type>
+  </mime-mapping>
+  <mime-mapping>
+    <extension>png</extension>
+    <mime-type>image/png</mime-type>
+  </mime-mapping>
+  <mime-mapping>
+    <extension>tiff</extension>
+    <mime-type>image/tiff</mime-type>
+  </mime-mapping>
+  <mime-mapping>
+    <extension>tif</extension>
+    <mime-type>image/tiff</mime-type>
+  </mime-mapping>
+  <mime-mapping>
+    <extension>css</extension>
+    <mime-type>text/css</mime-type>
+  </mime-mapping>
+    <mime-mapping>
+    <extension>asc</extension>
+    <mime-type>text/plain</mime-type>
+  </mime-mapping>
+  <mime-mapping>
+    <extension>txt</extension>
+    <mime-type>text/plain</mime-type>
+  </mime-mapping>
+  <mime-mapping>
+    <extension>xml</extension>
+    <mime-type>text/xml</mime-type>
+  </mime-mapping>
+  <mime-mapping>
+    <extension>html</extension>
+    <mime-type>text/html</mime-type>
+  </mime-mapping>
+  <mime-mapping>
+    <extension>htm</extension>
+    <mime-type>text/html</mime-type>
+  </mime-mapping>
+  <mime-mapping>
+    <extension>json</extension>
+    <mime-type>application/json</mime-type>
+  </mime-mapping>
+
+</web-app>
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..91087ef
--- /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);
+        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, CONTENT_TYPE_PLAIN);
+        getContent(urlOfNewNode + ".txt", CONTENT_TYPE_PLAIN);
+        getContent(urlOfNewNode + ".html", CONTENT_TYPE_HTML);
+        getContent(urlOfNewNode + ".json", CONTENT_TYPE_JSON);
+
+        // And extensions for which we have no renderer fail
+        assertHttpStatus(urlOfNewNode + ".xml", 500);
+        assertHttpStatus(urlOfNewNode + ".pdf", 500);
+        assertHttpStatus(urlOfNewNode + ".someWeirdExtension", 500);
+    }
+
+    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);
+        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);
+        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/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/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..0cca856
--- /dev/null
+++ b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/GetStarTest.java
@@ -0,0 +1,65 @@
+/*
+ * 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;
+
+/** A GET to *.html and *.json must work even if there is no Node
+ *  at the specified path (SLING-344)
+ */
+public class GetStarTest extends HttpTestBase {
+    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);
+    }
+    
+    public void testGetStarWithScript() throws IOException {
+        final String scriptPath = "/apps/" + random;
+        testClient.mkdirs(WEBDAV_BASE_URL, scriptPath);
+        urlsToDelete.add(WEBDAV_BASE_URL + scriptPath);
+        final String fakeNodePath = HTTP_BASE_URL + "/sling-test-pbrt/" + random + "/something/*.html"; 
+
+        {
+            final String content = getContent(fakeNodePath, CONTENT_TYPE_HTML);
+            assertTrue("Without script, default renderer marker must be present (" + content + ")",
+                    content.contains("Node dumped by HtmlRendererServlet"));
+        }
+
+        final String urlToDelete = uploadTestScript(scriptPath, "rendering-test.esp", "html.esp");
+        try {
+            final String content = getContent(fakeNodePath, CONTENT_TYPE_HTML);
+            assertTrue("With script, test script marker must be present (" + content + ")",
+                    content.contains("ESP template"));
+        } finally {
+            testClient.delete(urlToDelete);
+        }
+        
+    }
+
+}
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..8f06986
--- /dev/null
+++ b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/IncludeTest.java
@@ -0,0 +1,147 @@
+/*
+ * 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 javax.servlet.http.HttpServletResponse;
+
+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);
+        
+        // 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", new URL(nodeUrlA).getPath());
+        nodeUrlB = testClient.createNode(url, props);
+        
+        // Node E is like B but with an extension on the include path
+        props.put("pathToInclude", new URL(nodeUrlA).getPath() + ".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", new URL(nodeUrlA).getPath());
+        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("InfiniteIncludeLoopException"));
+        
+        // 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..1490620
--- /dev/null
+++ b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/InitialContentTest.java
@@ -0,0 +1,29 @@
+/* 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));
+    }
+}
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..f862723
--- /dev/null
+++ b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/JsonRenderingTest.java
@@ -0,0 +1,177 @@
+/*
+ * 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 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 + "/" + getClass().getSimpleName() + "_"
+            + 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
+                + ")");
+        }
+    }
+}
\ No newline at end of file
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..8b1a592
--- /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, 200, testDirUrl);
+        
+        try {
+            testClient.mkdir(testDirUrl);
+        } catch(IOException ioe) {
+            fail("mkdir must succeed on an existing directory, got IOException:" + ioe);
+        }
+        
+        assertHttpStatus(testDirUrl, 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,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..7490193
--- /dev/null
+++ b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/NodetypeRenderingTest.java
@@ -0,0 +1,169 @@
+/*
+ * 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);
+        assertTrue("Content includes PlainTextRendererServlet marker",content.contains("dumped by PlainTextRendererServlet"));
+    }
+
+    public void testWithoutScriptHtml() throws IOException {
+        final String content = getContent(displayUrl + ".html", CONTENT_TYPE_HTML);
+        assertTrue("Content contains default rendering",content.contains("Node 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 testEspHtml() 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 testEspXml() throws IOException {
+        final String toDelete = uploadTestScript("rendering-test.esp","xml.esp");
+        try {
+            final String content = getContent(displayUrl + ".xml", CONTENT_TYPE_XML);
+            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_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);
+            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 testEspPlain() throws IOException {
+        final String toDelete = uploadTestScript("rendering-test.esp","txt.esp");
+        try {
+            final String content = getContent(displayUrl + ".txt", 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);
+        }
+    }
+
+    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/PathBasedResourceTypeTest.java b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/PathBasedResourceTypeTest.java
new file mode 100644
index 0000000..2082a8c
--- /dev/null
+++ b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/PathBasedResourceTypeTest.java
@@ -0,0 +1,71 @@
+/*
+ * 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 the SLING-340 way of deriving the resource type from
+ *  the content path.
+ */
+
+public class PathBasedResourceTypeTest extends HttpTestBase {
+    
+    public static final String testPath = "sling-integration-test-" + System.currentTimeMillis();
+    public static final String contentPath = "/sling-test-pbrt/" + testPath;
+    
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        urlsToDelete.add(WEBDAV_BASE_URL + contentPath);
+    }
+
+    public void testDefaultResourceType() throws IOException {
+        final TestNode tn = new TestNode(HTTP_BASE_URL + contentPath, null);
+        
+        // without script -> default rendering
+        String content = getContent(tn.nodeUrl + ".html", CONTENT_TYPE_HTML);
+        assertTrue("Content contains default rendering",content.contains("Node dumped by HtmlRendererServlet"));
+        
+        // check default resource type
+        final String scriptPath = "/apps/" + testPath;
+        testClient.mkdirs(WEBDAV_BASE_URL, scriptPath);
+        urlsToDelete.add(WEBDAV_BASE_URL + scriptPath);
+        final String urlsToDelete = uploadTestScript(scriptPath, "rendering-test.esp", "html.esp");
+        try {
+            content = getContent(tn.nodeUrl + ".html", CONTENT_TYPE_HTML);
+            assertTrue("Test script marker found in content (" + content + ")",content.contains("ESP template"));
+        } finally {
+            testClient.delete(urlsToDelete);
+        }
+    }
+    
+    public void testExplicitResourceType() throws IOException {
+        
+        final String resourceType = getClass().getSimpleName();
+        final Map<String, String> properties = new HashMap<String, String>();
+        properties.put(SLING_RESOURCE_TYPE, resourceType);
+        final TestNode tn = new TestNode(HTTP_BASE_URL + contentPath, properties);
+        
+        urlsToDelete.add(uploadTestScript(tn.scriptPath, "rendering-test-2.esp", "html.esp"));
+        final String content = getContent(tn.nodeUrl + ".html", CONTENT_TYPE_HTML);
+        assertTrue("Test script marker found in content (" + content + ")",content.contains("Template #2 for ESP tests"));
+    }
+}
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..17bd8e9
--- /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);
+        assertEquals(testText, data);
+    }
+    
+    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..5f5861f
--- /dev/null
+++ b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/RenderingTestBase.java
@@ -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.
+ */
+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);
+    }
+}
\ No newline at end of file
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..28af28e
--- /dev/null
+++ b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/SlingResourceTypeRenderingTest.java
@@ -0,0 +1,305 @@
+/*
+ * 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);
+        assertTrue("Content includes PlainTextRendererServlet marker",content.contains("dumped by PlainTextRendererServlet"));
+    }
+
+    public void testWithoutScriptHtml() throws IOException {
+        final String content = getContent(displayUrl + ".html", CONTENT_TYPE_HTML);
+        assertTrue("Content contains default rendering",content.contains("Node 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);
+            assertTrue("Content includes ESP marker",content.contains("ESP template"));
+            assertTrue("Content contains formatted test text",content.contains("<p>" + testText + "</p>"));
+            assertTrue("Content (" + content + ") contains attribute generated with simplified syntax",
+                    content.contains("<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);
+            assertTrue("Content includes ESP marker",content.contains("ESP template"));
+            assertTrue("Content contains java code output",content.contains("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 include ESP marker before test",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);
+            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_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);
+            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 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_testJstHtml() throws IOException {
+        final String toDelete = uploadTestScript("rendering-test.jst","html.jst");
+        try {
+            final String content = getContent(displayUrl + ".html", CONTENT_TYPE_HTML);
+            assertTrue("Content includes JST marker",content.contains("JST template"));
+            assertTrue("Content contains JSON data",content.contains("\"text\":\"" + testText + "\""));
+            assertTrue("Content contains default rendering",content.contains("div id=\"JstDefaultRendering"));
+            assertTrue("Content contains javascript rendering code",content.contains("out.write( currentNode.text )"));
+        } finally {
+            testClient.delete(toDelete);
+        }
+    }
+
+    public void TODO_FAILS_testJstScriptTagA() throws IOException {
+        final String toDelete = uploadTestScript("rendering-test.jst","html.jst");
+        try {
+            final String content = getContent(displayUrl + ".html", CONTENT_TYPE_HTML);
+            assertTrue("Content includes JST marker",content.contains("JST template"));
+            assertTrue("Content contains scripted stuff (" + content + ")",
+                    content.contains("something scripted"));
+            assertFalse("Script opening tag must be broken in two in content (" + content + ")",
+                    content.contains("<script>something")); 
+            assertFalse("Script closing tag must be broken in two in content (" + content + ")",
+                    content.contains("scripted</script>")); 
+        } finally {
+            testClient.delete(toDelete);
+        }
+    }
+
+    /** TODO this test currently fails, see SLING-114 */
+    public void TODO_FAILS_testJstHtmlScriptTagB() throws IOException {
+        final String toDelete = uploadTestScript("rendering-test.jst","html.jst");
+        try {
+            final String content = getContent(displayUrl + ".html", CONTENT_TYPE_HTML);
+            assertTrue("Content includes JST marker",content.contains("JST template"));
+            assertTrue("Content contains scripted stuff (" + content + ")",
+                    content.contains("more scripting"));
+            assertFalse("Script opening tag must be broken in two in content (" + content + ")",
+                    content.contains("<script>more")); 
+            assertFalse("Script closing tag must be broken in two in content (" + content + ")",
+                    content.contains("scripting</script>")); 
+        } finally {
+            testClient.delete(toDelete);
+        }
+    }
+
+    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
+            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 testEspXml() throws IOException {
+        final String toDelete = uploadTestScript("rendering-test.esp","xml.esp");
+        try {
+            final String content = getContent(displayUrl + ".xml", CONTENT_TYPE_XML);
+            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 testEspPlain() throws IOException {
+        final String toDelete = uploadTestScript("rendering-test.esp","txt.esp");
+        try {
+            final String content = getContent(displayUrl + ".txt", 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);
+        }
+    }
+
+    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);
+        }
+    }
+}
\ 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..e3ad1fe
--- /dev/null
+++ b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/UploadFileTest.java
@@ -0,0 +1,150 @@
+/*
+ * 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.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\""));
+    }
+
+}
\ 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/apt/SimpleAptRenderingTest.java b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/apt/SimpleAptRenderingTest.java
new file mode 100644
index 0000000..9589add
--- /dev/null
+++ b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/apt/SimpleAptRenderingTest.java
@@ -0,0 +1,46 @@
+/*
+ * 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.apt;
+
+import org.apache.sling.commons.testing.integration.HttpTestBase;
+
+public class SimpleAptRenderingTest extends HttpTestBase {
+    
+     private final static String EOL = System.getProperty( "line.separator" );
+
+     public void testAptDocument() throws Exception {
+        testClient.mkdirs(WEBDAV_BASE_URL, "/apt-test");
+        final String toDelete = uploadTestScript("/apt-test", "apt/apt-test.apt", "apt-test.apt");
+        try {
+            // .apt returns plain text
+            getContent(HTTP_BASE_URL + "/apt-test/apt-test.apt", CONTENT_TYPE_PLAIN);
+            
+            // .apt.aptml converts APT to html
+            final String content = getContent(HTTP_BASE_URL + "/apt-test/apt-test.apt.aptml", CONTENT_TYPE_HTML);
+            assertTrue("HTML opening tag present (" + content + ")", content.startsWith("<html>"));
+            assertTrue("HTML closing tag present (" + content + ")", content.endsWith("</html>" + EOL));
+            assertTrue("title parsed as expected (" + content + ")", content.contains("<title>Simple APT file test</title>"));
+            assertTrue("body opening tag is present (" + content + ")", content.contains("</head>" + EOL + "<body>"));
+            assertTrue("body closing tag is present (" + content + ")", content.endsWith("</body>" + EOL + "</html>" + EOL));
+            assertTrue("h1 parsed as expected (" + content + ")", content.contains("<h1>h1 heading"));
+            assertTrue("h2 parsed as expected (" + content + ")", content.contains("<h2>h2 heading"));
+            assertTrue("h3 parsed as expected (" + content + ")", content.contains("<h3>h3 heading"));
+        } finally {
+            testClient.delete(toDelete);
+        }
+    }
+}
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/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..c26e40a
--- /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, 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, 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, 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, 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..13197ad
--- /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, HttpServletResponse.SC_OK, "A must initially exist");
+        assertHttpStatus(urlB, HttpServletResponse.SC_OK, "B must initially exist");
+        assertHttpStatus(urlC, HttpServletResponse.SC_OK, "C must initially exist");
+        assertHttpStatus(urlD, 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, HttpServletResponse.SC_NOT_FOUND, "A must be deleted (1)");
+        assertHttpStatus(urlB, HttpServletResponse.SC_OK, "B must still exist");
+        assertHttpStatus(urlC, HttpServletResponse.SC_OK, "C must still exist");
+        assertHttpStatus(urlD, 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, HttpServletResponse.SC_NOT_FOUND, "A must be deleted (2)");
+        assertHttpStatus(urlB, HttpServletResponse.SC_NOT_FOUND, "B must be deleted (2)");
+        assertHttpStatus(urlC, HttpServletResponse.SC_NOT_FOUND, "C must be deleted (2)");
+        assertHttpStatus(urlD, 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, HttpServletResponse.SC_OK, "A must initially exist");
+        assertHttpStatus(urlB, HttpServletResponse.SC_OK, "B must initially exist");
+        assertHttpStatus(urlC, HttpServletResponse.SC_OK, "C must initially exist");
+        assertHttpStatus(urlD, 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, HttpServletResponse.SC_NOT_FOUND, "A must be deleted (1)");
+        assertHttpStatus(urlB, HttpServletResponse.SC_NOT_FOUND, "B must be deleted (1)");
+        assertHttpStatus(urlC, HttpServletResponse.SC_OK, "C must still exist");
+        assertHttpStatus(urlD, 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, HttpServletResponse.SC_NOT_FOUND, "A must be deleted (2)");
+        assertHttpStatus(urlB, HttpServletResponse.SC_NOT_FOUND, "B must be deleted (2)");
+        assertHttpStatus(urlC, HttpServletResponse.SC_NOT_FOUND, "C must be deleted (2)");
+        assertHttpStatus(urlD, 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/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..ab39937
--- /dev/null
+++ b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/post/PostServletUpdateTest.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.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 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);
+    }
+}
\ 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/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/resources/integration-test/apt/apt-test.apt b/src/test/resources/integration-test/apt/apt-test.apt
new file mode 100644
index 0000000..e382fb7
--- /dev/null
+++ b/src/test/resources/integration-test/apt/apt-test.apt
@@ -0,0 +1,15 @@
+   -----------------------------
+   Simple APT file test
+   -----------------------------
+
+h1 heading
+
+* h2 heading
+
+  Text paragraph
+  with several lines
+  which must be indented in the APT file.
+  
+** h3 heading
+
+  And so on...  
\ No newline at end of file
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/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/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-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/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/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/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.erb b/src/test/resources/integration-test/rendering-test.erb
new file mode 100644
index 0000000..2ffa5e3
--- /dev/null
+++ b/src/test/resources/integration-test/rendering-test.erb
@@ -0,0 +1,36 @@
+<!-- 
+/*
+ * 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>
+    <p><span>Ruby template <%= Time.now %></span></p>
+		<p><span><%= resource.getNode().getProperty("text").getString() %></span></p>
+    <% unless props.nil? or props.empty? %>
+      <table>
+        <% for prop, val in props %>
+          <tr><td><b><%= prop %></b>:</td><td><%= val %></td></tr>
+        <% end %>
+      </table>
+    <% end %>
+  </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.ftl b/src/test/resources/integration-test/rendering-test.ftl
new file mode 100644
index 0000000..799731c
--- /dev/null
+++ b/src/test/resources/integration-test/rendering-test.ftl
@@ -0,0 +1,7 @@
+<%-- used by ScriptedRenderingTest --%>
+<html>
+	<body>
+		FreeMarker template
+		<p><span>${resource.getNode().getProperty("text").getString()}</span></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/rendering-test.jst b/src/test/resources/integration-test/rendering-test.jst
new file mode 100644
index 0000000..d639507
--- /dev/null
+++ b/src/test/resources/integration-test/rendering-test.jst
@@ -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 ScriptedRenderingTest --%>
+<p>
+	JST template.
+</p>
+
+<p>
+  <%= currentNode.title %> </b>
+</p>
+
+<p>
+  <%= currentNode.text %> </em>
+</p>
+
+<!-- verify that script tag is broken in two when rendering -->
+<!-- (SLING-114) -->
+ 
+<script>something scripted</script>
+
+<% for(i=0; i< 10; i++) {
+} %><script>more scripting</script><% for(i=0; i< 10; i++) {
+} %>
\ No newline at end of file
diff --git a/src/test/resources/integration-test/rendering-test.vlt b/src/test/resources/integration-test/rendering-test.vlt
new file mode 100644
index 0000000..e68ccce
--- /dev/null
+++ b/src/test/resources/integration-test/rendering-test.vlt
@@ -0,0 +1,28 @@
+<!--
+/*
+ * 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>
+		Velocity template
+		<p><b>$resource.getNode().getProperty("text").getString()</b></p>
+	</body>
+</html>
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