commons-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From chtom...@apache.org
Subject [1/2] [text] TEXT-28: Add XSI escape/unescape support
Date Thu, 15 Dec 2016 17:53:43 GMT
Repository: commons-text
Updated Branches:
  refs/heads/master 5cdb77906 -> 56eef1f88


TEXT-28: Add XSI escape/unescape support


Project: http://git-wip-us.apache.org/repos/asf/commons-text/repo
Commit: http://git-wip-us.apache.org/repos/asf/commons-text/commit/6b0ff8df
Tree: http://git-wip-us.apache.org/repos/asf/commons-text/tree/6b0ff8df
Diff: http://git-wip-us.apache.org/repos/asf/commons-text/diff/6b0ff8df

Branch: refs/heads/master
Commit: 6b0ff8df40c1e65598ca43a62815c410095ecae1
Parents: 5cdb779
Author: Rob Tompkins <chtompki@gmail.com>
Authored: Thu Dec 15 09:26:41 2016 -0500
Committer: Rob Tompkins <chtompki@gmail.com>
Committed: Thu Dec 15 09:26:41 2016 -0500

----------------------------------------------------------------------
 .../apache/commons/text/StringEscapeUtils.java  | 109 +++++++++++++++++++
 .../commons/text/StringEscapeUtilsTest.java     |  20 ++++
 2 files changed, 129 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/commons-text/blob/6b0ff8df/src/main/java/org/apache/commons/text/StringEscapeUtils.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/text/StringEscapeUtils.java b/src/main/java/org/apache/commons/text/StringEscapeUtils.java
index 6b88275..7866566 100644
--- a/src/main/java/org/apache/commons/text/StringEscapeUtils.java
+++ b/src/main/java/org/apache/commons/text/StringEscapeUtils.java
@@ -279,6 +279,39 @@ public class StringEscapeUtils {
         }
     }
 
+    /**
+     * Translator object for escaping Shell command language.
+     *
+     * @see <a href="http://pubs.opengroup.org/onlinepubs/7908799/xcu/chap2.html">Shell
Command Language</a>
+     */
+    public static final CharSequenceTranslator ESCAPE_XSI =
+        new LookupTranslator(
+            new String[][] {
+                    {"|", "\\|"},
+                    {"&", "\\&"},
+                    {";", "\\;"},
+                    {"<", "\\<"},
+                    {">", "\\>"},
+                    {"(", "\\("},
+                    {")", "\\)"},
+                    {"$", "\\$"},
+                    {"`", "\\`"},
+                    {"\\", "\\\\"},
+                    {"\"", "\\\""},
+                    {"'", "\\'"},
+                    {" ", "\\ "},
+                    {"\t", "\\\t"},
+                    {"\r\n", ""},
+                    {"\n", ""},
+                    {"*", "\\*"},
+                    {"?", "\\?"},
+                    {"[", "\\["},
+                    {"#", "\\#"},
+                    {"~", "\\~"},
+                    {"=", "\\="},
+                    {"%", "\\%"},
+            });
+
     /* UNESCAPE TRANSLATORS */
 
     /**
@@ -420,6 +453,47 @@ public class StringEscapeUtils {
         }
     }
 
+    public static final CharSequenceTranslator UNESCAPE_XSI = new XsiUnescaper();
+
+    /**
+     * Translator object for unescaping backslash escaped entries.
+     *
+     * @since 3.6
+     */
+    static class XsiUnescaper extends CharSequenceTranslator {
+
+        private static final char BACKSLASH = '\\';
+
+        @Override
+        public int translate(final CharSequence input, final int index, final Writer out)
throws IOException {
+
+            if(index != 0) {
+                throw new IllegalStateException("XsiUnescaper should never reach the [1]
index");
+            }
+
+            String s = input.toString();
+
+            int segmentStart = 0;
+            int searchOffset = 0;
+            while (true) {
+                int pos = s.indexOf(BACKSLASH, searchOffset);
+                if (pos == -1) {
+                    if (segmentStart < s.length()) {
+                        out.write(s.substring(segmentStart));
+                    }
+                    break;
+                }
+                if (pos > segmentStart) {
+                    out.write(s.substring(segmentStart, pos));
+                }
+                segmentStart = pos + 1;
+                searchOffset = pos + 2;
+            }
+
+            return Character.codePointCount(input, 0, input.length());
+        }
+    }
+
     /* Helper functions */
 
     /**
@@ -808,4 +882,39 @@ public class StringEscapeUtils {
         return UNESCAPE_CSV.translate(input);
     }
 
+    // Shell
+    /**
+     * <p>Escapes the characters in a {@code String} using XSI rules.</p>
+     *
+     * <p><b>Beware!</b> In most cases you don't want to escape shell commands
but use multi-argument
+     * methods provided by {@link java.lang.ProcessBuilder} or {@link java.lang.Runtime#exec(String[])}
+     * instead.</p>
+     *
+     * <p>Example:</p>
+     * <pre>
+     * input string: He didn't say, "Stop!"
+     * output string: He\ didn\'t\ say,\ \"Stop!\"
+     * </pre>
+     *
+     * @see <a href="http://pubs.opengroup.org/onlinepubs/7908799/xcu/chap2.html">Shell
Command Language</a>
+     * @param input  String to escape values in, may be null
+     * @return String with escaped values, {@code null} if null string input
+     * @since 3.6
+     */
+    public static final String escapeXSI(final String input) {
+        return ESCAPE_XSI.translate(input);
+    }
+
+    /**
+     * <p>Unescapes the characters in a {@code String} using XSI rules.</p>
+     *
+     * @see StringEscapeUtils#escapeXSI(String)
+     * @param input  the {@code String} to unescape, may be null
+     * @return a new unescaped {@code String}, {@code null} if null string input
+     * @since 3.6
+     */
+    public static final String unescapeXSI(final String input) {
+        return UNESCAPE_XSI.translate(input);
+    }
+
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/commons-text/blob/6b0ff8df/src/test/java/org/apache/commons/text/StringEscapeUtilsTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/commons/text/StringEscapeUtilsTest.java b/src/test/java/org/apache/commons/text/StringEscapeUtilsTest.java
index 4700cde..e5fd3a0 100644
--- a/src/test/java/org/apache/commons/text/StringEscapeUtilsTest.java
+++ b/src/test/java/org/apache/commons/text/StringEscapeUtilsTest.java
@@ -16,9 +16,12 @@
  */
 package org.apache.commons.text;
 
+import static org.apache.commons.text.StringEscapeUtils.escapeXSI;
+import static org.apache.commons.text.StringEscapeUtils.unescapeXSI;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
@@ -618,4 +621,21 @@ public class StringEscapeUtilsTest {
         assertEquals(expected, StringEscapeUtils.escapeJson(input));
     }
 
+    @Test
+    public void testEscapeXSI() {
+        assertNull(null, escapeXSI(null));
+        assertEquals("He\\ didn\\'t\\ say,\\ \\\"Stop!\\\"", escapeXSI("He didn't say, \"Stop!\""));
+        assertEquals("\\\\", escapeXSI("\\"));
+        assertEquals("", escapeXSI("\n"));
+    }
+
+    @Test
+    public void testUnscapeXSI() {
+        assertNull(null, unescapeXSI(null));
+        assertEquals("\"", unescapeXSI("\\\""));
+        assertEquals("He didn't say, \"Stop!\"", unescapeXSI("He\\ didn\\'t\\ say,\\ \\\"Stop!\\\""));
+        assertEquals("\\", unescapeXSI("\\\\"));
+        assertEquals("", unescapeXSI("\\"));
+    }
+
 }
\ No newline at end of file


Mime
View raw message