PageRenderTime 321ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 1ms

/jEdit/tags/jedit-4-0-pre3/org/gjt/sp/jedit/MiscUtilities.java

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