PageRenderTime 64ms CodeModel.GetById 31ms RepoModel.GetById 0ms app.codeStats 1ms

/jEdit/tags/jedit-4-1-pre5/org/gjt/sp/jedit/MiscUtilities.java

#
Java | 1108 lines | 674 code | 91 blank | 343 comment | 134 complexity | 99af4faecdc37006f0baeee17cddad29 MD5 | raw file
Possible License(s): BSD-3-Clause, AGPL-1.0, Apache-2.0, LGPL-2.0, LGPL-3.0, GPL-2.0, CC-BY-SA-3.0, LGPL-2.1, GPL-3.0, MPL-2.0-no-copyleft-exception, IPL-1.0
  1. /*
  2. * MiscUtilities.java - Various miscallaneous utility functions
  3. * :tabSize=8:indentSize=8:noTabs=false:
  4. * :folding=explicit:collapseFolds=1:
  5. *
  6. * Copyright (C) 1999, 2000, 2001 Slava Pestov
  7. * Portions copyright (C) 2000 Richard S. Hall
  8. * Portions copyright (C) 2001 Dirk Moebius
  9. *
  10. * This program is free software; you can redistribute it and/or
  11. * modify it under the terms of the GNU General Public License
  12. * as published by the Free Software Foundation; either version 2
  13. * of the License, or any later version.
  14. *
  15. * This program is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU General Public License
  21. * along with this program; if not, write to the Free Software
  22. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  23. */
  24. package org.gjt.sp.jedit;
  25. //{{{ Imports
  26. import gnu.regexp.RE;
  27. import javax.swing.text.Segment;
  28. import javax.swing.JMenuItem;
  29. import java.io.*;
  30. import java.util.*;
  31. import org.gjt.sp.jedit.io.*;
  32. import org.gjt.sp.util.Log;
  33. //}}}
  34. /**
  35. * Class with several useful miscellaneous functions.
  36. *
  37. * @author Slava Pestov
  38. * @version $Id: MiscUtilities.java 4331 2002-08-29 22:09:26Z spestov $
  39. */
  40. public class MiscUtilities
  41. {
  42. //{{{ Path name methods
  43. //{{{ canonPath() method
  44. /**
  45. * Returns the canonical form of the specified path name. Currently
  46. * only expands a leading <code>~</code>. <b>For local path names
  47. * only.</b>
  48. * @param path The path name
  49. * @since jEdit 4.0pre2
  50. */
  51. public static String canonPath(String path)
  52. {
  53. if(File.separatorChar == '\\')
  54. {
  55. // get rid of mixed paths on Windows
  56. path = path.replace('/','\\');
  57. }
  58. if(path.startsWith("~" + File.separator))
  59. {
  60. path = path.substring(2);
  61. String home = System.getProperty("user.home");
  62. if(home.endsWith(File.separator))
  63. return home + path;
  64. else
  65. return home + File.separator + path;
  66. }
  67. else if(path.equals("~"))
  68. return System.getProperty("user.home");
  69. else
  70. return path;
  71. } //}}}
  72. //{{{ constructPath() method
  73. /**
  74. * Constructs an absolute path name from a directory and another
  75. * path name. This method is VFS-aware.
  76. * @param parent The directory
  77. * @param path The path name
  78. */
  79. public static String constructPath(String parent, String path)
  80. {
  81. if(MiscUtilities.isURL(path))
  82. return path;
  83. else if(path.startsWith("~"))
  84. return path;
  85. else
  86. {
  87. // have to handle these cases specially on windows.
  88. if(OperatingSystem.isDOSDerived())
  89. {
  90. if(path.length() == 2 && path.charAt(1) == ':')
  91. return path;
  92. else if(path.length() > 2 && path.charAt(1) == ':')
  93. {
  94. if(path.charAt(2) != '\\')
  95. {
  96. path = path.substring(0,2) + '\\'
  97. + path.substring(2);
  98. }
  99. return resolveSymlinks(path);
  100. }
  101. else if(path.startsWith("\\\\"))
  102. return resolveSymlinks(path);
  103. }
  104. else if(OperatingSystem.isUnix())
  105. {
  106. // nice and simple
  107. if(path.length() > 0 && path.charAt(0) == '/')
  108. return resolveSymlinks(path);
  109. }
  110. }
  111. if(parent == null)
  112. parent = System.getProperty("user.dir");
  113. if(OperatingSystem.isDOSDerived() && path.startsWith("\\"))
  114. parent = parent.substring(0,2);
  115. VFS vfs = VFSManager.getVFSForPath(parent);
  116. return vfs.constructPath(parent,path);
  117. } //}}}
  118. //{{{ constructPath() method
  119. /**
  120. * Constructs an absolute path name from three path components.
  121. * This method is VFS-aware.
  122. * @param parent The parent directory
  123. * @param path1 The first path
  124. * @param path2 The second path
  125. */
  126. public static String constructPath(String parent,
  127. String path1, String path2)
  128. {
  129. return constructPath(constructPath(parent,path1),path2);
  130. } //}}}
  131. //{{{ concatPath() method
  132. /**
  133. * Like constructPath(), except <code>path</code> will be
  134. * appended to <code>parent</code> even if it is absolute.
  135. * @param path
  136. * @param parent
  137. */
  138. public static String concatPath(String parent, String path)
  139. {
  140. parent = canonPath(parent);
  141. path = canonPath(path);
  142. // Make all child paths relative.
  143. if (path.startsWith(File.separator))
  144. path = path.substring(1);
  145. else if ((path.length() >= 3) && (path.charAt(1) == ':'))
  146. path = path.replace(':', File.separatorChar);
  147. if (parent == null)
  148. parent = System.getProperty("user.dir");
  149. if (parent.endsWith(File.separator))
  150. return parent + path;
  151. else
  152. return parent + File.separator + path;
  153. } //}}}
  154. //{{{ getFileExtension() method
  155. /**
  156. * Returns the extension of the specified filename, or an empty
  157. * string if there is none.
  158. * @param name The file name
  159. */
  160. public static String getFileExtension(String name)
  161. {
  162. int index = name.indexOf('.');
  163. if(index == -1)
  164. return "";
  165. else
  166. return name.substring(index);
  167. } //}}}
  168. //{{{ getFileName() method
  169. /**
  170. * Returns the last component of the specified path.
  171. * This method is VFS-aware.
  172. * @param path The path name
  173. */
  174. public static String getFileName(String path)
  175. {
  176. return VFSManager.getVFSForPath(path).getFileName(path);
  177. } //}}}
  178. //{{{ getFileNameNoExtension() method
  179. /**
  180. * Returns the last component of the specified path name without the
  181. * trailing extension (if there is one).
  182. * @param path The path name
  183. * @since jEdit 4.0pre8
  184. */
  185. public static String getFileNameNoExtension(String path)
  186. {
  187. String name = getFileName(path);
  188. int index = name.lastIndexOf('.');
  189. if(index == -1)
  190. return name;
  191. else
  192. return name.substring(0,index);
  193. } //}}}
  194. //{{{ getFileParent() method
  195. /**
  196. * @deprecated Call getParentOfPath() instead
  197. */
  198. public static String getFileParent(String path)
  199. {
  200. return getParentOfPath(path);
  201. } //}}}
  202. //{{{ getParentOfPath() method
  203. /**
  204. * Returns the parent of the specified path. This method is VFS-aware.
  205. * @param path The path name
  206. * @since jEdit 2.6pre5
  207. */
  208. public static String getParentOfPath(String path)
  209. {
  210. return VFSManager.getVFSForPath(path).getParentOfPath(path);
  211. } //}}}
  212. //{{{ getFileProtocol() method
  213. /**
  214. * @deprecated Call getProtocolOfURL() instead
  215. */
  216. public static String getFileProtocol(String url)
  217. {
  218. return getProtocolOfURL(url);
  219. } //}}}
  220. //{{{ getProtocolOfURL() method
  221. /**
  222. * Returns the protocol specified by a URL.
  223. * @param url The URL
  224. * @since jEdit 2.6pre5
  225. */
  226. public static String getProtocolOfURL(String url)
  227. {
  228. return url.substring(0,url.indexOf(':'));
  229. } //}}}
  230. //{{{ isURL() method
  231. /**
  232. * Checks if the specified string is a URL.
  233. * @param str The string to check
  234. * @return True if the string is a URL, false otherwise
  235. */
  236. public static boolean isURL(String str)
  237. {
  238. int fsIndex = Math.max(str.indexOf(File.separatorChar),
  239. str.indexOf('/'));
  240. if(fsIndex == 0) // /etc/passwd
  241. return false;
  242. else if(fsIndex == 2) // C:\AUTOEXEC.BAT
  243. return false;
  244. int cIndex = str.indexOf(':');
  245. if(cIndex <= 1) // D:\WINDOWS
  246. return false;
  247. else if(fsIndex != -1 && cIndex > fsIndex) // /tmp/RTF::read.pm
  248. return false;
  249. return true;
  250. } //}}}
  251. //{{{ saveBackup() method
  252. /**
  253. * Saves a backup (optionally numbered) of a file.
  254. * @param file A local file
  255. * @param backups The number of backups. Must be >= 1. If > 1, backup
  256. * files will be numbered.
  257. * @param backupPrefix The backup file name prefix
  258. * @param backupSuffix The backup file name suffix
  259. * @param backupDirectory The directory where to save backups; if null,
  260. * they will be saved in the same directory as the file itself.
  261. * @since jEdit 4.0pre1
  262. */
  263. public static void saveBackup(File file, int backups,
  264. String backupPrefix, String backupSuffix,
  265. String backupDirectory)
  266. {
  267. if(backupPrefix == null)
  268. backupPrefix = "";
  269. if(backupSuffix == null)
  270. backupSuffix = "";
  271. String name = file.getName();
  272. // If backups is 1, create ~ file
  273. if(backups == 1)
  274. {
  275. File backupFile = new File(backupDirectory,
  276. backupPrefix + name + backupSuffix);
  277. backupFile.delete();
  278. file.renameTo(backupFile);
  279. }
  280. // If backups > 1, move old ~n~ files, create ~1~ file
  281. else
  282. {
  283. new File(backupDirectory,
  284. backupPrefix + name + backupSuffix
  285. + backups + backupSuffix).delete();
  286. for(int i = backups - 1; i > 0; i--)
  287. {
  288. File backup = new File(backupDirectory,
  289. backupPrefix + name + backupSuffix
  290. + i + backupSuffix);
  291. backup.renameTo(new File(backupDirectory,
  292. backupPrefix + name + backupSuffix
  293. + (i+1) + backupSuffix));
  294. }
  295. file.renameTo(new File(backupDirectory,
  296. backupPrefix + name + backupSuffix
  297. + "1" + backupSuffix));
  298. }
  299. } //}}}
  300. //{{{ fileToClass() method
  301. /**
  302. * Converts a file name to a class name. All slash characters are
  303. * replaced with periods and the trailing '.class' is removed.
  304. * @param name The file name
  305. */
  306. public static String fileToClass(String name)
  307. {
  308. char[] clsName = name.toCharArray();
  309. for(int i = clsName.length - 6; i >= 0; i--)
  310. if(clsName[i] == '/')
  311. clsName[i] = '.';
  312. return new String(clsName,0,clsName.length - 6);
  313. } //}}}
  314. //{{{ classToFile() method
  315. /**
  316. * Converts a class name to a file name. All periods are replaced
  317. * with slashes and the '.class' extension is added.
  318. * @param name The class name
  319. */
  320. public static String classToFile(String name)
  321. {
  322. return name.replace('.','/').concat(".class");
  323. } //}}}
  324. //}}}
  325. //{{{ Text methods
  326. //{{{ getLeadingWhiteSpace() method
  327. /**
  328. * Returns the number of leading white space characters in the
  329. * specified string.
  330. * @param str The string
  331. */
  332. public static int getLeadingWhiteSpace(String str)
  333. {
  334. int whitespace = 0;
  335. loop: for(;whitespace < str.length();)
  336. {
  337. switch(str.charAt(whitespace))
  338. {
  339. case ' ': case '\t':
  340. whitespace++;
  341. break;
  342. default:
  343. break loop;
  344. }
  345. }
  346. return whitespace;
  347. } //}}}
  348. //{{{ getTrailingWhiteSpace() method
  349. /**
  350. * Returns the number of trailing whitespace characters in the
  351. * specified string.
  352. * @param str The string
  353. * @since jEdit 2.5pre5
  354. */
  355. public static int getTrailingWhiteSpace(String str)
  356. {
  357. int whitespace = 0;
  358. loop: for(int i = str.length() - 1; i >= 0; i--)
  359. {
  360. switch(str.charAt(i))
  361. {
  362. case ' ': case '\t':
  363. whitespace++;
  364. break;
  365. default:
  366. break loop;
  367. }
  368. }
  369. return whitespace;
  370. } //}}}
  371. //{{{ getLeadingWhiteSpaceWidth() method
  372. /**
  373. * Returns the width of the leading white space in the specified
  374. * string.
  375. * @param str The string
  376. * @param tabSize The tab size
  377. */
  378. public static int getLeadingWhiteSpaceWidth(String str, int tabSize)
  379. {
  380. int whitespace = 0;
  381. loop: for(int i = 0; i < str.length(); i++)
  382. {
  383. switch(str.charAt(i))
  384. {
  385. case ' ':
  386. whitespace++;
  387. break;
  388. case '\t':
  389. whitespace += (tabSize - whitespace % tabSize);
  390. break;
  391. default:
  392. break loop;
  393. }
  394. }
  395. return whitespace;
  396. } //}}}
  397. //{{{ getVirtualWidth() method
  398. /**
  399. * Returns the virtual column number (taking tabs into account) of the
  400. * specified offset in the segment.
  401. *
  402. * @param seg The segment
  403. * @param tabSize The tab size
  404. * @since jEdit 4.1pre1
  405. */
  406. public static int getVirtualWidth(Segment seg, int tabSize)
  407. {
  408. int virtualPosition = 0;
  409. for (int i = 0; i < seg.count; i++)
  410. {
  411. char ch = seg.array[seg.offset + i];
  412. if (ch == '\t')
  413. {
  414. virtualPosition += tabSize
  415. - (virtualPosition % tabSize);
  416. }
  417. else
  418. {
  419. ++virtualPosition;
  420. }
  421. }
  422. return virtualPosition;
  423. } //}}}
  424. //{{{ getOffsetOfVirtualColumn() method
  425. /**
  426. * Returns the array offset of a virtual column number (taking tabs
  427. * into account) in the segment.
  428. *
  429. * @param seg The segment
  430. * @param tabSize The tab size
  431. * @param column The virtual column number
  432. * @param totalVirtualWidth If this array is non-null, the total
  433. * virtual width will be stored in its first location if this method
  434. * returns -1.
  435. *
  436. * @return -1 if the column is out of bounds
  437. *
  438. * @since jEdit 4.1pre1
  439. */
  440. public static int getOffsetOfVirtualColumn(Segment seg, int tabSize,
  441. int column, int[] totalVirtualWidth)
  442. {
  443. int virtualPosition = 0;
  444. for (int i = 0; i < seg.count; i++)
  445. {
  446. char ch = seg.array[seg.offset + i];
  447. if (ch == '\t')
  448. {
  449. int tabWidth = tabSize
  450. - (virtualPosition % tabSize);
  451. if(virtualPosition >= column)
  452. return i;
  453. else
  454. virtualPosition += tabWidth;
  455. }
  456. else
  457. {
  458. if(virtualPosition == column)
  459. return i;
  460. else
  461. ++virtualPosition;
  462. }
  463. }
  464. if(totalVirtualWidth != null)
  465. totalVirtualWidth[0] = virtualPosition;
  466. return -1;
  467. } //}}}
  468. //{{{ createWhiteSpace() method
  469. /**
  470. * Creates a string of white space with the specified length.
  471. * @param len The length
  472. * @param tabSize The tab size, or 0 if tabs are not to be used
  473. */
  474. public static String createWhiteSpace(int len, int tabSize)
  475. {
  476. StringBuffer buf = new StringBuffer();
  477. if(tabSize == 0)
  478. {
  479. while(len-- > 0)
  480. buf.append(' ');
  481. }
  482. else
  483. {
  484. int count = len / tabSize;
  485. while(count-- > 0)
  486. buf.append('\t');
  487. count = len % tabSize;
  488. while(count-- > 0)
  489. buf.append(' ');
  490. }
  491. return buf.toString();
  492. } //}}}
  493. //{{{ globToRE() method
  494. /**
  495. * Converts a Unix-style glob to a regular expression.
  496. * ? becomes ., * becomes .*, {aa,bb} becomes (aa|bb).
  497. * @param glob The glob pattern
  498. */
  499. public static String globToRE(String glob)
  500. {
  501. StringBuffer buf = new StringBuffer();
  502. boolean backslash = false;
  503. boolean insideGroup = false;
  504. boolean insideNegativeLookahead = false;
  505. for(int i = 0; i < glob.length(); i++)
  506. {
  507. char c = glob.charAt(i);
  508. if(backslash)
  509. {
  510. buf.append('\\');
  511. buf.append(c);
  512. backslash = false;
  513. continue;
  514. }
  515. switch(c)
  516. {
  517. case '\\':
  518. backslash = true;
  519. break;
  520. case '?':
  521. buf.append('.');
  522. break;
  523. case '.':
  524. buf.append("\\.");
  525. break;
  526. case '*':
  527. buf.append(".*");
  528. break;
  529. case '{':
  530. buf.append('(');
  531. if(i + 1 != glob.length() && glob.charAt(i + 1) == '!')
  532. {
  533. buf.append('?');
  534. insideNegativeLookahead = true;
  535. }
  536. else
  537. insideGroup = true;
  538. break;
  539. case ',':
  540. if(insideGroup)
  541. {
  542. if(insideNegativeLookahead)
  543. {
  544. buf.append(").*");
  545. insideNegativeLookahead = false;
  546. }
  547. buf.append('|');
  548. }
  549. else
  550. buf.append(',');
  551. break;
  552. case '}':
  553. if(insideNegativeLookahead)
  554. {
  555. buf.append(").*");
  556. insideNegativeLookahead = false;
  557. }
  558. else if(insideGroup)
  559. {
  560. buf.append(')');
  561. insideGroup = false;
  562. }
  563. else
  564. buf.append('}');
  565. break;
  566. default:
  567. buf.append(c);
  568. }
  569. }
  570. return buf.toString();
  571. } //}}}
  572. //{{{ escapesToChars() method
  573. /**
  574. * Converts "\n" and "\t" escapes in the specified string to
  575. * newlines and tabs.
  576. * @param str The string
  577. * @since jEdit 2.3pre1
  578. */
  579. public static String escapesToChars(String str)
  580. {
  581. StringBuffer buf = new StringBuffer();
  582. for(int i = 0; i < str.length(); i++)
  583. {
  584. char c = str.charAt(i);
  585. switch(c)
  586. {
  587. case '\\':
  588. if(i == str.length() - 1)
  589. {
  590. buf.append('\\');
  591. break;
  592. }
  593. c = str.charAt(++i);
  594. switch(c)
  595. {
  596. case 'n':
  597. buf.append('\n');
  598. break;
  599. case 't':
  600. buf.append('\t');
  601. break;
  602. default:
  603. buf.append(c);
  604. break;
  605. }
  606. break;
  607. default:
  608. buf.append(c);
  609. }
  610. }
  611. return buf.toString();
  612. } //}}}
  613. //{{{ charsToEscapes() method
  614. /**
  615. * Escapes newlines, tabs, backslashes, and quotes in the specified
  616. * string.
  617. * @param str The string
  618. * @since jEdit 2.3pre1
  619. */
  620. public static String charsToEscapes(String str)
  621. {
  622. return charsToEscapes(str,"\n\t\\\"'");
  623. } //}}}
  624. //{{{ charsToEscapes() method
  625. /**
  626. * Escapes the specified characters in the specified string.
  627. * @param str The string
  628. * @param extra Any characters that require escaping
  629. * @since jEdit 4.1pre3
  630. */
  631. public static String charsToEscapes(String str, String toEscape)
  632. {
  633. StringBuffer buf = new StringBuffer();
  634. for(int i = 0; i < str.length(); i++)
  635. {
  636. char c = str.charAt(i);
  637. if(toEscape.indexOf(c) != -1)
  638. {
  639. if(c == '\n')
  640. buf.append("\\n");
  641. else if(c == '\t')
  642. buf.append("\\t");
  643. else
  644. {
  645. buf.append('\\');
  646. buf.append(c);
  647. }
  648. }
  649. else
  650. buf.append(c);
  651. }
  652. return buf.toString();
  653. } //}}}
  654. //{{{ compareVersions() method
  655. /**
  656. * @deprecated Call <code>compareStrings()</code> instead
  657. */
  658. public static int compareVersions(String v1, String v2)
  659. {
  660. return compareStrings(v1,v2,false);
  661. } //}}}
  662. //{{{ compareStrings() method
  663. /**
  664. * A more intelligent version of String.compareTo() that handles
  665. * numbers specially. For example, it places "My file 2" before
  666. * "My file 10".
  667. * @param str1 The first string
  668. * @param str2 The second string
  669. * @param ignoreCase If true, case will be ignored
  670. * @return negative If str1 &lt; str2, 0 if both are the same,
  671. * positive if str1 &gt; str2
  672. * @since jEdit 4.0pre1
  673. */
  674. public static int compareStrings(String str1, String str2, boolean ignoreCase)
  675. {
  676. char[] char1 = str1.toCharArray();
  677. char[] char2 = str2.toCharArray();
  678. int len = Math.min(char1.length,char2.length);
  679. for(int i = 0, j = 0; i < len && j < len; i++, j++)
  680. {
  681. char ch1 = char1[i];
  682. char ch2 = char2[j];
  683. if(Character.isDigit(ch1) && Character.isDigit(ch2)
  684. && ch1 != '0' && ch2 != '0')
  685. {
  686. int _i = i + 1;
  687. int _j = j + 1;
  688. for(; _i < char1.length; _i++)
  689. {
  690. if(!Character.isDigit(char1[_i]))
  691. {
  692. //_i--;
  693. break;
  694. }
  695. }
  696. for(; _j < char2.length; _j++)
  697. {
  698. if(!Character.isDigit(char2[_j]))
  699. {
  700. //_j--;
  701. break;
  702. }
  703. }
  704. int len1 = _i - i;
  705. int len2 = _j - j;
  706. if(len1 > len2)
  707. return 1;
  708. else if(len1 < len2)
  709. return -1;
  710. else
  711. {
  712. for(int k = 0; k < len1; k++)
  713. {
  714. ch1 = char1[i + k];
  715. ch2 = char2[j + k];
  716. if(ch1 != ch2)
  717. return ch1 - ch2;
  718. }
  719. }
  720. i = _i - 1;
  721. j = _j - 1;
  722. }
  723. else
  724. {
  725. if(ignoreCase)
  726. {
  727. ch1 = Character.toLowerCase(ch1);
  728. ch2 = Character.toLowerCase(ch2);
  729. }
  730. if(ch1 != ch2)
  731. return ch1 - ch2;
  732. }
  733. }
  734. return char1.length - char2.length;
  735. } //}}}
  736. //{{{ stringsEqual() method
  737. /**
  738. * Returns if two strings are equal. This correctly handles null pointers,
  739. * as opposed to calling <code>s1.equals(s2)</code>.
  740. * @since jEdit 4.1pre5
  741. */
  742. public static boolean stringsEqual(String s1, String s2)
  743. {
  744. if(s1 == null)
  745. {
  746. if(s2 == null)
  747. return true;
  748. else
  749. return false;
  750. }
  751. else if(s2 == null)
  752. return false;
  753. else
  754. return s1.equals(s2);
  755. } //}}}
  756. //}}}
  757. //{{{ Sorting methods
  758. //{{{ quicksort() method
  759. /**
  760. * Sorts the specified array. Equivalent to calling
  761. * <code>Arrays.sort()</code>.
  762. * @param obj The array
  763. * @param compare Compares the objects
  764. * @since jEdit 4.0pre4
  765. */
  766. public static void quicksort(Object[] obj, Comparator compare)
  767. {
  768. Arrays.sort(obj,compare);
  769. } //}}}
  770. //{{{ quicksort() method
  771. /**
  772. * Sorts the specified vector.
  773. * @param vector The vector
  774. * @param compare Compares the objects
  775. * @since jEdit 4.0pre4
  776. */
  777. public static void quicksort(Vector vector, Comparator compare)
  778. {
  779. Collections.sort(vector,compare);
  780. } //}}}
  781. //{{{ quicksort() method
  782. /**
  783. * Sorts the specified list.
  784. * @param list The list
  785. * @param compare Compares the objects
  786. * @since jEdit 4.0pre4
  787. */
  788. public static void quicksort(List list, Comparator compare)
  789. {
  790. Collections.sort(list,compare);
  791. } //}}}
  792. //{{{ quicksort() method
  793. /**
  794. * Sorts the specified array. Equivalent to calling
  795. * <code>Arrays.sort()</code>.
  796. * @param obj The array
  797. * @param compare Compares the objects
  798. */
  799. public static void quicksort(Object[] obj, Compare compare)
  800. {
  801. Arrays.sort(obj,compare);
  802. } //}}}
  803. //{{{ quicksort() method
  804. /**
  805. * Sorts the specified vector.
  806. * @param vector The vector
  807. * @param compare Compares the objects
  808. */
  809. public static void quicksort(Vector vector, Compare compare)
  810. {
  811. Collections.sort(vector,compare);
  812. } //}}}
  813. //{{{ Compare interface
  814. /**
  815. * An interface for comparing objects. This is a hold-over from
  816. * they days when jEdit had its own sorting API due to JDK 1.1
  817. * compatibility requirements. Use <code>java.util.Comparable</code>
  818. * instead.
  819. */
  820. public interface Compare extends Comparator
  821. {
  822. int compare(Object obj1, Object obj2);
  823. } //}}}
  824. //{{{ StringCompare class
  825. /**
  826. * Compares strings.
  827. */
  828. public static class StringCompare implements Compare
  829. {
  830. public int compare(Object obj1, Object obj2)
  831. {
  832. return compareStrings(obj1.toString(),
  833. obj2.toString(),false);
  834. }
  835. } //}}}
  836. //{{{ StringICaseCompare class
  837. /**
  838. * Compares strings ignoring case.
  839. */
  840. public static class StringICaseCompare implements Compare
  841. {
  842. public int compare(Object obj1, Object obj2)
  843. {
  844. return compareStrings(obj1.toString(),
  845. obj2.toString(),true);
  846. }
  847. } //}}}
  848. //{{{ MenuItemCompare class
  849. public static class MenuItemCompare implements Compare
  850. {
  851. public int compare(Object obj1, Object obj2)
  852. {
  853. return compareStrings(((JMenuItem)obj1).getText(),
  854. ((JMenuItem)obj2).getText(),true);
  855. }
  856. } //}}}
  857. //}}}
  858. //{{{ buildToVersion() method
  859. /**
  860. * Converts an internal version number (build) into a
  861. * `human-readable' form.
  862. * @param build The build
  863. */
  864. public static String buildToVersion(String build)
  865. {
  866. if(build.length() != 11)
  867. return "<unknown version: " + build + ">";
  868. // First 2 chars are the major version number
  869. int major = Integer.parseInt(build.substring(0,2));
  870. // Second 2 are the minor number
  871. int minor = Integer.parseInt(build.substring(3,5));
  872. // Then the pre-release status
  873. int beta = Integer.parseInt(build.substring(6,8));
  874. // Finally the bug fix release
  875. int bugfix = Integer.parseInt(build.substring(9,11));
  876. return "" + major + "." + minor
  877. + (beta != 99 ? "pre" + beta :
  878. (bugfix != 0 ? "." + bugfix : "final"));
  879. } //}}}
  880. //{{{ isToolsJarAvailable() method
  881. /**
  882. * If on JDK 1.2 or higher, make sure that tools.jar is available.
  883. * This method should be called by plugins requiring the classes
  884. * in this library.
  885. * <p>
  886. * tools.jar is searched for in the following places:
  887. * <ol>
  888. * <li>the classpath that was used when jEdit was started,
  889. * <li>jEdit's jars folder in the user's home,
  890. * <li>jEdit's system jars folder,
  891. * <li><i>java.home</i>/lib/. In this case, tools.jar is added to
  892. * jEdit's list of known jars using jEdit.addPluginJAR(),
  893. * so that it gets loaded through JARClassLoader.
  894. * </ol><p>
  895. *
  896. * On older JDK's this method does not perform any checks, and returns
  897. * <code>true</code> (even though there is no tools.jar).
  898. *
  899. * @return <code>false</code> if and only if on JDK 1.2 and tools.jar
  900. * could not be found. In this case it prints some warnings on Log,
  901. * too, about the places where it was searched for.
  902. * @since jEdit 3.2.2
  903. */
  904. public static boolean isToolsJarAvailable()
  905. {
  906. Log.log(Log.DEBUG, MiscUtilities.class,"Searching for tools.jar...");
  907. Vector paths = new Vector();
  908. //{{{ 1. Check whether tools.jar is in the system classpath:
  909. paths.addElement("System classpath: "
  910. + System.getProperty("java.class.path"));
  911. try
  912. {
  913. // Either class sun.tools.javac.Main or
  914. // com.sun.tools.javac.Main must be there:
  915. try
  916. {
  917. Class.forName("sun.tools.javac.Main");
  918. }
  919. catch(ClassNotFoundException e1)
  920. {
  921. Class.forName("com.sun.tools.javac.Main");
  922. }
  923. Log.log(Log.DEBUG, MiscUtilities.class,
  924. "- is in classpath. Fine.");
  925. return true;
  926. }
  927. catch(ClassNotFoundException e)
  928. {
  929. //Log.log(Log.DEBUG, MiscUtilities.class,
  930. // "- is not in system classpath.");
  931. } //}}}
  932. //{{{ 2. Check whether it is in the jEdit user settings jars folder:
  933. String settingsDir = jEdit.getSettingsDirectory();
  934. if(settingsDir != null)
  935. {
  936. String toolsPath = constructPath(settingsDir, "jars",
  937. "tools.jar");
  938. paths.addElement(toolsPath);
  939. if(new File(toolsPath).exists())
  940. {
  941. Log.log(Log.DEBUG, MiscUtilities.class,
  942. "- is in the user's jars folder. Fine.");
  943. // jEdit will load it automatically
  944. return true;
  945. }
  946. } //}}}
  947. //{{{ 3. Check whether it is in jEdit's system jars folder:
  948. String jEditDir = jEdit.getJEditHome();
  949. if(jEditDir != null)
  950. {
  951. String toolsPath = constructPath(jEditDir, "jars", "tools.jar");
  952. paths.addElement(toolsPath);
  953. if(new File(toolsPath).exists())
  954. {
  955. Log.log(Log.DEBUG, MiscUtilities.class,
  956. "- is in jEdit's system jars folder. Fine.");
  957. // jEdit will load it automatically
  958. return true;
  959. }
  960. } //}}}
  961. //{{{ 4. Check whether it is in <java.home>/lib:
  962. String toolsPath = System.getProperty("java.home");
  963. if(toolsPath.toLowerCase().endsWith(File.separator + "jre"))
  964. toolsPath = toolsPath.substring(0, toolsPath.length() - 4);
  965. toolsPath = constructPath(toolsPath, "lib", "tools.jar");
  966. paths.addElement(toolsPath);
  967. if(!(new File(toolsPath).exists()))
  968. {
  969. Log.log(Log.WARNING, MiscUtilities.class,
  970. "Could not find tools.jar.\n"
  971. + "I checked the following locations:\n"
  972. + paths.toString());
  973. return false;
  974. } //}}}
  975. //{{{ Load it, if not yet done:
  976. EditPlugin.JAR jar = jEdit.getPluginJAR(toolsPath);
  977. if(jar == null)
  978. {
  979. Log.log(Log.DEBUG, MiscUtilities.class,
  980. "- adding " + toolsPath + " to jEdit plugins.");
  981. try
  982. {
  983. jEdit.addPluginJAR(new EditPlugin.JAR(toolsPath,
  984. new JARClassLoader(toolsPath)));
  985. }
  986. catch(IOException ioex)
  987. {
  988. Log.log(Log.ERROR, MiscUtilities.class,
  989. "- I/O error loading " + toolsPath);
  990. Log.log(Log.ERROR, MiscUtilities.class, ioex);
  991. return false;
  992. }
  993. }
  994. else
  995. Log.log(Log.DEBUG, MiscUtilities.class,
  996. "- has been loaded before.");
  997. //}}}
  998. return true;
  999. } //}}}
  1000. //{{{ Private members
  1001. private MiscUtilities() {}
  1002. //{{{ resolveSymlinks() method
  1003. private static String resolveSymlinks(String path)
  1004. {
  1005. try
  1006. {
  1007. return new File(path).getCanonicalPath();
  1008. }
  1009. catch(IOException io)
  1010. {
  1011. return path;
  1012. }
  1013. } //}}}
  1014. //}}}
  1015. }