View Javadoc
1   package com.atlassian.sal.core.pluginsettings;
2   
3   import java.io.IOException;
4   import java.io.StringWriter;
5   import java.io.Writer;
6   
7   /**
8    * Escape utility methods which only escapes VERTICAL_TAB and NEW_LINE.
9    *
10   * The escape logic is custom made here instead of using StringEscapeUtils in apache common since
11   * we don't want to interfere with other special characters that we don't use in {@link AbstractStringPluginSettings}.
12   *
13   * For example, in that case if the data read from the backing store is "this is \\me", we're not sure whether
14   * it's escaped or non-escaped.
15   *
16   * @since 2.2.0
17   */
18  class EscapeUtils {
19      // Not for instantiation.
20      private EscapeUtils() {
21      }
22  
23      protected static final char VERTICAL_TAB = '\f';
24      protected static final char NEW_LINE = '\n';
25  
26      /**
27       * This only escapes VERTICAL_TAB and NEW_LINE.
28       */
29      protected static String escape(String str) {
30          if (str == null) {
31              return null;
32          }
33  
34          StringWriter writer = new StringWriter(str.length() * 2);
35          try {
36              escape(writer, str);
37          } catch (IOException e) {
38              throw new RuntimeException("exception while writing to StringWriter (should be impossible in this context)", e);
39          }
40  
41          return writer.toString();
42      }
43  
44      private static void escape(Writer out, String str) throws IOException {
45          int len = str.length();
46          for (int i = 0; i < len; i++) {
47              char ch = str.charAt(i);
48  
49              if (ch == VERTICAL_TAB) {
50                  out.write('\\');
51                  out.write('f');
52              } else if (ch == NEW_LINE) {
53                  out.write('\\');
54                  out.write('n');
55              } else if (ch == '\\') {
56                  out.write('\\');
57                  out.write('\\');
58              } else {
59                  out.write(ch);
60              }
61          }
62      }
63  
64      public static String unescape(String str) {
65          if (str == null) {
66              return null;
67          }
68          try {
69              StringWriter writer = new StringWriter(str.length());
70              unescape(writer, str);
71              return writer.toString();
72          } catch (IOException e) {
73              throw new RuntimeException("exception while writing to StringWriter (should be impossible in this context)", e);
74          }
75      }
76  
77      private static void unescape(Writer out, String str) throws IOException {
78          int len = str.length();
79          boolean hadSlash = false;
80  
81          for (int i = 0; i < len; i++) {
82              char ch = str.charAt(i);
83              if (hadSlash) {
84                  switch (ch) {
85                      case 'f':
86                          out.write('\f');
87                          break;
88                      case 'n':
89                          out.write('\n');
90                          break;
91                      default:
92                          out.write(ch);
93                          break;
94                  }
95                  // the slash is taken care of.
96                  hadSlash = false;
97                  continue;
98              } else if (ch == '\\') {
99                  hadSlash = true;
100                 continue;
101             }
102             out.write(ch);
103         }
104         // the the slash is the last character, then just give it out.
105         if (hadSlash) {
106             out.write('\\');
107         }
108     }
109 }