1 21 22 package org.armedbear.j; 23 24 import gnu.regexp.RE; 25 import gnu.regexp.REMatch; 26 import gnu.regexp.UncheckedRE; 27 import java.awt.Color ; 28 import java.awt.Component ; 29 import java.awt.Graphics ; 30 import java.awt.event.KeyEvent ; 31 import java.io.BufferedInputStream ; 32 import java.io.BufferedOutputStream ; 33 import java.io.BufferedReader ; 34 import java.io.FileOutputStream ; 35 import java.io.IOException ; 36 import java.io.InputStream ; 37 import java.io.InputStreamReader ; 38 import java.io.OutputStream ; 39 import java.io.UnsupportedEncodingException ; 40 import java.lang.reflect.InvocationTargetException ; 41 import java.lang.reflect.Method ; 42 import java.net.URL ; 43 import java.util.ArrayList ; 44 import java.util.List ; 45 import java.util.Properties ; 46 import java.util.StringTokenizer ; 47 import java.util.zip.GZIPInputStream ; 48 import java.util.zip.ZipInputStream ; 49 import javax.swing.BorderFactory ; 50 import javax.swing.BoxLayout ; 51 import javax.swing.ImageIcon ; 52 import javax.swing.JPanel ; 53 import javax.swing.KeyStroke ; 54 import javax.swing.border.Border ; 55 import javax.swing.border.TitledBorder ; 56 import org.xml.sax.XMLReader ; 57 import org.xml.sax.helpers.XMLReaderFactory ; 58 59 public final class Utilities implements Constants 60 { 61 public static boolean isLowerCase(String s) 64 { 65 for (int i = s.length()-1; i >= 0; i--) { 66 if (Character.isUpperCase(s.charAt(i))) 67 return false; 68 } 69 return true; 70 } 71 72 public static boolean isUpperCase(String s) 76 { 77 boolean containsLetter = false; 78 for (int i = s.length()-1; i >= 0; i--) { 79 char c = s.charAt(i); 80 if (Character.isLetter(c)) { 81 if (!Character.isUpperCase(c)) 82 return false; 83 containsLetter = true; 84 } 85 } 86 return containsLetter; 88 } 89 90 public static boolean isWhitespace(String s) 91 { 92 for (int i = s.length()-1; i >= 0; i--) { 93 if (!Character.isWhitespace(s.charAt(i))) 94 return false; 95 } 96 return true; 97 } 98 99 public static int countLines(String s) 100 { 101 int count = 0; 102 for (int i = s.length(); i-- > 0;) 103 if (s.charAt(i) == '\n') 104 ++count; 105 return count; 106 } 107 108 public static boolean isDelimited(Buffer buffer, Position pos, int length) 109 { 110 if (buffer != null) 111 return isDelimited(buffer.getMode(), pos, length); 112 else 113 return isDelimited(pos, length); 114 } 115 116 public static boolean isDelimited(Mode mode, Position pos, int length) 117 { 118 if (mode == null) 119 return isDelimited(pos, length); 120 final int before = pos.getOffset() - 1; 121 if (before >= 0 && mode.isIdentifierPart(pos.getLine().charAt(before))) 122 return false; 123 final int after = pos.getOffset() + length; 124 if (after < pos.getLineLength() && mode.isIdentifierPart(pos.getLine().charAt(after))) 125 return false; 126 return true; 127 } 128 129 public static boolean isDelimited(Position pos, int length) 130 { 131 final int before = pos.getOffset() - 1; 132 if (before >= 0 && Character.isJavaIdentifierPart(pos.getLine().charAt(before))) 133 return false; 134 final int after = pos.getOffset() + length; 135 if (after < pos.getLineLength() && Character.isJavaIdentifierPart(pos.getLine().charAt(after))) 136 return false; 137 return true; 138 } 139 140 public static boolean isDelimited(String s, int index, int length) 141 { 142 final int before = index - 1; 143 if (before >= 0 && Character.isJavaIdentifierPart(s.charAt(before))) 144 return false; 145 final int after = index + length; 146 if (after < s.length() && Character.isJavaIdentifierPart(s.charAt(after))) 147 return false; 148 return true; 149 } 150 151 public static boolean isDelimited(String s, int index, int length, 152 Mode mode) 153 { 154 if (mode == null) 155 return isDelimited(s, index, length); 156 final int before = index - 1; 157 if (before >= 0 && mode.isIdentifierPart(s.charAt(before))) 158 return false; 159 final int after = index + length; 160 if (after < s.length() && mode.isIdentifierPart(s.charAt(after))) 161 return false; 162 return true; 163 } 164 165 public static boolean isDelimited(Mode mode, String s, 166 int startIndex, int endIndex) 167 { 168 if (mode == null) 169 mode = JavaMode.getMode(); 170 final int before = startIndex - 1; 171 if (before >= 0 && mode.isIdentifierPart(s.charAt(before))) 172 return false; 173 if (endIndex < s.length() && mode.isIdentifierPart(s.charAt(endIndex))) 174 return false; 175 return true; 176 } 177 178 public static String getExtension(String filename) 180 { 181 int indexOfLastDot = filename.lastIndexOf('.'); 182 if (indexOfLastDot < 0) 183 return null; 184 int indexOfLastFileSeparatorChar = filename.lastIndexOf(LocalFile.getSeparatorChar()); 185 if (indexOfLastDot < indexOfLastFileSeparatorChar) 186 return null; else 188 return filename.substring(indexOfLastDot); 189 } 190 191 public static String getExtension(File file) 193 { 194 String name = file.getName(); 196 int index = name.lastIndexOf('.'); 197 if (index < 0) 198 return null; 199 else 200 return name.substring(index); 201 } 202 203 public static final File getTempFile() 204 { 205 return getTempFile(Directories.getTempDirectory()); 206 } 207 208 public static final File getTempFile(File dir) 209 { 210 return getTempFile(dir, ""); 211 } 212 213 public static final File getTempFile(String dir) 214 { 215 return getTempFile(File.getInstance(dir), ""); 216 } 217 218 private static int tempFileCount = 0; 222 223 public static synchronized File getTempFile(File dir, String extension) 224 { 225 if (dir == null) 226 return null; 227 228 if (extension == null) { 229 extension = ""; 230 } else if (extension.length() > 0) { 231 if (extension.charAt(0) != '.') 232 extension = ".".concat(extension); 233 } 234 235 long date = System.currentTimeMillis(); 236 237 for (int i = 0; i < 100; i++) { 238 File file = File.getInstance(dir, 239 String.valueOf(date + tempFileCount).concat(extension)); 240 ++tempFileCount; 241 if (!file.exists()) 242 return file; 243 } 244 245 return null; 246 } 247 248 public static boolean isDirectoryWritable(File dir) 249 { 250 boolean isWritable = false; 251 File file = getTempFile(dir); 252 if (file != null) { 253 try { 254 FileOutputStream out = file.getOutputStream(); 257 out.close(); 258 if (file.isFile()) { 259 isWritable = true; 260 file.delete(); 261 } 262 } 263 catch (IOException e) {} 264 } 265 return isWritable; 266 } 267 268 public static String detab(String s, int tabWidth, int startCol) 269 { 270 if (tabWidth <= 0) 271 return s; 272 int limit = s.length(); 273 int i; 274 for (i = 0; i < limit; i++) { 275 if (s.charAt(i) == '\t') 276 break; 277 } 278 if (i == limit) 279 return s; 281 283 char[] charArray = new char[limit * tabWidth]; 285 s.getChars(0, i, charArray, 0); 286 int col = startCol + i; 287 do { 289 charArray[col - startCol] = ' '; 290 ++col; 291 } while ((col % tabWidth) != 0); 292 ++i; 294 while (i < limit) { 296 char c = s.charAt(i++); 297 if (c == '\t') { 298 for (int j = tabWidth - col % tabWidth - 1; j >= 0; j--) { 299 charArray[col - startCol] = ' '; 300 ++col; 301 } 302 } else { 303 charArray[col - startCol] = c; 304 ++col; 305 } 306 } 307 return charArray == null ? s : new String (charArray, 0, col - startCol); 308 } 309 310 public static final String detab(String s, int tabWidth) 311 { 312 return detab(s, tabWidth, 0); 313 } 314 315 public static String entab(String s, int tabWidth, int startCol) 316 { 317 if (tabWidth <= 0) 318 return s; 319 int limit = s.length(); 320 if (limit < tabWidth) 321 return s; 322 s = detab(s, tabWidth, startCol); 324 limit = s.length(); 326 327 FastStringBuffer sb = new FastStringBuffer(limit); 328 int i = 0; 329 while (i < limit) { 330 char c = s.charAt(i); 331 if (c == ' ') { 332 int nextTabStop = ((startCol + i) / tabWidth + 1) * tabWidth; 333 if (nextTabStop < startCol + limit && nextTabStop - (startCol + i) > 1) { 334 boolean replace = true; 335 int j = i + 1; 336 while (j < nextTabStop - startCol) { 337 if (s.charAt(j++) != ' ') { 338 replace = false; 339 break; 340 } 341 } 342 if (replace) { 343 sb.append('\t'); 344 i = j; 345 continue; 346 } 347 } 348 } 349 sb.append(c); 350 i++; 351 } 352 return sb.toString(); 353 } 354 355 public static final String entab(String s, int tabWidth) 356 { 357 return entab(s, tabWidth, 0); 358 } 359 360 public static String makeTabsVisible(String s, int tabWidth) 361 { 362 if (tabWidth <= 0) 363 return s; 364 int limit = s.length(); 365 if (limit == 0) 366 return s; 367 final char tabChar = '^'; 368 FastStringBuffer sb = new FastStringBuffer(limit); 369 int col = 0; 370 for (int i = 0; i < limit; i++) { 371 char c = s.charAt(i); 372 if (c == '\t') { 373 sb.append(tabChar); 374 ++col; 375 while ((col % tabWidth) != 0) { 376 sb.append(' '); 377 ++col; 378 } 379 } else { 380 sb.append(c); 381 ++col; 382 } 383 } 384 return sb.toString(); 385 } 386 387 public static String wrap(String s, int wrapCol, int tabWidth) 388 { 389 FastStringBuffer sb = new FastStringBuffer(); 390 int i = 0; 391 final int limit = s.length(); 392 int startOffs = 0; 393 while (i < limit) { 394 int col = 0; 395 int breakOffs = 0; 396 startOffs = i; 397 boolean inUrl = false; 398 while (i < limit) { 399 char c = s.charAt(i++); 400 if (c == '\n') { 401 sb.append(trimTrailing(s.substring(startOffs, i))); 402 startOffs = i; 403 break; 404 } 405 if (c == '\t') 406 col += tabWidth - col % tabWidth; 407 else 408 ++col; 409 if (!inUrl && col > wrapCol) { 410 if (breakOffs <= startOffs) 412 breakOffs = i; 413 sb.append(trimTrailing(s.substring(startOffs, breakOffs))); 414 sb.append('\n'); 415 i = breakOffs; 416 while (i < limit && s.charAt(i) == ' ') 418 ++i; 419 break; 420 } 421 if (c == ' ' || c == '\t') { 422 breakOffs = i; 424 inUrl = false; 425 } else if (c == 'h' && lookingAt(s, i, "ttp://", false)) { 426 inUrl = true; 427 i += 6; 428 } else if (c == 'h' && lookingAt(s, i, "ttps://", false)) { 429 inUrl = true; 430 i += 7; 431 } else if (c == 'f' && lookingAt(s, i, "tp://", false)) { 432 inUrl = true; 433 i += 5; 434 } 435 } 436 } 437 if (i > startOffs) 438 sb.append(trimTrailing(s.substring(startOffs, i))); 439 return sb.toString(); 440 } 441 442 public static int getDetabbedLength(String s, int tabWidth) 443 { 444 final int limit = s.length(); 445 int detabbedLength = 0; 446 for (int i = 0; i < limit; i++) { 447 if (s.charAt(i) == '\t') 448 detabbedLength += tabWidth - detabbedLength % tabWidth; 449 else 450 ++detabbedLength; 451 } 452 return detabbedLength; 453 } 454 455 public static String trimLeading(String s) 457 { 458 final int length = s.length(); 459 int i = 0; 460 while (i < length) { 461 if (s.charAt(i) != ' ') 462 break; 463 ++i; 464 } 465 return s.substring(i); 466 } 467 468 public static String trimTrailing(String s) 470 { 471 int length = s.length(); 472 if (length == 0 || s.charAt(length-1) != ' ') 473 return s; 474 do { 475 --length; 476 } while (length > 0 && s.charAt(length-1) == ' '); 477 return s.substring(0, length); 478 } 479 480 public static boolean isLinePaste(String s) 482 { 483 final char c = s.charAt(s.length()-1); 484 return c == '\r' || c == '\n'; 485 } 486 487 public static int getIntegerProperty(Properties props, String key, int defaultValue) 488 { 489 try { 490 String s = props.getProperty(key); 491 if (s != null) 492 return Integer.parseInt(s); 493 } 494 catch (NumberFormatException e) {} 495 return defaultValue; 496 } 497 498 508 public static String extractInclude(String line) 509 { 510 String s = line.trim(); 511 if (s.length() < 12) return null; 513 if (s.charAt(0) != '#') 514 return null; 515 REMatch match = includeRE.getMatch(s); 516 if (match == null) 517 return null; 518 s = s.substring(match.getEndIndex()).trim(); 519 if (s.length() < 2) 520 return null; 521 char c = s.charAt(0); 522 int lastIndex = -1; 523 if (c == '"') 524 lastIndex = s.indexOf('"', 1); 525 else if (c == '<') 526 lastIndex = s.indexOf('>', 1); 527 if (lastIndex < 0) 528 return null; 529 return s.substring(0, lastIndex+1); 530 } 531 532 private static final RE includeRE = new UncheckedRE("#[ \t]*include[ \t]"); 533 534 547 public static File findInclude(String s, String path, 548 File currentDirectory) 549 { 550 char c = s.charAt(0); 551 final String fileName = s.substring(1, s.length()-1); 552 if (c == '"') { 553 File file = File.getInstance(currentDirectory, fileName); 556 if (file != null && file.isLocal() && file.isFile()) 557 return file; 558 } 559 return Utilities.findFileInPath(fileName, path, currentDirectory); 560 } 561 562 public static File findFileInPath(String filename, String path, 564 File currentDirectory) 565 { 566 if (path != null) { 567 int index; 568 do { 569 index = path.indexOf(LocalFile.getPathSeparatorChar()); 570 String dirname; 571 if (index < 0) { 572 dirname = path; 573 } else { 574 dirname = path.substring(0, index); 575 path = path.substring(index + 1); 576 } 577 File dir; 578 if (currentDirectory != null && currentDirectory.isLocal()) 579 dir = File.getInstance(currentDirectory, dirname); 580 else 581 dir = File.getInstance(dirname); 582 if (dir != null) { 583 File file = File.getInstance(dir, filename); 584 if (file != null && file.isLocal() && file.isFile()) 585 return file; 586 } 587 } while (index >= 0); 588 } 589 return null; 590 } 591 592 public static List getDirectoriesInPath(String path) 594 { 595 ArrayList list = new ArrayList (); 596 if (path != null) { 597 final char sep = LocalFile.getPathSeparatorChar(); 598 int begin = 0; 599 int end; 600 do { 601 end = path.indexOf(sep, begin); 602 String dir; 603 if (end < 0) { 604 dir = path.substring(begin); 605 } else { 606 dir = path.substring(begin, end); 607 begin = end + 1; 608 } 609 if (dir.length() != 0) 610 list.add(dir); 611 } while (end >= 0); 612 } 613 return list; 614 } 615 616 public static File findFile(Editor editor, String filename) 619 { 620 final Buffer buffer = editor.getBuffer(); 621 final File currentDirectory = 622 buffer != null ? buffer.getCurrentDirectory() : null; 623 624 if (filename.toLowerCase().endsWith(".h")) { 626 String includePath; 627 if (buffer != null) 628 includePath = buffer.getStringProperty(Property.INCLUDE_PATH); 629 else 630 includePath = Editor.preferences().getStringProperty(Property.INCLUDE_PATH); 631 if (includePath != null) { 632 File file = findFileInPath(filename, includePath, currentDirectory); 633 if (file != null) 634 return file; 635 } 636 } 637 638 String sourcePath; 640 if (buffer != null) 641 sourcePath = buffer.getStringProperty(Property.SOURCE_PATH); 642 else 643 sourcePath = Editor.preferences().getStringProperty(Property.SOURCE_PATH); 644 if (sourcePath != null) { 645 File file = findFileInPath(filename, sourcePath, currentDirectory); 646 if (file != null) 647 return file; 648 } 649 650 Mode mode = Editor.getModeList().getModeForFileName(filename); 653 if (mode != null) { 654 sourcePath = mode.getStringProperty(Property.SOURCE_PATH); 655 if (sourcePath != null) { 656 File file = findFileInPath(filename, sourcePath, currentDirectory); 657 if (file != null) 658 return file; 659 } 660 } 661 662 sourcePath = Editor.preferences().getStringProperty(Property.SOURCE_PATH); 664 if (sourcePath != null) { 665 File file = findFileInPath(filename, sourcePath, currentDirectory); 666 if (file != null) 667 return file; 668 } 669 670 return null; 671 } 672 673 public static boolean checkParentDirectory(File file, String context) 676 { 677 File parent = file.getParentFile(); 678 if (parent != null && parent.isDirectory()) 679 return true; 680 FastStringBuffer sb = new FastStringBuffer("Invalid path \""); 681 sb.append(file.netPath()); 682 sb.append('"'); 683 MessageDialog.showMessageDialog(sb.toString(), context); 684 return false; 685 } 686 687 public static boolean isFilenameAbsolute(String filename) 688 { 689 final int length = filename.length(); 690 if (length > 0) { 691 char c0 = filename.charAt(0); 692 if (c0 == '\\' || c0 == '/') 693 return true; 694 if (length > 2) { 695 if (Platform.isPlatformWindows()) { 696 char c1 = filename.charAt(1); 698 if (c1 == ':') { 699 if (c0 >= 'a' && c0 <= 'z') 700 return true; 701 if (c0 >= 'A' && c0 <= 'Z') 702 return true; 703 } 704 } else if (Platform.isPlatformUnix()) { 705 if (filename.equals("~") || filename.startsWith("~/")) 706 return true; 707 } 708 if (File.hasRemotePrefix(filename)) 709 return true; 710 if (File.hasLocalPrefix(filename)) 711 return true; 712 } 713 } 714 return false; 715 } 716 717 private static String getStringFromUnicodeBytes(byte[] bytes, int start, 719 int length, boolean isLittleEndian) 720 { 721 FastStringBuffer sb = new FastStringBuffer(length); 722 int i = start; 723 int limit = start + length; 724 while (i < limit - 1) { 725 byte b1 = bytes[i++]; 726 byte b2 = bytes[i++]; 727 if (isLittleEndian) 728 sb.append((char) ((b2 << 16) + b1)); 729 else 730 sb.append((char) ((b1 << 16) + b2)); 731 } 732 return sb.toString(); 733 } 734 735 public static int getFileType(File file) 737 { 738 if (file == null) 739 return FILETYPE_UNKNOWN; 740 int fileType = FILETYPE_UNKNOWN; 741 try { 742 InputStream in = file.getInputStream(); 743 byte[] bytes = new byte[4096]; 744 int bytesRead = in.read(bytes); 745 in.close(); 746 boolean isUnicode = false; 747 boolean isLittleEndian = false; 748 if (bytesRead >= 2) { 749 if (bytes[0] == (byte)0xfe && bytes[1] == (byte)0xff) { 750 isUnicode = true; 751 isLittleEndian = false; 752 } else if (bytes[0] == (byte)0xff && bytes[1] == (byte)0xfe) 753 isUnicode = true; 754 } 755 if (!isUnicode) { 756 for (int i = 0; i < bytesRead; i++) { 757 if (bytes[i] == 0) { 758 fileType = FILETYPE_BINARY; 759 break; 760 } 761 } 762 } 763 if (fileType == FILETYPE_BINARY) { 764 if (bytesRead > 2) { 765 if (bytes[0] == (byte) 0xd0 && bytes[1] == (byte) 0xcf) 766 fileType = FILETYPE_WORD; 767 else if (bytes[0] == (byte) 0xff && bytes[1] == (byte) 0xd8) 768 fileType = FILETYPE_JPEG; 769 else if (bytes[0] == (byte) 'P' && bytes[1] == 'K') { 770 try { 772 ZipInputStream istream = 773 new ZipInputStream (file.getInputStream()); 774 fileType = FILETYPE_ZIP; 775 istream.close(); 776 } 777 catch (Exception e) {} 778 } else { 779 try { 780 GZIPInputStream istream = 781 new GZIPInputStream (file.getInputStream()); 782 fileType = FILETYPE_GZIP; 783 istream.close(); 784 } 785 catch (IOException e) {} 786 } 787 } 788 } else { 789 fileType = FILETYPE_TEXT; 791 String s; 792 if (isUnicode) 793 s = getStringFromUnicodeBytes(bytes, 2, bytesRead, 794 isLittleEndian); 795 else 796 s = new String (bytes, 0, bytesRead); 797 if (s.length() >= 3) { 798 if (s.charAt(0) == '#' && s.charAt(1) == '!') { 799 int index = s.indexOf('\n'); 801 if (index >= 0) 802 s = s.substring(0, index); 803 index = s.indexOf('\r'); 804 if (index >= 0) 805 s = s.substring(0, index); 806 if (s.indexOf("/bin/sh") >=0 || 807 s.indexOf("/bin/bash") >= 0 || 808 s.indexOf("/bin/tcsh") >= 0) 809 fileType = FILETYPE_SHELLSCRIPT; 810 else if (s.indexOf("/bin/perl") >= 0) 811 fileType = FILETYPE_PERL; 812 } else if (s.startsWith("<?xml")) { 813 fileType = FILETYPE_XML; 814 } else if (s.startsWith("<?php")) { 815 fileType = FILETYPE_PHP; 816 } else if (s.startsWith("<?") && 817 Character.isWhitespace(s.charAt(2))) { 818 fileType = FILETYPE_PHP; 819 } 820 } 821 } 822 } 823 catch (Exception e) {} 824 return fileType; 825 } 826 827 public static boolean deleteRename(File source, File destination) 828 { 829 if (!source.isFile()) { 830 Log.warn("deleteRename source file " + source + " does not exist"); 831 return false; 832 } 833 for (int i = 0; i < 5; i++) { 836 if (destination.exists()) 837 destination.delete(); 838 if (source.renameTo(destination)) 839 return true; 840 Log.warn("deleteRename renameTo failed i = " + i); 841 System.gc(); 842 try { 843 Thread.sleep(100); 844 } 845 catch (InterruptedException ex) {} 846 } 847 Log.warn("deleteRename calling overwriteFile"); 851 if (overwriteFile(source, destination)) { 852 source.delete(); 853 return true; 854 } 855 Log.warn("deleteRename returning false"); 856 return false; 857 } 858 859 public static boolean copyFile(File source, File destination) 860 { 861 if (!source.isFile()) { 862 Log.error("copyFile error - source is not a file: " + source); 863 return false; 864 } 865 if (destination.isDirectory()) { 866 Log.error("copyFile error - destination is a directory: " + destination); 867 return false; 868 } 869 if (destination.isFile() && !destination.canWrite()) { 870 Log.error("copyFile error - destination is read only: " + destination); 871 return false; 872 } 873 boolean error = false; 874 File tempFile = getTempFile(destination.getParent()); 875 final long length = source.length(); 876 long bytesCopied = 0; 877 InputStream in = null; 878 OutputStream out = null; 879 try { 881 in = source.getInputStream(); 882 out = tempFile.getOutputStream(); 883 final int bufsize = length < 32768 ? (int) length : 32768; 884 byte[] buffer = new byte[bufsize]; 885 while (bytesCopied < length) { 886 int bytesRead = in.read(buffer, 0, bufsize); 887 if (bytesRead > 0) { 888 out.write(buffer, 0, bytesRead); 889 bytesCopied += bytesRead; 890 } else 891 break; 892 } 893 } 894 catch (IOException e) { 895 error = true; 896 } 897 try { 898 if (in != null) 899 in.close(); 900 if (out != null) { 901 out.flush(); 902 out.close(); 903 } 904 } 905 catch (IOException e) { 906 Log.error(e); 907 error = true; 908 } 909 if (error) { 910 Log.error("copyFile error"); 911 tempFile.delete(); 912 return false; 913 } 914 if (bytesCopied != length) { 915 Log.error("copyFile error - bytesCopied != length"); 916 tempFile.delete(); 917 return false; 918 } 919 if (destination.exists()) { 920 destination.delete(); 921 if (destination.exists()) { 922 Log.error("copyFile error - unable to delete existing destination file: " + destination); 924 tempFile.delete(); 925 return false; 926 } 927 } 928 if (!tempFile.renameTo(destination)) { 929 Log.error("copyFile error - unable to rename temporary file"); 930 Log.error("tempFile = " + tempFile.netPath()); 931 Log.error("destination = " + destination.netPath()); 932 tempFile.delete(); 933 return false; 934 } 935 if (Platform.isPlatformUnix()) 936 destination.setPermissions(source.getPermissions()); 937 destination.setLastModified(source.lastModified()); 938 return true; } 940 941 private static boolean overwriteFile(File source, File destination) 942 { 943 if (!source.isFile()) 944 return false; 945 boolean error = false; 946 long length = source.length(); 947 long totalBytes = 0; 948 BufferedInputStream in = null; 949 BufferedOutputStream out = null; 950 try { 951 in = new BufferedInputStream (source.getInputStream()); 952 out = new BufferedOutputStream (destination.getOutputStream()); 953 final int bufsize = 4096; 954 byte[] buffer = new byte[bufsize]; 955 while (totalBytes < length) { 956 int numBytes = in.read(buffer, 0, bufsize); 957 if (numBytes > 0) { 958 out.write(buffer, 0, numBytes); 959 totalBytes += numBytes; 960 } else 961 break; 962 } 963 } 964 catch (IOException e) { 965 Log.error(e); 966 error = true; 967 } 968 969 try { 970 if (in != null) 971 in.close(); 972 if (out != null) { 973 out.flush(); 974 out.close(); 975 } 976 } 977 catch (IOException e) { 978 Log.error(e); 979 error = true; 980 } 981 if (error) 982 return false; 983 if (totalBytes != length) 984 return false; 985 return true; 986 } 987 988 public static boolean makeBackup(File file, boolean keepOriginal) 989 { 990 return makeBackup(file, file.getName(), keepOriginal); 991 } 992 993 public static boolean makeBackup(File file, String name, 994 boolean keepOriginal) 995 { 996 if (!file.isFile()) 998 return true; 999 File backupDir = null; 1000 String backupDirectory = 1001 Editor.preferences().getStringProperty(Property.BACKUP_DIRECTORY); 1002 if (backupDirectory != null) { 1003 backupDir = File.getInstance(backupDirectory); 1004 } else { 1005 backupDir = File.getInstance(Directories.getUserHomeDirectory(), 1007 "backup"); 1008 } 1009 if (backupDir == null) 1010 return false; 1011 if (!backupDir.isDirectory() && !backupDir.mkdirs()) { 1012 Log.error("can't create backup directory ".concat(backupDir.canonicalPath())); 1013 return false; 1014 } 1015 File backupFile = File.getInstance(backupDir, name); 1016 if (!keepOriginal) { 1017 if (backupFile.isFile() && !backupFile.delete()) 1018 Log.error("can't delete old backupFile file ".concat(backupFile.toString())); 1019 if (file.renameTo(backupFile)) 1020 return true; 1021 } 1022 if (copyFile(file, backupFile)) 1023 return true; 1024 if (backupFile.isFile() && !backupFile.canWrite()) { 1027 Log.debug("deleting old backup file " + backupFile); 1028 backupFile.delete(); 1029 Log.debug("retrying copyFile..."); 1030 if (copyFile(file, backupFile)) 1031 return true; 1032 } 1033 Log.error("makeBackup copyFile failed, returning false"); 1034 return false; 1035 } 1036 1037 public static Color getColor(String s) 1038 { 1039 Color color = null; 1040 s = s.trim(); 1041 if (s.equals("black")) 1042 color = Color.black; 1043 else if (s.equals("white")) 1044 color = Color.white; 1045 else if (s.equals("yellow")) 1046 color = Color.yellow; 1047 else if (s.equals("blue")) 1048 color = Color.blue; 1049 else if (s.equals("red")) 1050 color = Color.red; 1051 else if (s.equals("gray")) 1052 color = Color.gray; 1053 else if (s.equals("green")) 1054 color = Color.green; 1055 else { 1056 try { 1057 StringTokenizer st = new StringTokenizer (s); 1060 if (st.countTokens() == 3) { 1061 int r = Integer.parseInt(st.nextToken()); 1062 int g = Integer.parseInt(st.nextToken()); 1063 int b = Integer.parseInt(st.nextToken()); 1064 color = new Color (r, g, b); 1065 } 1066 } 1067 catch (Exception e) { 1068 Log.error(e); 1069 } 1070 } 1071 return color; 1072 } 1073 1074 private static final String filenameChars = 1076 "#-./0123456789:ABCDEFGHIJKLMNOPQRSTUVWXYZ\\_abcdefghijklmnopqrstuvwxyz~"; 1077 1078 public static boolean isFilenameChar(char c) 1079 { 1080 return (filenameChars.indexOf(c) >= 0); 1081 } 1082 1083 public static boolean isProcessAlive(Process process) 1084 { 1085 if (process == null) 1086 return false; 1087 try { 1088 process.exitValue(); 1089 return false; 1091 } 1092 catch (IllegalThreadStateException e) { 1093 return true; 1095 } 1096 } 1097 1098 public static void kill(int pid) 1099 { 1100 if (Platform.isPlatformUnix()) { 1101 try { 1102 String [] cmdarray = { "/bin/sh", "-c", "kill -9 " + pid }; 1103 Process p = Runtime.getRuntime().exec(cmdarray); 1104 p.waitFor(); 1105 } 1106 catch (Throwable t) { 1107 Log.error(t); 1108 } 1109 } 1110 } 1111 1112 private static int haveJpty = -1; 1113 1114 public static boolean haveJpty() 1115 { 1116 if (haveJpty == -1) 1117 haveJpty = have("jpty") ? 1 : 0; 1118 return haveJpty == 1; 1119 } 1120 1121 private static int haveLs = -1; 1122 1123 public static boolean haveLs() 1124 { 1125 if (haveLs == -1) 1126 haveLs = have("ls") ? 1 : 0; 1127 return haveLs == 1; 1128 } 1129 1130 public static boolean have(final String s) 1131 { 1132 try { 1133 final Process p = Runtime.getRuntime().exec(s); 1134 if (p != null) { 1135 Thread t = new Thread ("Utilities.have(\"" + s + "\") destroy") { 1136 public void run() 1137 { 1138 try { 1139 final BufferedReader reader = 1140 new BufferedReader (new InputStreamReader (p.getInputStream())); 1141 while (reader.readLine() != null) 1142 ; 1143 p.getInputStream().close(); 1144 p.getOutputStream().close(); 1145 p.getErrorStream().close(); 1146 } 1147 catch (IOException e) { 1148 Log.error(e); 1149 } 1150 p.destroy(); 1151 try { 1152 p.waitFor(); 1153 } 1154 catch (InterruptedException e) { 1155 Log.error(e); 1156 } 1157 } 1158 }; 1159 t.setDaemon(true); 1160 t.setPriority(Thread.MIN_PRIORITY); 1161 t.start(); 1162 return true; 1163 } 1164 } 1165 catch (Throwable t) {} 1166 return false; 1167 } 1168 1169 private static String userHome; 1170 1171 public static final void setUserHome(String s) 1172 { 1173 Debug.bugIfNot(userHome == null); userHome = s; 1175 } 1176 1177 public static String getUserHome() 1178 { 1179 if (userHome == null) { 1180 if (Platform.isPlatformWindows()) { 1181 String [] cmdarray = {"bash", "-c", "echo $HOME"}; 1182 String output = exec(cmdarray); 1183 if (output != null) { 1184 output = output.trim(); 1185 if (output.length() > 0) { 1186 if (output.indexOf('/') >= 0) 1187 userHome = uncygnify(output); 1188 else 1189 userHome = output; 1190 } 1191 } 1192 } 1193 if (userHome == null) { 1194 userHome = System.getProperty("user.home"); 1195 File home = File.getInstance(userHome); 1197 if (home != null) 1198 userHome = home.canonicalPath(); 1199 } 1200 } 1201 return userHome; 1202 } 1203 1204 public static String cygnify(String s) 1205 { 1206 String [] cmdArray = {"cygpath", "-u", s}; 1207 String converted = Utilities.exec(cmdArray); 1208 return converted != null ? converted : s; 1209 } 1210 1211 public static String uncygnify(String s) 1212 { 1213 String [] cmdArray = {"cygpath", "-w", s}; 1214 String converted = Utilities.exec(cmdArray); 1215 return converted != null ? converted : s; 1216 } 1217 1218 public static String exec(String [] cmdarray) 1219 { 1220 try { 1221 Process process = Runtime.getRuntime().exec(cmdarray); 1222 BufferedReader reader = 1223 new BufferedReader (new InputStreamReader (process.getInputStream())); 1224 FastStringBuffer sb = new FastStringBuffer(); 1225 String s; 1226 while ((s = reader.readLine()) != null) { 1227 if (s.length() > 0) { 1228 if (sb.length() > 0) 1229 sb.append('\n'); 1230 sb.append(s); 1231 } 1232 } 1233 process.getInputStream().close(); 1234 process.getOutputStream().close(); 1235 process.getErrorStream().close(); 1236 process.waitFor(); 1237 return sb.toString(); 1238 } 1239 catch (Throwable t) { 1240 Log.error(t); 1241 return null; 1242 } 1243 } 1244 1245 public static ImageIcon getIconFromFile(String iconFile) 1246 { 1247 URL url = Editor.class.getResource("images/".concat(iconFile)); 1248 if (url == null) 1249 return null; 1250 return new ImageIcon (url); 1251 } 1252 1253 public static int parseInt(String s) throws NumberFormatException 1255 { 1256 final int limit = s.length(); 1257 int i; 1258 for (i = 0; i < limit; i++) { 1259 if (!Character.isDigit(s.charAt(i))) 1260 break; 1261 } 1262 if (i == 0) throw new NumberFormatException (); 1264 return Integer.parseInt(s.substring(0, i)); 1265 } 1266 1267 public static String rightJustify(int n, int fieldWidth) 1268 { 1269 String s = String.valueOf(n); 1270 int pad = fieldWidth - s.length(); 1271 if (pad <= 0) 1272 return s; 1273 FastStringBuffer sb = new FastStringBuffer(spaces(pad)); 1274 sb.append(s); 1275 return sb.toString(); 1276 } 1277 1278 public static String rightJustify(String s, int fieldWidth) 1279 { 1280 int pad = fieldWidth - s.length(); 1281 if (pad <= 0) 1282 return s; 1283 FastStringBuffer sb = new FastStringBuffer(spaces(pad)); 1284 sb.append(s); 1285 return sb.toString(); 1286 } 1287 1288 public static final boolean lookingAt(String s, int i, String pattern, 1289 boolean ignoreCase) 1290 { 1291 return s.regionMatches(ignoreCase, i, pattern, 0, pattern.length()); 1292 } 1293 1294 public static boolean isOneOf(String s, String [] strings) 1295 { 1296 if (s != null) { 1297 for (int i = strings.length-1; i >= 0; i--) 1298 if (s.equals(strings[i])) 1299 return true; 1300 } 1301 return false; 1302 } 1303 1304 private static final String SPACES; 1305 private static final int SPACES_LENGTH = 256; 1306 1307 static { 1308 char[] chars = new char[SPACES_LENGTH]; 1309 for (int i = 0; i < SPACES_LENGTH; i++) 1310 chars[i] = ' '; 1311 SPACES = new String (chars); 1312 } 1313 1314 public static String spaces(int count) 1315 { 1316 if (count <= 0) 1317 return ""; 1318 else if (count <= SPACES_LENGTH) 1319 return SPACES.substring(0, count); 1320 else { 1321 FastStringBuffer sb = new FastStringBuffer(count); 1322 for (int i = 0; i < count; i++) 1323 sb.append(' '); 1324 return sb.toString(); 1325 } 1326 } 1327 1328 public static final String getCharsetFromContentType(String contentType) 1329 { 1330 if (contentType == null) 1331 return null; 1332 int index = contentType.toLowerCase().indexOf("charset="); 1333 if (index < 0) 1334 return null; 1335 String s = contentType.substring(index + 8); 1336 FastStringBuffer sb = new FastStringBuffer(); 1337 boolean inQuote = false; 1338 for (int i = 0; i < s.length(); i++) { 1339 char c = s.charAt(i); 1340 if (i == 0 && c == '"') { 1341 inQuote = true; 1342 continue; 1343 } 1344 if (inQuote && c == '"') 1345 break; if (!inQuote && c == ';') 1347 break; sb.append(c); } 1350 return sb.toString(); 1351 } 1352 1353 public static final String getEncodingFromCharset(String charset) 1354 { 1355 if (charset == null) 1356 return "iso-8859-1"; 1357 String lower = charset.toLowerCase(); 1358 if (lower.equals("unknown-8bit") || 1359 lower.equals("x-unknown") || 1360 lower.equals("us-ascii") || 1361 lower.equals("default_charset") || 1362 lower.equals("latin-iso8859-1")) 1363 return "iso-8859-1"; 1364 return charset; 1365 } 1366 1367 public static boolean isSupportedEncoding(String encoding) 1368 { 1369 if (encoding != null) { 1370 try { 1371 "test".getBytes(encoding); 1372 return true; 1373 } 1374 catch (UnsupportedEncodingException e) {} 1375 } 1376 return false; 1377 } 1378 1379 public static String getTagName(String s) 1381 { 1382 Debug.assertTrue(s != null); 1383 Debug.assertTrue(s.length() > 0); 1384 Debug.assertTrue(s.charAt(0) == '<'); 1385 int length = s.length(); 1386 int start = 1; 1387 for (int i = start; i < length; i++) { 1388 switch (s.charAt(i)) { 1389 case ' ': 1390 case '>': 1391 case '\t': 1392 case '\n': 1393 case '\r': 1394 return s.substring(start, i); 1395 } 1396 } 1397 return s; 1398 } 1399 1400 public static List tokenize(String s) 1402 { 1403 ArrayList list = new ArrayList (); 1404 if (s != null) { 1405 FastStringBuffer sb = new FastStringBuffer(); 1406 boolean inQuote = false; 1407 final int limit = s.length(); 1408 for (int i = 0; i < limit; i++) { 1409 char c = s.charAt(i); 1410 switch (c) { 1411 case ' ': 1412 if (inQuote) 1413 sb.append(c); 1414 else if (sb.length() > 0) { 1415 list.add(sb.toString()); 1416 sb.setLength(0); 1417 } 1418 break; 1419 case '"': 1420 if (inQuote) { 1421 if (sb.length() > 0) { 1422 list.add(sb.toString()); 1423 sb.setLength(0); 1424 } 1425 inQuote = false; 1426 } else 1427 inQuote = true; 1428 break; 1429 default: 1430 sb.append(c); 1431 break; 1432 } 1433 } 1434 if (sb.length() > 0) 1435 list.add(sb.toString()); 1436 } 1437 return list; 1438 } 1439 1440 public static String getFirstIdentifier(String s, Mode mode) 1441 { 1442 FastStringBuffer sb = new FastStringBuffer(); 1443 int length = s.length(); 1444 if (length > 0) { 1445 char c = s.charAt(0); 1446 if (mode.isIdentifierStart(c)) { 1447 sb.append(c); 1448 for (int i = 1; i < length; i++) { 1449 c = s.charAt(i); 1450 if (mode.isIdentifierPart(c)) 1451 sb.append(c); 1452 else 1453 break; 1454 } 1455 } 1456 } 1457 return sb.toString(); 1458 } 1459 1460 public static KeyStroke getKeyStroke(String keyText) 1461 { 1462 if (keyText == null) 1463 return null; 1464 keyText = keyText.trim(); 1465 if (keyText.length() == 0) 1466 return null; 1467 if (keyText.startsWith("'")) { 1468 if (keyText.length() != 3) 1469 return null; 1470 if (keyText.charAt(2) != '\'') 1471 return null; 1472 return KeyStroke.getKeyStroke(keyText.charAt(1)); 1473 } 1474 int modifiers = 0; 1475 while (true) { 1476 if (keyText.startsWith("Ctrl ") || keyText.startsWith("Ctrl\t")) { 1477 modifiers |= CTRL_MASK; 1478 keyText = keyText.substring(5).trim(); 1479 continue; 1480 } 1481 if (keyText.startsWith("Shift ") || keyText.startsWith("Shift\t")) { 1482 modifiers |= SHIFT_MASK; 1483 keyText = keyText.substring(6).trim(); 1484 continue; 1485 } 1486 if (keyText.startsWith("Alt ") || keyText.startsWith("Alt\t")){ 1487 modifiers |= ALT_MASK; 1488 keyText = keyText.substring(4).trim(); 1489 continue; 1490 } 1491 if (keyText.startsWith("Meta ") || keyText.startsWith("Meta\t")){ 1492 modifiers |= META_MASK; 1493 keyText = keyText.substring(5).trim(); 1494 continue; 1495 } 1496 break; 1498 } 1499 if (modifiers == 0 && keyText.length() == 1) { 1500 char c = keyText.charAt(0); 1501 return KeyStroke.getKeyStroke(c); 1502 } 1503 if (modifiers == SHIFT_MASK && keyText.length() == 1) { 1504 char c = keyText.charAt(0); 1505 char lower = Character.toLowerCase(c); 1506 char upper = Character.toUpperCase(c); 1507 if (lower != upper) 1508 return KeyStroke.getKeyStroke(upper); 1509 } 1510 int keyCode = getKeyCode(keyText); 1511 if (keyCode == 0) 1512 return null; 1513 return KeyStroke.getKeyStroke(keyCode, modifiers); 1514 } 1515 1516 public static final String getKeyText(KeyStroke keyStroke) 1517 { 1518 return getKeyText(keyStroke.getKeyChar(), keyStroke.getKeyCode(), keyStroke.getModifiers()); 1519 } 1520 1521 public static String getKeyText(char keyChar, int keyCode, int modifiers) 1522 { 1523 FastStringBuffer sb = new FastStringBuffer(); 1524 if (keyChar != 0 && keyChar != 0xffff) { 1525 if (keyChar >= 'A' && keyChar <= 'Z') { 1527 sb.append("Shift "); 1528 sb.append(keyChar); 1529 } else { 1530 sb.append('\''); 1531 sb.append(keyChar); 1532 sb.append('\''); 1533 } 1534 } else { 1535 if ((modifiers & CTRL_MASK) != 0) 1537 sb.append("Ctrl "); 1538 if ((modifiers & SHIFT_MASK) != 0) 1539 sb.append("Shift "); 1540 if ((modifiers & ALT_MASK) != 0) 1541 sb.append("Alt "); 1542 if ((modifiers & META_MASK) != 0) 1543 sb.append("Meta "); 1544 sb.append(getKeyName(keyCode)); 1545 } 1546 return sb.toString(); 1547 } 1548 1549 private static String [] keyNames = { 1550 "Enter", 1551 "Backspace", 1552 "Tab", 1553 "Escape", 1554 "Space", 1555 "Page Up", 1556 "Page Down", 1557 "Home", 1558 "End", 1559 "Delete", 1560 "Left", 1561 "Right", 1562 "Up", 1563 "Down", 1564 "NumPad Left", 1565 "NumPad Right", 1566 "NumPad Up", 1567 "NumPad Down", 1568 "NumPad *", 1569 "NumPad +", 1570 "NumPad -", 1571 "NumPad Insert", 1572 "Mouse-1", 1573 "Double Mouse-1", 1574 "Mouse-2", 1575 "Double Mouse-2", 1576 "Mouse-3", 1577 "Double Mouse-3" 1578 }; 1579 1580 private static int[] keyCodes = { 1581 KeyEvent.VK_ENTER, 1582 KeyEvent.VK_BACK_SPACE, 1583 KeyEvent.VK_TAB, 1584 KeyEvent.VK_ESCAPE, 1585 KeyEvent.VK_SPACE, 1586 KeyEvent.VK_PAGE_UP, 1587 KeyEvent.VK_PAGE_DOWN, 1588 KeyEvent.VK_HOME, 1589 KeyEvent.VK_END, 1590 KeyEvent.VK_DELETE, 1591 KeyEvent.VK_LEFT, 1592 KeyEvent.VK_RIGHT, 1593 KeyEvent.VK_UP, 1594 KeyEvent.VK_DOWN, 1595 KeyEvent.VK_KP_LEFT, 1596 KeyEvent.VK_KP_RIGHT, 1597 KeyEvent.VK_KP_UP, 1598 KeyEvent.VK_KP_DOWN, 1599 0x6a, 1600 0x6b, 1601 0x6d, 1602 0x9b, 1603 VK_MOUSE_1, 1604 VK_DOUBLE_MOUSE_1, 1605 VK_MOUSE_2, 1606 VK_DOUBLE_MOUSE_2, 1607 VK_MOUSE_3, 1608 VK_DOUBLE_MOUSE_3 1609 }; 1610 1611 private static int getKeyCode(String keyName) 1612 { 1613 if (keyName.length() == 0) 1614 return 0; 1615 if (keyName.length() == 1) 1616 return (int) keyName.charAt(0); 1617 if (keyName.startsWith("0x")) { 1618 try { 1619 return Integer.parseInt(keyName.substring(2), 16); 1620 } 1621 catch (NumberFormatException e) { 1622 Log.error(e); 1623 } 1624 return 0; 1625 } 1626 for (int i = 0; i < keyNames.length; i++) { 1627 if (keyName.equals(keyNames[i])) 1628 return keyCodes[i]; 1629 } 1630 if (keyName.charAt(0) == 'F') { 1631 try { 1632 int n = Integer.parseInt(keyName.substring(1)); 1633 return KeyEvent.VK_F1 + n - 1; 1634 } 1635 catch (NumberFormatException e) { 1636 Log.error(e); 1637 } 1638 } 1639 return 0; 1640 } 1641 1642 private static String getKeyName(int keyCode) 1643 { 1644 if (keyCode >= KeyEvent.VK_0 && keyCode <= KeyEvent.VK_9 || keyCode >= KeyEvent.VK_A && keyCode <= KeyEvent.VK_Z) 1645 return String.valueOf((char) keyCode); 1646 if (keyCode >= KeyEvent.VK_F1 && keyCode <= KeyEvent.VK_F12) 1647 return "F" + Integer.toString(keyCode - KeyEvent.VK_F1 + 1); 1648 if (",./;=[\\]".indexOf(keyCode) >= 0) 1649 return String.valueOf((char) keyCode); 1650 for (int i = 0; i < keyCodes.length; i++){ 1651 if (keyCode == keyCodes[i]) 1652 return keyNames[i]; 1653 } 1654 return "0x" + Integer.toString(keyCode, 16); 1655 } 1656 1657 public static String propertyToXml(String name, String value) 1658 { 1659 FastStringBuffer sb = new FastStringBuffer("<property name=\""); 1660 sb.append(name); 1661 sb.append("\" value=\""); 1662 sb.append(value); 1663 sb.append("\"/>"); 1664 return sb.toString(); 1665 } 1666 1667 public static JPanel createPanel(String title) 1668 { 1669 JPanel panel = new JPanel (); 1670 panel.setLayout(new BoxLayout (panel, BoxLayout.Y_AXIS)); 1671 Border border = 1672 new TitledBorder (BorderFactory.createEtchedBorder(), title) { 1673 public void paintBorder(Component c, Graphics g, int x, int y, 1674 int width, int height) 1675 { 1676 Display.setRenderingHints(g); 1677 super.paintBorder(c, g, x, y, width, height); 1678 } 1679 }; 1680 panel.setBorder(border); 1681 return panel; 1682 } 1683 1684 private static String defaultXMLReaderImpl; 1685 static { 1686 if (Platform.isJava14()) { 1687 defaultXMLReaderImpl = 1689 "org.apache.crimson.parser.XMLReaderImpl"; 1690 } else { 1691 defaultXMLReaderImpl = 1693 "com.sun.org.apache.xerces.internal.parsers.SAXParser"; 1694 } 1695 } 1696 1697 public static synchronized XMLReader getDefaultXMLReader() 1698 { 1699 if (defaultXMLReaderImpl != null) { 1700 try { 1701 return XMLReaderFactory.createXMLReader(defaultXMLReaderImpl); 1702 } 1703 catch (Exception e) { 1704 Log.debug(defaultXMLReaderImpl + " is not available"); 1706 defaultXMLReaderImpl = null; 1708 } 1710 } 1711 try { 1712 return XMLReaderFactory.createXMLReader(); 1714 } 1715 catch (Throwable t) { 1716 Log.error(t); 1718 return null; 1719 } 1720 } 1721} 1722 | Popular Tags |