blob: f3a0edb511cf62626a16e8c4a2979ecfb5c3f4e7 [file] [log] [blame]
/*
* 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 org.apache.commons.lang3.StringUtils;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.api.servlets.ServletResolverConstants;
import org.apache.sling.api.servlets.SlingAllMethodsServlet;
import org.apache.sling.event.jobs.Job;
import org.apache.sling.pipes.AbstractInputStreamPipe;
import org.apache.sling.pipes.BasePipe;
import org.apache.sling.pipes.OutputWriter;
import org.apache.sling.pipes.Plumber;
import org.apache.sling.pipes.internal.slingquery.ChildrenPipe;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.Servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
/**
* 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 + "=" + ChildrenPipe.RESOURCE_TYPE,
ServletResolverConstants.SLING_SERVLET_METHODS + "=GET",
ServletResolverConstants.SLING_SERVLET_METHODS + "=POST",
ServletResolverConstants.SLING_SERVLET_EXTENSIONS + "=json",
ServletResolverConstants.SLING_SERVLET_EXTENSIONS + "=csv"
})
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_ASYNC = "async";
protected static final String PARAM_FILE = "pipes_inputFile";
@Reference
Plumber plumber;
@Override
protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response) throws ServletException, IOException {
if (Arrays.asList(request.getRequestPathInfo().getSelectors()).contains(BasePipe.PN_STATUS)){
response.getWriter().append(plumber.getStatus(request.getResource()));
} else {
execute(request, response, false);
}
}
@Override
protected void doPost(SlingHttpServletRequest request, SlingHttpServletResponse response) throws ServletException, IOException {
execute(request, response, true);
}
/**
* Execution of a pipe corresponding to a request
* @param request original request
* @param response given response
* @param writeAllowed should we consider this execution is about to modify content
* @throws ServletException in case something is wrong...
*/
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");
}
Map bindings = getBindingsFromRequest(request, writeAllowed);
String asyncParam = request.getParameter(PARAM_ASYNC);
if (StringUtils.isNotBlank(asyncParam) && asyncParam.equals(Boolean.TRUE.toString())){
Job job = plumber.executeAsync(request.getResourceResolver(), path, bindings);
if (job != null){
response.getWriter().append("pipe execution registered as " + job.getId());
response.setStatus(HttpServletResponse.SC_CREATED);
} else {
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Some issue with your request, or server not being ready for async execution");
}
} else {
OutputWriter writer = getWriter(request, response);
plumber.execute(request.getResourceResolver(), path, bindings, writer, true);
}
} catch (Exception e) {
throw new ServletException(e);
}
}
/**
* Converts request into pipe bindings
* @param request from where to extract bindings
* @param writeAllowed should we consider this execution is about to modify content
* @return map of bindings
* @throws IOException in case something turns wrong with an input stream
*/
protected Map getBindingsFromRequest(SlingHttpServletRequest request, boolean writeAllowed) throws IOException{
Map bindings = new HashMap<>();
String dryRun = request.getParameter(BasePipe.DRYRUN_KEY);
if (StringUtils.isNotBlank(dryRun) && !dryRun.equals(Boolean.FALSE.toString())) {
bindings.put(BasePipe.DRYRUN_KEY, true);
}
String paramBindings = request.getParameter(PARAM_BINDINGS);
if (StringUtils.isNotBlank(paramBindings)){
try {
bindings.putAll(JsonUtil.unbox(JsonUtil.parseObject(paramBindings)));
} catch (Exception e){
log.error("Unable to retrieve bindings information", e);
}
}
if (request.getRequestParameterMap() != null && request.getRequestParameterMap().containsKey(PARAM_FILE)){
bindings.put(AbstractInputStreamPipe.BINDING_IS, request.getRequestParameter(PARAM_FILE).getInputStream());
}
bindings.put(BasePipe.READ_ONLY, !writeAllowed);
return bindings;
}
/**
* Retrieve an output writer depending on the request
* @param request original request against which writers will be tested
* @param response response writers will point to
* @return instance of the created writer
* @throws IOException bad handling of I/O streams,
*/
OutputWriter getWriter(SlingHttpServletRequest request, SlingHttpServletResponse response) throws IOException {
OutputWriter[] candidates = new OutputWriter[]{new CsvWriter(), new JsonWriter()};
for (OutputWriter candidate : candidates) {
if (candidate.handleRequest(request)) {
candidate.init(request, response);
return candidate;
}
}
return null;
}
}