/* * 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.pipes; import org.apache.commons.lang.StringUtils; import org.apache.felix.scr.annotations.Reference; import org.apache.felix.scr.annotations.sling.SlingServlet; import org.apache.sling.api.SlingHttpServletRequest; import org.apache.sling.api.SlingHttpServletResponse; import org.apache.sling.api.resource.Resource; import org.apache.sling.api.resource.ResourceResolver; import org.apache.sling.api.servlets.SlingAllMethodsServlet; import org.apache.sling.commons.json.JSONObject; import org.apache.sling.commons.json.io.JSONWriter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.servlet.ServletException; import java.io.IOException; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Set; /** * Servlet executing plumber for a pipe path given as 'path' parameter, * it can also be launched against a container pipe resource directly (no need for path parameter) * */ @SlingServlet(resourceTypes = {Plumber.RESOURCE_TYPE, ContainerPipe.RESOURCE_TYPE, AuthorizablePipe.RESOURCE_TYPE, WritePipe.RESOURCE_TYPE, SlingQueryPipe.RESOURCE_TYPE}, methods={"GET","POST"}, extensions = {"json"}) public class PlumberServlet extends SlingAllMethodsServlet { Logger log = LoggerFactory.getLogger(this.getClass()); protected static final String PARAM_PATH = "path"; public static final String PATH_KEY = "path"; protected static final String PARAM_BINDINGS = "bindings"; protected static final String PARAM_WRITER = "writer"; protected static final String PARAM_SIZE = "size"; public static final int NB_MAX = 10; public static final String KEY_SIZE = PARAM_SIZE; public static final String KEY_ITEMS = "items"; @Reference Plumber plumber; @Override protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response) throws ServletException, IOException { execute(request, response, false); } @Override protected void doPost(SlingHttpServletRequest request, SlingHttpServletResponse response) throws ServletException, IOException { execute(request, response, true); } protected void execute(SlingHttpServletRequest request, SlingHttpServletResponse response, boolean writeAllowed) throws ServletException { String path = request.getResource().getResourceType().equals(Plumber.RESOURCE_TYPE) ? request.getParameter(PARAM_PATH) : request.getResource().getPath(); try { if (StringUtils.isBlank(path)) { throw new Exception("path should be provided"); } String dryRun = request.getParameter(BasePipe.DRYRUN_KEY); String paramBindings = request.getParameter(PARAM_BINDINGS); int size = request.getParameter(PARAM_SIZE) != null ? Integer.parseInt(request.getParameter(PARAM_SIZE)) : NB_MAX; Map additionalBindings = null; if (StringUtils.isNotBlank(dryRun) && dryRun.equals(Boolean.TRUE.toString())) { additionalBindings = new HashMap<>(); additionalBindings.put(BasePipe.DRYRUN_KEY, true); } if (StringUtils.isNotBlank(paramBindings)){ try { JSONObject bindingJSON = new JSONObject(paramBindings); additionalBindings = additionalBindings != null ? additionalBindings: new HashMap<>(); for (Iterator<String> keys = bindingJSON.keys(); keys.hasNext();){ String key = keys.next(); additionalBindings.put(key, bindingJSON.get(key)); } } catch (Exception e){ log.error("Unable to retrieve bindings information", e); } } String paramWriter = request.getParameter(PARAM_WRITER); JSONObject writerObj = null; if (StringUtils.isNotBlank(paramWriter)){ try { writerObj = new JSONObject(paramWriter); } catch (Exception e) { log.error("Unable to retrieve the writer object"); } } response.setCharacterEncoding("utf-8"); response.setContentType("application/json"); JSONWriter writer = new JSONWriter(response.getWriter()); ResourceResolver resolver = request.getResourceResolver(); Resource pipeResource = resolver.getResource(path); Pipe pipe = plumber.getPipe(pipeResource); if (!writeAllowed && pipe.modifiesContent()) { throw new Exception("This pipe modifies content, you should use a POST request"); } writer.object(); int i = 0; if (writerObj != null) { pipe.getBindings().addBindings(additionalBindings); Iterator<Resource> resourceIterator = pipe.getOutput(); writer.key(KEY_ITEMS).array(); while (resourceIterator.hasNext()){ Resource resource = resourceIterator.next(); if (i ++ < NB_MAX) { writer.object(); writer.key(PATH_KEY).value(resource.getPath()); Iterator<String> keys = writerObj.keys(); while (keys.hasNext()) { String key = keys.next(); writer.key(key).value(pipe.getBindings().instantiateObject(writerObj.getString(key))); } writer.endObject(); } } writer.endArray(); writer.key(KEY_SIZE).value(i); } else { Set<String> resources = plumber.execute(resolver, pipe, additionalBindings, true); writer.key(KEY_SIZE).value(resources.size()); writer.key(KEY_ITEMS); writer.array(); for (String resource : resources) { if (i ++ > NB_MAX){ break; } else { writer.value(resource); } } writer.endArray(); } writer.endObject(); response.flushBuffer(); } catch (Exception e) { throw new ServletException(e); } } }