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 c74d4f6a3709d79479fc8a4300f885ce297c7221 Author: Bertrand Delacretaz <[email protected]> AuthorDate: Wed Aug 26 16:43:46 2020 +0200 Basic navigation, properties filtering and api/metadata/content/children output --- dokapi/.gitignore | 2 + dokapi/pom.xml | 18 ++++- .../sling/dokapi/impl/ChildrenProcessor.java | 49 +++++++++++++ .../apache/sling/dokapi/impl/ContentProcessor.java | 34 +++++++++ .../apache/sling/dokapi/impl/DokapiServlet.java | 64 +++++++++++++++++ .../apache/sling/dokapi/impl/JsonProcessor.java | 24 +++++++ .../sling/dokapi/impl/MetadataProcessor.java | 34 +++++++++ .../main/java/org/apache/sling/dokapi/impl/P.java | 76 ++++++++++++++++++++ .../apache/sling/dokapi/impl/PipelineContext.java | 81 ++++++++++++++++++++++ 9 files changed, 381 insertions(+), 1 deletion(-) diff --git a/dokapi/.gitignore b/dokapi/.gitignore new file mode 100644 index 0000000..f87a37c --- /dev/null +++ b/dokapi/.gitignore @@ -0,0 +1,2 @@ +conf/ +launcher/ diff --git a/dokapi/pom.xml b/dokapi/pom.xml index 232a9fa..c6dcde1 100644 --- a/dokapi/pom.xml +++ b/dokapi/pom.xml @@ -82,7 +82,17 @@ <commandlineArgs>-s src/test/resources/features/feature-sling12.json -af src/test/resources/features/feature-dokapi-test.json</commandlineArgs> </configuration> </plugin> - </plugins> + <plugin> + <groupId>org.apache.rat</groupId> + <artifactId>apache-rat-plugin</artifactId> + <configuration> + <excludes> + <exclude>launcher/**</exclude> + <exclude>conf/**</exclude> + </excludes> + </configuration> + </plugin> +</plugins> </build> <dependencies> @@ -119,6 +129,12 @@ <version>0.0.2</version> <scope>runtime</scope> </dependency> + <dependency> + <groupId>org.apache.sling</groupId> + <artifactId>org.apache.sling.commons.johnzon</artifactId> + <version>1.2.2</version> + <scope>provided</scope> + </dependency> </dependencies> </project> diff --git a/dokapi/src/main/java/org/apache/sling/dokapi/impl/ChildrenProcessor.java b/dokapi/src/main/java/org/apache/sling/dokapi/impl/ChildrenProcessor.java new file mode 100644 index 0000000..7ba1fa7 --- /dev/null +++ b/dokapi/src/main/java/org/apache/sling/dokapi/impl/ChildrenProcessor.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.dokapi.impl; + +import javax.json.Json; +import javax.json.JsonObjectBuilder; + +import org.apache.sling.api.resource.Resource; +import org.apache.sling.api.resource.ValueMap; + +class ChildrenProcessor implements JsonProcessor { + @Override + public void process(PipelineContext pc) { + if(pc.resource.hasChildren()) { + for(Resource child: pc.resource.getChildren()) { + if(P.ignoreResource(child.getName())) { + continue; + } + final JsonObjectBuilder childBuilder = Json.createObjectBuilder(); + final ValueMap vm = child.adaptTo(ValueMap.class); + if(vm != null) { + childBuilder.add("_path", child.getPath()); + childBuilder.add("_url", pc.pathToUrl(child.getPath())); + P.maybeAdd(childBuilder, "sling:resourceType", "_resourceType", vm); + P.maybeAddOneOf(childBuilder, "title", vm, P.TITLE_PROPS); + P.maybeAddOneOf(childBuilder, "name", vm, P.NAME_PROPS); + } + pc.children.add(child.getName(), childBuilder.build()); + } + } + } +} \ No newline at end of file diff --git a/dokapi/src/main/java/org/apache/sling/dokapi/impl/ContentProcessor.java b/dokapi/src/main/java/org/apache/sling/dokapi/impl/ContentProcessor.java new file mode 100644 index 0000000..0f4c9f4 --- /dev/null +++ b/dokapi/src/main/java/org/apache/sling/dokapi/impl/ContentProcessor.java @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.sling.dokapi.impl; + +import org.apache.sling.api.resource.ValueMap; + +class ContentProcessor implements JsonProcessor { + @Override + public void process(PipelineContext pc) { + final ValueMap vm = pc.resource.adaptTo(ValueMap.class); + for(String key : vm.keySet()) { + if(!P.ignoreProperty(key) && !P.isMetadata(key)) { + P.maybeAdd(pc.content, key, P.convertName(key), vm); + } + } + } +} \ No newline at end of file diff --git a/dokapi/src/main/java/org/apache/sling/dokapi/impl/DokapiServlet.java b/dokapi/src/main/java/org/apache/sling/dokapi/impl/DokapiServlet.java new file mode 100644 index 0000000..346b7b9 --- /dev/null +++ b/dokapi/src/main/java/org/apache/sling/dokapi/impl/DokapiServlet.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.dokapi.impl; + +import java.io.IOException; + +import javax.json.Json; +import javax.json.JsonObject; +import javax.json.JsonObjectBuilder; +import javax.servlet.Servlet; + +import org.apache.sling.api.SlingHttpServletRequest; +import org.apache.sling.api.SlingHttpServletResponse; +import org.apache.sling.api.servlets.SlingSafeMethodsServlet; +import org.osgi.service.component.annotations.Component; + +/** Main Dokapi servlet */ +@Component(service = Servlet.class, + name="org.apache.sling.servlets.get.DefaultGetServlet", + property = { + "service.description=Sling Dokapi Servlet", + "service.vendor=The Apache Software Foundation", + + "sling.servlet.resourceTypes=sling/servlet/default", + "sling.servlet.prefix:Integer=-1", + + "sling.servlet.methods=GET", + "sling.servlet.methods=HEAD", + "sling.servlet.selectors=dkp", + "sling.servlet.extension=json", + }) +public class DokapiServlet extends SlingSafeMethodsServlet { + private static final long serialVersionUID = 1L; + + @Override + public void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response) throws IOException { + final PipelineContext pc = new PipelineContext(request); + new MetadataProcessor().process(pc); + new ChildrenProcessor().process(pc); + new ContentProcessor().process(pc); + final JsonObject json = pc.build(); + + response.setCharacterEncoding("UTF-8"); + response.setContentType("application/json"); + response.getWriter().write(json.toString()); + } +} \ No newline at end of file diff --git a/dokapi/src/main/java/org/apache/sling/dokapi/impl/JsonProcessor.java b/dokapi/src/main/java/org/apache/sling/dokapi/impl/JsonProcessor.java new file mode 100644 index 0000000..228b974 --- /dev/null +++ b/dokapi/src/main/java/org/apache/sling/dokapi/impl/JsonProcessor.java @@ -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. + */ + +package org.apache.sling.dokapi.impl; + +public interface JsonProcessor { + void process(PipelineContext pc); +} \ No newline at end of file diff --git a/dokapi/src/main/java/org/apache/sling/dokapi/impl/MetadataProcessor.java b/dokapi/src/main/java/org/apache/sling/dokapi/impl/MetadataProcessor.java new file mode 100644 index 0000000..9ed90f4 --- /dev/null +++ b/dokapi/src/main/java/org/apache/sling/dokapi/impl/MetadataProcessor.java @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.sling.dokapi.impl; + +import org.apache.sling.api.resource.ValueMap; + +class MetadataProcessor implements JsonProcessor { + @Override + public void process(PipelineContext pc) { + final ValueMap vm = pc.resource.adaptTo(ValueMap.class); + for(String key : vm.keySet()) { + if(!P.ignoreProperty(key) && P.isMetadata(key)) { + P.maybeAdd(pc.metadata, key, P.convertName(key), vm); + } + } + } +} \ No newline at end of file diff --git a/dokapi/src/main/java/org/apache/sling/dokapi/impl/P.java b/dokapi/src/main/java/org/apache/sling/dokapi/impl/P.java new file mode 100644 index 0000000..1f5bce6 --- /dev/null +++ b/dokapi/src/main/java/org/apache/sling/dokapi/impl/P.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.dokapi.impl; + +import javax.json.Json; +import javax.json.JsonArrayBuilder; +import javax.json.JsonObjectBuilder; + +import org.apache.sling.api.resource.ValueMap; + +class P { + static final String [] TITLE_PROPS = { "jcr:title", "title" }; + static final String [] NAME_PROPS = { "jcr:name", "name" }; + static final String [] TEXT_PROPS = { "jcr:text", "text" }; + static final String [] DESCRIPTION_PROPS = { "jcr:description", "description" }; + + static boolean maybeAdd(JsonObjectBuilder b, String propName, String jsonName, ValueMap vm) { + if(vm.containsKey(propName)) { + final Object value = vm.get(propName); + if(value != null) { + if(value instanceof Object[]) { + final JsonArrayBuilder a = Json.createArrayBuilder(); + for(Object o : (Object[])value) { + a.add(o.toString()); + } + b.add(jsonName, a.build()); + } else { + b.add(jsonName, value.toString()); + } + } + return true; + } + return false; + } + + static void maybeAddOneOf(JsonObjectBuilder b, String propName, ValueMap vm, String [] props) { + for(String prop : NAME_PROPS) { + if(maybeAdd(b, prop, propName, vm)) { + break; + } + } + } + + static boolean ignoreProperty(String key) { + return key.startsWith("jcr:"); + } + + static boolean ignoreResource(String name) { + return name.startsWith("rep:"); + } + + static String convertName(String in) { + return in.replace("sling:", "_"); + } + + static boolean isMetadata(String propName) { + return propName.startsWith("sling:"); + } +} \ No newline at end of file diff --git a/dokapi/src/main/java/org/apache/sling/dokapi/impl/PipelineContext.java b/dokapi/src/main/java/org/apache/sling/dokapi/impl/PipelineContext.java new file mode 100644 index 0000000..06e6d8e --- /dev/null +++ b/dokapi/src/main/java/org/apache/sling/dokapi/impl/PipelineContext.java @@ -0,0 +1,81 @@ +/* + * 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.dokapi.impl; + +import javax.json.Json; +import javax.json.JsonObject; +import javax.json.JsonObjectBuilder; + +import org.apache.sling.api.SlingHttpServletRequest; +import org.apache.sling.api.resource.Resource; + +public class PipelineContext { + private final SlingHttpServletRequest request; + public final Resource resource; + public final JsonObjectBuilder api; + public final JsonObjectBuilder metadata; + public final JsonObjectBuilder children; + public final JsonObjectBuilder content; + + PipelineContext(SlingHttpServletRequest request) { + this.request = request; + resource = request.getResource(); + + // TODO should create these on demand + api = Json.createObjectBuilder(); + metadata = Json.createObjectBuilder(); + children = Json.createObjectBuilder(); + content = Json.createObjectBuilder(); + + api.add("_url", pathToUrl(resource.getPath())); + if(resource.getParent() != null) { + api.add("_parentUrl", pathToUrl(resource.getParent().getPath())); + } + api.add("_id", resource.getPath()); + } + + private void maybeAdd(JsonObjectBuilder target, String key, JsonObjectBuilder src) { + final JsonObject jo = src.build(); + if(!jo.isEmpty()) { + target.add(key, jo); + } + } + + JsonObject build() { + final JsonObjectBuilder b = Json.createObjectBuilder(); + maybeAdd(b, "api", api); + maybeAdd(b, "metadata", metadata); + maybeAdd(b, "content", content); + maybeAdd(b, "children", children); + return b.build(); + } + + String pathToUrl(String path) { + return String.format( + "%s://%s:%d%s.%s.%s", + request.getScheme(), + request.getServerName(), + request.getServerPort(), + path, + request.getRequestPathInfo().getSelectorString(), + request.getRequestPathInfo().getExtension() + ); + } +} \ No newline at end of file
