1 31 32 package org.opencms.util; 33 34 import org.opencms.file.CmsResource; 35 import org.opencms.i18n.CmsEncoder; 36 import org.opencms.i18n.I_CmsMessageBundle; 37 import org.opencms.main.CmsIllegalArgumentException; 38 import org.opencms.main.CmsLog; 39 40 import java.awt.Color ; 41 import java.nio.charset.Charset ; 42 import java.util.ArrayList ; 43 import java.util.HashMap ; 44 import java.util.Iterator ; 45 import java.util.List ; 46 import java.util.Map ; 47 import java.util.regex.Matcher ; 48 import java.util.regex.Pattern ; 49 50 import org.apache.commons.logging.Log; 51 import org.apache.oro.text.perl.MalformedPerl5PatternException; 52 import org.apache.oro.text.perl.Perl5Util; 53 54 65 public final class CmsStringUtil { 66 67 68 public static final String BODY_END_REGEX = "<\\s*/\\s*body[^>]*>"; 69 70 71 public static final String BODY_START_REGEX = "<\\s*body[^>]*>"; 72 73 74 public static final String FALSE = Boolean.toString(false); 75 76 77 public static final String LINE_SEPARATOR = System.getProperty("line.separator"); 78 79 80 public static final String MACRO_OPENCMS_CONTEXT = "${OpenCmsContext}"; 81 82 83 public static final String TABULATOR = " "; 84 85 86 public static final String TRUE = Boolean.toString(true); 87 88 89 private static final Pattern BODY_END_PATTERN = Pattern.compile(BODY_END_REGEX, Pattern.CASE_INSENSITIVE); 90 91 92 private static final Pattern BODY_START_PATTERN = Pattern.compile(BODY_START_REGEX, Pattern.CASE_INSENSITIVE); 93 94 95 private static final long DAYS = 1000 * 60 * 60 * 24; 96 97 98 private static final long HOURS = 1000 * 60 * 60; 99 100 101 private static final Log LOG = CmsLog.getLog(CmsStringUtil.class); 102 103 104 private static String m_contextReplace; 105 106 107 private static String m_contextSearch; 108 109 110 private static final long MINUTES = 1000 * 60; 111 112 113 private static final long SECONDS = 1000; 114 115 116 private static final Pattern XML_ENCODING_REGEX = Pattern.compile( 117 "encoding\\s*=\\s*[\"'].+[\"']", 118 Pattern.CASE_INSENSITIVE); 119 120 121 private static final Pattern XML_HEAD_REGEX = Pattern.compile("<\\s*\\?.*\\?\\s*>", Pattern.CASE_INSENSITIVE); 122 123 127 private CmsStringUtil() { 128 129 } 131 132 139 public static String changeFileNameSuffixTo(String filename, String suffix) { 140 141 int dotPos = filename.lastIndexOf('.'); 142 if (dotPos != -1) { 143 return filename.substring(0, dotPos + 1) + suffix; 144 } else { 145 return filename; 147 } 148 } 149 150 168 public static void checkName(String name, String contraints, String key, I_CmsMessageBundle bundle) 169 throws CmsIllegalArgumentException { 170 171 int l = name.length(); 172 for (int i = 0; i < l; i++) { 173 char c = name.charAt(i); 174 if (((c < 'a') || (c > 'z')) 175 && ((c < '0') || (c > '9')) 176 && ((c < 'A') || (c > 'Z')) 177 && (contraints.indexOf(c) < 0)) { 178 179 throw new CmsIllegalArgumentException(bundle.container(key, new Object [] { 180 name, 181 new Character (c), 182 new Integer (i), 183 contraints})); 184 } 185 } 186 } 187 188 198 public static String escapeHtml(String source) { 199 200 if (source == null) { 201 return null; 202 } 203 source = CmsEncoder.escapeXml(source); 204 source = CmsStringUtil.substitute(source, "\r", ""); 205 source = CmsStringUtil.substitute(source, "\n", "<br/>\n"); 206 return source; 207 } 208 209 217 public static String escapeJavaScript(String source) { 218 219 source = CmsStringUtil.substitute(source, "\\", "\\\\"); 220 source = CmsStringUtil.substitute(source, "\"", "\\\""); 221 source = CmsStringUtil.substitute(source, "\'", "\\\'"); 222 source = CmsStringUtil.substitute(source, "\r\n", "\\n"); 223 source = CmsStringUtil.substitute(source, "\n", "\\n"); 224 return source; 225 } 226 227 237 public static String escapePattern(String source) { 238 239 if (source == null) { 240 return null; 241 } 242 StringBuffer result = new StringBuffer (source.length() * 2); 243 for (int i = 0; i < source.length(); ++i) { 244 char ch = source.charAt(i); 245 switch (ch) { 246 case '\\': 247 result.append("\\\\"); 248 break; 249 case '/': 250 result.append("\\/"); 251 break; 252 case '$': 253 result.append("\\$"); 254 break; 255 case '^': 256 result.append("\\^"); 257 break; 258 case '.': 259 result.append("\\."); 260 break; 261 case '*': 262 result.append("\\*"); 263 break; 264 case '+': 265 result.append("\\+"); 266 break; 267 case '|': 268 result.append("\\|"); 269 break; 270 case '?': 271 result.append("\\?"); 272 break; 273 case '{': 274 result.append("\\{"); 275 break; 276 case '}': 277 result.append("\\}"); 278 break; 279 case '[': 280 result.append("\\["); 281 break; 282 case ']': 283 result.append("\\]"); 284 break; 285 case '(': 286 result.append("\\("); 287 break; 288 case ')': 289 result.append("\\)"); 290 break; 291 default: 292 result.append(ch); 293 } 294 } 295 return new String (result); 296 } 297 298 312 public static Map extendAttribute(String text, String attribute, String defValue) { 313 314 Map retValue = new HashMap (); 315 retValue.put("text", text); 316 retValue.put("value", "'" + defValue + "'"); 317 if (text != null && text.toLowerCase().indexOf(attribute.toLowerCase()) >= 0) { 318 String quotation = "\'"; 320 int pos1 = text.toLowerCase().indexOf(attribute.toLowerCase()); 321 int pos2 = text.indexOf(quotation, pos1); 323 int test = text.indexOf("\"", pos1); 324 if (test > -1 && (pos2 == -1 || test < pos2)) { 325 quotation = "\""; 326 pos2 = test; 327 } 328 int pos3 = text.indexOf(quotation, pos2 + 1); 330 String newValue = quotation + defValue + text.substring(pos2 + 1, pos3 + 1); 332 String newText = text.substring(0, pos1); 334 if (pos3 < text.length()) { 335 newText += text.substring(pos3 + 1); 336 } 337 retValue.put("text", newText); 338 retValue.put("value", newValue); 339 } 340 return retValue; 341 } 342 343 352 public static String extractHtmlBody(String content) { 353 354 Matcher startMatcher = BODY_START_PATTERN.matcher(content); 355 Matcher endMatcher = BODY_END_PATTERN.matcher(content); 356 357 int start = 0; 358 int end = content.length(); 359 360 if (startMatcher.find()) { 361 start = startMatcher.end(); 362 } 363 364 if (endMatcher.find(start)) { 365 end = endMatcher.start(); 366 } 367 368 return content.substring(start, end); 369 } 370 371 388 public static String extractXmlEncoding(String content) { 389 390 String result = null; 391 Matcher xmlHeadMatcher = XML_HEAD_REGEX.matcher(content); 392 if (xmlHeadMatcher.find()) { 393 String xmlHead = xmlHeadMatcher.group(); 394 Matcher encodingMatcher = XML_ENCODING_REGEX.matcher(xmlHead); 395 if (encodingMatcher.find()) { 396 String encoding = encodingMatcher.group(); 397 int pos1 = encoding.indexOf('=') + 2; 398 String charset = encoding.substring(pos1, encoding.length() - 1); 399 if (Charset.isSupported(charset)) { 400 result = charset; 401 } 402 } 403 } 404 return result; 405 } 406 407 415 public static String formatResourceName(String name, int maxLength) { 416 417 if (name == null) { 418 return null; 419 } 420 if (name.length() <= maxLength) { 421 return name; 422 } 423 424 String result = CmsResource.getName(name); 425 name = CmsResource.getParentFolder(name); 426 while (name != null) { 427 String part = CmsResource.getName(name); 428 429 if ((part.length() + result.length()) <= maxLength) { 430 result = part + result; 431 } else { 432 result = "/" + result; 433 if (!part.equals("/")) { 434 result = "/..." + result; 435 } 436 break; 437 } 438 name = CmsResource.getParentFolder(name); 439 } 440 441 return result; 442 } 443 444 452 public static String formatRuntime(long runtime) { 453 454 long seconds = (runtime / SECONDS) % 60; 455 long minutes = (runtime / MINUTES) % 60; 456 long hours = (runtime / HOURS) % 24; 457 long days = runtime / DAYS; 458 StringBuffer strBuf = new StringBuffer (); 459 460 if (days > 0) { 461 if (days < 10) { 462 strBuf.append('0'); 463 } 464 strBuf.append(days); 465 strBuf.append(':'); 466 } 467 468 if (hours < 10) { 469 strBuf.append('0'); 470 } 471 strBuf.append(hours); 472 strBuf.append(':'); 473 474 if (minutes < 10) { 475 strBuf.append('0'); 476 } 477 strBuf.append(minutes); 478 strBuf.append(':'); 479 480 if (seconds < 10) { 481 strBuf.append('0'); 482 } 483 strBuf.append(seconds); 484 485 return strBuf.toString(); 486 } 487 488 499 public static Color getColorValue(String value, Color defaultValue, String key) { 500 501 Color result; 502 try { 503 char pre = value.charAt(0); 504 if (pre != '#') { 505 value = "#" + value; 506 } 507 result = Color.decode(value); 508 } catch (Exception e) { 509 if (LOG.isDebugEnabled()) { 510 LOG.debug(Messages.get().getBundle().key(Messages.ERR_UNABLE_TO_PARSE_COLOR_2, value, key)); 511 } 512 result = defaultValue; 513 } 514 return result; 515 } 516 517 528 public static int getIntValue(String value, int defaultValue, String key) { 529 530 int result; 531 try { 532 result = Integer.valueOf(value).intValue(); 533 } catch (Exception e) { 534 if (LOG.isDebugEnabled()) { 535 LOG.debug(Messages.get().getBundle().key(Messages.ERR_UNABLE_TO_PARSE_INT_2, value, key)); 536 } 537 result = defaultValue; 538 } 539 return result; 540 } 541 542 549 public static boolean isEmpty(String value) { 550 551 return (value == null) || (value.length() == 0); 552 } 553 554 561 public static boolean isEmptyOrWhitespaceOnly(String value) { 562 563 return isEmpty(value) || (value.trim().length() == 0); 564 } 565 566 573 public static boolean isNotEmpty(String value) { 574 575 return (value != null) && (value.length() != 0); 576 } 577 578 585 public static boolean isNotEmptyOrWhitespaceOnly(String value) { 586 587 return (value != null) && (value.trim().length() > 0); 588 } 589 590 596 public static boolean isValidJavaClassName(String className) { 597 598 if (CmsStringUtil.isEmpty(className)) { 599 return false; 600 } 601 int length = className.length(); 602 boolean nodot = true; 603 for (int i = 0; i < length; i++) { 604 char ch = className.charAt(i); 605 if (nodot) { 606 if (ch == '.') { 607 return false; 608 } else if (Character.isJavaIdentifierStart(ch)) { 609 nodot = false; 610 } else { 611 return false; 612 } 613 } else { 614 if (ch == '.') { 615 nodot = true; 616 } else if (Character.isJavaIdentifierPart(ch)) { 617 nodot = false; 618 } else { 619 return false; 620 } 621 } 622 } 623 return true; 624 } 625 626 634 public static String padLeft(String input, int size) { 635 636 return (new PrintfFormat("%" + size + "s")).sprintf(input); 637 } 638 639 647 public static String padRight(String input, int size) { 648 649 return (new PrintfFormat("%-" + size + "s")).sprintf(input); 650 } 651 652 661 public static String [] splitAsArray(String source, char delimiter) { 662 663 List result = splitAsList(source, delimiter); 664 return (String [])result.toArray(new String [result.size()]); 665 } 666 667 676 public static String [] splitAsArray(String source, String delimiter) { 677 678 List result = splitAsList(source, delimiter); 679 return (String [])result.toArray(new String [result.size()]); 680 } 681 682 691 public static List splitAsList(String source, char delimiter) { 692 693 return splitAsList(source, delimiter, false); 694 } 695 696 706 public static List splitAsList(String source, char delimiter, boolean trim) { 707 708 List result = new ArrayList (); 709 int i = 0; 710 int l = source.length(); 711 int n = source.indexOf(delimiter); 712 while (n != -1) { 713 if ((i < n) || (i > 0) && (i < l)) { 715 result.add(trim ? source.substring(i, n).trim() : source.substring(i, n)); 716 } 717 i = n + 1; 718 n = source.indexOf(delimiter, i); 719 } 720 if (n < 0) { 722 n = source.length(); 723 } 724 if (i < n) { 725 result.add(trim ? source.substring(i).trim() : source.substring(i)); 726 } 727 return result; 728 } 729 730 739 public static List splitAsList(String source, String delimiter) { 740 741 return splitAsList(source, delimiter, false); 742 } 743 744 754 public static List splitAsList(String source, String delimiter, boolean trim) { 755 756 int dl = delimiter.length(); 757 if (dl == 1) { 758 return splitAsList(source, delimiter.charAt(0), trim); 760 } 761 762 List result = new ArrayList (); 763 int i = 0; 764 int l = source.length(); 765 int n = source.indexOf(delimiter); 766 while (n != -1) { 767 if ((i < n) || (i > 0) && (i < l)) { 769 result.add(trim ? source.substring(i, n).trim() : source.substring(i, n)); 770 } 771 i = n + dl; 772 n = source.indexOf(delimiter, i); 773 } 774 if (n < 0) { 776 n = source.length(); 777 } 778 if (i < n) { 779 result.add(trim ? source.substring(i).trim() : source.substring(i)); 780 } 781 return result; 782 } 783 784 795 public static String substitute(String source, Map substitions) { 796 797 String result = source; 798 Iterator it = substitions.keySet().iterator(); 799 while (it.hasNext()) { 800 String key = it.next().toString(); 801 result = substitute(result, key, substitions.get(key).toString()); 802 } 803 return result; 804 } 805 806 819 public static String substitute(String source, String searchString, String replaceString) { 820 821 if (source == null) { 822 return null; 823 } 824 825 if (isEmpty(searchString)) { 826 return source; 827 } 828 829 if (replaceString == null) { 830 replaceString = ""; 831 } 832 int len = source.length(); 833 int sl = searchString.length(); 834 int rl = replaceString.length(); 835 int length; 836 if (sl == rl) { 837 length = len; 838 } else { 839 int c = 0; 840 int s = 0; 841 int e; 842 while ((e = source.indexOf(searchString, s)) != -1) { 843 c++; 844 s = e + sl; 845 } 846 if (c == 0) { 847 return source; 848 } 849 length = len - (c * (sl - rl)); 850 } 851 852 int s = 0; 853 int e = source.indexOf(searchString, s); 854 if (e == -1) { 855 return source; 856 } 857 StringBuffer sb = new StringBuffer (length); 858 while (e != -1) { 859 sb.append(source.substring(s, e)); 860 sb.append(replaceString); 861 s = e + sl; 862 e = source.indexOf(searchString, s); 863 } 864 e = len; 865 sb.append(source.substring(s, e)); 866 return sb.toString(); 867 } 868 869 877 public static String substituteContextPath(String htmlContent, String context) { 878 879 if (m_contextSearch == null) { 880 m_contextSearch = "([^\\w/])" + context; 881 m_contextReplace = "$1" + CmsStringUtil.escapePattern(CmsStringUtil.MACRO_OPENCMS_CONTEXT) + "/"; 882 } 883 return substitutePerl(htmlContent, m_contextSearch, m_contextReplace, "g"); 884 } 885 886 895 public static String substitutePerl(String content, String searchString, String replaceItem, String occurences) { 896 897 String translationRule = "s#" + searchString + "#" + replaceItem + "#" + occurences; 898 Perl5Util perlUtil = new Perl5Util(); 899 try { 900 return perlUtil.substitute(translationRule, content); 901 } catch (MalformedPerl5PatternException e) { 902 if (LOG.isDebugEnabled()) { 903 LOG.debug(Messages.get().getBundle().key(Messages.LOG_MALFORMED_TRANSLATION_RULE_1, translationRule), e); 904 } 905 } 906 return content; 907 } 908 909 921 public static String toUnicodeLiteral(String s) { 922 923 StringBuffer result = new StringBuffer (); 924 char[] carr = s.toCharArray(); 925 926 String unicode; 927 for (int i = 0; i < carr.length; i++) { 928 result.append("\\u"); 929 unicode = Integer.toHexString(carr[i]).toUpperCase(); 931 for (int j = 4 - unicode.length(); j > 0; j--) { 932 result.append("0"); 933 } 934 result.append(unicode); 935 } 936 return result.toString(); 937 } 938 939 947 public static String trimToSize(String source, int length) { 948 949 int end = 0; 950 int newend; 951 while (true) { 952 newend = source.indexOf(" ", end); 953 if (newend > length && end > 0) { 954 return source.substring(0, length - 3) + "..."; 955 } else if (newend == -1) { 956 if (length < source.length()) { 957 return source.substring(0, length - 3) + "..."; 958 } else { 959 return source; 960 } 961 } else { 962 end = newend + 1; 963 } 964 } 965 } 966 967 976 public static boolean validateRegex(String value, String regex, boolean allowEmpty) { 977 978 if (CmsStringUtil.isEmptyOrWhitespaceOnly(value)) { 979 return allowEmpty; 980 } 981 Pattern pattern = Pattern.compile(regex); 982 Matcher matcher = pattern.matcher(value); 983 return matcher.matches(); 984 } 985 986 996 public static boolean validateResourceName(String name) { 997 998 if (name == null) { 999 return false; 1000 } 1001 int l = name.length(); 1002 if (l == 0) { 1003 return false; 1004 } 1005 if (name.length() != name.trim().length()) { 1006 return false; 1008 } 1009 for (int i = 0; i < l; i++) { 1010 char ch = name.charAt(i); 1011 switch (ch) { 1012 case '/': 1013 return false; 1014 case '\\': 1015 return false; 1016 case ':': 1017 return false; 1018 case '*': 1019 return false; 1020 case '?': 1021 return false; 1022 case '"': 1023 return false; 1024 case '>': 1025 return false; 1026 case '<': 1027 return false; 1028 case '|': 1029 return false; 1030 default: 1031 if (Character.isISOControl(ch)) { 1033 return false; 1034 } 1035 if (!Character.isDefined(ch)) { 1037 return false; 1038 } 1039 } 1040 } 1041 1042 return true; 1043 } 1044} | Popular Tags |