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