PageRenderTime 51ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 1ms

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

#
Java | 1865 lines | 1014 code | 144 blank | 707 comment | 281 complexity | 7ad52f1be46430dde30953518f87b4a9 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

Large files files are truncated, but you can click here to view the full file

  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, 2005 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 javax.swing.text.Segment;
  27. import javax.swing.JMenuItem;
  28. import java.io.*;
  29. import java.net.MalformedURLException;
  30. import java.net.URL;
  31. import java.nio.charset.MalformedInputException;
  32. import java.text.DecimalFormat;
  33. import java.util.*;
  34. import java.util.regex.Matcher;
  35. import java.util.regex.Pattern;
  36. import org.xml.sax.InputSource;
  37. import org.xml.sax.helpers.DefaultHandler;
  38. import org.gjt.sp.jedit.io.*;
  39. import org.gjt.sp.util.Log;
  40. import org.gjt.sp.util.ProgressObserver;
  41. import org.gjt.sp.util.StandardUtilities;
  42. import org.gjt.sp.util.IOUtilities;
  43. import org.gjt.sp.util.XMLUtilities;
  44. import org.gjt.sp.jedit.menu.MenuItemTextComparator;
  45. import org.gjt.sp.jedit.buffer.JEditBuffer;
  46. //}}}
  47. /**
  48. * Path name manipulation, string manipulation, and more.<p>
  49. *
  50. * The most frequently used members of this class are:<p>
  51. *
  52. * <b>Some path name methods:</b><p>
  53. * <ul>
  54. * <li>{@link #getFileName(String)}</li>
  55. * <li>{@link #getParentOfPath(String)}</li>
  56. * <li>{@link #constructPath(String,String)}</li>
  57. * </ul>
  58. * <b>String comparison:</b><p>
  59. * A {@link #compareStrings(String,String,boolean)} method that unlike
  60. * <function>String.compareTo()</function>, correctly recognizes and handles
  61. * embedded numbers.<p>
  62. *
  63. * This class also defines several inner classes for use with the
  64. * sorting features of the Java collections API:
  65. *
  66. * <ul>
  67. * <li>{@link MiscUtilities.StringICaseCompare}</li>
  68. * <li>{@link MiscUtilities.MenuItemCompare}</li>
  69. * </ul>
  70. *
  71. * For example, you might call:<p>
  72. *
  73. * <code>Arrays.sort(myListOfStrings,
  74. * new MiscUtilities.StringICaseCompare());</code>
  75. *
  76. * @author Slava Pestov
  77. * @author John Gellene (API documentation)
  78. * @version $Id: MiscUtilities.java 19902 2011-09-02 16:59:40Z shlomy $
  79. */
  80. public class MiscUtilities
  81. {
  82. /**
  83. * This encoding is not supported by Java, yet it is useful.
  84. * A UTF-8 file that begins with 0xEFBBBF.
  85. * @deprecated
  86. * Extended encodings are now supported as services.
  87. * This value is no longer used.
  88. */
  89. @Deprecated public static final String UTF_8_Y = "UTF-8Y";
  90. //{{{ Path name methods
  91. //{{{ canonPath() method
  92. /**
  93. * @return the canonical form of the specified path name. Currently
  94. * only expands a leading <code>~</code>. <b>For local path names
  95. * only.</b>
  96. * @param path The path name
  97. * @since jEdit 4.0pre2
  98. */
  99. public static String canonPath(String path)
  100. {
  101. if(path.length() == 0)
  102. return path;
  103. if(path.startsWith("file://"))
  104. path = path.substring("file://".length());
  105. else if(path.startsWith("file:"))
  106. path = path.substring("file:".length());
  107. else if(isURL(path))
  108. return path;
  109. if(File.separatorChar == '\\')
  110. {
  111. // get rid of mixed paths on Windows
  112. path = path.replace('/','\\');
  113. // also get rid of trailing spaces on Windows
  114. int trim = path.length();
  115. while(path.charAt(trim - 1) == ' ')
  116. trim--;
  117. if (path.charAt(trim - 1) == '\\')
  118. while (trim > 1 && path.charAt(trim - 2) == '\\')
  119. {
  120. trim--;
  121. }
  122. path = path.substring(0,trim);
  123. }
  124. if(path.startsWith('~' + File.separator))
  125. {
  126. path = path.substring(2);
  127. String home = System.getProperty("user.home");
  128. if(home.endsWith(File.separator))
  129. return home + path;
  130. else
  131. return home + File.separator + path;
  132. }
  133. else if("~".equals(path))
  134. return System.getProperty("user.home");
  135. else if ("-".equals(path))
  136. return getParentOfPath(jEdit.getActiveView().getBuffer().getPath());
  137. else
  138. return path;
  139. } //}}}
  140. //{{{ expandVariables() method
  141. static final String varPatternString = "(\\$([a-zA-Z0-9_]+))";
  142. static final String varPatternString2 = "(\\$\\{([^}]+)\\})";
  143. static final String winPatternString = "(%([^%]+)%)";
  144. static final Pattern varPattern = Pattern.compile(varPatternString);
  145. static final Pattern varPattern2 = Pattern.compile(varPatternString2);
  146. static final Pattern winPattern = Pattern.compile(winPatternString);
  147. /** Accepts a string from the user which may contain variables of various syntaxes.
  148. * The function supports the following expansion syntaxes:
  149. * $varname
  150. * ${varname} (on non-windows)
  151. * %varname% (on Windows)
  152. * And expand each of these by looking at the system environment variables for possible
  153. * expansions.
  154. * @return a string which is either the unchanged input string, or one with expanded variables.
  155. * @since 4.3pre7
  156. * @author ezust
  157. */
  158. public static String expandVariables(String arg)
  159. {
  160. Pattern p = varPattern;
  161. Matcher m = p.matcher(arg);
  162. if (!m.find())
  163. {
  164. if (OperatingSystem.isWindows())
  165. p = winPattern;
  166. else p = varPattern2;
  167. m = p.matcher(arg);
  168. if (!m.find()) // no variables to substitute
  169. return arg;
  170. }
  171. String varName = m.group(2);
  172. String expansion = System.getenv(varName);
  173. if (expansion == null)
  174. { // try everything uppercase?
  175. varName = varName.toUpperCase();
  176. String uparg = arg.toUpperCase();
  177. m = p.matcher(uparg);
  178. expansion = System.getenv(varName);
  179. }
  180. if (expansion != null)
  181. {
  182. expansion = expansion.replace("\\", "\\\\");
  183. return m.replaceFirst(expansion);
  184. }
  185. return arg;
  186. } //}}}
  187. //{{{ abbreviate() method
  188. /** returns an abbreviated path, replacing
  189. * values with variables, if a prefix exists.
  190. * @since jEdit 4.3pre16
  191. */
  192. public static String abbreviate(String path)
  193. {
  194. if (svc == null)
  195. svc = new VarCompressor();
  196. return svc.compress(path);
  197. } //}}}
  198. //{{{ resolveSymlinks() method
  199. /**
  200. * Resolves any symbolic links in the path name specified
  201. * using <code>File.getCanonicalPath()</code>. <b>For local path
  202. * names only.</b>
  203. * @since jEdit 4.2pre1
  204. */
  205. public static String resolveSymlinks(String path)
  206. {
  207. if(isURL(path))
  208. return path;
  209. // 2 aug 2003: OS/2 Java has a broken getCanonicalPath()
  210. if(OperatingSystem.isOS2())
  211. return path;
  212. // 18 nov 2003: calling this on a drive letter on Windows causes
  213. // drive access
  214. if(OperatingSystem.isDOSDerived())
  215. {
  216. if(path.length() == 2 || path.length() == 3)
  217. {
  218. if(path.charAt(1) == ':')
  219. return path;
  220. }
  221. }
  222. try
  223. {
  224. return new File(path).getCanonicalPath();
  225. }
  226. catch(IOException io)
  227. {
  228. return path;
  229. }
  230. } //}}}
  231. //{{{ isAbsolutePath() method
  232. /**
  233. * Returns if the specified path name is an absolute path or URL.
  234. * @since jEdit 4.1pre11
  235. */
  236. public static boolean isAbsolutePath(String path)
  237. {
  238. if(isURL(path))
  239. return true;
  240. else if(path.startsWith("~/") || path.startsWith('~' + File.separator) || "~".equals(path))
  241. return true;
  242. else if ("-".equals(path))
  243. return true;
  244. else if(OperatingSystem.isDOSDerived())
  245. {
  246. if(path.length() == 2 && path.charAt(1) == ':')
  247. return true;
  248. if(path.length() > 2 && path.charAt(1) == ':'
  249. && (path.charAt(2) == '\\'
  250. || path.charAt(2) == '/'))
  251. return true;
  252. if(path.startsWith("\\\\")
  253. || path.startsWith("//"))
  254. return true;
  255. }
  256. // not sure if this is correct for OpenVMS.
  257. else if(OperatingSystem.isUnix()
  258. || OperatingSystem.isVMS())
  259. {
  260. // nice and simple
  261. if(path.length() > 0 && path.charAt(0) == '/')
  262. return true;
  263. }
  264. return false;
  265. } //}}}
  266. //{{{ constructPath() methods
  267. /**
  268. * Constructs an absolute path name from a directory and another
  269. * path name. This method is VFS-aware.
  270. * @param parent The directory
  271. * @param path The path name
  272. */
  273. public static String constructPath(String parent, String path)
  274. {
  275. if(isAbsolutePath(path))
  276. return canonPath(path);
  277. if (parent == null)
  278. parent = System.getProperty("user.dir");
  279. if (path == null || path.length() == 0)
  280. return parent;
  281. // have to handle this case specially on windows.
  282. // insert \ between, eg A: and myfile.txt.
  283. if(OperatingSystem.isDOSDerived())
  284. {
  285. if(path.length() == 2 && path.charAt(1) == ':')
  286. return path;
  287. else if(path.length() > 2 && path.charAt(1) == ':'
  288. && path.charAt(2) != '\\')
  289. {
  290. path = path.substring(0,2) + '\\'
  291. + path.substring(2);
  292. return canonPath(path);
  293. }
  294. }
  295. String dd = ".." + File.separator;
  296. String d = '.' + File.separator;
  297. for(;;)
  298. {
  299. if(".".equals(path))
  300. return parent;
  301. else if("..".equals(path))
  302. return getParentOfPath(parent);
  303. else if(path.startsWith(dd) || path.startsWith("../"))
  304. {
  305. parent = getParentOfPath(parent);
  306. path = path.substring(3);
  307. }
  308. else if(path.startsWith(d) || path.startsWith("./"))
  309. path = path.substring(2);
  310. else
  311. break;
  312. }
  313. if(path.length() == 0)
  314. return parent;
  315. if(OperatingSystem.isDOSDerived()
  316. && !isURL(parent)
  317. && path.charAt(0) == '\\')
  318. parent = parent.substring(0,2);
  319. VFS vfs = VFSManager.getVFSForPath(parent);
  320. return canonPath(vfs.constructPath(parent,path));
  321. }
  322. /**
  323. * Constructs an absolute path name from three path components.
  324. * This method is VFS-aware.
  325. * @param parent The parent directory
  326. * @param path1 The first path
  327. * @param path2 The second path
  328. */
  329. public static String constructPath(String parent,
  330. String path1, String path2)
  331. {
  332. return constructPath(constructPath(parent,path1),path2);
  333. } //}}}
  334. //{{{ concatPath() method
  335. /**
  336. * Like {@link #constructPath}, except <code>path</code> will be
  337. * appended to <code>parent</code> even if it is absolute.
  338. * <b>For local path names only.</b>.
  339. *
  340. * @param parent the parent path
  341. * @param path the path to append to the parent
  342. */
  343. public static String concatPath(String parent, String path)
  344. {
  345. parent = canonPath(parent);
  346. path = canonPath(path);
  347. // Make all child paths relative.
  348. if (path.startsWith(File.separator))
  349. path = path.substring(1);
  350. else if (path.length() >= 3 && path.charAt(1) == ':')
  351. path = path.replace(':', File.separatorChar);
  352. if (parent == null)
  353. parent = System.getProperty("user.dir");
  354. if (parent.endsWith(File.separator))
  355. return parent + path;
  356. else
  357. return parent + File.separator + path;
  358. } //}}}
  359. //{{{ getFirstSeparatorIndex() method
  360. /**
  361. * Return the first index of either / or the OS-specific file
  362. * separator.
  363. * @param path The path
  364. * @since jEdit 4.3pre3
  365. */
  366. public static int getFirstSeparatorIndex(String path)
  367. {
  368. int start = getPathStart(path);
  369. int index = path.indexOf('/',start);
  370. if(index == -1)
  371. index = path.indexOf(File.separatorChar,start);
  372. return index;
  373. } //}}}
  374. //{{{ getLastSeparatorIndex() method
  375. /**
  376. * Return the last index of either / or the OS-specific file
  377. * separator.
  378. * @param path The path
  379. * @since jEdit 4.3pre3
  380. */
  381. public static int getLastSeparatorIndex(String path)
  382. {
  383. int start = getPathStart(path);
  384. if(start != 0)
  385. path = path.substring(start);
  386. int index = Math.max(
  387. path.lastIndexOf('/'), path.lastIndexOf(File.separatorChar));
  388. if(index == -1)
  389. return index;
  390. else
  391. return index + start;
  392. } //}}}
  393. //{{{ getFileExtension() method
  394. /**
  395. * Returns the extension of the specified filename, or an empty
  396. * string if there is none.
  397. * @param path The path
  398. */
  399. public static String getFileExtension(String path)
  400. {
  401. int fsIndex = getLastSeparatorIndex(path);
  402. int index = path.lastIndexOf('.');
  403. // there could be a dot in the path and no file extension
  404. if(index == -1 || index < fsIndex )
  405. return "";
  406. else
  407. return path.substring(index);
  408. } //}}}
  409. //{{{ getFileName() method
  410. /**
  411. * Returns the last component of the specified path.
  412. * This method is VFS-aware.
  413. * @param path The path name
  414. */
  415. public static String getFileName(String path)
  416. {
  417. return VFSManager.getVFSForPath(path).getFileName(path);
  418. } //}}}
  419. //{{{ getFileNameNoExtension() method
  420. /**
  421. * Returns the last component of the specified path name without the
  422. * trailing extension (if there is one).
  423. * @param path The path name
  424. * @since jEdit 4.0pre8
  425. */
  426. public static String getFileNameNoExtension(String path)
  427. {
  428. String name = getFileName(path);
  429. int index = name.indexOf('.');
  430. if(index == -1)
  431. return name;
  432. else
  433. return name.substring(0,index);
  434. } //}}}
  435. //{{{ getFileParent() method
  436. /**
  437. * @deprecated Call getParentOfPath() instead
  438. */
  439. @Deprecated
  440. public static String getFileParent(String path)
  441. {
  442. return getParentOfPath(path);
  443. } //}}}
  444. //{{{ getParentOfPath() method
  445. /**
  446. * Returns the parent of the specified path. This method is VFS-aware.
  447. * @param path The path name
  448. * @since jEdit 2.6pre5
  449. */
  450. public static String getParentOfPath(String path)
  451. {
  452. return VFSManager.getVFSForPath(path).getParentOfPath(path);
  453. } //}}}
  454. //{{{ getFileProtocol() method
  455. /**
  456. * @deprecated Call getProtocolOfURL() instead
  457. */
  458. @Deprecated
  459. public static String getFileProtocol(String url)
  460. {
  461. return getProtocolOfURL(url);
  462. } //}}}
  463. //{{{ getProtocolOfURL() method
  464. /**
  465. * Returns the protocol specified by a URL.
  466. * @param url The URL
  467. * @since jEdit 2.6pre5
  468. */
  469. public static String getProtocolOfURL(String url)
  470. {
  471. return url.substring(0,url.indexOf(':'));
  472. } //}}}
  473. //{{{ isURL() method
  474. /**
  475. * Checks if the specified string is a URL.
  476. * @param str The string to check
  477. * @return True if the string is a URL, false otherwise
  478. */
  479. public static boolean isURL(String str)
  480. {
  481. int fsIndex = getLastSeparatorIndex(str);
  482. if(fsIndex == 0) // /etc/passwd
  483. return false;
  484. else if(fsIndex == 2) // C:\AUTOEXEC.BAT
  485. return false;
  486. int cIndex = str.indexOf(':');
  487. if(cIndex <= 1) // D:\WINDOWS, or doesn't contain : at all
  488. return false;
  489. String protocol = str.substring(0,cIndex);
  490. VFS vfs = VFSManager.getVFSForProtocol(protocol);
  491. if(vfs != null && !(vfs instanceof UrlVFS))
  492. return true;
  493. try
  494. {
  495. new URL(str);
  496. return true;
  497. }
  498. catch(MalformedURLException mf)
  499. {
  500. return false;
  501. }
  502. } //}}}
  503. //{{{ saveBackup() methods
  504. /**
  505. * Saves a backup (optionally numbered) of a file.
  506. * @param file A local file
  507. * @param backups The number of backups. Must be >= 1. If > 1, backup
  508. * files will be numbered.
  509. * @param backupPrefix The backup file name prefix
  510. * @param backupSuffix The backup file name suffix
  511. * @param backupDirectory The directory where to save backups; if null,
  512. * they will be saved in the same directory as the file itself.
  513. * @since jEdit 4.0pre1
  514. */
  515. public static void saveBackup(File file, int backups,
  516. String backupPrefix, String backupSuffix,
  517. String backupDirectory)
  518. {
  519. saveBackup(file,backups,backupPrefix,backupSuffix,backupDirectory,0);
  520. }
  521. /**
  522. * Saves a backup (optionally numbered) of a file.
  523. * @param file A local file
  524. * @param backups The number of backups. Must be >= 1. If > 1, backup
  525. * files will be numbered.
  526. * @param backupPrefix The backup file name prefix
  527. * @param backupSuffix The backup file name suffix
  528. * @param backupDirectory The directory where to save backups; if null,
  529. * they will be saved in the same directory as the file itself.
  530. * @param backupTimeDistance The minimum time in minutes when a backup
  531. * version 1 shall be moved into version 2; if 0, backups are always
  532. * moved.
  533. * @since jEdit 4.2pre5
  534. */
  535. public static void saveBackup(File file, int backups,
  536. String backupPrefix, String backupSuffix,
  537. String backupDirectory, int backupTimeDistance)
  538. {
  539. if(backupPrefix == null)
  540. backupPrefix = "";
  541. if(backupSuffix == null)
  542. backupSuffix = "";
  543. String name = file.getName();
  544. // If backups is 1, create ~ file
  545. if(backups == 1)
  546. {
  547. File backupFile = new File(backupDirectory,
  548. backupPrefix + name + backupSuffix);
  549. long modTime = backupFile.lastModified();
  550. /* if backup file was created less than
  551. * 'backupTimeDistance' ago, we do not
  552. * create the backup */
  553. if(System.currentTimeMillis() - modTime
  554. >= backupTimeDistance)
  555. {
  556. Log.log(Log.DEBUG,MiscUtilities.class,
  557. "Saving backup of file \"" +
  558. file.getAbsolutePath() + "\" to \"" +
  559. backupFile.getAbsolutePath() + '"');
  560. backupFile.delete();
  561. if (!file.renameTo(backupFile))
  562. IOUtilities.moveFile(file, backupFile);
  563. }
  564. }
  565. // If backups > 1, move old ~n~ files, create ~1~ file
  566. else
  567. {
  568. /* delete a backup created using above method */
  569. new File(backupDirectory,
  570. backupPrefix + name + backupSuffix
  571. + backups + backupSuffix).delete();
  572. File firstBackup = new File(backupDirectory,
  573. backupPrefix + name + backupSuffix
  574. + '1' + backupSuffix);
  575. long modTime = firstBackup.lastModified();
  576. /* if backup file was created less than
  577. * 'backupTimeDistance' ago, we do not
  578. * create the backup */
  579. if(System.currentTimeMillis() - modTime
  580. >= backupTimeDistance)
  581. {
  582. for(int i = backups - 1; i > 0; i--)
  583. {
  584. File backup = new File(backupDirectory,
  585. backupPrefix + name
  586. + backupSuffix + i
  587. + backupSuffix);
  588. backup.renameTo(new File(backupDirectory,
  589. backupPrefix + name
  590. + backupSuffix + (i + 1)
  591. + backupSuffix));
  592. }
  593. File backupFile = new File(backupDirectory,
  594. backupPrefix + name + backupSuffix
  595. + '1' + backupSuffix);
  596. Log.log(Log.DEBUG,MiscUtilities.class,
  597. "Saving backup of file \"" +
  598. file.getAbsolutePath() + "\" to \"" +
  599. backupFile.getAbsolutePath() + '"');
  600. if (!file.renameTo(backupFile))
  601. IOUtilities.moveFile(file, backupFile);
  602. }
  603. }
  604. } //}}}
  605. //{{{ moveFile() method
  606. /**
  607. * Moves the source file to the destination.
  608. *
  609. * If the destination cannot be created or is a read-only file, the
  610. * method returns <code>false</code>. Otherwise, the contents of the
  611. * source are copied to the destination, the source is deleted,
  612. * and <code>true</code> is returned.
  613. *
  614. * @param source The source file to move.
  615. * @param dest The destination where to move the file.
  616. * @return true on success, false otherwise.
  617. *
  618. * @since jEdit 4.3pre1
  619. * @deprecated use {@link org.gjt.sp.util.IOUtilities#moveFile(java.io.File, java.io.File)}
  620. */
  621. @Deprecated
  622. public static boolean moveFile(File source, File dest)
  623. {
  624. return IOUtilities.moveFile(source, dest);
  625. } //}}}
  626. //{{{ copyStream() methods
  627. /**
  628. * Copy an input stream to an output stream.
  629. *
  630. * @param bufferSize the size of the buffer
  631. * @param progress the progress observer it could be null
  632. * @param in the input stream
  633. * @param out the output stream
  634. * @param canStop if true, the copy can be stopped by interrupting the thread
  635. * @return <code>true</code> if the copy was done, <code>false</code> if it was interrupted
  636. * @throws IOException IOException If an I/O error occurs
  637. * @since jEdit 4.3pre3
  638. * @deprecated use {@link IOUtilities#copyStream(int, org.gjt.sp.util.ProgressObserver, java.io.InputStream, java.io.OutputStream, boolean)}
  639. */
  640. @Deprecated
  641. public static boolean copyStream(int bufferSize, ProgressObserver progress,
  642. InputStream in, OutputStream out, boolean canStop)
  643. throws IOException
  644. {
  645. return IOUtilities.copyStream(bufferSize, progress, in, out, canStop);
  646. }
  647. /**
  648. * Copy an input stream to an output stream with a buffer of 4096 bytes.
  649. *
  650. * @param progress the progress observer it could be null
  651. * @param in the input stream
  652. * @param out the output stream
  653. * @param canStop if true, the copy can be stopped by interrupting the thread
  654. * @return <code>true</code> if the copy was done, <code>false</code> if it was interrupted
  655. * @throws IOException IOException If an I/O error occurs
  656. * @since jEdit 4.3pre3
  657. * @deprecated use {@link IOUtilities#copyStream(org.gjt.sp.util.ProgressObserver, java.io.InputStream, java.io.OutputStream, boolean)}
  658. */
  659. @Deprecated
  660. public static boolean copyStream(ProgressObserver progress, InputStream in, OutputStream out, boolean canStop)
  661. throws IOException
  662. {
  663. return IOUtilities.copyStream(4096,progress, in, out, canStop);
  664. } //}}}
  665. //{{{ isBinary() methods
  666. /**
  667. * Check if a Reader is binary.
  668. * @deprecated
  669. * Use isBinary(InputStream) instead.
  670. */
  671. @Deprecated
  672. public static boolean isBinary(Reader reader) throws IOException
  673. {
  674. return containsNullCharacter(reader);
  675. }
  676. /**
  677. * Check if an InputStream is binary.
  678. * First this tries encoding auto detection. If an encoding is
  679. * detected, the stream should be a text stream. Otherwise, this
  680. * will check the first characters 100
  681. * (jEdit property vfs.binaryCheck.length) in the system default
  682. * encoding. If more than 1 (jEdit property vfs.binaryCheck.count)
  683. * NUL(\u0000) was found, the stream is declared binary.
  684. *
  685. * This is not 100% because sometimes the autodetection could fail.
  686. *
  687. * This method will not close the stream. You have to do it yourself
  688. *
  689. * @param in the stream
  690. * @return <code>true</code> if the stream was detected as binary
  691. * @throws IOException IOException If an I/O error occurs
  692. * @since jEdit 4.3pre10
  693. */
  694. public static boolean isBinary(InputStream in) throws IOException
  695. {
  696. AutoDetection.Result detection = new AutoDetection.Result(in);
  697. // If an encoding is detected, this is a text stream
  698. if (detection.getDetectedEncoding() != null)
  699. {
  700. return false;
  701. }
  702. // Read the stream in system default encoding. The encoding
  703. // might be wrong. But enough for binary detection.
  704. try
  705. {
  706. return containsNullCharacter(
  707. new InputStreamReader(detection.getRewindedStream()));
  708. }
  709. catch (MalformedInputException mie)
  710. {
  711. // This error probably means the input is binary.
  712. return true;
  713. }
  714. } //}}}
  715. //{{{ isBackup() method
  716. /**
  717. * Check if the filename is a backup file.
  718. * @param filename the filename to check
  719. * @return true if this is a backup file.
  720. * @since jEdit 4.3pre5
  721. */
  722. public static boolean isBackup(String filename)
  723. {
  724. if (filename.startsWith("#")) return true;
  725. if (filename.endsWith("~")) return true;
  726. if (filename.endsWith(".bak")) return true;
  727. return false;
  728. } //}}}
  729. //{{{ autodetect() method
  730. /**
  731. * Tries to detect if the stream is gzipped, and if it has an encoding
  732. * specified with an XML PI.
  733. *
  734. * @param in the input stream reader that must be autodetected
  735. * @param buffer a buffer. It can be null if you only want to autodetect the encoding of a file
  736. * @return a Reader using the detected encoding
  737. * @throws IOException io exception during read
  738. * @since jEdit 4.3pre5
  739. */
  740. public static Reader autodetect(InputStream in, Buffer buffer) throws IOException
  741. {
  742. String encoding;
  743. if (buffer == null)
  744. encoding = System.getProperty("file.encoding");
  745. else
  746. encoding = buffer.getStringProperty(JEditBuffer.ENCODING);
  747. boolean gzipped = false;
  748. if (buffer == null || buffer.getBooleanProperty(Buffer.ENCODING_AUTODETECT))
  749. {
  750. AutoDetection.Result detection = new AutoDetection.Result(in);
  751. gzipped = detection.streamIsGzipped();
  752. if (gzipped)
  753. {
  754. Log.log(Log.DEBUG, MiscUtilities.class
  755. , "Stream is Gzipped");
  756. }
  757. String detected = detection.getDetectedEncoding();
  758. if (detected != null)
  759. {
  760. encoding = detected;
  761. Log.log(Log.DEBUG, MiscUtilities.class
  762. , "Stream encoding detected is " + detected);
  763. }
  764. in = detection.getRewindedStream();
  765. }
  766. else
  767. {
  768. // Make the stream buffered in the same way.
  769. in = AutoDetection.getMarkedStream(in);
  770. }
  771. Reader result = EncodingServer.getTextReader(in, encoding);
  772. if (buffer != null)
  773. {
  774. // Store the successful properties.
  775. if (gzipped)
  776. {
  777. buffer.setBooleanProperty(Buffer.GZIPPED,true);
  778. }
  779. buffer.setProperty(JEditBuffer.ENCODING, encoding);
  780. }
  781. return result;
  782. } //}}}
  783. //{{{ closeQuietly() method
  784. /**
  785. * Method that will close an {@link InputStream} ignoring it if it is null and ignoring exceptions.
  786. *
  787. * @param in the InputStream to close.
  788. * @since jEdit 4.3pre3
  789. * @deprecated use {@link IOUtilities#closeQuietly(java.io.InputStream)}
  790. */
  791. @Deprecated
  792. public static void closeQuietly(InputStream in)
  793. {
  794. IOUtilities.closeQuietly(in);
  795. } //}}}
  796. //{{{ copyStream() method
  797. /**
  798. * Method that will close an {@link OutputStream} ignoring it if it is null and ignoring exceptions.
  799. *
  800. * @param out the OutputStream to close.
  801. * @since jEdit 4.3pre3
  802. * @deprecated use {@link IOUtilities#closeQuietly(java.io.OutputStream)}
  803. */
  804. @Deprecated
  805. public static void closeQuietly(OutputStream out)
  806. {
  807. IOUtilities.closeQuietly(out);
  808. } //}}}
  809. //{{{ fileToClass() method
  810. /**
  811. * Converts a file name to a class name. All slash characters are
  812. * replaced with periods and the trailing '.class' is removed.
  813. * @param name The file name
  814. */
  815. public static String fileToClass(String name)
  816. {
  817. char[] clsName = name.toCharArray();
  818. for(int i = clsName.length - 6; i >= 0; i--)
  819. if(clsName[i] == '/')
  820. clsName[i] = '.';
  821. return new String(clsName,0,clsName.length - 6);
  822. } //}}}
  823. //{{{ classToFile() method
  824. /**
  825. * Converts a class name to a file name. All periods are replaced
  826. * with slashes and the '.class' extension is added.
  827. * @param name The class name
  828. */
  829. public static String classToFile(String name)
  830. {
  831. return name.replace('.','/').concat(".class");
  832. } //}}}
  833. //{{{ pathsEqual() method
  834. /**
  835. * @param p1 A path name
  836. * @param p2 A path name
  837. * @return True if both paths are equal, ignoring trailing slashes, as
  838. * well as case insensitivity on Windows.
  839. * @since jEdit 4.3pre2
  840. */
  841. public static boolean pathsEqual(String p1, String p2)
  842. {
  843. VFS v1 = VFSManager.getVFSForPath(p1);
  844. VFS v2 = VFSManager.getVFSForPath(p2);
  845. if(v1 != v2)
  846. return false;
  847. if(p1.endsWith("/") || p1.endsWith(File.separator))
  848. p1 = p1.substring(0,p1.length() - 1);
  849. if(p2.endsWith("/") || p2.endsWith(File.separator))
  850. p2 = p2.substring(0,p2.length() - 1);
  851. if((v1.getCapabilities() & VFS.CASE_INSENSITIVE_CAP) != 0)
  852. return p1.equalsIgnoreCase(p2);
  853. else
  854. return p1.equals(p2);
  855. } //}}}
  856. //}}}
  857. //{{{ Text methods
  858. //{{{ getLeadingWhiteSpace() method
  859. /**
  860. * Returns the number of leading white space characters in the
  861. * specified string.
  862. * @param str The string
  863. * @deprecated use {@link org.gjt.sp.util.StandardUtilities#getLeadingWhiteSpace(String)}
  864. */
  865. @Deprecated
  866. public static int getLeadingWhiteSpace(String str)
  867. {
  868. return StandardUtilities.getLeadingWhiteSpace(str);
  869. } //}}}
  870. //{{{ getTrailingWhiteSpace() method
  871. /**
  872. * Returns the number of trailing whitespace characters in the
  873. * specified string.
  874. * @param str The string
  875. * @since jEdit 2.5pre5
  876. * @deprecated use {@link org.gjt.sp.util.StandardUtilities#getTrailingWhiteSpace(String)}
  877. */
  878. @Deprecated
  879. public static int getTrailingWhiteSpace(String str)
  880. {
  881. return StandardUtilities.getTrailingWhiteSpace(str);
  882. } //}}}
  883. //{{{ getLeadingWhiteSpaceWidth() method
  884. /**
  885. * Returns the width of the leading white space in the specified
  886. * string.
  887. * @param str The string
  888. * @param tabSize The tab size
  889. * @deprecated use {@link org.gjt.sp.util.StandardUtilities#getLeadingWhiteSpace(String)}
  890. */
  891. @Deprecated
  892. public static int getLeadingWhiteSpaceWidth(String str, int tabSize)
  893. {
  894. return StandardUtilities.getLeadingWhiteSpaceWidth(str, tabSize);
  895. } //}}}
  896. //{{{ getVirtualWidth() method
  897. /**
  898. * Returns the virtual column number (taking tabs into account) of the
  899. * specified offset in the segment.
  900. *
  901. * @param seg The segment
  902. * @param tabSize The tab size
  903. * @since jEdit 4.1pre1
  904. * @deprecated use {@link org.gjt.sp.util.StandardUtilities#getVirtualWidth(javax.swing.text.Segment, int)}
  905. */
  906. @Deprecated
  907. public static int getVirtualWidth(Segment seg, int tabSize)
  908. {
  909. return StandardUtilities.getVirtualWidth(seg, tabSize);
  910. } //}}}
  911. //{{{ getOffsetOfVirtualColumn() method
  912. /**
  913. * Returns the array offset of a virtual column number (taking tabs
  914. * into account) in the segment.
  915. *
  916. * @param seg The segment
  917. * @param tabSize The tab size
  918. * @param column The virtual column number
  919. * @param totalVirtualWidth If this array is non-null, the total
  920. * virtual width will be stored in its first location if this method
  921. * returns -1.
  922. *
  923. * @return -1 if the column is out of bounds
  924. *
  925. * @since jEdit 4.1pre1
  926. * @deprecated use {@link org.gjt.sp.util.StandardUtilities#getVirtualWidth(javax.swing.text.Segment, int)}
  927. */
  928. @Deprecated
  929. public static int getOffsetOfVirtualColumn(Segment seg, int tabSize,
  930. int column, int[] totalVirtualWidth)
  931. {
  932. return StandardUtilities.getOffsetOfVirtualColumn(seg, tabSize, column, totalVirtualWidth);
  933. } //}}}
  934. //{{{ createWhiteSpace() methods
  935. /**
  936. * Creates a string of white space with the specified length.<p>
  937. *
  938. * To get a whitespace string tuned to the current buffer's
  939. * settings, call this method as follows:
  940. *
  941. * <pre>myWhitespace = MiscUtilities.createWhiteSpace(myLength,
  942. * (buffer.getBooleanProperty("noTabs") ? 0
  943. * : buffer.getTabSize()));</pre>
  944. *
  945. * @param len The length
  946. * @param tabSize The tab size, or 0 if tabs are not to be used
  947. * @deprecated use {@link org.gjt.sp.util.StandardUtilities#createWhiteSpace(int, int)}
  948. */
  949. @Deprecated
  950. public static String createWhiteSpace(int len, int tabSize)
  951. {
  952. return StandardUtilities.createWhiteSpace(len,tabSize,0);
  953. }
  954. /**
  955. * Creates a string of white space with the specified length.<p>
  956. *
  957. * To get a whitespace string tuned to the current buffer's
  958. * settings, call this method as follows:
  959. *
  960. * <pre>myWhitespace = MiscUtilities.createWhiteSpace(myLength,
  961. * (buffer.getBooleanProperty("noTabs") ? 0
  962. * : buffer.getTabSize()));</pre>
  963. *
  964. * @param len The length
  965. * @param tabSize The tab size, or 0 if tabs are not to be used
  966. * @param start The start offset, for tab alignment
  967. * @since jEdit 4.2pre1
  968. * @deprecated use {@link org.gjt.sp.util.StandardUtilities#createWhiteSpace(int, int, int)}
  969. */
  970. @Deprecated
  971. public static String createWhiteSpace(int len, int tabSize, int start)
  972. {
  973. return StandardUtilities.createWhiteSpace(len, tabSize, start);
  974. } //}}}
  975. //{{{ globToRE() method
  976. /**
  977. * Converts a Unix-style glob to a regular expression.<p>
  978. *
  979. * ? becomes ., * becomes .*, {aa,bb} becomes (aa|bb).
  980. * @param glob The glob pattern
  981. * @deprecated Use {@link org.gjt.sp.util.StandardUtilities#globToRE(String)}.
  982. */
  983. @Deprecated
  984. public static String globToRE(String glob)
  985. {
  986. return StandardUtilities.globToRE(glob);
  987. } //}}}
  988. //{{{ escapesToChars() method
  989. /**
  990. * Converts "\n" and "\t" escapes in the specified string to
  991. * newlines and tabs.
  992. * @param str The string
  993. * @since jEdit 2.3pre1
  994. */
  995. public static String escapesToChars(String str)
  996. {
  997. StringBuilder buf = new StringBuilder();
  998. for(int i = 0; i < str.length(); i++)
  999. {
  1000. char c = str.charAt(i);
  1001. switch(c)
  1002. {
  1003. case '\\':
  1004. if(i == str.length() - 1)
  1005. {
  1006. buf.append('\\');
  1007. break;
  1008. }
  1009. c = str.charAt(++i);
  1010. switch(c)
  1011. {
  1012. case 'n':
  1013. buf.append('\n');
  1014. break;
  1015. case 't':
  1016. buf.append('\t');
  1017. break;
  1018. default:
  1019. buf.append(c);
  1020. break;
  1021. }
  1022. break;
  1023. default:
  1024. buf.append(c);
  1025. }
  1026. }
  1027. return buf.toString();
  1028. } //}}}
  1029. //{{{ charsToEscapes() methods
  1030. /**
  1031. * Escapes newlines, tabs, backslashes, and quotes in the specified
  1032. * string.
  1033. * @param str The string
  1034. * @since jEdit 2.3pre1
  1035. * @deprecated use {@link org.gjt.sp.util.StandardUtilities#charsToEscapes(String)}
  1036. */
  1037. @Deprecated
  1038. public static String charsToEscapes(String str)
  1039. {
  1040. return StandardUtilities.charsToEscapes(str);
  1041. }
  1042. /**
  1043. * Escapes the specified characters in the specified string.
  1044. * @param str The string
  1045. * @param toEscape Any characters that require escaping
  1046. * @since jEdit 4.1pre3
  1047. * @deprecated use {@link org.gjt.sp.util.StandardUtilities#charsToEscapes(String)}
  1048. */
  1049. @Deprecated
  1050. public static String charsToEscapes(String str, String toEscape)
  1051. {
  1052. return StandardUtilities.charsToEscapes(str, toEscape);
  1053. } //}}}
  1054. //{{{ compareVersions() method
  1055. /**
  1056. * @deprecated Call {@link StandardUtilities#compareStrings(String, String, boolean)} instead
  1057. */
  1058. @Deprecated
  1059. public static int compareVersions(String v1, String v2)
  1060. {
  1061. return StandardUtilities.compareStrings(v1,v2,false);
  1062. } //}}}
  1063. //{{{ compareStrings() method
  1064. /**
  1065. * Compares two strings.<p>
  1066. *
  1067. * Unlike <function>String.compareTo()</function>,
  1068. * this method correctly recognizes and handles embedded numbers.
  1069. * For example, it places "My file 2" before "My file 10".<p>
  1070. *
  1071. * @param str1 The first string
  1072. * @param str2 The second string
  1073. * @param ignoreCase If true, case will be ignored
  1074. * @return negative If str1 &lt; str2, 0 if both are the same,
  1075. * positive if str1 &gt; str2
  1076. * @since jEdit 4.0pre1
  1077. * @deprecated use {@link org.gjt.sp.util.StandardUtilities#compareStrings(String, String, boolean)}
  1078. */
  1079. @Deprecated
  1080. public static int compareStrings(String str1, String str2, boolean ignoreCase)
  1081. {
  1082. return StandardUtilities.compareStrings(str1, str2, ignoreCase);
  1083. } //}}}
  1084. //{{{ stringsEqual() method
  1085. /**
  1086. * @deprecated Call {@link StandardUtilities#objectsEqual(Object, Object)} instead.
  1087. */
  1088. @Deprecated
  1089. public static boolean stringsEqual(String s1, String s2)
  1090. {
  1091. return StandardUtilities.objectsEqual(s1,s2);
  1092. } //}}}
  1093. //{{{ objectsEqual() method
  1094. /**
  1095. * Returns if two strings are equal. This correctly handles null pointers,
  1096. * as opposed to calling <code>o1.equals(o2)</code>.
  1097. * @since jEdit 4.2pre1
  1098. * @deprecated use {@link StandardUtilities#objectsEqual(Object, Object)}
  1099. */
  1100. @Deprecated
  1101. public static boolean objectsEqual(Object o1, Object o2)
  1102. {
  1103. return StandardUtilities.objectsEqual(o1, o2);
  1104. } //}}}
  1105. //{{{ charsToEntities() method
  1106. /**
  1107. * Converts &lt;, &gt;, &amp; in the string to their HTML entity
  1108. * equivalents.
  1109. * @param str The string
  1110. * @since jEdit 4.2pre1
  1111. * @deprecated Use {@link org.gjt.sp.util.XMLUtilities#charsToEntities(String, boolean)}.
  1112. */
  1113. @Deprecated
  1114. public static String charsToEntities(String str)
  1115. {
  1116. return XMLUtilities.charsToEntities(str,false);
  1117. } //}}}
  1118. //{{{ formatFileSize() method
  1119. @Deprecated
  1120. public static final DecimalFormat KB_FORMAT = new DecimalFormat("#.# kB");
  1121. @Deprecated
  1122. public static final DecimalFormat MB_FORMAT = new DecimalFormat("#.# MB");
  1123. /**
  1124. * Formats the given file size into a nice string (123 Bytes, 10.6 kB,
  1125. * 1.2 MB).
  1126. * @param length The size
  1127. * @since jEdit 4.2pre1
  1128. * @deprecated use {@link org.gjt.sp.util.StandardUtilities#formatFileSize(long)}
  1129. */
  1130. @Deprecated
  1131. public static String formatFileSize(long length)
  1132. {
  1133. return StandardUtilities.formatFileSize(length);
  1134. } //}}}
  1135. //{{{ getLongestPrefix() methods
  1136. /**
  1137. * Returns the longest common prefix in the given set of strings.
  1138. * @param str The strings
  1139. * @param ignoreCase If true, case insensitive
  1140. * @since jEdit 4.2pre2
  1141. */
  1142. public static String getLongestPrefix(List<String> str, boolean ignoreCase)
  1143. {
  1144. if(str.isEmpty())
  1145. return "";
  1146. int prefixLength = 0;
  1147. loop: for(;;)
  1148. {
  1149. String s = str.get(0);
  1150. if(prefixLength >= s.length())
  1151. break loop;
  1152. char ch = s.charAt(prefixLength);
  1153. for(int i = 1; i < str.size(); i++)
  1154. {
  1155. s = str.get(i);
  1156. if(prefixLength >= s.length())
  1157. break loop;
  1158. if(!compareChars(s.charAt(prefixLength),ch,ignoreCase))
  1159. break loop;
  1160. }
  1161. prefixLength++;
  1162. }
  1163. return str.get(0).substring(0,prefixLength);
  1164. }
  1165. /**
  1166. * Returns the longest common prefix in the given set of strings.
  1167. * @param str The strings
  1168. * @param ignoreCase If true, case insensitive
  1169. * @since jEdit 4.2pre2
  1170. */
  1171. public static String getLongestPrefix(String[] str, boolean ignoreCase)
  1172. {
  1173. return getLongestPrefix((Object[])str,ignoreCase);
  1174. }
  1175. /**
  1176. * Returns the longest common prefix in the given set of strings.
  1177. * @param str The strings (calls <code>toString()</code> on each object)
  1178. * @param ignoreCase If true, case insensitive
  1179. * @since jEdit 4.2pre6
  1180. */
  1181. public static String getLongestPrefix(Object[] str, boolean ignoreCase)
  1182. {
  1183. if(str.length == 0)
  1184. return "";
  1185. int prefixLength = 0;
  1186. String first = str[0].toString();
  1187. loop: for(;;)
  1188. {
  1189. if(prefixLength >= first.length())
  1190. break loop;
  1191. char ch = first.charAt(prefixLength);
  1192. for(int i = 1; i < str.length; i++)
  1193. {
  1194. String s = str[i].toString();
  1195. if(prefixLength >= s.length())
  1196. break loop;
  1197. if(!compareChars(s.charAt(prefixLength),ch,ignoreCase))
  1198. break loop;
  1199. }
  1200. prefixLength++;
  1201. }
  1202. return first.substring(0,prefixLength);
  1203. } //}}}
  1204. //}}}
  1205. //{{{ quicksort() deprecated methods
  1206. /**
  1207. * Sorts the specified array. Equivalent to calling
  1208. * <code>Arrays.sort()</code>.
  1209. * @param obj The array
  1210. * @param compare Compares the objects
  1211. * @since jEdit 4.0pre4
  1212. * @deprecated use <code>Arrays.sort()</code>
  1213. */
  1214. @Deprecated
  1215. public static void quicksort(Object[] obj, Comparator compare)
  1216. {
  1217. Arrays.sort(obj,compare);
  1218. }
  1219. /**
  1220. * Sorts the specified vector.
  1221. * @param vector The vector
  1222. * @param compare Compares the objects
  1223. * @since jEdit 4.0pre4
  1224. * @deprecated <code>Collections.sort()</code>
  1225. */
  1226. @Deprecated
  1227. public static void quicksort(Vector vector, Comparator compare)
  1228. {
  1229. Collections.sort(vector,compare);
  1230. }
  1231. /**
  1232. * Sorts the specified list.
  1233. * @param list The list
  1234. * @param compare Compares the objects
  1235. * @since jEdit 4.0pre4
  1236. * @deprecated <code>Collections.sort()</code>
  1237. */
  1238. @Deprecated
  1239. public static void quicksort(List list, Comparator compare)
  1240. {
  1241. Collections.sort(list,compare);
  1242. }
  1243. /**
  1244. * Sorts the specified array. Equivalent to calling
  1245. * <code>Arrays.sort()</code>.
  1246. * @param obj The array
  1247. * @param compare Compares the objects
  1248. * @deprecated use <code>Arrays.sort()</code>
  1249. */
  1250. @Deprecated
  1251. public static void quicksort(Object[] obj, Compare compare)
  1252. {
  1253. Arrays.sort(obj,compare);
  1254. }
  1255. /**
  1256. * Sorts the specified vector.
  1257. * @param vector The vector
  1258. * @param compare Compares the objects
  1259. * @deprecated <code>Collections.sort()</code>
  1260. */
  1261. @Deprecated
  1262. public static void quicksort(Vector vector, Compare compare)
  1263. {
  1264. Collections.sort(vector,compare);
  1265. } //}}}
  1266. //{{{ Compare deprecated interface
  1267. /**
  1268. * An interface for comparing objects. This is a hold-over from
  1269. * they days when jEdit had its own sorting API due to JDK 1.1
  1270. * compatibility requirements. Use <code>java.util.Comparator</code>
  1271. * instead.
  1272. * @deprecated
  1273. */
  1274. @Deprecated
  1275. public interface Compare extends Comparator
  1276. {
  1277. int compare(Object obj1, Object obj2);
  1278. } //}}}
  1279. //{{{ StringCompare deprecated class
  1280. /**
  1281. * Compares strings.
  1282. * @deprecated use {@link org.gjt.sp.util.StandardUtilities.StringCompare}
  1283. */
  1284. @Deprecated
  1285. public static class StringCompare implements Compare
  1286. {
  1287. public int compare(Object obj1, Object obj2)
  1288. {
  1289. return StandardUtilities.compareStrings(obj1.toString(),
  1290. obj2.toString(),false);
  1291. }
  1292. } //}}}
  1293. //{{{ StringICaseCompare deprecated class
  1294. /**
  1295. * Compares strings ignoring case.
  1296. * @deprecated use {@link org.gjt.sp.util.StandardUtilities.StringCompare}
  1297. */
  1298. @Deprecated
  1299. public static class StringICaseCompare implements Comparator<Object>
  1300. {
  1301. public int compare(Object obj1, Object obj2)
  1302. {
  1303. return StandardUtilities.compareStrings(obj1.toString(), obj2.toString(), true);
  1304. }
  1305. } //}}}
  1306. //{{{ MenuItemCompare deprecated class
  1307. /**
  1308. * Compares menu item labels.
  1309. * @deprecated Replaced with {@link org.gjt.sp.jedit.menu.MenuItemTextComparator}
  1310. */
  1311. @Deprecated
  1312. public static class MenuItemCompare implements Compare
  1313. {
  1314. private MenuItemTextComparator comparator = new MenuItemTextComparator();
  1315. public int compare(Object obj1, Object obj2)
  1316. {
  1317. return comparator.compare((JMenuItem)obj1, (JMenuItem)obj2);
  1318. }
  1319. } //}}}
  1320. //{{{ buildToVersion() method
  1321. /**
  1322. * Converts an internal version number (build) into a
  1323. * `human-readable' form.
  1324. * @param build The build
  1325. */
  1326. public static String buildToVersion(String build)
  1327. {
  1328. if(build.length() != 11)
  1329. return "<unknown version: " + build + '>';
  1330. // First 2 chars are the major version number
  1331. int major = Integer.parseInt(build.substring(0,2));
  1332. // Second 2 are the minor number
  1333. int minor = Integer.parseInt(build.substring(3,5));
  1334. // Then the pre-release status
  1335. int beta = Integer.parseInt(build.substring(6,8));
  1336. // Finally the bug fix release
  1337. int bugfix = Integer.parseInt(build.substring(9,11));
  1338. return major + "." + minor
  1339. + (beta != 99 ? "pre" + beta :
  1340. (bugfix != 0 ? "." + bugfix : ""));
  1341. } //}}}
  1342. //{{{ isToolsJarAvailable() method
  1343. /**
  1344. * If on JDK 1.2 or higher, make sure that tools.jar is available.
  1345. * This method should be called by plugins requiring the classes
  1346. * in this library.
  1347. * <p>
  1348. * tools.jar is searched for in the following places:
  1349. * <ol>
  1350. * <li>the classpath that was used when jEdit was started,
  1351. * <li>jEdit's jars folder in the user's home,
  1352. * <li>jEdit's system jars folder,
  1353. * <li><i>java.home</i>/lib/. In this case, tools.jar is added to
  1354. * jEdit's list of known jars using jEdit.addPluginJAR(),
  1355. * so that it gets loaded through JARClassLoader.
  1356. * </ol><p>
  1357. *
  1358. * On older JDK's this method does not perform any checks, and returns
  1359. * <code>true</code> (even though there is no tools.jar).
  1360. *
  1361. * @return <code>false</code> if and only if on JDK 1.2 and tools.jar
  1362. * could not be found. In this case it prints some warnings on Log,
  1363. * too, about the places where it was searched for.
  1364. * @since jEdit 3.2.2
  1365. */
  1366. public static boolean isToolsJarAvailable()
  1367. {
  1368. Log.log(Log.DEBUG, MiscUtilities.class,"Searching for tools.jar...");
  1369. Collection<String> paths = new LinkedList<String>();
  1370. //{{{ 1. Check whether tools.jar is in the system classpath:
  1371. paths.add("System classpath: "
  1372. + System.getProperty("java.class.path"));
  1373. try
  1374. {
  1375. // Either class sun.tools.javac.Main or
  1376. // com.sun.tools.javac.Main must be there:
  1377. try
  1378. {
  1379. Class.forName("sun.tools.javac.Main");
  1380. }
  1381. catch(ClassNotFoundException e1)
  1382. {
  1383. Class.forName("com.sun.tools.javac.Main");
  1384. }
  1385. Log.log(Log.DEBUG, MiscUtilities.class,
  1386. "- is in classpath. Fine.");
  1387. return true;
  1388. }
  1389. catch(ClassNotFoundException e)
  1390. {
  1391. //Log.log(Log.DEBUG, MiscUtilities.class,
  1392. // "- is not in system classpath.");
  1393. } //}}}
  1394. //{{{ 2. Check whether it is in the jEdit user settings jars folder:
  1395. String settingsDir = jEdit.getSettingsDirectory();
  1396. if(settingsDir != null)
  1397. {
  1398. String toolsPath = constructPath(settingsDir, "jars",
  1399. "tools.jar");
  1400. paths.add(toolsPath);
  1401. if(new File(toolsPath).exists())
  1402. {
  1403. Log.log(Log.DEBUG, MiscUtilities.class,
  1404. "- is in the user's jars folder. Fine.");
  1405. // jEdit will load it automatically
  1406. return true;
  1407. }
  1408. } //}}}
  1409. //{{{ 3. Check whether it is in jEdit's system jars folder:
  1410. String jEditDir = jEdit.getJEditHome();
  1411. if(jEditDir != null)
  1412. {
  1413. String toolsPath = constructPath(jEditDir, "jars", "tools.jar");
  1414. paths.add(toolsPath);
  1415. if(new File(toolsPath).exists())
  1416. {
  1417. Log.log(Log.DEBUG, MiscUtilities.class,
  1418. "- is in jEdit's system jars folder. Fine.");
  1419. // jEdit will load it automatically
  1420. return true;
  1421. }
  1422. } //}}}
  1423. //{{{ 4. Check whether it is in <java.home>/lib:
  1424. String toolsPath = System.getProperty("java.home");
  1425. if(toolsPath.toLowerCase().endsWith(File.separator + "jre"))
  1426. toolsPath = toolsPath.substring(0, toolsPath.length() - 4);
  1427. toolsPath = constructPath(toolsPath, "lib", "tools.jar");
  1428. paths.add(toolsPath);
  1429. if(!new File(toolsPath).exists())
  1430. {
  1431. Log.log(Log.WARNING, MiscUtilities.class,
  1432. "Could not find tools.jar.\n"
  1433. + "I checked the following locations:\n"
  1434. + paths.toString());
  1435. return false;
  1436. } //}}}
  1437. //{{{ Load it, if not yet done:
  1438. PluginJAR jar = jEdit.getPluginJAR(toolsPath);
  1439. if(jar == null)
  1440. {
  1441. Log.log(Log.DEBUG, MiscUtilities.class,
  1442. "- adding " + toolsPath + " to jEdit plugins.");
  1443. jEdit.addPluginJAR(toolsPath);
  1444. }
  1445. else
  1446. Log.log(Log.DEBUG, MiscUtilities.class,
  1447. "- has been loaded before.");
  1448. //}}}
  1449. return true;
  1450. } //}}}
  1451. //{{{ parsePermissions() method
  1452. /**
  1453. * Parse a Unix-style permission string (rwxrwxrwx).
  1454. * @param s The string (must be 9 characters long).
  1455. * @since jEdit 4.1pre8
  1456. */
  1457. public static int parsePermissions(String s)
  1458. {
  1459. int permissions = 0;
  1460. if(s.length() == 9)
  1461. {
  1462. if(s.charAt(0) == 'r')
  1463. permissions += 0400;
  1464. if(s.charAt(1) == 'w')
  1465. permissions += 0200;
  1466. if(s.charAt(2) == 'x')
  1467. permissions += 0100;
  1468. else if(s.charAt(2) == 's')
  1469. permissions += 04100;
  1470. else if(s.charAt(2) == 'S')
  1471. permissions += 04000;
  1472. if(s.charAt(3) == 'r')
  1473. permissions += 040;
  1474. if(s.charAt(4) == 'w')
  1475. permissions += 020;
  1476. if(s.charAt(5) == 'x')
  1477. permissions += 010;
  1478. else if(s.charAt(5) == 's')
  1479. permissions += 02010;
  1480. else if(s.charAt(5) == 'S')
  1481. permissions += 02000;
  1482. if(s.charAt(6) == 'r')
  1483. permissions += 04;
  1484. if(s.charAt(7) == 'w')
  1485. permissions += 02;
  1486. if(s.charAt(8) == 'x')
  1487. permissions += 01;
  1488. else if(s.charAt(8) == 't')
  1489. permissions += 01001;
  1490. else if(s.charAt(8) == 'T')
  1491. permissions += 01000;
  1492. }
  1493. return permissions;
  1494. } //}}}
  1495. //{{{ getEncodings() methods
  1496. /**
  1497. * Returns a list of supported character encodings.
  1498. * @since jEdit 4.2pre5
  1499. * @deprecated See #getEncodings(boolean)
  1500. */
  1501. @Deprecated
  1502. public static String[] getEncodings()
  1503. {
  1504. return getEncodings(false);
  1505. }
  1506. /**
  1507. * Returns a list of supported character encodings.
  1508. * @since jEdit 4.3pre5
  1509. * @param getSelected Whether to return just the selected encodings or all.
  1510. */
  1511. public static String[] getEncodings(boolean getSelected)
  1512. {
  1513. Set<String> set;
  1514. if (getSelected)
  1515. {
  1516. set = EncodingServer.getSelectedNames();
  1517. }
  1518. else
  1519. {
  1520. set = EncodingServer.getAvailableNames();
  1521. }
  1522. return set.toArray(new String[set.size()]);
  1523. } //}}}
  1524. //{{{ throwableToString() method
  1525. /**
  1526. * Returns a string containing the stack trace of the given throwable.
  1527. * @since jEdit 4.2pre6
  1528. */
  1529. public static String throwableToString(Throwable t)
  1530. {
  1531. StringWriter s = new StringWriter();
  1532. t.printStackTrace(new PrintWriter(s));
  1533. return s.toString();
  1534. } //}}}
  1535. //{{{ parseXML() method
  1536. /**
  1537. * Convenience method for parsing an XML file.
  1538. *
  1539. * @return Whether any error occured during parsing.
  1540. * @since jEdit 4.3pre5
  1541. * @deprecated Use {@link XMLUtilities#parseXML(InputStream,DefaultHandler)}.
  1542. */
  1543. @Deprecated
  1544. public static boolean parseXML(InputStream in, DefaultHandler handler)
  1545. throws IOException
  1546. {
  1547. return XMLUtilities.parseXML(in, handler);
  1548. } //}}}
  1549. //{{{ resolveEntity() method
  1550. /**
  1551. * Tries to find the given systemId in the context of the given
  1552. * class.
  1553. *
  1554. * @deprecated Use {@link XMLUtilities#findEntity(String,String,Class)}.
  1555. */
  1556. @Deprecated
  1557. public static InputSource findEntity(String systemId, String test, Class where)
  1558. {
  1559. return XMLUtilities.findEntity(systemId, test, where);
  1560. } //}}}
  1561. //{{{ Private members
  1562. private MiscUtilities() {}
  1563. //{{{ compareChars() method
  1564. /**
  1565. * Compares two chars.
  1566. * should this be public?
  1567. * @param ch1 the first char
  1568. * @param ch2 the second char
  1569. * @param ignoreCase true if you want to ignore case
  1570. */
  1571. private static boolean compareChars(char ch1, char ch2, boolean ignoreCase)
  1572. {
  1573. if(ignoreCase)
  1574. return Character.toUpperCase(ch1) == Character.toUpperCase(ch2);
  1575. else
  1576. return ch1 == ch2;
  1577. } //}}}
  1578. //{{{ getPathStart() method
  1579. private static int getPathStart(String path)
  1580. {
  1581. if(path.startsWith("/"))
  1582. return 0;
  1583. else if(OperatingSystem.isDOSDerived()
  1584. && path.length() >= 3
  1585. && path.charAt(1) == ':'
  1586. && (path.charAt(2) == '/'
  1587. || path.charAt(2) == '\\'))
  1588. return 3;
  1589. else
  1590. return 0;
  1591. } //}}}
  1592. //{{{ containsNullCharacter() method
  1593. private static boolean containsNullCharacter(Reader reader)
  1594. throws IOException
  1595. {
  1596. int nbChars = jEdit.getIntegerProperty("vfs.binaryCheck.length",100);
  1597. int authorized = jEdit.getIntegerProperty("vfs.binaryCheck.count",1);
  1598. for (long i = 0L;i < nbChars;i++)
  1599. {
  1600. int c = reader.read();
  1601. if (c == -1)
  1602. return false;
  1603. if (c == 0)
  1604. {
  1605. authorized--;
  1606. if (authorized == 0)
  1607. return true;
  1608. }
  1609. }
  1610. return false;
  1611. } //}}}
  1612. //}}}
  1613. static VarCompressor svc = null;
  1614. //{{{ VarCompressor class
  1615. /**
  1616. * Singleton class for quickly "compressing" paths into variable-prefixed values.
  1617. * @author alan ezust
  1618. */
  1619. static class VarCompressor
  1620. {
  1621. /** a reverse mapping of values to environment variable names */
  1622. final Map<String, String> prefixMap = new HashMap<String, String>();
  1623. /** previously compressed strings saved for quick access later */
  1624. final Map<String, String> previous = new HashMap<String, String>();
  1625. //{{{ VarCompressor constructor
  1626. VarCompressor()
  1627. {
  1628. ProcessBuilder pb = new ProcessBuilder();
  1629. Map<String, String> env = pb.environment();
  1630. if (OperatingSystem.isUnix())
  1631. prefixMap.put(System.getProperty("user.home"), "~");
  1632. for (Map.Entry<String, String> entry: env.entrySet())
  1633. {
  1634. String k = entry.getKey();
  1635. if (k.equalsIgnoreCase("pwd") || k.equalsIgnoreCase("oldpwd")) continue;
  1636. if (!Character.isLetter(k.charAt(0))) continue;
  1637. String v = entry.getValue();
  1638. // only add possible candidates to the prefix map
  1639. if (!canBePathPrefix(v)) continue;
  1640. // no need for trailing file separator
  1641. if (v.endsWith(File.separator))
  1642. v = v.substring(0, v.length()-1);
  1643. // check if it is actually shorter
  1644. if (OperatingSystem.isWindows())
  1645. if (k.length()+2 > v.length()) continue; // gets replaced by %FOO%
  1646. else
  1647. if (k.l

Large files files are truncated, but you can click here to view the full file