1 | /** |
---|
2 | * Licensed to the Apache Software Foundation (ASF) under one |
---|
3 | * or more contributor license agreements. See the NOTICE file |
---|
4 | * distributed with this work for additional information |
---|
5 | * regarding copyright ownership. The ASF licenses this file |
---|
6 | * to you under the Apache License, Version 2.0 (the |
---|
7 | * "License"); you may not use this file except in compliance |
---|
8 | * with the License. You may obtain a copy of the License at |
---|
9 | * |
---|
10 | * http://www.apache.org/licenses/LICENSE-2.0 |
---|
11 | * |
---|
12 | * Unless required by applicable law or agreed to in writing, software |
---|
13 | * distributed under the License is distributed on an "AS IS" BASIS, |
---|
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
---|
15 | * See the License for the specific language governing permissions and |
---|
16 | * limitations under the License. |
---|
17 | */ |
---|
18 | |
---|
19 | package org.apache.hadoop.util; |
---|
20 | |
---|
21 | import java.io.PrintWriter; |
---|
22 | import java.io.StringWriter; |
---|
23 | import java.net.InetAddress; |
---|
24 | import java.net.URI; |
---|
25 | import java.net.URISyntaxException; |
---|
26 | import java.net.UnknownHostException; |
---|
27 | import java.text.DateFormat; |
---|
28 | import java.text.DecimalFormat; |
---|
29 | import java.text.NumberFormat; |
---|
30 | import java.util.Locale; |
---|
31 | import java.util.ArrayList; |
---|
32 | import java.util.Arrays; |
---|
33 | import java.util.Date; |
---|
34 | import java.util.List; |
---|
35 | import java.util.StringTokenizer; |
---|
36 | import java.util.Collection; |
---|
37 | |
---|
38 | import org.apache.hadoop.fs.*; |
---|
39 | |
---|
40 | /** |
---|
41 | * General string utils |
---|
42 | */ |
---|
43 | public class StringUtils { |
---|
44 | |
---|
45 | private static final DecimalFormat decimalFormat; |
---|
46 | static { |
---|
47 | NumberFormat numberFormat = NumberFormat.getNumberInstance(Locale.ENGLISH); |
---|
48 | decimalFormat = (DecimalFormat) numberFormat; |
---|
49 | decimalFormat.applyPattern("#.##"); |
---|
50 | } |
---|
51 | |
---|
52 | /** |
---|
53 | * Make a string representation of the exception. |
---|
54 | * @param e The exception to stringify |
---|
55 | * @return A string with exception name and call stack. |
---|
56 | */ |
---|
57 | public static String stringifyException(Throwable e) { |
---|
58 | StringWriter stm = new StringWriter(); |
---|
59 | PrintWriter wrt = new PrintWriter(stm); |
---|
60 | e.printStackTrace(wrt); |
---|
61 | wrt.close(); |
---|
62 | return stm.toString(); |
---|
63 | } |
---|
64 | |
---|
65 | /** |
---|
66 | * Given a full hostname, return the word upto the first dot. |
---|
67 | * @param fullHostname the full hostname |
---|
68 | * @return the hostname to the first dot |
---|
69 | */ |
---|
70 | public static String simpleHostname(String fullHostname) { |
---|
71 | int offset = fullHostname.indexOf('.'); |
---|
72 | if (offset != -1) { |
---|
73 | return fullHostname.substring(0, offset); |
---|
74 | } |
---|
75 | return fullHostname; |
---|
76 | } |
---|
77 | |
---|
78 | private static DecimalFormat oneDecimal = new DecimalFormat("0.0"); |
---|
79 | |
---|
80 | /** |
---|
81 | * Given an integer, return a string that is in an approximate, but human |
---|
82 | * readable format. |
---|
83 | * It uses the bases 'k', 'm', and 'g' for 1024, 1024**2, and 1024**3. |
---|
84 | * @param number the number to format |
---|
85 | * @return a human readable form of the integer |
---|
86 | */ |
---|
87 | public static String humanReadableInt(long number) { |
---|
88 | long absNumber = Math.abs(number); |
---|
89 | double result = number; |
---|
90 | String suffix = ""; |
---|
91 | if (absNumber < 1024) { |
---|
92 | // nothing |
---|
93 | } else if (absNumber < 1024 * 1024) { |
---|
94 | result = number / 1024.0; |
---|
95 | suffix = "k"; |
---|
96 | } else if (absNumber < 1024 * 1024 * 1024) { |
---|
97 | result = number / (1024.0 * 1024); |
---|
98 | suffix = "m"; |
---|
99 | } else { |
---|
100 | result = number / (1024.0 * 1024 * 1024); |
---|
101 | suffix = "g"; |
---|
102 | } |
---|
103 | return oneDecimal.format(result) + suffix; |
---|
104 | } |
---|
105 | |
---|
106 | /** |
---|
107 | * Format a percentage for presentation to the user. |
---|
108 | * @param done the percentage to format (0.0 to 1.0) |
---|
109 | * @param digits the number of digits past the decimal point |
---|
110 | * @return a string representation of the percentage |
---|
111 | */ |
---|
112 | public static String formatPercent(double done, int digits) { |
---|
113 | DecimalFormat percentFormat = new DecimalFormat("0.00%"); |
---|
114 | double scale = Math.pow(10.0, digits+2); |
---|
115 | double rounded = Math.floor(done * scale); |
---|
116 | percentFormat.setDecimalSeparatorAlwaysShown(false); |
---|
117 | percentFormat.setMinimumFractionDigits(digits); |
---|
118 | percentFormat.setMaximumFractionDigits(digits); |
---|
119 | return percentFormat.format(rounded / scale); |
---|
120 | } |
---|
121 | |
---|
122 | /** |
---|
123 | * Given an array of strings, return a comma-separated list of its elements. |
---|
124 | * @param strs Array of strings |
---|
125 | * @return Empty string if strs.length is 0, comma separated list of strings |
---|
126 | * otherwise |
---|
127 | */ |
---|
128 | |
---|
129 | public static String arrayToString(String[] strs) { |
---|
130 | if (strs.length == 0) { return ""; } |
---|
131 | StringBuffer sbuf = new StringBuffer(); |
---|
132 | sbuf.append(strs[0]); |
---|
133 | for (int idx = 1; idx < strs.length; idx++) { |
---|
134 | sbuf.append(","); |
---|
135 | sbuf.append(strs[idx]); |
---|
136 | } |
---|
137 | return sbuf.toString(); |
---|
138 | } |
---|
139 | |
---|
140 | /** |
---|
141 | * Given an array of bytes it will convert the bytes to a hex string |
---|
142 | * representation of the bytes |
---|
143 | * @param bytes |
---|
144 | * @param start start index, inclusively |
---|
145 | * @param end end index, exclusively |
---|
146 | * @return hex string representation of the byte array |
---|
147 | */ |
---|
148 | public static String byteToHexString(byte[] bytes, int start, int end) { |
---|
149 | if (bytes == null) { |
---|
150 | throw new IllegalArgumentException("bytes == null"); |
---|
151 | } |
---|
152 | StringBuilder s = new StringBuilder(); |
---|
153 | for(int i = start; i < end; i++) { |
---|
154 | s.append(String.format("%02x", bytes[i])); |
---|
155 | } |
---|
156 | return s.toString(); |
---|
157 | } |
---|
158 | |
---|
159 | /** Same as byteToHexString(bytes, 0, bytes.length). */ |
---|
160 | public static String byteToHexString(byte bytes[]) { |
---|
161 | return byteToHexString(bytes, 0, bytes.length); |
---|
162 | } |
---|
163 | |
---|
164 | /** |
---|
165 | * Given a hexstring this will return the byte array corresponding to the |
---|
166 | * string |
---|
167 | * @param hex the hex String array |
---|
168 | * @return a byte array that is a hex string representation of the given |
---|
169 | * string. The size of the byte array is therefore hex.length/2 |
---|
170 | */ |
---|
171 | public static byte[] hexStringToByte(String hex) { |
---|
172 | byte[] bts = new byte[hex.length() / 2]; |
---|
173 | for (int i = 0; i < bts.length; i++) { |
---|
174 | bts[i] = (byte) Integer.parseInt(hex.substring(2 * i, 2 * i + 2), 16); |
---|
175 | } |
---|
176 | return bts; |
---|
177 | } |
---|
178 | /** |
---|
179 | * |
---|
180 | * @param uris |
---|
181 | */ |
---|
182 | public static String uriToString(URI[] uris){ |
---|
183 | if (uris == null) { |
---|
184 | return null; |
---|
185 | } |
---|
186 | StringBuffer ret = new StringBuffer(uris[0].toString()); |
---|
187 | for(int i = 1; i < uris.length;i++){ |
---|
188 | ret.append(","); |
---|
189 | ret.append(uris[i].toString()); |
---|
190 | } |
---|
191 | return ret.toString(); |
---|
192 | } |
---|
193 | |
---|
194 | /** |
---|
195 | * |
---|
196 | * @param str |
---|
197 | */ |
---|
198 | public static URI[] stringToURI(String[] str){ |
---|
199 | if (str == null) |
---|
200 | return null; |
---|
201 | URI[] uris = new URI[str.length]; |
---|
202 | for (int i = 0; i < str.length;i++){ |
---|
203 | try{ |
---|
204 | uris[i] = new URI(str[i]); |
---|
205 | }catch(URISyntaxException ur){ |
---|
206 | System.out.println("Exception in specified URI's " + StringUtils.stringifyException(ur)); |
---|
207 | //making sure its asssigned to null in case of an error |
---|
208 | uris[i] = null; |
---|
209 | } |
---|
210 | } |
---|
211 | return uris; |
---|
212 | } |
---|
213 | |
---|
214 | /** |
---|
215 | * |
---|
216 | * @param str |
---|
217 | */ |
---|
218 | public static Path[] stringToPath(String[] str){ |
---|
219 | if (str == null) { |
---|
220 | return null; |
---|
221 | } |
---|
222 | Path[] p = new Path[str.length]; |
---|
223 | for (int i = 0; i < str.length;i++){ |
---|
224 | p[i] = new Path(str[i]); |
---|
225 | } |
---|
226 | return p; |
---|
227 | } |
---|
228 | /** |
---|
229 | * |
---|
230 | * Given a finish and start time in long milliseconds, returns a |
---|
231 | * String in the format Xhrs, Ymins, Z sec, for the time difference between two times. |
---|
232 | * If finish time comes before start time then negative valeus of X, Y and Z wil return. |
---|
233 | * |
---|
234 | * @param finishTime finish time |
---|
235 | * @param startTime start time |
---|
236 | */ |
---|
237 | public static String formatTimeDiff(long finishTime, long startTime){ |
---|
238 | long timeDiff = finishTime - startTime; |
---|
239 | return formatTime(timeDiff); |
---|
240 | } |
---|
241 | |
---|
242 | /** |
---|
243 | * |
---|
244 | * Given the time in long milliseconds, returns a |
---|
245 | * String in the format Xhrs, Ymins, Z sec. |
---|
246 | * |
---|
247 | * @param timeDiff The time difference to format |
---|
248 | */ |
---|
249 | public static String formatTime(long timeDiff){ |
---|
250 | StringBuffer buf = new StringBuffer(); |
---|
251 | long hours = timeDiff / (60*60*1000); |
---|
252 | long rem = (timeDiff % (60*60*1000)); |
---|
253 | long minutes = rem / (60*1000); |
---|
254 | rem = rem % (60*1000); |
---|
255 | long seconds = rem / 1000; |
---|
256 | |
---|
257 | if (hours != 0){ |
---|
258 | buf.append(hours); |
---|
259 | buf.append("hrs, "); |
---|
260 | } |
---|
261 | if (minutes != 0){ |
---|
262 | buf.append(minutes); |
---|
263 | buf.append("mins, "); |
---|
264 | } |
---|
265 | // return "0sec if no difference |
---|
266 | buf.append(seconds); |
---|
267 | buf.append("sec"); |
---|
268 | return buf.toString(); |
---|
269 | } |
---|
270 | /** |
---|
271 | * Formats time in ms and appends difference (finishTime - startTime) |
---|
272 | * as returned by formatTimeDiff(). |
---|
273 | * If finish time is 0, empty string is returned, if start time is 0 |
---|
274 | * then difference is not appended to return value. |
---|
275 | * @param dateFormat date format to use |
---|
276 | * @param finishTime fnish time |
---|
277 | * @param startTime start time |
---|
278 | * @return formatted value. |
---|
279 | */ |
---|
280 | public static String getFormattedTimeWithDiff(DateFormat dateFormat, |
---|
281 | long finishTime, long startTime){ |
---|
282 | StringBuffer buf = new StringBuffer(); |
---|
283 | if (0 != finishTime) { |
---|
284 | buf.append(dateFormat.format(new Date(finishTime))); |
---|
285 | if (0 != startTime){ |
---|
286 | buf.append(" (" + formatTimeDiff(finishTime , startTime) + ")"); |
---|
287 | } |
---|
288 | } |
---|
289 | return buf.toString(); |
---|
290 | } |
---|
291 | |
---|
292 | /** |
---|
293 | * Returns an arraylist of strings. |
---|
294 | * @param str the comma seperated string values |
---|
295 | * @return the arraylist of the comma seperated string values |
---|
296 | */ |
---|
297 | public static String[] getStrings(String str){ |
---|
298 | Collection<String> values = getStringCollection(str); |
---|
299 | if(values.size() == 0) { |
---|
300 | return null; |
---|
301 | } |
---|
302 | return values.toArray(new String[values.size()]); |
---|
303 | } |
---|
304 | |
---|
305 | /** |
---|
306 | * Returns a collection of strings. |
---|
307 | * @param str comma seperated string values |
---|
308 | * @return an <code>ArrayList</code> of string values |
---|
309 | */ |
---|
310 | public static Collection<String> getStringCollection(String str){ |
---|
311 | List<String> values = new ArrayList<String>(); |
---|
312 | if (str == null) |
---|
313 | return values; |
---|
314 | StringTokenizer tokenizer = new StringTokenizer (str,","); |
---|
315 | values = new ArrayList<String>(); |
---|
316 | while (tokenizer.hasMoreTokens()) { |
---|
317 | values.add(tokenizer.nextToken()); |
---|
318 | } |
---|
319 | return values; |
---|
320 | } |
---|
321 | |
---|
322 | final public static char COMMA = ','; |
---|
323 | final public static String COMMA_STR = ","; |
---|
324 | final public static char ESCAPE_CHAR = '\\'; |
---|
325 | |
---|
326 | /** |
---|
327 | * Split a string using the default separator |
---|
328 | * @param str a string that may have escaped separator |
---|
329 | * @return an array of strings |
---|
330 | */ |
---|
331 | public static String[] split(String str) { |
---|
332 | return split(str, ESCAPE_CHAR, COMMA); |
---|
333 | } |
---|
334 | |
---|
335 | /** |
---|
336 | * Split a string using the given separator |
---|
337 | * @param str a string that may have escaped separator |
---|
338 | * @param escapeChar a char that be used to escape the separator |
---|
339 | * @param separator a separator char |
---|
340 | * @return an array of strings |
---|
341 | */ |
---|
342 | public static String[] split( |
---|
343 | String str, char escapeChar, char separator) { |
---|
344 | if (str==null) { |
---|
345 | return null; |
---|
346 | } |
---|
347 | ArrayList<String> strList = new ArrayList<String>(); |
---|
348 | StringBuilder split = new StringBuilder(); |
---|
349 | int index = 0; |
---|
350 | while ((index = findNext(str, separator, escapeChar, index, split)) >= 0) { |
---|
351 | ++index; // move over the separator for next search |
---|
352 | strList.add(split.toString()); |
---|
353 | split.setLength(0); // reset the buffer |
---|
354 | } |
---|
355 | strList.add(split.toString()); |
---|
356 | // remove trailing empty split(s) |
---|
357 | int last = strList.size(); // last split |
---|
358 | while (--last>=0 && "".equals(strList.get(last))) { |
---|
359 | strList.remove(last); |
---|
360 | } |
---|
361 | return strList.toArray(new String[strList.size()]); |
---|
362 | } |
---|
363 | |
---|
364 | /** |
---|
365 | * Finds the first occurrence of the separator character ignoring the escaped |
---|
366 | * separators starting from the index. Note the substring between the index |
---|
367 | * and the position of the separator is passed. |
---|
368 | * @param str the source string |
---|
369 | * @param separator the character to find |
---|
370 | * @param escapeChar character used to escape |
---|
371 | * @param start from where to search |
---|
372 | * @param split used to pass back the extracted string |
---|
373 | */ |
---|
374 | public static int findNext(String str, char separator, char escapeChar, |
---|
375 | int start, StringBuilder split) { |
---|
376 | int numPreEscapes = 0; |
---|
377 | for (int i = start; i < str.length(); i++) { |
---|
378 | char curChar = str.charAt(i); |
---|
379 | if (numPreEscapes == 0 && curChar == separator) { // separator |
---|
380 | return i; |
---|
381 | } else { |
---|
382 | split.append(curChar); |
---|
383 | numPreEscapes = (curChar == escapeChar) |
---|
384 | ? (++numPreEscapes) % 2 |
---|
385 | : 0; |
---|
386 | } |
---|
387 | } |
---|
388 | return -1; |
---|
389 | } |
---|
390 | |
---|
391 | /** |
---|
392 | * Escape commas in the string using the default escape char |
---|
393 | * @param str a string |
---|
394 | * @return an escaped string |
---|
395 | */ |
---|
396 | public static String escapeString(String str) { |
---|
397 | return escapeString(str, ESCAPE_CHAR, COMMA); |
---|
398 | } |
---|
399 | |
---|
400 | /** |
---|
401 | * Escape <code>charToEscape</code> in the string |
---|
402 | * with the escape char <code>escapeChar</code> |
---|
403 | * |
---|
404 | * @param str string |
---|
405 | * @param escapeChar escape char |
---|
406 | * @param charToEscape the char to be escaped |
---|
407 | * @return an escaped string |
---|
408 | */ |
---|
409 | public static String escapeString( |
---|
410 | String str, char escapeChar, char charToEscape) { |
---|
411 | return escapeString(str, escapeChar, new char[] {charToEscape}); |
---|
412 | } |
---|
413 | |
---|
414 | // check if the character array has the character |
---|
415 | private static boolean hasChar(char[] chars, char character) { |
---|
416 | for (char target : chars) { |
---|
417 | if (character == target) { |
---|
418 | return true; |
---|
419 | } |
---|
420 | } |
---|
421 | return false; |
---|
422 | } |
---|
423 | |
---|
424 | /** |
---|
425 | * @param charsToEscape array of characters to be escaped |
---|
426 | */ |
---|
427 | public static String escapeString(String str, char escapeChar, |
---|
428 | char[] charsToEscape) { |
---|
429 | if (str == null) { |
---|
430 | return null; |
---|
431 | } |
---|
432 | StringBuilder result = new StringBuilder(); |
---|
433 | for (int i=0; i<str.length(); i++) { |
---|
434 | char curChar = str.charAt(i); |
---|
435 | if (curChar == escapeChar || hasChar(charsToEscape, curChar)) { |
---|
436 | // special char |
---|
437 | result.append(escapeChar); |
---|
438 | } |
---|
439 | result.append(curChar); |
---|
440 | } |
---|
441 | return result.toString(); |
---|
442 | } |
---|
443 | |
---|
444 | /** |
---|
445 | * Unescape commas in the string using the default escape char |
---|
446 | * @param str a string |
---|
447 | * @return an unescaped string |
---|
448 | */ |
---|
449 | public static String unEscapeString(String str) { |
---|
450 | return unEscapeString(str, ESCAPE_CHAR, COMMA); |
---|
451 | } |
---|
452 | |
---|
453 | /** |
---|
454 | * Unescape <code>charToEscape</code> in the string |
---|
455 | * with the escape char <code>escapeChar</code> |
---|
456 | * |
---|
457 | * @param str string |
---|
458 | * @param escapeChar escape char |
---|
459 | * @param charToEscape the escaped char |
---|
460 | * @return an unescaped string |
---|
461 | */ |
---|
462 | public static String unEscapeString( |
---|
463 | String str, char escapeChar, char charToEscape) { |
---|
464 | return unEscapeString(str, escapeChar, new char[] {charToEscape}); |
---|
465 | } |
---|
466 | |
---|
467 | /** |
---|
468 | * @param charsToEscape array of characters to unescape |
---|
469 | */ |
---|
470 | public static String unEscapeString(String str, char escapeChar, |
---|
471 | char[] charsToEscape) { |
---|
472 | if (str == null) { |
---|
473 | return null; |
---|
474 | } |
---|
475 | StringBuilder result = new StringBuilder(str.length()); |
---|
476 | boolean hasPreEscape = false; |
---|
477 | for (int i=0; i<str.length(); i++) { |
---|
478 | char curChar = str.charAt(i); |
---|
479 | if (hasPreEscape) { |
---|
480 | if (curChar != escapeChar && !hasChar(charsToEscape, curChar)) { |
---|
481 | // no special char |
---|
482 | throw new IllegalArgumentException("Illegal escaped string " + str + |
---|
483 | " unescaped " + escapeChar + " at " + (i-1)); |
---|
484 | } |
---|
485 | // otherwise discard the escape char |
---|
486 | result.append(curChar); |
---|
487 | hasPreEscape = false; |
---|
488 | } else { |
---|
489 | if (hasChar(charsToEscape, curChar)) { |
---|
490 | throw new IllegalArgumentException("Illegal escaped string " + str + |
---|
491 | " unescaped " + curChar + " at " + i); |
---|
492 | } else if (curChar == escapeChar) { |
---|
493 | hasPreEscape = true; |
---|
494 | } else { |
---|
495 | result.append(curChar); |
---|
496 | } |
---|
497 | } |
---|
498 | } |
---|
499 | if (hasPreEscape ) { |
---|
500 | throw new IllegalArgumentException("Illegal escaped string " + str + |
---|
501 | ", not expecting " + escapeChar + " in the end." ); |
---|
502 | } |
---|
503 | return result.toString(); |
---|
504 | } |
---|
505 | |
---|
506 | /** |
---|
507 | * Return hostname without throwing exception. |
---|
508 | * @return hostname |
---|
509 | */ |
---|
510 | public static String getHostname() { |
---|
511 | try {return "" + InetAddress.getLocalHost();} |
---|
512 | catch(UnknownHostException uhe) {return "" + uhe;} |
---|
513 | } |
---|
514 | |
---|
515 | /** |
---|
516 | * Return a message for logging. |
---|
517 | * @param prefix prefix keyword for the message |
---|
518 | * @param msg content of the message |
---|
519 | * @return a message for logging |
---|
520 | */ |
---|
521 | private static String toStartupShutdownString(String prefix, String [] msg) { |
---|
522 | StringBuffer b = new StringBuffer(prefix); |
---|
523 | b.append("\n/************************************************************"); |
---|
524 | for(String s : msg) |
---|
525 | b.append("\n" + prefix + s); |
---|
526 | b.append("\n************************************************************/"); |
---|
527 | return b.toString(); |
---|
528 | } |
---|
529 | |
---|
530 | /** |
---|
531 | * Print a log message for starting up and shutting down |
---|
532 | * @param clazz the class of the server |
---|
533 | * @param args arguments |
---|
534 | * @param LOG the target log object |
---|
535 | */ |
---|
536 | public static void startupShutdownMessage(Class<?> clazz, String[] args, |
---|
537 | final org.apache.commons.logging.Log LOG) { |
---|
538 | final String hostname = getHostname(); |
---|
539 | final String classname = clazz.getSimpleName(); |
---|
540 | LOG.info( |
---|
541 | toStartupShutdownString("STARTUP_MSG: ", new String[] { |
---|
542 | "Starting " + classname, |
---|
543 | " host = " + hostname, |
---|
544 | " args = " + Arrays.asList(args), |
---|
545 | " version = " + VersionInfo.getVersion(), |
---|
546 | " build = " + VersionInfo.getUrl() + " -r " |
---|
547 | + VersionInfo.getRevision() |
---|
548 | + "; compiled by '" + VersionInfo.getUser() |
---|
549 | + "' on " + VersionInfo.getDate()} |
---|
550 | ) |
---|
551 | ); |
---|
552 | |
---|
553 | Runtime.getRuntime().addShutdownHook(new Thread() { |
---|
554 | public void run() { |
---|
555 | LOG.info(toStartupShutdownString("SHUTDOWN_MSG: ", new String[]{ |
---|
556 | "Shutting down " + classname + " at " + hostname})); |
---|
557 | } |
---|
558 | }); |
---|
559 | } |
---|
560 | |
---|
561 | /** |
---|
562 | * The traditional binary prefixes, kilo, mega, ..., exa, |
---|
563 | * which can be represented by a 64-bit integer. |
---|
564 | * TraditionalBinaryPrefix symbol are case insensitive. |
---|
565 | */ |
---|
566 | public static enum TraditionalBinaryPrefix { |
---|
567 | KILO(1024), |
---|
568 | MEGA(KILO.value << 10), |
---|
569 | GIGA(MEGA.value << 10), |
---|
570 | TERA(GIGA.value << 10), |
---|
571 | PETA(TERA.value << 10), |
---|
572 | EXA(PETA.value << 10); |
---|
573 | |
---|
574 | public final long value; |
---|
575 | public final char symbol; |
---|
576 | |
---|
577 | TraditionalBinaryPrefix(long value) { |
---|
578 | this.value = value; |
---|
579 | this.symbol = toString().charAt(0); |
---|
580 | } |
---|
581 | |
---|
582 | /** |
---|
583 | * @return The TraditionalBinaryPrefix object corresponding to the symbol. |
---|
584 | */ |
---|
585 | public static TraditionalBinaryPrefix valueOf(char symbol) { |
---|
586 | symbol = Character.toUpperCase(symbol); |
---|
587 | for(TraditionalBinaryPrefix prefix : TraditionalBinaryPrefix.values()) { |
---|
588 | if (symbol == prefix.symbol) { |
---|
589 | return prefix; |
---|
590 | } |
---|
591 | } |
---|
592 | throw new IllegalArgumentException("Unknown symbol '" + symbol + "'"); |
---|
593 | } |
---|
594 | |
---|
595 | /** |
---|
596 | * Convert a string to long. |
---|
597 | * The input string is first be trimmed |
---|
598 | * and then it is parsed with traditional binary prefix. |
---|
599 | * |
---|
600 | * For example, |
---|
601 | * "-1230k" will be converted to -1230 * 1024 = -1259520; |
---|
602 | * "891g" will be converted to 891 * 1024^3 = 956703965184; |
---|
603 | * |
---|
604 | * @param s input string |
---|
605 | * @return a long value represented by the input string. |
---|
606 | */ |
---|
607 | public static long string2long(String s) { |
---|
608 | s = s.trim(); |
---|
609 | final int lastpos = s.length() - 1; |
---|
610 | final char lastchar = s.charAt(lastpos); |
---|
611 | if (Character.isDigit(lastchar)) |
---|
612 | return Long.parseLong(s); |
---|
613 | else { |
---|
614 | long prefix = TraditionalBinaryPrefix.valueOf(lastchar).value; |
---|
615 | long num = Long.parseLong(s.substring(0, lastpos)); |
---|
616 | if (num > (Long.MAX_VALUE/prefix) || num < (Long.MIN_VALUE/prefix)) { |
---|
617 | throw new IllegalArgumentException(s + " does not fit in a Long"); |
---|
618 | } |
---|
619 | return num * prefix; |
---|
620 | } |
---|
621 | } |
---|
622 | } |
---|
623 | |
---|
624 | /** |
---|
625 | * Escapes HTML Special characters present in the string. |
---|
626 | * @param string |
---|
627 | * @return HTML Escaped String representation |
---|
628 | */ |
---|
629 | public static String escapeHTML(String string) { |
---|
630 | if(string == null) { |
---|
631 | return null; |
---|
632 | } |
---|
633 | StringBuffer sb = new StringBuffer(); |
---|
634 | boolean lastCharacterWasSpace = false; |
---|
635 | char[] chars = string.toCharArray(); |
---|
636 | for(char c : chars) { |
---|
637 | if(c == ' ') { |
---|
638 | if(lastCharacterWasSpace){ |
---|
639 | lastCharacterWasSpace = false; |
---|
640 | sb.append(" "); |
---|
641 | }else { |
---|
642 | lastCharacterWasSpace=true; |
---|
643 | sb.append(" "); |
---|
644 | } |
---|
645 | }else { |
---|
646 | lastCharacterWasSpace = false; |
---|
647 | switch(c) { |
---|
648 | case '<': sb.append("<"); break; |
---|
649 | case '>': sb.append(">"); break; |
---|
650 | case '&': sb.append("&"); break; |
---|
651 | case '"': sb.append("""); break; |
---|
652 | default : sb.append(c);break; |
---|
653 | } |
---|
654 | } |
---|
655 | } |
---|
656 | |
---|
657 | return sb.toString(); |
---|
658 | } |
---|
659 | |
---|
660 | /** |
---|
661 | * Return an abbreviated English-language desc of the byte length |
---|
662 | */ |
---|
663 | public static String byteDesc(long len) { |
---|
664 | double val = 0.0; |
---|
665 | String ending = ""; |
---|
666 | if (len < 1024 * 1024) { |
---|
667 | val = (1.0 * len) / 1024; |
---|
668 | ending = " KB"; |
---|
669 | } else if (len < 1024 * 1024 * 1024) { |
---|
670 | val = (1.0 * len) / (1024 * 1024); |
---|
671 | ending = " MB"; |
---|
672 | } else if (len < 1024L * 1024 * 1024 * 1024) { |
---|
673 | val = (1.0 * len) / (1024 * 1024 * 1024); |
---|
674 | ending = " GB"; |
---|
675 | } else if (len < 1024L * 1024 * 1024 * 1024 * 1024) { |
---|
676 | val = (1.0 * len) / (1024L * 1024 * 1024 * 1024); |
---|
677 | ending = " TB"; |
---|
678 | } else { |
---|
679 | val = (1.0 * len) / (1024L * 1024 * 1024 * 1024 * 1024); |
---|
680 | ending = " PB"; |
---|
681 | } |
---|
682 | return limitDecimalTo2(val) + ending; |
---|
683 | } |
---|
684 | |
---|
685 | public static synchronized String limitDecimalTo2(double d) { |
---|
686 | return decimalFormat.format(d); |
---|
687 | } |
---|
688 | } |
---|