You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by bd...@apache.org on 2015/12/07 15:19:52 UTC
svn commit: r1718377 [2/3] - in /sling/trunk/contrib/extensions/sling-pipes:
./ src/ src/main/ src/main/java/ src/main/java/org/
src/main/java/org/apache/ src/main/java/org/apache/sling/
src/main/java/org/apache/sling/pipes/ src/main/java/org/apache/sl...
Added: sling/trunk/contrib/extensions/sling-pipes/src/main/java/org/apache/sling/pipes/PipeBindings.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/sling-pipes/src/main/java/org/apache/sling/pipes/PipeBindings.java?rev=1718377&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/sling-pipes/src/main/java/org/apache/sling/pipes/PipeBindings.java (added)
+++ sling/trunk/contrib/extensions/sling-pipes/src/main/java/org/apache/sling/pipes/PipeBindings.java Mon Dec 7 14:19:52 2015
@@ -0,0 +1,256 @@
+/*
+ * 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.io.IOUtils;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.api.resource.ValueMap;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.script.Bindings;
+import javax.script.Invocable;
+import javax.script.ScriptContext;
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineManager;
+import javax.script.ScriptException;
+import javax.script.SimpleScriptContext;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.URL;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Execution bindings of a pipe
+ */
+public class PipeBindings {
+ private static final Logger log = LoggerFactory.getLogger(PipeBindings.class);
+
+ public static final String NN_ADDITIONALBINDINGS = "additionalBindings";
+
+ public static final String PN_ADDITIONALSCRIPTS = "additionalScripts";
+
+ ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");
+
+ ScriptContext scriptContext = new SimpleScriptContext();
+
+ public static final String PATH_BINDING = "path";
+
+ Map<String, String> pathBindings = new HashMap<>();
+
+ Map<String, Resource> outputResources = new HashMap<>();
+
+ private static final Pattern INJECTED_SCRIPT = Pattern.compile("\\$\\{([^\\}]*)\\}");
+
+ /**
+ * public constructor
+ */
+ public PipeBindings(Resource resource){
+ engine.setContext(scriptContext);
+ //add path bindings where path.MyPipe will give MyPipe current resource path
+ getBindings().put(PATH_BINDING, pathBindings);
+
+ //additional bindings (global variables to use in child pipes expressions)
+ Resource additionalBindings = resource.getChild(NN_ADDITIONALBINDINGS);
+ if (additionalBindings != null) {
+ ValueMap bindings = additionalBindings.adaptTo(ValueMap.class);
+ addBindings(bindings);
+ }
+
+ Resource scriptsResource = resource.getChild(PN_ADDITIONALSCRIPTS);
+ if (scriptsResource != null) {
+ String[] scripts = scriptsResource.adaptTo(String[].class);
+ if (scripts != null) {
+ for (String script : scripts){
+ addScript(resource.getResourceResolver(), script);
+ }
+ }
+ }
+ }
+
+ /**
+ * add a script file to the engine
+ * @param resolver
+ * @param path
+ */
+ public void addScript(ResourceResolver resolver, String path) {
+ InputStream is = null;
+ try {
+ if (path.startsWith("http")) {
+ try {
+ URL remoteScript = new URL(path);
+ is = remoteScript.openStream();
+ } catch (Exception e) {
+ log.error("unable to retrieve remote script", e);
+ }
+ } else if (path.startsWith("/")) {
+ Resource scriptResource = resolver.getResource(path);
+ if (scriptResource != null) {
+ is = scriptResource.adaptTo(InputStream.class);
+ }
+ }
+ if (is != null) {
+ try {
+ engine.eval(new InputStreamReader(is), scriptContext);
+ } catch (Exception e) {
+ log.error("unable to execute {}", path);
+ }
+ }
+ } finally {
+ IOUtils.closeQuietly(is);
+ }
+ }
+
+ /**
+ * adds additional bindings (global variables to use in child pipes expressions)
+ * @param bindings
+ */
+ public void addBindings(Map bindings) {
+ log.info("Adding bindings {}", bindings);
+ getBindings().putAll(bindings);
+ }
+
+ /**
+ * Update current resource of a given pipe, and appropriate binding
+ * @param pipe
+ * @param resource
+ */
+ public void updateBindings(Pipe pipe, Resource resource) {
+ outputResources.put(pipe.getName(), resource);
+ if (resource != null) {
+ pathBindings.put(pipe.getName(), resource.getPath());
+ }
+ addBinding(pipe.getName(), pipe.getOutputBinding());
+ }
+
+ public void addBinding(String name, Object value){
+ getBindings().put(name, value);
+ }
+
+ public boolean isBindingDefined(String name){
+ return getBindings().containsKey(name);
+ }
+
+ public Bindings getBindings() {
+ return scriptContext.getBindings(ScriptContext.ENGINE_SCOPE);
+ }
+
+ /**
+ * Doesn't look like nashorn likes template strings :-(
+ * @param expr
+ * @return
+ */
+ protected String computeECMA5Expression(String expr){
+ StringBuilder expression = new StringBuilder();
+ Matcher matcher = INJECTED_SCRIPT.matcher(expr);
+ int start = 0;
+ while (matcher.find()){
+ if (matcher.start() > start){
+ if (expression.length() == 0){
+ expression.append("'");
+ }
+ expression.append(expr.substring(start,matcher.start()));
+ }
+ if (expression.length() > 0){
+ expression.append("' + ");
+ }
+ expression.append(matcher.group(1));
+ start = matcher.end();
+ if (start < expr.length()){
+ expression.append(" + '");
+ }
+ }
+ if (start < expr.length()){
+ expression.append(expr.substring(start) + "'");
+ }
+ return expression.toString();
+ }
+
+ /**
+ *
+ * @param expr
+ * @return
+ * @throws ScriptException
+ */
+ private Object evaluate(String expr) throws ScriptException {
+ return engine.eval(computeECMA5Expression(expr), scriptContext);
+ }
+
+ /**
+ * Expression is a function of variables from execution context, that
+ * we implement here as a String
+ * @param expr
+ * @return
+ */
+ public String instantiateExpression(String expr){
+ try {
+ return (String)evaluate(expr);
+ } catch (ScriptException e) {
+ log.error("Unable to evaluate the script", e);
+ }
+ return expr;
+ }
+
+ /**
+ * Instantiate object from expression
+ * @param expr
+ * @return
+ */
+ public Object instantiateObject(String expr){
+ try {
+ Object result = evaluate(expr);
+ if (! result.getClass().getName().startsWith("java.lang.")) {
+ //special case of the date in which case jdk.nashorn.api.scripting.ScriptObjectMirror will
+ //be returned
+ JsDate jsDate = ((Invocable) engine).getInterface(result, JsDate.class);
+ if (jsDate != null ) {
+ Date date = new Date(jsDate.getTime() + jsDate.getTimezoneOffset() * 60 * 1000);
+ Calendar cal = Calendar.getInstance();
+ cal.setTime(date);
+ return cal;
+ }
+ }
+ return result;
+ } catch (ScriptException e) {
+ log.error("Unable to evaluate the script for expr {} ", expr, e);
+ }
+ return expr;
+ }
+
+ /**
+ *
+ * @param name
+ * @return
+ */
+ public Resource getExecutedResource(String name) {
+ return outputResources.get(name);
+ }
+
+ /**
+ * interface mapping a javascript date
+ */
+ public interface JsDate {
+ long getTime();
+ int getTimezoneOffset();
+ }
+}
Added: sling/trunk/contrib/extensions/sling-pipes/src/main/java/org/apache/sling/pipes/Plumber.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/sling-pipes/src/main/java/org/apache/sling/pipes/Plumber.java?rev=1718377&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/sling-pipes/src/main/java/org/apache/sling/pipes/Plumber.java (added)
+++ sling/trunk/contrib/extensions/sling-pipes/src/main/java/org/apache/sling/pipes/Plumber.java Mon Dec 7 14:19:52 2015
@@ -0,0 +1,67 @@
+/*
+ * 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.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceResolver;
+
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Plumber is an osgi service aiming to make pipes available to the sling system, in order to
+ */
+public interface Plumber {
+
+ public static final String RESOURCE_TYPE = "slingPipes/plumber";
+
+ /**
+ * Instantiate a pipe from the given resource and returns it
+ * @param resource
+ * @return
+ */
+ Pipe getPipe(Resource resource);
+
+ /**
+ * Executes a pipe at a certain path
+ * @param resolver resource resolver with which pipe will be executed
+ * @param path path of a valid pipe configuration
+ * @param bindings bindings to add to the execution of the pipe, can be null
+ * @param save in case that pipe writes anything, wether the plumber should save changes or not
+ *
+ * @return
+ */
+ Set<String> execute(ResourceResolver resolver, String path, Map bindings, boolean save) throws Exception;
+
+ /**
+ * Executes a given pipe
+ * @param resolver resource resolver with which pipe will be executed
+ * @param pipe pipe to execute
+ * @param bindings bindings to add to the execution of the pipe, can be null
+ * @param save in case that pipe writes anything, wether the plumber should save changes or not
+ *
+ * @return
+ */
+ Set<String> execute(ResourceResolver resolver, Pipe pipe, Map bindings, boolean save) throws Exception;
+
+ /**
+ * Registers
+ * @param type
+ * @param pipeClass
+ */
+ void registerPipe(String type, Class<? extends BasePipe> pipeClass);
+}
Added: sling/trunk/contrib/extensions/sling-pipes/src/main/java/org/apache/sling/pipes/PlumberServlet.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/sling-pipes/src/main/java/org/apache/sling/pipes/PlumberServlet.java?rev=1718377&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/sling-pipes/src/main/java/org/apache/sling/pipes/PlumberServlet.java (added)
+++ sling/trunk/contrib/extensions/sling-pipes/src/main/java/org/apache/sling/pipes/PlumberServlet.java Mon Dec 7 14:19:52 2015
@@ -0,0 +1,148 @@
+/*
+ * 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";
+
+ @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);
+
+ 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.array();
+ if (writerObj != null) {
+ pipe.getBindings().addBindings(additionalBindings);
+ Iterator<Resource> resourceIterator = pipe.getOutput();
+ while (resourceIterator.hasNext()){
+ Resource resource = resourceIterator.next();
+ 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();
+ }
+ } else {
+ Set<String> resources = plumber.execute(resolver, pipe, additionalBindings, true);
+ for (String resource : resources) {
+ writer.value(resource);
+ }
+ }
+ writer.endArray();
+ response.flushBuffer();
+ } catch (Exception e) {
+ throw new ServletException(e);
+ }
+ }
+}
Added: sling/trunk/contrib/extensions/sling-pipes/src/main/java/org/apache/sling/pipes/ReferencePipe.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/sling-pipes/src/main/java/org/apache/sling/pipes/ReferencePipe.java?rev=1718377&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/sling-pipes/src/main/java/org/apache/sling/pipes/ReferencePipe.java (added)
+++ sling/trunk/contrib/extensions/sling-pipes/src/main/java/org/apache/sling/pipes/ReferencePipe.java Mon Dec 7 14:19:52 2015
@@ -0,0 +1,73 @@
+/*
+ * 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.sling.api.resource.Resource;
+
+import java.util.Iterator;
+
+/**
+ * executes a pipe referred in the configuration
+ */
+public class ReferencePipe extends BasePipe {
+ public static final String RESOURCE_TYPE = "slingPipes/reference";
+
+ Pipe reference;
+
+ public ReferencePipe(Plumber plumber, Resource resource) throws Exception {
+ super(plumber, resource);
+ Resource pipeResource = resolver.getResource(getPath());
+ if (pipeResource == null){
+ throw new Exception("Reference configuration error: There is no resource at " + getPath());
+ }
+ reference = plumber.getPipe(pipeResource);
+ if (reference == null){
+ throw new Exception("Unable to build out pipe out of " + getPath());
+ }
+ }
+
+ @Override
+ public Iterator<Resource> getOutput() {
+ return reference.getOutput();
+ }
+
+ @Override
+ public void setParent(ContainerPipe parent) {
+ super.setParent(parent);
+ reference.setParent(parent);
+ }
+
+ @Override
+ public Object getOutputBinding() {
+ return reference.getOutputBinding();
+ }
+
+ @Override
+ public boolean modifiesContent() {
+ return reference.modifiesContent();
+ }
+
+ @Override
+ public Resource getInput() {
+ return reference.getInput();
+ }
+
+ @Override
+ public Resource getConfiguredInput() {
+ return reference.getConfiguredInput();
+ }
+}
\ No newline at end of file
Added: sling/trunk/contrib/extensions/sling-pipes/src/main/java/org/apache/sling/pipes/RemovePipe.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/sling-pipes/src/main/java/org/apache/sling/pipes/RemovePipe.java?rev=1718377&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/sling-pipes/src/main/java/org/apache/sling/pipes/RemovePipe.java (added)
+++ sling/trunk/contrib/extensions/sling-pipes/src/main/java/org/apache/sling/pipes/RemovePipe.java Mon Dec 7 14:19:52 2015
@@ -0,0 +1,126 @@
+/*
+ * 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.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ValueMap;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.jcr.Node;
+import javax.jcr.NodeIterator;
+import javax.jcr.Property;
+import javax.jcr.RepositoryException;
+import java.util.Collections;
+import java.util.Iterator;
+
+/**
+ * this pipe tries to remove the input resource, abstracting its type,
+ * returning parent of the input
+ */
+public class RemovePipe extends BasePipe {
+ private static Logger logger = LoggerFactory.getLogger(RemovePipe.class);
+ public static final String RESOURCE_TYPE = "slingPipes/rm";
+
+ /**
+ * In case input resource is a node and configuration is set, only configured properties,
+ * and subtrees will be removed
+ */
+ Resource filter;
+
+ public RemovePipe(Plumber plumber, Resource resource) throws Exception {
+ super(plumber, resource);
+ filter = getConfiguration();
+ }
+
+ @Override
+ public boolean modifiesContent() {
+ return true;
+ }
+
+ @Override
+ public Iterator<Resource> getOutput() {
+ Resource resource = getInput();
+ String parentPath = null;
+ try {
+ if (resource.adaptTo(Node.class) != null) {
+ parentPath = removeTree(resource, filter);
+ } else if (resource.adaptTo(Property.class) != null){
+ Property property = resource.adaptTo(Property.class);
+ parentPath = property.getParent().getPath();
+ logger.info("removing property {}", property.getPath());
+ if (!isDryRun()){
+ property.remove();
+ }
+ }
+ } catch (RepositoryException e){
+ logger.error("unable to remove current resource {}", resource.getPath(), e);
+ }
+ if (parentPath != null) {
+ return Collections.singleton(resolver.getResource(parentPath)).iterator();
+ }
+ return Collections.emptyIterator();
+ }
+
+ /**
+ * remove properties, returns the number of properties that were configured to be removed
+ * @return
+ */
+ private int removeProperties(Resource resource, Resource configuration) throws RepositoryException {
+ int count = 0;
+ if (configuration != null) {
+ Node node = resource.adaptTo(Node.class);
+ ValueMap configuredProperties = configuration.adaptTo(ValueMap.class);
+ for (String key : configuredProperties.keySet()){
+ if (! IGNORED_PROPERTIES.contains(key)){
+ count++;
+ if (node.hasProperty(key)){
+ logger.info("removing {}", node.getProperty(key).getPath());
+ if (! isDryRun()){
+ node.getProperty(key).remove();
+ }
+ }
+ }
+ }
+ }
+ return count;
+ }
+
+ private String removeTree(Resource resource, Resource configuration) throws RepositoryException {
+ String remainingPath = resource.getPath();
+ int configuredProperties = removeProperties(resource, configuration);
+ Node configuredNode = configuration != null ? configuration.adaptTo(Node.class) : null;
+ NodeIterator childrenConfiguration = configuredNode != null ? configuredNode.getNodes() : null;
+ if (childrenConfiguration == null || (! childrenConfiguration.hasNext() && configuredProperties == 0)){
+ //explicit configuration to remove the node altogether
+ logger.info("removing {}", resource.getPath());
+ remainingPath = resource.getParent().getPath();
+ if (! isDryRun()){
+ resource.adaptTo(Node.class).remove();
+ }
+ } else {
+ while (childrenConfiguration.hasNext()){
+ Node childConf = childrenConfiguration.nextNode();
+ Resource child = resource.getChild(childConf.getName());
+ if (child != null){
+ removeTree(child, configuration.getChild(childConf.getName()));
+ }
+ }
+ }
+ return remainingPath;
+ }
+}
Added: sling/trunk/contrib/extensions/sling-pipes/src/main/java/org/apache/sling/pipes/SlingQueryPipe.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/sling-pipes/src/main/java/org/apache/sling/pipes/SlingQueryPipe.java?rev=1718377&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/sling-pipes/src/main/java/org/apache/sling/pipes/SlingQueryPipe.java (added)
+++ sling/trunk/contrib/extensions/sling-pipes/src/main/java/org/apache/sling/pipes/SlingQueryPipe.java Mon Dec 7 14:19:52 2015
@@ -0,0 +1,56 @@
+/*
+ * 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.sling.api.resource.Resource;
+import org.apache.sling.query.SlingQuery;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static org.apache.sling.query.SlingQuery.$;
+
+import java.util.Iterator;
+
+/**
+ * this pipe uses SlingQuery to filters children (filter defined in expr property) of
+ * a resource (defined in the path property)
+ */
+public class SlingQueryPipe extends BasePipe {
+ private static Logger logger = LoggerFactory.getLogger(SlingQueryPipe.class);
+
+ public final static String RESOURCE_TYPE = "slingPipes/slingQuery";
+
+ public SlingQueryPipe(Plumber plumber, Resource resource) throws Exception {
+ super(plumber, resource);
+ }
+
+ @Override
+ public boolean modifiesContent() {
+ return false;
+ }
+
+ public Iterator<Resource> getOutput() {
+ Resource resource = getInput();
+ if (resource != null) {
+ String queryExpression = getExpr();
+ SlingQuery query = $(resource).children(getExpr());
+ logger.info("[sling query]: executing $({}).children({})", resource.getPath(), queryExpression);
+ return query.iterator();
+ }
+ return EMPTY_ITERATOR;
+ }
+}
Added: sling/trunk/contrib/extensions/sling-pipes/src/main/java/org/apache/sling/pipes/WritePipe.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/sling-pipes/src/main/java/org/apache/sling/pipes/WritePipe.java?rev=1718377&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/sling-pipes/src/main/java/org/apache/sling/pipes/WritePipe.java (added)
+++ sling/trunk/contrib/extensions/sling-pipes/src/main/java/org/apache/sling/pipes/WritePipe.java Mon Dec 7 14:19:52 2015
@@ -0,0 +1,172 @@
+/*
+ * 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.sling.api.resource.ModifiableValueMap;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ValueMap;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.jcr.Node;
+import javax.jcr.NodeIterator;
+import javax.jcr.Property;
+import javax.jcr.RepositoryException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * pipe that writes to configured resource
+ */
+public class WritePipe extends BasePipe {
+ private static final Logger logger = LoggerFactory.getLogger(WritePipe.class);
+ public static final String RESOURCE_TYPE = "slingPipes/write";
+ Node confTree;
+ String resourceExpression;
+ Pattern addPatch = Pattern.compile("\\+\\[(.*)\\]");
+ Pattern multi = Pattern.compile("\\[(.*)\\]");
+
+ public WritePipe(Plumber plumber, Resource resource) throws Exception {
+ super(plumber, resource);
+ if (getConfiguration() == null){
+ throw new Exception("write pipe is misconfigured: it should have a configuration node");
+ }
+ confTree = getConfiguration().adaptTo(Node.class);
+ resourceExpression = getPath();
+ }
+
+ /**
+ * convert the configured value in an actual one
+ * @param expression
+ * @return
+ */
+ protected Object computeValue(Resource resource, String key, Object expression) {
+ if (expression instanceof String) {
+ Object value = bindings.instantiateObject((String) expression);
+ if (value != null && value instanceof String) {
+ //in that case we treat special case like MV or patches
+ String sValue = (String)value;
+ Matcher patch = addPatch.matcher(sValue);
+ if (patch.matches()) {
+ String newValue = patch.group(1);
+ String[] actualValues = resource.adaptTo(ValueMap.class).get(key, String[].class);
+ List<String> newValues = actualValues != null ? new LinkedList<>(Arrays.asList(actualValues)) : new ArrayList<String>();
+ if (!newValues.contains(newValue)) {
+ newValues.add(newValue);
+ }
+ return newValues.toArray(new String[newValues.size()]);
+ }
+ Matcher multiMatcher = multi.matcher(sValue);
+ if (multiMatcher.matches()) {
+ return multiMatcher.group(1).split(",");
+ }
+ }
+ return value;
+ }
+ return expression;
+ }
+
+ @Override
+ public boolean modifiesContent() {
+ return true;
+ }
+
+ /**
+ * Write properties from the configuration to the target resource,
+ * instantiating both property names & values
+ *
+ * @param conf
+ * @param target
+ * @throws RepositoryException
+ */
+ private void copyProperties(Resource conf, Resource target) throws RepositoryException {
+ ValueMap writeMap = conf.adaptTo(ValueMap.class);
+ ModifiableValueMap properties = target.adaptTo(ModifiableValueMap.class);
+
+ //writing current node
+ if (properties != null && writeMap != null) {
+ for (Map.Entry<String, Object> entry : writeMap.entrySet()) {
+ if (!IGNORED_PROPERTIES.contains(entry.getKey())) {
+ String key = parent != null ? bindings.instantiateExpression(entry.getKey()) : entry.getKey();
+ Object value = computeValue(target, key, entry.getValue());
+ if (value == null) {
+ //null value are not handled by modifiable value maps,
+ //removing the property if it exists
+ Resource propertyResource = resource.getChild(key);
+ if (propertyResource != null) {
+ logger.info("removing {}", propertyResource.getPath());
+ if (!isDryRun()){
+ Property property = propertyResource.adaptTo(Property.class);
+ if (property != null) {
+ property.remove();
+ }
+ }
+ }
+ } else {
+ logger.info("writing {}={}",target.getPath() + "@" + key, value);
+ if (!isDryRun()){
+ properties.put(key, value);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * write the configured tree at the target resource, creating each node if needed, copying values.
+ * @param conf
+ * @return
+ */
+ private void writeTree(Node conf, Resource target) throws RepositoryException {
+ copyProperties(resolver.getResource(conf.getPath()), target);
+ NodeIterator childrenConf = conf.getNodes();
+ if (childrenConf.hasNext()){
+ Node targetNode = target.adaptTo(Node.class);
+ while (childrenConf.hasNext()){
+ Node childConf = childrenConf.nextNode();
+ String name = childConf.getName();
+ logger.info("dubbing {} at {}", conf.getPath(), target.getPath());
+ if (!isDryRun()){
+ Node childTarget = targetNode.hasNode(name) ? targetNode.getNode(name) : targetNode.addNode(name, childConf.getPrimaryNodeType().getName());
+ writeTree(childConf, resolver.getResource(childTarget.getPath()));
+ }
+ }
+ }
+ }
+
+
+ @Override
+ public Iterator<Resource> getOutput() {
+ try {
+ Resource resource = getInput();
+ if (resource != null) {
+ writeTree(confTree, resource);
+ return super.getOutput();
+ }
+ } catch (Exception e) {
+ logger.error("unable to write values, cutting pipe", e);
+ }
+ return EMPTY_ITERATOR;
+ }
+}
Added: sling/trunk/contrib/extensions/sling-pipes/src/main/java/org/apache/sling/pipes/XPathPipe.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/sling-pipes/src/main/java/org/apache/sling/pipes/XPathPipe.java?rev=1718377&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/sling-pipes/src/main/java/org/apache/sling/pipes/XPathPipe.java (added)
+++ sling/trunk/contrib/extensions/sling-pipes/src/main/java/org/apache/sling/pipes/XPathPipe.java Mon Dec 7 14:19:52 2015
@@ -0,0 +1,44 @@
+/*
+ * 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.sling.api.resource.Resource;
+
+import javax.jcr.query.Query;
+import java.util.Iterator;
+
+/**
+ * generates output based on an xpath query (no input is considered)
+ */
+public class XPathPipe extends BasePipe {
+
+ public static final String RESOURCE_TYPE = "slingPipes/xpath";
+
+ public XPathPipe(Plumber plumber, Resource resource) throws Exception {
+ super(plumber, resource);
+ }
+
+ @Override
+ public Iterator<Resource> getOutput() {
+ String query = getExpr();
+ if (StringUtils.isNotBlank(query)){
+ return resource.getResourceResolver().findResources(query, Query.XPATH);
+ }
+ return EMPTY_ITERATOR;
+ }
+}
Added: sling/trunk/contrib/extensions/sling-pipes/src/main/java/org/apache/sling/pipes/impl/PlumberImpl.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/sling-pipes/src/main/java/org/apache/sling/pipes/impl/PlumberImpl.java?rev=1718377&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/sling-pipes/src/main/java/org/apache/sling/pipes/impl/PlumberImpl.java (added)
+++ sling/trunk/contrib/extensions/sling-pipes/src/main/java/org/apache/sling/pipes/impl/PlumberImpl.java Mon Dec 7 14:19:52 2015
@@ -0,0 +1,150 @@
+/*
+ * 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.impl;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.apache.felix.scr.annotations.ReferencePolicy;
+import org.apache.felix.scr.annotations.Service;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.distribution.DistributionRequest;
+import org.apache.sling.distribution.DistributionRequestType;
+import org.apache.sling.distribution.DistributionResponse;
+import org.apache.sling.distribution.Distributor;
+import org.apache.sling.distribution.SimpleDistributionRequest;
+import org.apache.sling.pipes.AuthorizablePipe;
+import org.apache.sling.pipes.BasePipe;
+import org.apache.sling.pipes.ContainerPipe;
+import org.apache.sling.pipes.FilterPipe;
+import org.apache.sling.pipes.PathPipe;
+import org.apache.sling.pipes.JsonPipe;
+import org.apache.sling.pipes.MovePipe;
+import org.apache.sling.pipes.MultiPropertyPipe;
+import org.apache.sling.pipes.ParentPipe;
+import org.apache.sling.pipes.Pipe;
+import org.apache.sling.pipes.Plumber;
+import org.apache.sling.pipes.ReferencePipe;
+import org.apache.sling.pipes.RemovePipe;
+import org.apache.sling.pipes.SlingQueryPipe;
+import org.apache.sling.pipes.WritePipe;
+import org.apache.sling.pipes.XPathPipe;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import java.util.logging.Filter;
+
+/**
+ * implements plumber interface, and registers default pipes
+ */
+@Component
+@Service
+public class PlumberImpl implements Plumber {
+ private final Logger log = LoggerFactory.getLogger(this.getClass());
+
+ Map<String, Class<? extends BasePipe>> registry;
+
+ @Reference (policy= ReferencePolicy.DYNAMIC, cardinality= ReferenceCardinality.OPTIONAL_UNARY)
+ protected volatile Distributor distributor = null;
+
+ @Activate
+ public void activate(){
+ registry = new HashMap<>();
+ registerPipe(BasePipe.RESOURCE_TYPE, BasePipe.class);
+ registerPipe(ContainerPipe.RESOURCE_TYPE, ContainerPipe.class);
+ registerPipe(SlingQueryPipe.RESOURCE_TYPE, SlingQueryPipe.class);
+ registerPipe(WritePipe.RESOURCE_TYPE, WritePipe.class);
+ registerPipe(JsonPipe.RESOURCE_TYPE, JsonPipe.class);
+ registerPipe(MultiPropertyPipe.RESOURCE_TYPE, MultiPropertyPipe.class);
+ registerPipe(AuthorizablePipe.RESOURCE_TYPE, AuthorizablePipe.class);
+ registerPipe(XPathPipe.RESOURCE_TYPE, XPathPipe.class);
+ registerPipe(ReferencePipe.RESOURCE_TYPE, ReferencePipe.class);
+ registerPipe(RemovePipe.RESOURCE_TYPE, RemovePipe.class);
+ registerPipe(ParentPipe.RESOURCE_TYPE, ParentPipe.class);
+ registerPipe(MovePipe.RESOURCE_TYPE, MovePipe.class);
+ registerPipe(PathPipe.RESOURCE_TYPE, PathPipe.class);
+ registerPipe(FilterPipe.RESOURCE_TYPE, FilterPipe.class);
+ }
+
+ @Override
+ public Pipe getPipe(Resource resource) {
+ if ((resource == null) || !registry.containsKey(resource.getResourceType())) {
+ log.error("Pipe configuration resource is either null, or its type is not registered");
+ } else {
+ try {
+ Class<? extends Pipe> pipeClass = registry.get(resource.getResourceType());
+ return pipeClass.getDeclaredConstructor(Plumber.class, Resource.class).newInstance(this, resource);
+ } catch (Exception e) {
+ log.error("Unable to properly instantiate the pipe configured in {}", resource.getPath(), e);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public Set<String> execute(ResourceResolver resolver, String path, Map additionalBindings, boolean save) throws Exception {
+ Resource pipeResource = resolver.getResource(path);
+ Pipe pipe = getPipe(pipeResource);
+ if (pipe == null) {
+ throw new Exception("unable to build pipe based on configuration at " + path);
+ }
+ return execute(resolver, pipe, additionalBindings, save);
+ }
+
+ @Override
+ public Set<String> execute(ResourceResolver resolver, Pipe pipe, Map additionalBindings, boolean save) throws Exception {
+ if (additionalBindings != null && pipe instanceof ContainerPipe){
+ pipe.getBindings().addBindings(additionalBindings);
+ }
+
+ log.info("[{}] execution starts, save ({})", pipe, save);
+ Set<String> set = new HashSet<>();
+ for (Iterator<Resource> it = pipe.getOutput(); it.hasNext();){
+ Resource resource = it.next();
+ if (resource != null) {
+ log.debug("[{}] retrieved {}", pipe.getName(), resource.getPath());
+ set.add(resource.getPath());
+ }
+ }
+ if (pipe.modifiesContent() && save && resolver.hasChanges() && !pipe.isDryRun()){
+ log.info("[{}] saving changes...", pipe.getName());
+ resolver.commit();
+ if (distributor != null && StringUtils.isNotBlank(pipe.getDistributionAgent())) {
+ log.info("a distribution agent is configured, will try to distribute the changes");
+ DistributionRequest request = new SimpleDistributionRequest(DistributionRequestType.ADD, true, set.toArray(new String[set.size()]));
+ DistributionResponse response = distributor.distribute(pipe.getDistributionAgent(), resolver, request);
+ log.info("distribution response : {}", response);
+ }
+ }
+ log.info("[{}] done executing.", pipe.getName());
+ return set;
+ }
+
+ @Override
+ public void registerPipe(String type, Class<? extends BasePipe> pipeClass) {
+ registry.put(type, pipeClass);
+ }
+}
Added: sling/trunk/contrib/extensions/sling-pipes/src/test/java/org/apache/sling/pipes/AbstractPipeTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/sling-pipes/src/test/java/org/apache/sling/pipes/AbstractPipeTest.java?rev=1718377&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/sling-pipes/src/test/java/org/apache/sling/pipes/AbstractPipeTest.java (added)
+++ sling/trunk/contrib/extensions/sling-pipes/src/test/java/org/apache/sling/pipes/AbstractPipeTest.java Mon Dec 7 14:19:52 2015
@@ -0,0 +1,55 @@
+/*
+ * 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.sling.pipes.dummies.DummyNull;
+import org.apache.sling.pipes.dummies.DummySearch;
+import org.apache.sling.pipes.impl.PlumberImpl;
+import org.apache.sling.testing.mock.sling.ResourceResolverType;
+import org.apache.sling.testing.mock.sling.junit.SlingContext;
+import org.junit.Before;
+import org.junit.Rule;
+
+/**
+ * this abstract class for pipes implements a plumber with all registered pipes, plus some test ones, and give some paths,
+ * it also provides a testing Sling Context, with some content.
+ */
+public class AbstractPipeTest {
+
+ protected static final String PATH_PIPE = "/etc/pipe";
+ protected static final String PATH_FRUITS = "/content/fruits";
+ protected static final String PATH_BANANA = PATH_FRUITS + "/banana";
+ protected static final String PATH_APPLE = PATH_FRUITS + "/apple";
+ protected static final String NN_SIMPLE = "simple";
+ protected static final String NN_COMPLEX = "complex";
+ protected static final String PN_INDEX = "/index";
+ Plumber plumber;
+
+ @Rule
+ public SlingContext context = new SlingContext(ResourceResolverType.JCR_MOCK);
+
+ @Before
+ public void setup(){
+ PlumberImpl plumberImpl = new PlumberImpl();
+ plumberImpl.activate();
+ plumberImpl.registerPipe("slingPipes/dummyNull", DummyNull.class);
+ plumberImpl.registerPipe("slingPipes/dummySearch", DummySearch.class);
+ plumber = plumberImpl;
+ context.load().json("/fruits.json", PATH_FRUITS);
+ }
+
+}
Added: sling/trunk/contrib/extensions/sling-pipes/src/test/java/org/apache/sling/pipes/ContainerPipeTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/sling-pipes/src/test/java/org/apache/sling/pipes/ContainerPipeTest.java?rev=1718377&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/sling-pipes/src/test/java/org/apache/sling/pipes/ContainerPipeTest.java (added)
+++ sling/trunk/contrib/extensions/sling-pipes/src/test/java/org/apache/sling/pipes/ContainerPipeTest.java Mon Dec 7 14:19:52 2015
@@ -0,0 +1,114 @@
+/*
+ * 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.sling.api.resource.Resource;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.Iterator;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * testing container with dummy child pipes
+ */
+public class ContainerPipeTest extends AbstractPipeTest {
+
+ public static final String NN_DUMMYTREE = "dummyTree";
+ public static final String NN_OTHERTREE = "otherTree";
+ public static final String NN_ROTTENTREE = "rottenTree";
+ public static final String NN_ONEPIPE = "onePipeContainer";
+
+ @Before
+ public void setup() {
+ super.setup();
+ context.load().json("/container.json", PATH_PIPE);
+ }
+
+ @Test
+ public void testDummyTree() throws Exception {
+ Resource resource = context.resourceResolver().getResource(PATH_PIPE + "/" + NN_DUMMYTREE);
+ ContainerPipe pipe = (ContainerPipe)plumber.getPipe(resource);
+ assertNotNull("A container pipe should be built out from the given configuration", pipe);
+ Iterator<Resource> resourceIterator = pipe.getOutput();
+ assertTrue("There should be some results", resourceIterator.hasNext());
+ Resource firstResource = resourceIterator.next();
+ assertNotNull("First resource should not be null", firstResource);
+ assertEquals("First resource should be instantiated path with apple & pea",
+ PATH_FRUITS + "/apple/isnota/pea/buttheyhavesamecolor",
+ firstResource.getPath());
+ assertTrue("There should still be another item", resourceIterator.hasNext());
+ Resource secondResource = resourceIterator.next();
+ assertNotNull("Second resource should not be null", secondResource);
+ assertEquals("Second resource should be instantiated path with apple & carrot",
+ PATH_FRUITS + "/apple/isnota/carrot/andtheircolorisdifferent",
+ secondResource.getPath());
+ assertTrue("There should still be another item", resourceIterator.hasNext());
+ Resource thirdResource = resourceIterator.next();
+ assertNotNull("Third resource should not be null", thirdResource);
+ assertEquals("Third resource should be instantiated path with banana & pea",
+ PATH_FRUITS + "/banana/isnota/pea/andtheircolorisdifferent",
+ thirdResource.getPath());
+ assertTrue("There should still be another item", resourceIterator.hasNext());
+ Resource fourthResource = resourceIterator.next();
+ assertNotNull("Fourth resource should not be null", fourthResource);
+ assertEquals("fourthResource resource should be instantiated path with banana & carrot",
+ PATH_FRUITS + "/banana/isnota/carrot/andtheircolorisdifferent",
+ fourthResource.getPath());
+ assertFalse("There should be no more items", resourceIterator.hasNext());
+ }
+
+ @Test
+ public void testOtherTree() throws Exception {
+ Resource resource = context.resourceResolver().getResource(PATH_PIPE + "/" + NN_OTHERTREE);
+ ContainerPipe pipe = (ContainerPipe)plumber.getPipe(resource);
+ Iterator<Resource> resourceIterator = pipe.getOutput();
+ assertTrue("There should be some results", resourceIterator.hasNext());
+ Resource firstResource = resourceIterator.next();
+ assertNotNull("First resource should not be null", firstResource);
+ assertEquals("First resource should be instantiated path with apple & pea",
+ PATH_FRUITS + "/apple/isnota/pea/buttheyhavesamecolor",
+ firstResource.getPath());
+ assertTrue("There should still be another item", resourceIterator.hasNext());
+ Resource secondResource = resourceIterator.next();
+ assertNotNull("Second resource should not be null", secondResource);
+ assertEquals("Second resource should be instantiated path with banana & pea",
+ PATH_FRUITS + "/banana/isnota/pea/andtheircolorisdifferent",
+ secondResource.getPath());
+ assertFalse("There should be no more items", resourceIterator.hasNext());
+ }
+
+ @Test
+ public void testRottenTree() throws Exception {
+ Resource resource = context.resourceResolver().getResource(PATH_PIPE + "/" + NN_ROTTENTREE);
+ ContainerPipe pipe = (ContainerPipe)plumber.getPipe(resource);
+ Iterator<Resource> resourceIterator = pipe.getOutput();
+ assertFalse("There shouldn't be any resource", resourceIterator.hasNext());
+ }
+
+ @Test
+ public void testOnePipe() throws Exception {
+ Resource resource = context.resourceResolver().getResource(PATH_PIPE + "/" + NN_ONEPIPE);
+ ContainerPipe pipe = (ContainerPipe)plumber.getPipe(resource);
+ Iterator<Resource> resourceIterator = pipe.getOutput();
+ assertTrue("There should be children", resourceIterator.hasNext());
+ }
+}
\ No newline at end of file
Added: sling/trunk/contrib/extensions/sling-pipes/src/test/java/org/apache/sling/pipes/FilterPipeTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/sling-pipes/src/test/java/org/apache/sling/pipes/FilterPipeTest.java?rev=1718377&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/sling-pipes/src/test/java/org/apache/sling/pipes/FilterPipeTest.java (added)
+++ sling/trunk/contrib/extensions/sling-pipes/src/test/java/org/apache/sling/pipes/FilterPipeTest.java Mon Dec 7 14:19:52 2015
@@ -0,0 +1,89 @@
+/*
+ * 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.lang3.StringUtils;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ValueMap;
+import org.junit.Test;
+
+import java.util.Iterator;
+
+import static org.junit.Assert.*;
+
+/**
+ * testing different kind of filters
+ */
+public class FilterPipeTest extends AbstractPipeTest {
+ public static final String NN_PROPERTIES = "properties";
+ public static final String NN_NOCHILDREN = "noChildrenPasses";
+ public static final String NN_NOCHILDREN_FAILS = "noChildrenVoid";
+ public static final String NN_TEST = "testPasses";
+ public static final String NN_TEST_FAILS = "testFails";
+ public void setup() {
+ super.setup();
+ context.load().json("/filter.json", PATH_PIPE);
+ }
+
+ @Test
+ public void testFilterProperties(){
+ Resource resource = context.resourceResolver().getResource(PATH_PIPE + "/" + NN_PROPERTIES);
+ ContainerPipe pipe = (ContainerPipe)plumber.getPipe(resource);
+ Iterator<Resource> resourceIterator = pipe.getOutput();
+ assertTrue("output has one resource...", resourceIterator.hasNext());
+ ValueMap properties = resourceIterator.next().adaptTo(ValueMap.class);
+ assertFalse("...and only One", resourceIterator.hasNext());
+ assertEquals("output resource's color is green", "green", properties.get("color", String.class));
+ assertTrue("output resource's name is not void", StringUtils.isNotBlank(properties.get("name", String.class)));
+ }
+
+ @Test
+ public void testNoChildrenPasses(){
+ Resource resource = context.resourceResolver().getResource(PATH_PIPE + "/" + NN_NOCHILDREN);
+ Pipe pipe = plumber.getPipe(resource);
+ Iterator<Resource> resourceIterator = pipe.getOutput();
+ assertTrue("output has one resource...", resourceIterator.hasNext());
+ resourceIterator.next().adaptTo(ValueMap.class);
+ assertFalse("...and only One", resourceIterator.hasNext());
+ }
+
+
+ @Test
+ public void testNoChildrenFails(){
+ Resource resource = context.resourceResolver().getResource(PATH_PIPE + "/" + NN_NOCHILDREN_FAILS);
+ Pipe pipe = plumber.getPipe(resource);
+ Iterator<Resource> resourceIterator = pipe.getOutput();
+ assertFalse("output has no resource...", resourceIterator.hasNext());
+ }
+
+ @Test
+ public void testTestPasses() {
+ Resource resource = context.resourceResolver().getResource(PATH_PIPE + "/" + NN_TEST);
+ Pipe pipe = plumber.getPipe(resource);
+ Iterator<Resource> resourceIterator = pipe.getOutput();
+ assertTrue("output has one resource...", resourceIterator.hasNext());
+ }
+
+ @Test
+ public void testTestFails() {
+ Resource resource = context.resourceResolver().getResource(PATH_PIPE + "/" + NN_TEST_FAILS);
+ Pipe pipe = plumber.getPipe(resource);
+ Iterator<Resource> resourceIterator = pipe.getOutput();
+ assertFalse("output has no resource...", resourceIterator.hasNext());
+ }
+
+}
\ No newline at end of file
Added: sling/trunk/contrib/extensions/sling-pipes/src/test/java/org/apache/sling/pipes/JsonPipeTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/sling-pipes/src/test/java/org/apache/sling/pipes/JsonPipeTest.java?rev=1718377&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/sling-pipes/src/test/java/org/apache/sling/pipes/JsonPipeTest.java (added)
+++ sling/trunk/contrib/extensions/sling-pipes/src/test/java/org/apache/sling/pipes/JsonPipeTest.java Mon Dec 7 14:19:52 2015
@@ -0,0 +1,67 @@
+/*
+ * 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.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ValueMap;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.Iterator;
+
+import static org.junit.Assert.*;
+
+/**
+ * testing json pipe with anonymous yahoo meteo API
+ */
+public class JsonPipeTest extends AbstractPipeTest {
+ public static final String CONF = "/content/json/conf/weather";
+ public static final String ARRAY = "/content/json/conf/array";
+
+ @Before
+ public void setup() {
+ super.setup();
+ context.load().json("/json.json", "/content/json");
+ }
+
+ @Test
+ public void testPipedJson() throws Exception{
+ Resource resource = context.resourceResolver().getResource(CONF);
+ Pipe pipe = plumber.getPipe(resource);
+ Iterator<Resource> outputs = pipe.getOutput();
+ outputs.next();
+ Resource result = outputs.next();
+ context.resourceResolver().commit();
+ ValueMap properties = result.adaptTo(ValueMap.class);
+ assertTrue("There should be a Paris property", properties.containsKey("Paris"));
+ assertTrue("There should be a Bucharest property", properties.containsKey("Bucharest"));
+ }
+
+ @Test
+ public void testPipedArray() throws Exception {
+ Resource resource = context.resourceResolver().getResource(ARRAY);
+ ContainerPipe pipe = (ContainerPipe)plumber.getPipe(resource);
+ Iterator<Resource> outputs = pipe.getOutput();
+ Resource first = outputs.next();
+ Resource second = outputs.next();
+ Resource third = outputs.next();
+ assertFalse("there should be only three elements", outputs.hasNext());
+ assertEquals("first resource should be one", "/content/json/array/one", first.getPath());
+ assertEquals("second resource should be two", "/content/json/array/two", second.getPath());
+ assertEquals("third resource should be three", "/content/json/array/three", third.getPath());
+ }
+}
\ No newline at end of file
Added: sling/trunk/contrib/extensions/sling-pipes/src/test/java/org/apache/sling/pipes/MovePipeTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/sling-pipes/src/test/java/org/apache/sling/pipes/MovePipeTest.java?rev=1718377&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/sling-pipes/src/test/java/org/apache/sling/pipes/MovePipeTest.java (added)
+++ sling/trunk/contrib/extensions/sling-pipes/src/test/java/org/apache/sling/pipes/MovePipeTest.java Mon Dec 7 14:19:52 2015
@@ -0,0 +1,70 @@
+/*
+ * 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.sling.api.resource.Resource;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import javax.jcr.Session;
+import java.util.Iterator;
+
+/**
+ * testing moving nodes & properties
+ */
+public class MovePipeTest extends AbstractPipeTest {
+
+ static final String MOVENODE_PIPE = "/moveNode";
+ static final String MOVEPROPERTY_PIPE = "/moveProperty";
+ static final String MOVED_NODE_PATH = "/granny";
+ static final String MOVED_PROPERTY_PATH = "/indexFruits";
+
+ @Before
+ public void setup() {
+ super.setup();
+ context.load().json("/move.json", PATH_PIPE);
+ }
+
+ @Ignore //move operation is not supported yet by MockSession
+ @Test
+ public void testMoveNode() throws Exception {
+ Resource resource = context.resourceResolver().getResource(PATH_PIPE + MOVENODE_PIPE);
+ Pipe pipe = plumber.getPipe(resource);
+ Iterator<Resource> output = pipe.getOutput();
+ Assert.assertTrue(output.hasNext());
+ output.next();
+ Session session = context.resourceResolver().adaptTo(Session.class);
+ session.save();
+ Assert.assertTrue("new node path should exists", session.nodeExists(PATH_FRUITS + MOVED_NODE_PATH));
+ }
+
+ @Ignore //move operation is not supported yet by MockSession
+ @Test
+ public void testMoveProperty() throws Exception {
+ Resource resource = context.resourceResolver().getResource(PATH_PIPE + MOVEPROPERTY_PIPE);
+ Pipe pipe = plumber.getPipe(resource);
+ Iterator<Resource> output = pipe.getOutput();
+ Assert.assertTrue(output.hasNext());
+ output.next();
+ Session session = context.resourceResolver().adaptTo(Session.class);
+ session.save();
+ Assert.assertTrue("new property path should exists", session.propertyExists(PATH_FRUITS + MOVED_NODE_PATH));
+ Assert.assertFalse("old property path should not", session.propertyExists(PATH_FRUITS + PN_INDEX));
+ }
+}
\ No newline at end of file
Added: sling/trunk/contrib/extensions/sling-pipes/src/test/java/org/apache/sling/pipes/MultiPropertyPipeTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/sling-pipes/src/test/java/org/apache/sling/pipes/MultiPropertyPipeTest.java?rev=1718377&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/sling-pipes/src/test/java/org/apache/sling/pipes/MultiPropertyPipeTest.java (added)
+++ sling/trunk/contrib/extensions/sling-pipes/src/test/java/org/apache/sling/pipes/MultiPropertyPipeTest.java Mon Dec 7 14:19:52 2015
@@ -0,0 +1,69 @@
+/*
+ * 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.sling.api.resource.Resource;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.Iterator;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+
+/**
+ * testing normal case of MV Property Pipe
+ */
+public class MultiPropertyPipeTest extends AbstractPipeTest {
+
+ @Before
+ public void setup() {
+ super.setup();
+ context.load().json("/multiProperty.json", PATH_PIPE);
+ }
+
+ @Test
+ public void testMV() throws Exception{
+ Resource conf = context.resourceResolver().getResource(PATH_PIPE + "/working");
+ Pipe pipe = plumber.getPipe(conf);
+ Iterator<Resource> outputs = pipe.getOutput();
+ Resource resource = outputs.next();
+ assertNotNull(resource);
+ assertEquals("Resource path should be the input", PATH_FRUITS + PN_INDEX, resource.getPath());
+ String fruit = (String)pipe.getOutputBinding();
+ assertEquals("First resource binding should be apple", "apple", fruit);
+ resource = outputs.next();
+ assertNotNull(resource);
+ assertEquals("Resource path should be the input", PATH_FRUITS + PN_INDEX, resource.getPath());
+ fruit = (String)pipe.getOutputBinding();
+ assertEquals("Second resource binding should be banana", "banana", fruit);
+ }
+
+ @Test
+ public void testNonWorkingMV() throws Exception{
+ Resource conf = context.resourceResolver().getResource(PATH_PIPE + "/typo");
+ Pipe pipe = plumber.getPipe(conf);
+ assertFalse("There should not be next for a non existing resource", pipe.getOutput().hasNext());
+ conf = context.resourceResolver().getResource(PATH_PIPE + "/notProperty");
+ pipe = plumber.getPipe(conf);
+ assertFalse("There should not be next for a resource that is not a property", pipe.getOutput().hasNext());
+ conf = context.resourceResolver().getResource(PATH_PIPE + "/notMultiple");
+ pipe = plumber.getPipe(conf);
+ assertFalse("There should not be next for a property that is not multiple", pipe.getOutput().hasNext());
+ }
+}
Added: sling/trunk/contrib/extensions/sling-pipes/src/test/java/org/apache/sling/pipes/PipeBindingsTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/sling-pipes/src/test/java/org/apache/sling/pipes/PipeBindingsTest.java?rev=1718377&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/sling-pipes/src/test/java/org/apache/sling/pipes/PipeBindingsTest.java (added)
+++ sling/trunk/contrib/extensions/sling-pipes/src/test/java/org/apache/sling/pipes/PipeBindingsTest.java Mon Dec 7 14:19:52 2015
@@ -0,0 +1,103 @@
+/*
+ * 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.sling.api.resource.Resource;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.Calendar;
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.junit.Assert.*;
+
+/**
+ * testing binding's expressions instanciations
+ */
+public class PipeBindingsTest extends AbstractPipeTest {
+
+ private static final String NN_MOREBINDINGS = "moreBindings";
+
+ @Before
+ public void setup() {
+ super.setup();
+ context.load().json("/container.json", PATH_PIPE);
+ }
+
+ @Test
+ public void computeEcma5Expression() {
+ Resource resource = context.resourceResolver().getResource(PATH_PIPE + "/" + ContainerPipeTest.NN_DUMMYTREE);
+ PipeBindings bindings = new PipeBindings(resource);
+ Map<String,String> expressions = new HashMap<>();
+ expressions.put("blah ${blah} blah", "'blah ' + blah + ' blah'");
+ expressions.put("${blah}", "blah");
+ expressions.put("${blah} blah", "blah + ' blah'");
+ expressions.put("blah ${blah}", "'blah ' + blah");
+ expressions.put("${blah}${blah}", "blah + '' + blah");
+ expressions.put("+[${blah}]", "'+[' + blah + ']'");
+ for (Map.Entry<String,String> test : expressions.entrySet()){
+ assertEquals(test.getKey() + " should be transformed in " + test.getValue(), test.getValue(), bindings.computeECMA5Expression(test.getKey()));
+ }
+ }
+
+ @Test
+ public void testInstantiateExpression() throws Exception {
+ Resource resource = context.resourceResolver().getResource(PATH_PIPE + "/" + ContainerPipeTest.NN_DUMMYTREE);
+ PipeBindings bindings = new PipeBindings(resource);
+ Map<String, String> testMap = new HashMap<>();
+ testMap.put("a", "apricots");
+ testMap.put("b", "bananas");
+ bindings.getBindings().put("test", testMap);
+ String newExpression = bindings.instantiateExpression("${test.a} and ${test.b}");
+ assertEquals("expression should be correctly instantiated", "apricots and bananas", newExpression);
+ }
+
+ @Test
+ public void testInstantiateObject() throws Exception {
+ Resource resource = context.resourceResolver().getResource(PATH_PIPE + "/" + ContainerPipeTest.NN_DUMMYTREE);
+ PipeBindings bindings = new PipeBindings(resource);
+ Map<String, String> testMap = new HashMap<>();
+ testMap.put("a", "apricots");
+ testMap.put("b", "bananas");
+ bindings.getBindings().put("test", testMap);
+ String newExpression = (String)bindings.instantiateObject("${test.a} and ${test.b}");
+ assertEquals("expression should be correctly instantiated", "apricots and bananas", newExpression);
+ Calendar cal = (Calendar)bindings.instantiateObject("${new Date(2012,04,12)}");
+ assertNotNull("calendar should be instantiated", cal);
+ assertEquals("year should be correct", 2012, cal.get(Calendar.YEAR));
+ assertEquals("month should be correct", 4, cal.get(Calendar.MONTH));
+ assertEquals("date should be correct", 11, cal.get(Calendar.DAY_OF_MONTH));
+ }
+
+ @Test
+ public void testAdditionalBindings() throws Exception {
+ Resource resource = context.resourceResolver().getResource(PATH_PIPE + "/" + NN_MOREBINDINGS);
+ PipeBindings bindings = new PipeBindings(resource);
+ String expression = bindings.instantiateExpression("${three}");
+ assertEquals("computed expression should be taking additional bindings 'three' in account", "3", expression);
+ }
+
+ @Test
+ public void testAdditionalScript() throws Exception {
+ context.load().binaryFile("/testSum.js", "/content/test/testSum.js");
+ Resource resource = context.resourceResolver().getResource(PATH_PIPE + "/" + NN_MOREBINDINGS);
+ PipeBindings bindings = new PipeBindings(resource);
+ Number expression = (Number)bindings.instantiateObject("${testSumFunction(1,2)}");
+ assertEquals("computed expression have testSum script's functionavailable", 3, expression.intValue());
+ }
+}
\ No newline at end of file
Added: sling/trunk/contrib/extensions/sling-pipes/src/test/java/org/apache/sling/pipes/PlumberServletTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/sling-pipes/src/test/java/org/apache/sling/pipes/PlumberServletTest.java?rev=1718377&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/sling-pipes/src/test/java/org/apache/sling/pipes/PlumberServletTest.java (added)
+++ sling/trunk/contrib/extensions/sling-pipes/src/test/java/org/apache/sling/pipes/PlumberServletTest.java Mon Dec 7 14:19:52 2015
@@ -0,0 +1,188 @@
+/*
+ * 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.lang3.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.resource.ValueMap;
+import org.apache.sling.commons.json.JSONArray;
+import org.apache.sling.commons.json.JSONException;
+import org.apache.sling.commons.json.JSONObject;
+import org.junit.Before;
+import org.junit.Test;
+
+import javax.servlet.ServletException;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+/**
+ * testing the servlet logic (parameters & output)
+ */
+public class PlumberServletTest extends AbstractPipeTest {
+
+ String containersPath = PATH_PIPE + "/" + "containers";
+
+ String dummyTreePath = containersPath + "/" + ContainerPipeTest.NN_DUMMYTREE;
+
+ String writePath = PATH_PIPE + "/" + "write";
+
+ String pipedWritePath = writePath + "/" + WritePipeTest.NN_PIPED;
+
+ StringWriter stringResponse;
+
+ SlingHttpServletResponse response;
+
+ PlumberServlet servlet = new PlumberServlet();
+
+ @Before
+ public void setup() {
+ super.setup();
+ context.load().json("/plumber.json", PATH_PIPE);
+ context.load().json("/container.json", containersPath);
+ context.load().json("/write.json", writePath);
+ servlet.plumber = plumber;
+ stringResponse = new StringWriter();
+ try {
+ response = mockPlumberServletResponse(stringResponse);
+ } catch (Exception e){
+
+ }
+ }
+
+ private void assertDummyTree() throws JSONException {
+ String finalResponse = stringResponse.toString();
+ assertFalse("There should be a response", StringUtils.isBlank(finalResponse));
+ JSONArray array = new JSONArray(finalResponse);
+ assertEquals("response should be an array with 4 results", 4, array.length());
+ }
+
+ @Test
+ public void testDummyTreeThroughRT() throws Exception {
+ SlingHttpServletRequest request = mockPlumberServletRequest(context.resourceResolver(), dummyTreePath, null, null, null, null);
+ servlet.execute(request, response, false);
+ assertDummyTree();
+ }
+
+ @Test
+ public void testDummyTreeThroughPlumber() throws Exception {
+ SlingHttpServletRequest request = mockPlumberServletRequest(context.resourceResolver(), PATH_PIPE, dummyTreePath, null, null, null);
+ servlet.execute(request, response, false);
+ assertDummyTree();
+ }
+
+ @Test
+ public void testWriteExecute() throws ServletException {
+ SlingHttpServletRequest request = mockPlumberServletRequest(context.resourceResolver(), pipedWritePath, null, null, null, null);
+ servlet.execute(request, response, true);
+ String finalResponse = stringResponse.toString();
+ assertFalse("There should be a response", StringUtils.isBlank(finalResponse));
+ }
+
+ /**
+ * in this test we execute a pipe that modifies content, with a flag mocking the GET request:
+ * the execution should fail.
+ */
+ @Test
+ public void testGetOnWriteExecute() throws ServletException {
+ SlingHttpServletRequest request = mockPlumberServletRequest(context.resourceResolver(), pipedWritePath, null, null, null, null);
+ boolean hasFailed = true;
+ try {
+ servlet.execute(request, response, false);
+ hasFailed = false;
+ } catch (Exception e){
+
+ }
+ assertTrue("Execution should have failed", hasFailed);
+ }
+
+ @Test
+ public void testAdditionalBindingsAndWriter() throws Exception {
+ String testBinding = "testBinding";
+ String testBindingLength = testBinding + "Length";
+ String bindingValue = "testBindingValue";
+ String pathLengthParam = "pathLength";
+ JSONObject bindings = new JSONObject("{'" + testBinding + "':'" + bindingValue + "'}");
+ JSONObject respObject = new JSONObject("{'" + pathLengthParam + "':'${path.get(\"dummyGrandChild\").length}','" + testBindingLength + "':'${" + testBinding + ".length}'}");
+ SlingHttpServletRequest request =
+ mockPlumberServletRequest(context.resourceResolver(), dummyTreePath, null, bindings.toString(), respObject.toString(), null);
+ servlet.execute(request, response, false);
+ assertDummyTree();
+ JSONArray array = new JSONArray(stringResponse.toString());
+ for (int i = 0; i < array.length(); i++) {
+ JSONObject object = array.optJSONObject(i);
+ assertNotNull("there should be an object returned at each time", object);
+ String path = object.optString(PlumberServlet.PATH_KEY);
+ assertNotNull("the string path should be returned for each item, containing the path of the resource");
+ String pathLength = object.optString(pathLengthParam);
+ assertNotNull("there should be a pathLength param, as specified in the writer", pathLength);
+ assertEquals("Pathlength should be the string representation of the path length", path.length() + "", pathLength);
+ String testBindingLengthValue = object.optString(testBindingLength);
+ assertNotNull("testBindingLength should be there", testBindingLengthValue);
+ assertEquals("testBindingLength should be the string representation of the additional binding length",
+ bindingValue.length() + "", testBindingLengthValue);
+ }
+ }
+
+ @Test
+ public void testDryRun() throws Exception {
+ SlingHttpServletRequest dryRunRequest =
+ mockPlumberServletRequest(context.resourceResolver(), pipedWritePath, null, null, null, "true");
+ servlet.execute(dryRunRequest, response, true);
+ Resource resource = context.resourceResolver().getResource("/content/fruits");
+ ValueMap properties = resource.adaptTo(ValueMap.class);
+ assertFalse("property fruits shouldn't have been written", properties.containsKey("fruits"));
+ SlingHttpServletRequest request =
+ mockPlumberServletRequest(context.resourceResolver(), pipedWritePath, null, null, null, "false");
+ servlet.execute(request, response, true);
+ WritePipeTest.assertPiped(resource);
+ }
+
+ public static SlingHttpServletRequest mockPlumberServletRequest(ResourceResolver resolver,
+ String path,
+ String pathParam,
+ String bindings,
+ String writer,
+ String dryRun){
+ SlingHttpServletRequest request = mock(SlingHttpServletRequest.class);
+ Resource resource = resolver.getResource(path);
+ when(request.getResourceResolver()).thenReturn(resolver);
+ when(request.getResource()).thenReturn(resource);
+ when(request.getParameter(PlumberServlet.PARAM_PATH)).thenReturn(pathParam);
+ when(request.getParameter(PlumberServlet.PARAM_BINDINGS)).thenReturn(bindings);
+ when(request.getParameter(PlumberServlet.PARAM_WRITER)).thenReturn(writer);
+ when(request.getParameter(BasePipe.DRYRUN_KEY)).thenReturn(dryRun);
+ return request;
+ }
+
+ public static SlingHttpServletResponse mockPlumberServletResponse(StringWriter writer) throws IOException {
+ SlingHttpServletResponse response = mock(SlingHttpServletResponse.class);
+ PrintWriter printWriter = new PrintWriter(writer);
+ when(response.getWriter()).thenReturn(printWriter);
+ return response;
+ }
+}