1 16 package org.directwebremoting.util; 17 18 import java.io.BufferedReader ; 19 import java.io.IOException ; 20 import java.io.StringReader ; 21 import java.util.Arrays ; 22 import java.util.Locale ; 23 import java.util.SortedSet ; 24 import java.util.TreeSet ; 25 26 44 public class JavascriptUtil 45 { 46 51 public static final int COMPRESS_STRIP_SL_COMMENTS = 1 << 0; 52 53 57 public static final int COMPRESS_STRIP_ML_COMMENTS = 1 << 1; 58 59 63 public static final int COMPRESS_TRIM_LINES = 1 << 2; 64 65 71 public static final int COMPRESS_STRIP_BLANKLINES = 1 << 3; 72 73 78 public static final int COMPRESS_SHRINK_VARS = 1 << 4; 79 80 86 public static final int COMPRESS_REMOVE_NEWLINES = 1 << 5; 87 88 91 public static final int LEVEL_NONE = 0; 92 93 97 public static final int LEVEL_DEBUGGABLE = COMPRESS_STRIP_SL_COMMENTS | COMPRESS_STRIP_ML_COMMENTS | COMPRESS_TRIM_LINES; 98 99 104 public static final int LEVEL_NORMAL = LEVEL_DEBUGGABLE | COMPRESS_STRIP_BLANKLINES | COMPRESS_SHRINK_VARS; 105 106 112 public static final int LEVEL_ULTRA = LEVEL_NORMAL | COMPRESS_REMOVE_NEWLINES; 113 114 121 public static String compress(String text, int level) 122 { 123 String reply = text; 124 125 if ((level & COMPRESS_STRIP_ML_COMMENTS) != 0) 127 { 128 reply = stripMultiLineComments(text); 129 } 130 131 if ((level & COMPRESS_STRIP_SL_COMMENTS) != 0) 132 { 133 reply = stripSingleLineComments(reply); 134 } 135 136 if ((level & COMPRESS_TRIM_LINES) != 0) 137 { 138 reply = trimLines(reply); 139 } 140 141 if ((level & COMPRESS_STRIP_BLANKLINES) != 0) 142 { 143 reply = stripBlankLines(reply); 144 } 145 146 if ((level & COMPRESS_SHRINK_VARS) != 0) 147 { 148 reply = shrinkVariableNames(reply); 149 } 150 151 if ((level & COMPRESS_REMOVE_NEWLINES) != 0) 152 { 153 reply = stripNewlines(reply); 154 } 155 156 return reply; 157 } 158 159 167 public static String trimLines(String text) 168 { 169 if (text == null) 170 { 171 return null; 172 } 173 174 try 175 { 176 StringBuffer output = new StringBuffer (); 177 178 BufferedReader in = new BufferedReader (new StringReader (text)); 180 while (true) 181 { 182 String line = in.readLine(); 183 if (line == null) 184 { 185 break; 186 } 187 188 output.append(line.trim()); 189 output.append('\n'); 190 } 191 192 return output.toString(); 193 } 194 catch (IOException ex) 195 { 196 log.error("IOExecption unexpected.", ex); 197 throw new IllegalArgumentException ("IOExecption unexpected."); 198 } 199 } 200 201 206 public static String stripSingleLineComments(String text) 207 { 208 if (text == null) 209 { 210 return null; 211 } 212 213 try 214 { 215 StringBuffer output = new StringBuffer (); 216 217 BufferedReader in = new BufferedReader (new StringReader (text)); 218 while (true) 219 { 220 String line = in.readLine(); 221 if (line == null) 222 { 223 break; 224 } 225 226 if (line.indexOf(COMMENT_RETAIN) == -1) 228 { 229 int cstart = line.indexOf(COMMENT_SL_START); 230 if (cstart >= 0) 231 { 232 line = line.substring(0, cstart); 233 } 234 } 235 236 output.append(line); 237 output.append('\n'); 238 } 239 240 return output.toString(); 241 } 242 catch (IOException ex) 243 { 244 log.error("IOExecption unexpected.", ex); 245 throw new IllegalArgumentException ("IOExecption unexpected."); 246 } 247 } 248 249 254 public static String stripMultiLineComments(String text) 255 { 256 if (text == null) 257 { 258 return null; 259 } 260 261 try 262 { 263 StringBuffer output = new StringBuffer (); 264 265 271 boolean inMultiLine = false; 273 BufferedReader in = new BufferedReader (new StringReader (text)); 274 while (true) 275 { 276 String line = in.readLine(); 277 if (line == null) 278 { 279 break; 280 } 281 282 if (!inMultiLine) 283 { 284 int cstart = line.indexOf(COMMENT_ML_START); 286 if (cstart >= 0) 287 { 288 int cend = line.indexOf(COMMENT_ML_END, cstart + COMMENT_ML_START.length()); 290 if (cend >= 0) 291 { 292 line = line.substring(0, cstart) + SPACE + line.substring(cend + COMMENT_ML_END.length()); 295 } 296 else 297 { 298 inMultiLine = true; 300 line = line.substring(0, cstart) + SPACE; 301 } 302 } 303 else 304 { 305 } 309 } 310 else 311 { 312 int cend = line.indexOf(COMMENT_ML_END); 314 if (cend >= 0) 315 { 316 line = line.substring(cend + COMMENT_ML_END.length()); 318 inMultiLine = false; 319 } 320 else 321 { 322 line = SPACE; 324 } 325 } 326 327 output.append(line); 328 output.append('\n'); 329 } 330 331 return output.toString(); 332 } 333 catch (IOException ex) 334 { 335 log.error("IOExecption unexpected.", ex); 336 throw new IllegalArgumentException ("IOExecption unexpected."); 337 } 338 } 339 340 347 public static String stripBlankLines(String text) 348 { 349 if (text == null) 350 { 351 return null; 352 } 353 354 try 355 { 356 StringBuffer output = new StringBuffer (); 357 358 BufferedReader in = new BufferedReader (new StringReader (text)); 359 boolean doneOneLine = false; 360 while (true) 361 { 362 String line = in.readLine(); 363 if (line == null) 364 { 365 break; 366 } 367 368 if (line.trim().length() > 0) 369 { 370 output.append(line); 371 output.append('\n'); 372 doneOneLine = true; 373 } 374 } 375 376 if (!doneOneLine) 377 { 378 output.append('\n'); 379 } 380 381 return output.toString(); 382 } 383 catch (IOException ex) 384 { 385 log.error("IOExecption unexpected.", ex); 386 throw new IllegalArgumentException ("IOExecption unexpected."); 387 } 388 } 389 390 395 public static String stripNewlines(String text) 396 { 397 if (text == null) 398 { 399 return null; 400 } 401 402 try 403 { 404 StringBuffer output = new StringBuffer (); 405 406 BufferedReader in = new BufferedReader (new StringReader (text)); 407 while (true) 408 { 409 String line = in.readLine(); 410 if (line == null) 411 { 412 break; 413 } 414 415 output.append(line); 416 output.append(SPACE); 417 } 418 output.append('\n'); 419 420 return output.toString(); 421 } 422 catch (IOException ex) 423 { 424 log.error("IOExecption unexpected.", ex); 425 throw new IllegalArgumentException ("IOExecption unexpected."); 426 } 427 } 428 429 434 public static String shrinkVariableNames(String text) 435 { 436 if (text == null) 437 { 438 return null; 439 } 440 441 throw new UnsupportedOperationException ("Variable name shrinking is not supported"); 442 } 443 444 465 public static String escapeJavaScript(String str) 466 { 467 if (str == null) 468 { 469 return null; 470 } 471 472 StringBuffer writer = new StringBuffer (str.length() * 2); 473 474 int sz = str.length(); 475 for (int i = 0; i < sz; i++) 476 { 477 char ch = str.charAt(i); 478 479 if (ch > 0xfff) 481 { 482 writer.append("\\u"); 483 writer.append(hex(ch)); 484 } 485 else if (ch > 0xff) 486 { 487 writer.append("\\u0"); 488 writer.append(hex(ch)); 489 } 490 else if (ch > 0x7f) 491 { 492 writer.append("\\u00"); 493 writer.append(hex(ch)); 494 } 495 else if (ch < 32) 496 { 497 switch (ch) 498 { 499 case '\b': 500 writer.append('\\'); 501 writer.append('b'); 502 break; 503 case '\n': 504 writer.append('\\'); 505 writer.append('n'); 506 break; 507 case '\t': 508 writer.append('\\'); 509 writer.append('t'); 510 break; 511 case '\f': 512 writer.append('\\'); 513 writer.append('f'); 514 break; 515 case '\r': 516 writer.append('\\'); 517 writer.append('r'); 518 break; 519 default: 520 if (ch > 0xf) 521 { 522 writer.append("\\u00"); 523 writer.append(hex(ch)); 524 } 525 else 526 { 527 writer.append("\\u000"); 528 writer.append(hex(ch)); 529 } 530 break; 531 } 532 } 533 else 534 { 535 switch (ch) 536 { 537 case '\'': 538 writer.append('\\'); 541 writer.append('\''); 542 break; 543 case '"': 544 writer.append('\\'); 545 writer.append('"'); 546 break; 547 case '\\': 548 writer.append('\\'); 549 writer.append('\\'); 550 break; 551 default: 552 writer.append(ch); 553 break; 554 } 555 } 556 } 557 558 return writer.toString(); 559 } 560 561 567 private static String hex(char ch) 568 { 569 return Integer.toHexString(ch).toUpperCase(Locale.ENGLISH); 570 } 571 572 580 public static String unescapeJavaScript(String str) 581 { 582 if (str == null) 583 { 584 return null; 585 } 586 587 StringBuffer writer = new StringBuffer (str.length()); 588 int sz = str.length(); 589 StringBuffer unicode = new StringBuffer (4); 590 boolean hadSlash = false; 591 boolean inUnicode = false; 592 593 for (int i = 0; i < sz; i++) 594 { 595 char ch = str.charAt(i); 596 if (inUnicode) 597 { 598 unicode.append(ch); 601 if (unicode.length() == 4) 602 { 603 try 606 { 607 int value = Integer.parseInt(unicode.toString(), 16); 608 writer.append((char) value); 609 unicode.setLength(0); 610 inUnicode = false; 611 hadSlash = false; 612 } 613 catch (NumberFormatException nfe) 614 { 615 throw new IllegalArgumentException ("Unable to parse unicode value: " + unicode + " cause: " + nfe); 616 } 617 } 618 continue; 619 } 620 621 if (hadSlash) 622 { 623 hadSlash = false; 625 switch (ch) 626 { 627 case '\\': 628 writer.append('\\'); 629 break; 630 case '\'': 631 writer.append('\''); 632 break; 633 case '\"': 634 writer.append('"'); 635 break; 636 case 'r': 637 writer.append('\r'); 638 break; 639 case 'f': 640 writer.append('\f'); 641 break; 642 case 't': 643 writer.append('\t'); 644 break; 645 case 'n': 646 writer.append('\n'); 647 break; 648 case 'b': 649 writer.append('\b'); 650 break; 651 case 'u': 652 inUnicode = true; 654 break; 655 default: 656 writer.append(ch); 657 break; 658 } 659 continue; 660 } 661 else if (ch == '\\') 662 { 663 hadSlash = true; 664 continue; 665 } 666 writer.append(ch); 667 } 668 669 if (hadSlash) 670 { 671 writer.append('\\'); 674 } 675 676 return writer.toString(); 677 } 678 679 685 public static boolean isReservedWord(String name) 686 { 687 return reserved.contains(name); 688 } 689 690 693 private static final String [] RESERVED_ARRAY = new String [] 694 { 695 "as", 697 "break", 698 "case", 699 "catch", 700 "class", 701 "const", 702 "continue", 703 "default", 704 "delete", 705 "do", 706 "else", 707 "export", 708 "extends", 709 "false", 710 "finally", 711 "for", 712 "function", 713 "if", 714 "import", 715 "in", 716 "instanceof", 717 "is", 718 "namespace", 719 "new", 720 "null", 721 "package", 722 "private", 723 "public", 724 "return", 725 "super", 726 "switch", 727 "this", 728 "throw", 729 "true", 730 "try", 731 "typeof", 732 "use", 733 "var", 734 "void", 735 "while", 736 "with", 737 "abstract", 739 "debugger", 740 "enum", 741 "goto", 742 "implements", 743 "interface", 744 "native", 745 "protected", 746 "synchronized", 747 "throws", 748 "transient", 749 "volatile", 750 "boolean", 752 "byte", 753 "char", 754 "double", 755 "final", 756 "float", 757 "int", 758 "long", 759 "short", 760 "static", 761 762 786 }; 787 788 private static SortedSet reserved = new TreeSet (); 789 790 793 static 794 { 795 reserved.addAll(Arrays.asList(RESERVED_ARRAY)); 797 } 798 799 private static final String SPACE = " "; 800 801 804 private static final String COMMENT_ML_START = "/*"; 805 806 809 private static final String COMMENT_ML_END = "*/"; 810 811 814 private static final String COMMENT_SL_START = "//"; 815 816 819 private static final String COMMENT_RETAIN = "#DWR"; 820 821 824 private static final Logger log = Logger.getLogger(JavascriptUtil.class); 825 } 826 | Popular Tags |