You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by bd...@apache.org on 2015/02/02 18:58:35 UTC
svn commit: r1656529 - in /sling/trunk:
bundles/commons/testing/src/main/java/org/apache/sling/commons/testing/integration/
bundles/servlets/get/
bundles/servlets/get/src/main/java/org/apache/sling/servlets/get/impl/version/
bundles/servlets/get/src/ma...
Author: bdelacretaz
Date: Mon Feb 2 17:58:34 2015
New Revision: 1656529
URL: http://svn.apache.org/r1656529
Log:
SLING-4318 - new VersionInfoServlet, requires an OSGi config to be enabled. Contributed by Tomek Rękawek, thanks!
Added:
sling/trunk/bundles/servlets/get/src/main/java/org/apache/sling/servlets/get/impl/version/
sling/trunk/bundles/servlets/get/src/main/java/org/apache/sling/servlets/get/impl/version/VersionInfoServlet.java
sling/trunk/launchpad/integration-tests/src/main/java/org/apache/sling/launchpad/webapp/integrationtest/VersionInfoServletTest.java
Modified:
sling/trunk/bundles/commons/testing/src/main/java/org/apache/sling/commons/testing/integration/SlingIntegrationTestClient.java
sling/trunk/bundles/servlets/get/pom.xml
sling/trunk/bundles/servlets/get/src/main/resources/OSGI-INF/metatype/metatype.properties
sling/trunk/launchpad/builder/src/main/bundles/list.xml
Modified: sling/trunk/bundles/commons/testing/src/main/java/org/apache/sling/commons/testing/integration/SlingIntegrationTestClient.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/commons/testing/src/main/java/org/apache/sling/commons/testing/integration/SlingIntegrationTestClient.java?rev=1656529&r1=1656528&r2=1656529&view=diff
==============================================================================
--- sling/trunk/bundles/commons/testing/src/main/java/org/apache/sling/commons/testing/integration/SlingIntegrationTestClient.java (original)
+++ sling/trunk/bundles/commons/testing/src/main/java/org/apache/sling/commons/testing/integration/SlingIntegrationTestClient.java Mon Feb 2 17:58:34 2015
@@ -22,8 +22,10 @@ import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
+import java.util.Map.Entry;
import org.apache.commons.httpclient.HttpClient;
+import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.methods.DeleteMethod;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.InputStreamRequestEntity;
@@ -246,4 +248,20 @@ public class SlingIntegrationTestClient
throw new HttpStatusCodeException(expected, status, "POST", HttpTestBase.getResponseBodyAsStream(post, 0));
}
}
+
+ public int post(String url, Map<String,String> properties) throws HttpException, IOException {
+ final PostMethod post = new PostMethod(url);
+ post.getParams().setContentCharset("UTF-8");
+ for(Entry<String, String> e : properties.entrySet()) {
+ post.addParameter(e.getKey(), e.getValue());
+ }
+ return httpClient.executeMethod(post);
+ }
+
+ public int get(String url) throws HttpException, IOException {
+ final GetMethod get = new GetMethod(url);
+ get.getParams().setContentCharset("UTF-8");
+ return httpClient.executeMethod(get);
+ }
+
}
Modified: sling/trunk/bundles/servlets/get/pom.xml
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/servlets/get/pom.xml?rev=1656529&r1=1656528&r2=1656529&view=diff
==============================================================================
--- sling/trunk/bundles/servlets/get/pom.xml (original)
+++ sling/trunk/bundles/servlets/get/pom.xml Mon Feb 2 17:58:34 2015
@@ -96,6 +96,12 @@
<scope>provided</scope>
</dependency>
<dependency>
+ <groupId>org.apache.jackrabbit</groupId>
+ <artifactId>jackrabbit-jcr-commons</artifactId>
+ <version>2.2.9</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.core</artifactId>
</dependency>
Added: sling/trunk/bundles/servlets/get/src/main/java/org/apache/sling/servlets/get/impl/version/VersionInfoServlet.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/servlets/get/src/main/java/org/apache/sling/servlets/get/impl/version/VersionInfoServlet.java?rev=1656529&view=auto
==============================================================================
--- sling/trunk/bundles/servlets/get/src/main/java/org/apache/sling/servlets/get/impl/version/VersionInfoServlet.java (added)
+++ sling/trunk/bundles/servlets/get/src/main/java/org/apache/sling/servlets/get/impl/version/VersionInfoServlet.java Mon Feb 2 17:58:34 2015
@@ -0,0 +1,151 @@
+/*
+ * 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.servlets.get.impl.version;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import javax.jcr.version.Version;
+import javax.jcr.version.VersionHistory;
+import javax.jcr.version.VersionIterator;
+import javax.servlet.Servlet;
+import javax.servlet.ServletException;
+
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.ConfigurationPolicy;
+import org.apache.felix.scr.annotations.Properties;
+import org.apache.felix.scr.annotations.Property;
+import org.apache.felix.scr.annotations.Service;
+import org.apache.jackrabbit.JcrConstants;
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.SlingHttpServletResponse;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.servlets.SlingSafeMethodsServlet;
+import org.apache.sling.commons.json.JSONException;
+import org.apache.sling.commons.json.JSONObject;
+import org.apache.sling.commons.json.io.JSONRenderer;
+import org.apache.sling.commons.json.jcr.JsonItemWriter;
+
+/**
+ * The <code>VersionInfoServlet</code> renders list of versions available for
+ * the current resource.
+ *
+ * At the moment only JCR nodes are supported.
+ */
+@Component(immediate=true, metatype=true, name="org.apache.sling.servlets.get.impl.version.VersionInfoServlet", label="%servlet.version.name", description="%servlet.version.description", policy=ConfigurationPolicy.REQUIRE)
+@Service(Servlet.class)
+@Properties({
+ @Property(name="service.description", value="Version info servlet"),
+ @Property(name="service.vendor", value="The Apache Software Foundation"),
+
+ @Property(name="sling.servlet.resourceTypes", value="sling/servlet/default", propertyPrivate=true),
+ @Property(name="sling.servlet.selectors", value="V"),
+ @Property(name="sling.servlet.methods", value="GET", propertyPrivate=true),
+ @Property(name="sling.servlet.extensions", value="json", propertyPrivate=true),
+})
+public class VersionInfoServlet extends SlingSafeMethodsServlet {
+
+ private static final long serialVersionUID = 1656887064561951302L;
+
+ /** Selector that means "pretty-print the output */
+ public static final String TIDY = "tidy";
+
+ /**
+ * Selector that causes hierarchy to be rendered as arrays instead of child objects - useful to preserve
+ * the order of those child objects
+ */
+ public static final String HARRAY = "harray";
+
+ /** How much to indent in tidy mode */
+ public static final int INDENT_SPACES = 2;
+
+ private final JSONRenderer renderer = new JSONRenderer();
+
+ public void doGet(SlingHttpServletRequest req, SlingHttpServletResponse resp) throws ServletException,
+ IOException {
+ resp.setContentType(req.getResponseContentType());
+ resp.setCharacterEncoding("UTF-8");
+ final boolean tidy = hasSelector(req, TIDY);
+ final boolean harray = hasSelector(req, HARRAY);
+
+ final JSONRenderer.Options opt = renderer.options().withIndent(tidy ? INDENT_SPACES : 0)
+ .withArraysForChildren(harray);
+ try {
+ resp.getWriter().write(renderer.prettyPrint(getJsonObject(req.getResource()), opt));
+ } catch (RepositoryException e) {
+ throw new ServletException(e);
+ } catch (JSONException e) {
+ throw new ServletException(e);
+ }
+ }
+
+ private JSONObject getJsonObject(Resource resource) throws RepositoryException, JSONException {
+ final JSONObject result = new JSONObject();
+ final Node node = resource.adaptTo(Node.class);
+ if (node == null || !node.isNodeType(JcrConstants.MIX_VERSIONABLE)) {
+ return result;
+ }
+
+ final VersionHistory history = node.getVersionHistory();
+ final Version baseVersion = node.getBaseVersion();
+ for (final VersionIterator it = history.getAllVersions(); it.hasNext();) {
+ final Version v = it.nextVersion();
+ final JSONObject obj = new JSONObject();
+ obj.put("created", createdDate(v));
+ obj.put("successors", getNames(v.getSuccessors()));
+ obj.put("predecessors", getNames(v.getPredecessors()));
+ obj.put("labels", Arrays.asList(history.getVersionLabels(v)));
+ obj.put("baseVersion", baseVersion.isSame(v));
+ result.put(v.getName(), obj);
+ }
+
+ final JSONObject wrapper = new JSONObject();
+ wrapper.put("versions", result);
+ return wrapper;
+ }
+
+ private static Collection<String> getNames(Version[] versions) throws RepositoryException {
+ final List<String> result = new ArrayList<String>();
+ for (Version s : versions) {
+ result.add(s.getName());
+ }
+ return result;
+ }
+
+ /** True if our request has the given selector */
+ private boolean hasSelector(SlingHttpServletRequest req, String selectorToCheck) {
+ for (String selector : req.getRequestPathInfo().getSelectors()) {
+ if (selectorToCheck.equals(selector)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private static String createdDate(Node node) throws RepositoryException {
+ return JsonItemWriter.format(node.getProperty(JcrConstants.JCR_CREATED).getDate());
+ }
+
+}
Modified: sling/trunk/bundles/servlets/get/src/main/resources/OSGI-INF/metatype/metatype.properties
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/servlets/get/src/main/resources/OSGI-INF/metatype/metatype.properties?rev=1656529&r1=1656528&r2=1656529&view=diff
==============================================================================
--- sling/trunk/bundles/servlets/get/src/main/resources/OSGI-INF/metatype/metatype.properties (original)
+++ sling/trunk/bundles/servlets/get/src/main/resources/OSGI-INF/metatype/metatype.properties Mon Feb 2 17:58:34 2015
@@ -26,6 +26,10 @@
servlet.get.name = Apache Sling GET Servlet
servlet.get.description = The Sling GET servlet is registered as the default \
servlet to handle GET requests.
+
+servlet.version.name = Apache Sling Version Info Servlet
+servlet.version.description = The Sling Version Info Servlet renders list of \
+versions available for the current resource
aliases.name = Extension Aliases
aliases.description = The aliases can be used to map several extensions to a \
Modified: sling/trunk/launchpad/builder/src/main/bundles/list.xml
URL: http://svn.apache.org/viewvc/sling/trunk/launchpad/builder/src/main/bundles/list.xml?rev=1656529&r1=1656528&r2=1656529&view=diff
==============================================================================
--- sling/trunk/launchpad/builder/src/main/bundles/list.xml (original)
+++ sling/trunk/launchpad/builder/src/main/bundles/list.xml Mon Feb 2 17:58:34 2015
@@ -220,7 +220,7 @@
<bundle>
<groupId>org.apache.sling</groupId>
<artifactId>org.apache.sling.servlets.get</artifactId>
- <version>2.1.10</version>
+ <version>2.1.11-SNAPSHOT</version>
</bundle>
<bundle>
<groupId>org.apache.sling</groupId>
Added: sling/trunk/launchpad/integration-tests/src/main/java/org/apache/sling/launchpad/webapp/integrationtest/VersionInfoServletTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/launchpad/integration-tests/src/main/java/org/apache/sling/launchpad/webapp/integrationtest/VersionInfoServletTest.java?rev=1656529&view=auto
==============================================================================
--- sling/trunk/launchpad/integration-tests/src/main/java/org/apache/sling/launchpad/webapp/integrationtest/VersionInfoServletTest.java (added)
+++ sling/trunk/launchpad/integration-tests/src/main/java/org/apache/sling/launchpad/webapp/integrationtest/VersionInfoServletTest.java Mon Feb 2 17:58:34 2015
@@ -0,0 +1,99 @@
+package org.apache.sling.launchpad.webapp.integrationtest;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.commons.httpclient.HttpException;
+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;
+
+public class VersionInfoServletTest extends HttpTestBase {
+
+ public static final String TEST_BASE_PATH = "/sling-tests";
+
+ public static final String CONFIG_SERVLET = HTTP_BASE_URL + "/system/console/configMgr/org.apache.sling.servlets.get.impl.version.VersionInfoServlet";
+
+ private String postUrl;
+
+ private Map<String,String> params;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ postUrl = HTTP_BASE_URL + TEST_BASE_PATH + "/" + System.currentTimeMillis();
+ params = new HashMap<String,String>();
+ params.put("jcr:mixinTypes", "mix:versionable");
+ }
+
+ private String createVersionableNode() throws IOException {
+ params.put(":checkinNewVersionableNodes", "true");
+ final String location = testClient.createNode(postUrl + SlingPostConstants.DEFAULT_CREATE_SUFFIX, params);
+
+ final String content = getContent(location + ".txt", CONTENT_TYPE_PLAIN);
+ assertTrue("Node (" + location + ") should be checked in.", content.contains("jcr:isCheckedOut: false"));
+ return location;
+ }
+
+ public void testDisabledServlet() throws IOException, JSONException, InterruptedException {
+ deleteConfiguration();
+ waitUntilSlingIsStable();
+ getContent(createVersionableNode() + ".V.json", CONTENT_TYPE_HTML, null, 400);
+ }
+
+ public void testStandardVersionsList() throws IOException, JSONException, InterruptedException {
+ createConfiguration("V");
+ waitUntilSlingIsStable();
+ final JSONObject versions = new JSONObject(getContent(createVersionableNode() + ".V.json", CONTENT_TYPE_JSON));
+ assertTrue("Expecting versions subtree", versions.has("versions"));
+ assertTrue("Expecting root version", versions.getJSONObject("versions").has("jcr:rootVersion"));
+ assertTrue("Expecting version 1.0", versions.getJSONObject("versions").has("1.0"));
+
+ final JSONObject oneZero = versions.getJSONObject("versions").getJSONObject("1.0");
+ assertTrue("Expecting non-empty creation date", oneZero.get("created").toString().length() > 0);
+ assertEquals("Expecting no successors", 0, oneZero.getJSONArray("successors").length());
+ assertEquals("Expecting root version predecessor", "jcr:rootVersion", oneZero.getJSONArray("predecessors").getString(0));
+ assertEquals("Expecting no labels", 0, oneZero.getJSONArray("labels").length());
+ assertEquals("Expecting true baseVersion", "true", oneZero.getString("baseVersion"));
+ }
+
+ public void testHarrayVersionsList() throws Exception {
+ // No need to test everything in detail, just verify that the output
+ // is reformatted with the harray option
+ createConfiguration("V");
+ waitForSlingStartup();
+ waitUntilSlingIsStable();
+ final JSONObject versions = new JSONObject(getContent(createVersionableNode() + ".V.harray.json", CONTENT_TYPE_JSON));
+ assertTrue("Expecting children array", versions.has("__children__"));
+ assertEquals("Expecting versions object", "versions",
+ versions.getJSONArray("__children__").getJSONObject(0).get("__name__"));
+ }
+
+ private void createConfiguration(final String selector) throws IOException {
+ Map<String, String> properties = new HashMap<String, String>();
+ properties.put("apply", "true");
+ properties.put("sling.servlet.selectors", selector);
+ properties.put("propertylist", "sling.servlet.selectors");
+ assertEquals(302, testClient.post(CONFIG_SERVLET, properties));
+ }
+
+ private void deleteConfiguration() throws IOException {
+ Map<String, String> properties = new HashMap<String, String>();
+ properties.put("apply", "true");
+ properties.put("delete", "true");
+ assertEquals(200, testClient.post(CONFIG_SERVLET, properties));
+ }
+
+ private void waitUntilSlingIsStable() throws HttpException, IOException,
+ InterruptedException {
+ for (int i = 0; i < 10; i++) {
+ Thread.sleep(1000);
+ if (testClient.get(HTTP_BASE_URL + "/.json") == 200) {
+ return;
+ }
+ }
+ fail("Sling instance fails to respond with status 200");
+ }
+}