This is an automated email from the ASF dual-hosted git repository. bdelacretaz pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/sling-whiteboard.git
commit 0eb969a4d73923e0e8c0a882ad0182256ae3f702 Author: Bertrand Delacretaz <[email protected]> AuthorDate: Mon Nov 8 15:12:23 2021 +0100 JSON store, first commit --- json-store/README.md | 24 ++++++ json-store/pom.xml | 95 ++++++++++++++++++++++ .../org/apache/sling/jsonstore/api/JsonStore.java | 28 +++++++ .../sling/jsonstore/api/JsonStoreConstants.java | 35 ++++++++ .../apache/sling/jsonstore/impl/JsonStoreImpl.java | 49 +++++++++++ .../sling/jsonstore/impl/SitesParentServlet.java | 57 +++++++++++++ 6 files changed, 288 insertions(+) diff --git a/json-store/README.md b/json-store/README.md new file mode 100644 index 0000000..3000e3f --- /dev/null +++ b/json-store/README.md @@ -0,0 +1,24 @@ +# Apache Sling JSON Store + +TODO: Explain more, a content store using Sling that introduces that +stores content as JSON blobs validated by JSON schemas. + +## Storage Model +* A _site_ is the root of a subtree of content that belongs together. +* Below the _site_ resource: +** The _schema_ subtree stores JSON schema keyed by resource type +** The _elements_ subtree stores validated reusable elements of content +** The _content_ subtree stores the actual validated content: pages etc. + +## How to test this + +Install this bundle and create a "JSON store root" node: + + curl -u admin:admin -F sling:resourceType=sling/jsonstore/root http://localhost:8080/content/sites + +POST to that resource to create a test site: + + curl -u admin:admin -F path=example.com http://localhost:8080/content/sites + +This creates the required structure under "sites/example.com" to store JSON schemas, +elements and content. \ No newline at end of file diff --git a/json-store/pom.xml b/json-store/pom.xml new file mode 100644 index 0000000..950c14f --- /dev/null +++ b/json-store/pom.xml @@ -0,0 +1,95 @@ +<?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. +--> +<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/xsd/maven-4.0.0.xsd"> + + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.apache.sling</groupId> + <artifactId>sling-bundle-parent</artifactId> + <version>46</version> + <relativePath /> + </parent> + + <artifactId>org.apache.sling.jsonstore</artifactId> + <version>0.0.1-SNAPSHOT</version> + + <name>Apache Sling JSON store</name> + + <properties> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> + <project.build.outputTimestamp>1</project.build.outputTimestamp> + </properties> + + <build> + <plugins> + <plugin> + <groupId>biz.aQute.bnd</groupId> + <artifactId>bnd-maven-plugin</artifactId> + </plugin> + <plugin> + <groupId>biz.aQute.bnd</groupId> + <artifactId>bnd-baseline-maven-plugin</artifactId> + <configuration> + <!-- TODO remove this once we have a release of this module --> + <failOnMissing>false</failOnMissing> + </configuration> + </plugin> + </plugins> + </build> + + <dependencies> + <dependency> + <groupId>org.osgi</groupId> + <artifactId>org.osgi.service.component.annotations</artifactId> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.apache.sling</groupId> + <artifactId>org.apache.sling.api</artifactId> + <version>2.23.6</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.apache.sling</groupId> + <artifactId>org.apache.sling.servlets.annotations</artifactId> + <version>1.2.6</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-api</artifactId> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>javax.servlet</groupId> + <artifactId>javax.servlet-api</artifactId> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.jetbrains</groupId> + <artifactId>annotations</artifactId> + <version>16.0.3</version> + <scope>provided</scope> + </dependency> + </dependencies> + +</project> \ No newline at end of file diff --git a/json-store/src/main/java/org/apache/sling/jsonstore/api/JsonStore.java b/json-store/src/main/java/org/apache/sling/jsonstore/api/JsonStore.java new file mode 100644 index 0000000..060af7f --- /dev/null +++ b/json-store/src/main/java/org/apache/sling/jsonstore/api/JsonStore.java @@ -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. + */ + + package org.apache.sling.jsonstore.api; + +import org.apache.sling.api.resource.PersistenceException; +import org.apache.sling.api.resource.Resource; + +public interface JsonStore { + /** Create a Site and return its root */ + Resource createSite(Resource parent, String relativeSitePath) throws PersistenceException; +} diff --git a/json-store/src/main/java/org/apache/sling/jsonstore/api/JsonStoreConstants.java b/json-store/src/main/java/org/apache/sling/jsonstore/api/JsonStoreConstants.java new file mode 100644 index 0000000..63e781f --- /dev/null +++ b/json-store/src/main/java/org/apache/sling/jsonstore/api/JsonStoreConstants.java @@ -0,0 +1,35 @@ +/* + * 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.jsonstore.api; + +public class JsonStoreConstants { + public static final String STORE_ROOT_RESOURCE_TYPE = "sling/jsonstore/root"; + public static final String SITE_ROOT_RESOURCE_TYPE = "sling/jsonstore/site"; + public static final String SCHEMA_ROOT_RESOURCE_TYPE = "sling/jsonstore/schema/root"; + public static final String ELEMENTS_ROOT_RESOURCE_TYPE = "sling/jsonstore/elements/root"; + public static final String CONTENT_ROOT_RESOURCE_TYPE = "sling/jsonstore/content/root"; + + public static final String SCHEMA_ROOT_NAME = "schema"; + public static final String ELEMENTS_ROOT_NAME = "elements"; + public static final String CONTENT_ROOT_NAME = "content"; + + public static final String PARAM_PATH = "path"; + private JsonStoreConstants() {} +} diff --git a/json-store/src/main/java/org/apache/sling/jsonstore/impl/JsonStoreImpl.java b/json-store/src/main/java/org/apache/sling/jsonstore/impl/JsonStoreImpl.java new file mode 100644 index 0000000..4bf74a1 --- /dev/null +++ b/json-store/src/main/java/org/apache/sling/jsonstore/impl/JsonStoreImpl.java @@ -0,0 +1,49 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + package org.apache.sling.jsonstore.impl; + +import static org.apache.sling.jsonstore.api.JsonStoreConstants.*; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.sling.api.resource.PersistenceException; +import org.apache.sling.api.resource.Resource; +import org.apache.sling.jsonstore.api.JsonStore; +import org.osgi.service.component.annotations.Component; + +@Component(service=JsonStore.class) +public class JsonStoreImpl implements JsonStore { + + public Resource createSite(Resource parent, String name) throws PersistenceException { + final Resource site = createChild(parent, name, SITE_ROOT_RESOURCE_TYPE); + createChild(site, SCHEMA_ROOT_NAME, SCHEMA_ROOT_RESOURCE_TYPE); + createChild(site, ELEMENTS_ROOT_NAME, ELEMENTS_ROOT_RESOURCE_TYPE); + createChild(site, CONTENT_ROOT_NAME, CONTENT_ROOT_RESOURCE_TYPE); + site.getResourceResolver().commit(); + return site; + } + + private Resource createChild(Resource parent, String name, String resourceType) throws PersistenceException { + final Map<String, Object> props = new HashMap<>(); + props.put("sling:resourceType", resourceType); + return parent.getResourceResolver().create(parent, name, props); + } +} diff --git a/json-store/src/main/java/org/apache/sling/jsonstore/impl/SitesParentServlet.java b/json-store/src/main/java/org/apache/sling/jsonstore/impl/SitesParentServlet.java new file mode 100644 index 0000000..961b03b --- /dev/null +++ b/json-store/src/main/java/org/apache/sling/jsonstore/impl/SitesParentServlet.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.jsonstore.impl; + +import java.io.IOException; + +import javax.servlet.Servlet; +import javax.servlet.http.HttpServletResponse; + +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.SlingAllMethodsServlet; +import org.apache.sling.jsonstore.api.JsonStore; +import org.apache.sling.jsonstore.api.JsonStoreConstants; +import org.apache.sling.servlets.annotations.SlingServletResourceTypes; +import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Reference; + +@Component(service = Servlet.class) +@SlingServletResourceTypes( + resourceTypes=JsonStoreConstants.STORE_ROOT_RESOURCE_TYPE, + methods= "POST" +) +public class SitesParentServlet extends SlingAllMethodsServlet { + @Reference + private JsonStore store; + + @Override + public void doPost(SlingHttpServletRequest request, SlingHttpServletResponse response) throws IOException { + final String relativeSitePath = request.getParameter(JsonStoreConstants.PARAM_PATH); + if(relativeSitePath == null) { + response.sendError(HttpServletResponse.SC_BAD_REQUEST, String.format("Missing required parameter '%s'")); + } + final Resource result = store.createSite(request.getResource(), relativeSitePath); + + // TODO set Location header etc. + response.getWriter().write(String.format("Created site %s", result.getPath())); + } +}
