/* * 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.internal; import java.io.IOException; import java.util.HashSet; import java.util.Iterator; import java.util.Set; import javax.servlet.Servlet; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.lang.StringUtils; 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.api.servlets.ServletResolverConstants; import org.apache.sling.commons.json.JSONException; import org.apache.sling.commons.json.JSONObject; import org.apache.sling.pipes.BasePipe; import org.apache.sling.pipes.ContainerPipe; import org.apache.sling.pipes.OutputWriter; import org.apache.sling.pipes.Pipe; import org.apache.sling.pipes.PipeBindings; import org.apache.sling.pipes.Plumber; import org.osgi.service.component.annotations.Component; import org.osgi.service.component.annotations.Reference; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * 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) * */ @Component(service = {Servlet.class}, property= { ServletResolverConstants.SLING_SERVLET_RESOURCE_TYPES + "=" + Plumber.RESOURCE_TYPE, ServletResolverConstants.SLING_SERVLET_RESOURCE_TYPES + "=" + ContainerPipe.RESOURCE_TYPE, ServletResolverConstants.SLING_SERVLET_RESOURCE_TYPES + "=" + AuthorizablePipe.RESOURCE_TYPE, ServletResolverConstants.SLING_SERVLET_RESOURCE_TYPES + "=" + WritePipe.RESOURCE_TYPE, ServletResolverConstants.SLING_SERVLET_RESOURCE_TYPES + "=" + SlingQueryPipe.RESOURCE_TYPE, ServletResolverConstants.SLING_SERVLET_METHODS + "=GET", ServletResolverConstants.SLING_SERVLET_METHODS + "=POST", ServletResolverConstants.SLING_SERVLET_EXTENSIONS + "=json" }) public class PlumberServlet extends SlingAllMethodsServlet { Logger log = LoggerFactory.getLogger(this.getClass()); protected static final String PARAM_PATH = "path"; protected static final String PARAM_BINDINGS = "bindings"; protected static final String PARAM_SIZE = "size"; public static final int NB_MAX = 10; @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); int size = request.getParameter(PARAM_SIZE) != null ? Integer.parseInt(request.getParameter(PARAM_SIZE)) : NB_MAX; if (size < 0) { size = Integer.MAX_VALUE; } ResourceResolver resolver = request.getResourceResolver(); Resource pipeResource = resolver.getResource(path); Pipe pipe = plumber.getPipe(pipeResource); PipeBindings bindings = pipe.getBindings(); if (StringUtils.isNotBlank(dryRun) && dryRun.equals(Boolean.TRUE.toString())) { bindings.addBinding(BasePipe.DRYRUN_KEY, true); } String paramBindings = request.getParameter(PARAM_BINDINGS); if (StringUtils.isNotBlank(paramBindings)){ try { JSONObject bindingJSON = new JSONObject(paramBindings); for (Iterator<String> keys = bindingJSON.keys(); keys.hasNext();){ String key = keys.next(); bindings.addBinding(key, bindingJSON.get(key)); } } catch (Exception e){ log.error("Unable to retrieve bindings information", e); } } if (!writeAllowed && pipe.modifiesContent()) { throw new Exception("This pipe modifies content, you should use a POST request"); } OutputWriter writer = getWriter(request, response, pipe); int i = 0; Iterator<Resource> resourceIterator = pipe.getOutput(); Set<String> paths = new HashSet<String>(); while (resourceIterator.hasNext()){ Resource resource = resourceIterator.next(); paths.add(resource.getPath()); if (i++ < size) { writer.writeItem(resource); } } writer.ends(i); plumber.persist(resolver, pipe, paths); } catch (Exception e) { throw new ServletException(e); } } OutputWriter getWriter(SlingHttpServletRequest request, SlingHttpServletResponse response, Pipe pipe) throws IOException, JSONException { OutputWriter[] candidates = new OutputWriter[]{new CustomJsonWriter(), new CustomWriter(), new DefaultOutputWriter()}; for (OutputWriter candidate : candidates) { if (candidate.handleRequest(request)) { candidate.init(request, response, pipe); return candidate; } } return null; } }