You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by np...@apache.org on 2022/04/20 19:42:17 UTC

[sling-org-apache-sling-pipes] branch master updated: SLING-11267 fix whitespace escapes in commands

This is an automated email from the ASF dual-hosted git repository.

npeltier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-pipes.git


The following commit(s) were added to refs/heads/master by this push:
     new 7da5483  SLING-11267 fix whitespace escapes in commands
7da5483 is described below

commit 7da54839a44f02cc694e80ccc397ba344f690985
Author: Nicolas Peltier <np...@apache.org>
AuthorDate: Wed Apr 20 21:38:25 2022 +0200

    SLING-11267 fix whitespace escapes in commands
    
    - fixing regexp so subtokens "a"="b", a="b", "a"=b are passed as such,
    - managing in command util translation of "a"="b" into a & b
---
 .../sling/pipes/internal/CommandExecutorImpl.java   | 10 +++++++---
 .../apache/sling/pipes/internal/CommandUtil.java    | 17 +++++++++++++++--
 .../org/apache/sling/pipes/PipeBuilderTest.java     |  8 ++++++++
 .../pipes/internal/CommandExecutorImplTest.java     | 12 ++++++++++++
 .../sling/pipes/internal/CommandUtilTest.java       | 21 ++++++++++++++++++---
 5 files changed, 60 insertions(+), 8 deletions(-)

diff --git a/src/main/java/org/apache/sling/pipes/internal/CommandExecutorImpl.java b/src/main/java/org/apache/sling/pipes/internal/CommandExecutorImpl.java
index 58792fa..8c2ea0f 100644
--- a/src/main/java/org/apache/sling/pipes/internal/CommandExecutorImpl.java
+++ b/src/main/java/org/apache/sling/pipes/internal/CommandExecutorImpl.java
@@ -89,6 +89,8 @@ public class CommandExecutorImpl extends AbstractPlumberServlet implements Comma
     static final String REQ_PARAM_HELP = "pipe_help";
     static final String CMD_LINE_PREFIX = "cmd_line_";
     static final String PN_DESCRIPTION = "commandParsed";
+
+    static final String TOKEN = "token";
     static final String WHITE_SPACE_SEPARATOR = "[\\s\\h]";
     static final String COMMENT_PREFIX = "#";
     static final String SEPARATOR = "|";
@@ -97,9 +99,8 @@ public class CommandExecutorImpl extends AbstractPlumberServlet implements Comma
     static final String PARAMS = "@";
     static final List<String> JSON_EXPR_KEYS = Arrays.asList(JsonPipe.JSON_KEY);
     static final String JSON_START = "\"[{";
-
     static final String PARAMS_SEPARATOR = WHITE_SPACE_SEPARATOR + "+" + PARAMS + WHITE_SPACE_SEPARATOR + "*";
-    static final Pattern SUB_TOKEN_PATTERN = Pattern.compile("(([^\"]\\S*)|\"([^\"]+)\")\\s*");
+    static final Pattern SUB_TOKEN_PATTERN = Pattern.compile("\\s*(?<" + TOKEN + ">((\"[^\"]*\")|([^\\s\"]+))*)\\s*" );
     static final String KEY_NAME = "name";
     static final String KEY_PATH = "path";
     static final String KEY_EXPR = "expr";
@@ -468,7 +469,10 @@ public class CommandExecutorImpl extends AbstractPlumberServlet implements Comma
         List<String> subTokens = new ArrayList<>();
         Matcher matcher = SUB_TOKEN_PATTERN.matcher(token);
         while (matcher.find()){
-            subTokens.add(matcher.group(2) != null ? matcher.group(2) : matcher.group(3));
+            String subToken = matcher.group(TOKEN);
+            if (StringUtils.isNotBlank(subToken)) {
+                subTokens.add(CommandUtil.trimQuotes(subToken));
+            }
         }
         return subTokens;
     }
diff --git a/src/main/java/org/apache/sling/pipes/internal/CommandUtil.java b/src/main/java/org/apache/sling/pipes/internal/CommandUtil.java
index 527e5d7..dd0799d 100644
--- a/src/main/java/org/apache/sling/pipes/internal/CommandUtil.java
+++ b/src/main/java/org/apache/sling/pipes/internal/CommandUtil.java
@@ -40,6 +40,8 @@ public class CommandUtil {
     static final String FIRST_KEY = "first";
     static final String SECOND_KEY = "second";
     static final String PN_JCR_MIXIN = "jcr:mixinTypes";
+
+    static final String QUOTE = "\"";
     static final Pattern MIXINS_ARRAY_PATTERN = Pattern.compile("^\\s*\\[(.*)\\]\\s*$");
     private static final Pattern UNEMBEDDEDSCRIPT_PATTERN = Pattern.compile("^(\\d+(\\.\\d+)?)|" + //21.42
             "\\[.*]$|" + //['one','two']
@@ -122,6 +124,17 @@ public class CommandUtil {
         return map;
     }
 
+    /**
+     * @param quotedString non null string with or without quotes
+     * @return if the string is wrapped with <code>"</code>, strip them away, otherwise return same string
+     */
+    public static String trimQuotes(@NotNull String quotedString) {
+        if (quotedString.startsWith(QUOTE) && quotedString.endsWith(QUOTE)) {
+            return quotedString.substring(1, quotedString.length() - 1);
+        }
+        return quotedString;
+    }
+
     /**
      * @param o list of key value strings key1=value1,key2=value2,...
      * @return String [] key1,value1,key2,value2,... corresponding to the pipe builder API
@@ -132,8 +145,8 @@ public class CommandUtil {
             for (String pair : o) {
                 Matcher matcher = CONFIGURATION_PATTERN.matcher(pair.trim());
                 if (matcher.matches()) {
-                    args.add(matcher.group(FIRST_KEY));
-                    args.add(matcher.group(SECOND_KEY));
+                    args.add(trimQuotes(matcher.group(FIRST_KEY)));
+                    args.add(trimQuotes(matcher.group(SECOND_KEY)));
                 }
             }
         }
diff --git a/src/test/java/org/apache/sling/pipes/PipeBuilderTest.java b/src/test/java/org/apache/sling/pipes/PipeBuilderTest.java
index 045a319..ea91e18 100644
--- a/src/test/java/org/apache/sling/pipes/PipeBuilderTest.java
+++ b/src/test/java/org/apache/sling/pipes/PipeBuilderTest.java
@@ -21,6 +21,8 @@ import org.apache.sling.pipes.internal.JsonUtil;
 import org.junit.Test;
 
 import javax.json.JsonObject;
+
+import java.lang.reflect.InvocationTargetException;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.HashMap;
@@ -97,6 +99,12 @@ public class PipeBuilderTest extends AbstractPipeTest {
             assertEquals("written path should be the same as actual path", path, writtenPath);
         }
     }
+    @Test
+    public void whitespaces() throws InvocationTargetException, IllegalAccessException {
+        execute("echo /content/fruits | write jcr:title=\"white space\"");
+        assertEquals("property should have been written correctly",
+                "white space", context.resourceResolver().getResource(PATH_FRUITS).getValueMap().get("jcr:title"));
+    }
 
     @Test
     public void additionalBindings() throws Exception {
diff --git a/src/test/java/org/apache/sling/pipes/internal/CommandExecutorImplTest.java b/src/test/java/org/apache/sling/pipes/internal/CommandExecutorImplTest.java
index 0c37edf..cdaec07 100644
--- a/src/test/java/org/apache/sling/pipes/internal/CommandExecutorImplTest.java
+++ b/src/test/java/org/apache/sling/pipes/internal/CommandExecutorImplTest.java
@@ -301,6 +301,18 @@ public class CommandExecutorImplTest extends AbstractPipeTest {
         assertDeclBinding("binding csvStart =", "csvStart", "");
     }
 
+
+    void assertSpaceSeparatedTokens(String input, String... tokens) {
+        assertArrayEquals(tokens,  commands.getSpaceSeparatedTokens(input).toArray());
+    }
+    @Test
+    public void getSpaceSeparatedToken() {
+        assertSpaceSeparatedTokens("rm","rm");
+        assertSpaceSeparatedTokens("write foo=bar a=b", "write", "foo=bar", "a=b");
+        assertSpaceSeparatedTokens("check \"foo bar\"", "check", "foo bar");
+        assertSpaceSeparatedTokens("write prop=\"foo bar\"","write", "prop=\"foo bar\"");
+    }
+
     @Test
     public void testDeclaredBindingBasedInit() throws ServletException, IOException {
         JsonObject response = executeFile("declbasedinit");
diff --git a/src/test/java/org/apache/sling/pipes/internal/CommandUtilTest.java b/src/test/java/org/apache/sling/pipes/internal/CommandUtilTest.java
index eaaf336..4eed460 100644
--- a/src/test/java/org/apache/sling/pipes/internal/CommandUtilTest.java
+++ b/src/test/java/org/apache/sling/pipes/internal/CommandUtilTest.java
@@ -19,18 +19,21 @@ package org.apache.sling.pipes.internal;
 import static org.apache.sling.pipes.internal.CommandUtil.CONFIGURATION_PATTERN;
 import static org.apache.sling.pipes.internal.CommandUtil.FIRST_KEY;
 import static org.apache.sling.pipes.internal.CommandUtil.SECOND_KEY;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
 
-import junit.framework.TestCase;
-
+import java.util.Arrays;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
+import org.apache.sling.pipes.AbstractPipeTest;
 import org.junit.Assert;
 import org.junit.Test;
 
-public class CommandUtilTest extends TestCase {
+public class CommandUtilTest extends AbstractPipeTest {
 
 
     private void assertMatch(Pattern pattern, String token, String first, String second) {
@@ -82,4 +85,16 @@ public class CommandUtilTest extends TestCase {
         assertEquals("${['one','two']}", map.get("p3"));
         Assert.assertArrayEquals(new String [] {"rep:versionable", "some:OtherMixin"}, (String[])map.get("jcr:mixinTypes"));
     }
+
+    @Test
+    public void testTrimQuotes() {
+        assertEquals("blah", CommandUtil.trimQuotes("\"blah\""));
+        assertEquals("blah", CommandUtil.trimQuotes("blah"));
+    }
+
+    @Test
+    public void testKeyValuesToArray() {
+        assertArrayEquals(new String[] {"foo","bar","another","with spaces "},
+                CommandUtil.keyValuesToArray(Arrays.asList("foo=bar","another=\"with spaces \"")));
+    }
 }
\ No newline at end of file