You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

StringUtils.java 11 kB

11 years ago
8 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324
  1. /*
  2. * Licensed to the Apache Software Foundation (ASF) under one or more
  3. * contributor license agreements. See the NOTICE file distributed with
  4. * this work for additional information regarding copyright ownership.
  5. * The ASF licenses this file to You under the Apache License, Version 2.0
  6. * (the "License"); you may not use this file except in compliance with
  7. * the License. You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. *
  17. */
  18. package org.apache.tools.ant.util;
  19. import java.io.PrintWriter;
  20. import java.io.StringWriter;
  21. import java.util.Arrays;
  22. import java.util.Collection;
  23. import java.util.Vector;
  24. import java.util.stream.Collector;
  25. import java.util.stream.Collectors;
  26. import org.apache.tools.ant.BuildException;
  27. /**
  28. * A set of helper methods related to string manipulation.
  29. *
  30. */
  31. public final class StringUtils {
  32. private static final long KILOBYTE = 1024;
  33. private static final long MEGABYTE = KILOBYTE * 1024;
  34. private static final long GIGABYTE = MEGABYTE * 1024;
  35. private static final long TERABYTE = GIGABYTE * 1024;
  36. private static final long PETABYTE = TERABYTE * 1024;
  37. /**
  38. * constructor to stop anyone instantiating the class
  39. */
  40. private StringUtils() {
  41. }
  42. /** the line separator for this OS */
  43. public static final String LINE_SEP = System.lineSeparator();
  44. /**
  45. * Splits up a string into a list of lines. It is equivalent
  46. * to <tt>split(data, '\n')</tt>.
  47. * @param data the string to split up into lines.
  48. * @return the list of lines available in the string.
  49. */
  50. public static Vector<String> lineSplit(String data) {
  51. return split(data, '\n');
  52. }
  53. /**
  54. * Splits up a string where elements are separated by a specific
  55. * character and return all elements.
  56. * @param data the string to split up.
  57. * @param ch the separator character.
  58. * @return the list of elements.
  59. */
  60. public static Vector<String> split(String data, int ch) {
  61. Vector<String> elems = new Vector<>();
  62. int pos = -1;
  63. int i = 0;
  64. while ((pos = data.indexOf(ch, i)) != -1) {
  65. String elem = data.substring(i, pos);
  66. elems.addElement(elem);
  67. i = pos + 1;
  68. }
  69. elems.addElement(data.substring(i));
  70. return elems;
  71. }
  72. /**
  73. * Replace occurrences into a string.
  74. * @param data the string to replace occurrences into
  75. * @param from the occurrence to replace.
  76. * @param to the occurrence to be used as a replacement.
  77. * @return the new string with replaced occurrences.
  78. * @deprecated Use {@link String#replace(CharSequence, CharSequence)} now.
  79. */
  80. @Deprecated
  81. public static String replace(String data, String from, String to) {
  82. return data.replace(from, to);
  83. }
  84. /**
  85. * Convenient method to retrieve the full stacktrace from a given exception.
  86. * @param t the exception to get the stacktrace from.
  87. * @return the stacktrace from the given exception.
  88. */
  89. public static String getStackTrace(Throwable t) {
  90. StringWriter sw = new StringWriter();
  91. PrintWriter pw = new PrintWriter(sw, true);
  92. t.printStackTrace(pw); //NOSONAR
  93. pw.flush();
  94. pw.close();
  95. return sw.toString();
  96. }
  97. /**
  98. * Checks that a string buffer ends up with a given string. It may sound
  99. * trivial with the existing
  100. * JDK API but the various implementation among JDKs can make those
  101. * methods extremely resource intensive
  102. * and perform poorly due to massive memory allocation and copying. See
  103. * @param buffer the buffer to perform the check on
  104. * @param suffix the suffix
  105. * @return <code>true</code> if the character sequence represented by the
  106. * argument is a suffix of the character sequence represented by
  107. * the StringBuffer object; <code>false</code> otherwise. Note that the
  108. * result will be <code>true</code> if the argument is the
  109. * empty string.
  110. */
  111. public static boolean endsWith(StringBuffer buffer, String suffix) {
  112. if (suffix.length() > buffer.length()) {
  113. return false;
  114. }
  115. // this loop is done on purpose to avoid memory allocation performance
  116. // problems on various JDKs
  117. // StringBuffer.lastIndexOf() was introduced in jdk 1.4 and
  118. // implementation is ok though does allocation/copying
  119. // StringBuffer.toString().endsWith() does massive memory
  120. // allocation/copying on JDK 1.5
  121. // See http://issues.apache.org/bugzilla/show_bug.cgi?id=37169
  122. int endIndex = suffix.length() - 1;
  123. int bufferIndex = buffer.length() - 1;
  124. while (endIndex >= 0) {
  125. if (buffer.charAt(bufferIndex) != suffix.charAt(endIndex)) {
  126. return false;
  127. }
  128. bufferIndex--;
  129. endIndex--;
  130. }
  131. return true;
  132. }
  133. /**
  134. * xml does not do "c" like interpretation of strings.
  135. * i.e. \n\r\t etc.
  136. * this method processes \n, \r, \t, \f, \\
  137. * also subs \s -&gt; " \n\r\t\f"
  138. * a trailing '\' will be ignored
  139. *
  140. * @param input raw string with possible embedded '\'s
  141. * @return converted string
  142. * @since Ant 1.7
  143. */
  144. public static String resolveBackSlash(String input) {
  145. StringBuilder b = new StringBuilder();
  146. boolean backSlashSeen = false;
  147. for (int i = 0; i < input.length(); ++i) {
  148. char c = input.charAt(i);
  149. if (!backSlashSeen) {
  150. if (c == '\\') {
  151. backSlashSeen = true;
  152. } else {
  153. b.append(c);
  154. }
  155. } else {
  156. switch (c) {
  157. case '\\':
  158. b.append('\\');
  159. break;
  160. case 'n':
  161. b.append('\n');
  162. break;
  163. case 'r':
  164. b.append('\r');
  165. break;
  166. case 't':
  167. b.append('\t');
  168. break;
  169. case 'f':
  170. b.append('\f');
  171. break;
  172. case 's':
  173. b.append(" \t\n\r\f");
  174. break;
  175. default:
  176. b.append(c);
  177. }
  178. backSlashSeen = false;
  179. }
  180. }
  181. return b.toString();
  182. }
  183. /**
  184. * Takes a human readable size representation eg 10K
  185. * a long value. Doesn't support 1.1K or other rational values.
  186. * @param humanSize the amount as a human readable string.
  187. * @return a long value representation
  188. * @throws Exception if there is a problem.
  189. * @since Ant 1.7
  190. */
  191. public static long parseHumanSizes(String humanSize) throws Exception { //NOSONAR
  192. long factor = 1L;
  193. char s = humanSize.charAt(0);
  194. switch (s) {
  195. case '+':
  196. humanSize = humanSize.substring(1);
  197. break;
  198. case '-':
  199. factor = -1L;
  200. humanSize = humanSize.substring(1);
  201. break;
  202. default:
  203. break;
  204. }
  205. //last character isn't a digit
  206. char c = humanSize.charAt(humanSize.length() - 1);
  207. if (!Character.isDigit(c)) {
  208. int trim = 1;
  209. switch (c) {
  210. case 'K':
  211. factor *= KILOBYTE;
  212. break;
  213. case 'M':
  214. factor *= MEGABYTE;
  215. break;
  216. case 'G':
  217. factor *= GIGABYTE;
  218. break;
  219. case 'T':
  220. factor *= TERABYTE;
  221. break;
  222. case 'P':
  223. factor *= PETABYTE;
  224. break;
  225. default:
  226. trim = 0;
  227. }
  228. humanSize = humanSize.substring(0, humanSize.length() - trim);
  229. }
  230. try {
  231. return factor * Long.parseLong(humanSize);
  232. } catch (NumberFormatException e) {
  233. throw new BuildException("Failed to parse \"" + humanSize + "\"", e);
  234. }
  235. }
  236. /**
  237. * Removes the suffix from a given string, if the string contains
  238. * that suffix.
  239. * @param string String for check
  240. * @param suffix Suffix to remove
  241. * @return the <i>string</i> with the <i>suffix</i>
  242. */
  243. public static String removeSuffix(String string, String suffix) {
  244. if (string.endsWith(suffix)) {
  245. return string.substring(0, string.length() - suffix.length());
  246. }
  247. return string;
  248. }
  249. /**
  250. * Removes the prefix from a given string, if the string contains
  251. * that prefix.
  252. * @param string String for check
  253. * @param prefix Prefix to remove
  254. * @return the <i>string</i> with the <i>prefix</i>
  255. */
  256. public static String removePrefix(String string, String prefix) {
  257. if (string.startsWith(prefix)) {
  258. return string.substring(prefix.length());
  259. }
  260. return string;
  261. }
  262. /**
  263. * Joins the string representation of the elements of a collection to
  264. * a joined string with a given separator.
  265. * @param collection Collection of the data to be joined (may be null)
  266. * @param separator Separator between elements (may be null)
  267. * @return the joined string
  268. */
  269. public static String join(Collection<?> collection, CharSequence separator) {
  270. if (collection == null) {
  271. return "";
  272. }
  273. return collection.stream().map(String::valueOf)
  274. .collect(joining(separator));
  275. }
  276. /**
  277. * Joins the string representation of the elements of an array to
  278. * a joined string with a given separator.
  279. * @param array Array of the data to be joined (may be null)
  280. * @param separator Separator between elements (may be null)
  281. * @return the joined string
  282. */
  283. public static String join(Object[] array, CharSequence separator) {
  284. if (array == null) {
  285. return "";
  286. }
  287. return join(Arrays.asList(array), separator);
  288. }
  289. private static Collector<CharSequence, ?, String> joining(CharSequence separator) {
  290. return separator == null ? Collectors.joining() : Collectors.joining(separator);
  291. }
  292. /**
  293. * @param inputString String to trim
  294. * @return null if the input string is null or empty or contain only empty spaces.
  295. * It returns the input string without leading and trailing spaces otherwise.
  296. *
  297. */
  298. public static String trimToNull(String inputString) {
  299. if (inputString == null) {
  300. return null;
  301. }
  302. String tmpString = inputString.trim();
  303. return tmpString.isEmpty() ? null : tmpString;
  304. }
  305. }