PageRenderTime 45ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/plugins/Console/tags/release-2-5-1/console/DefaultShell.java

#
Java | 523 lines | 434 code | 53 blank | 36 comment | 65 complexity | c26acda05a588db0eb7b451946ee98c9 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. * DefaultShell.java - Executes OS commands
  3. * Copyright (C) 1999, 2000, 2001 Slava Pestov
  4. *
  5. * This program is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU General Public License
  7. * as published by the Free Software Foundation; either version 2
  8. * of the License, or any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program; if not, write to the Free Software
  17. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  18. */
  19. package console;
  20. import java.lang.reflect.*;
  21. import java.io.*;
  22. import java.util.Hashtable;
  23. import java.util.Vector;
  24. import org.gjt.sp.jedit.*;
  25. import org.gjt.sp.util.Log;
  26. class DefaultShell extends Shell
  27. {
  28. public DefaultShell()
  29. {
  30. super("Console");
  31. try
  32. {
  33. Class[] classes = { String[].class, String[].class, File.class };
  34. java13exec = Runtime.class.getMethod("exec",classes);
  35. }
  36. catch(Exception e)
  37. {
  38. // do nothing
  39. }
  40. dir = System.getProperty("user.dir");
  41. String osName = System.getProperty("os.name");
  42. appendEXE = (osName.indexOf("Windows") != -1 ||
  43. osName.indexOf("OS/2") != -1);
  44. if(appendEXE)
  45. initTableWinBuiltIns();
  46. }
  47. public void printInfoMessage(Console console)
  48. {
  49. console.printInfo(jEdit.getProperty("console.shell.info"));
  50. }
  51. public void execute(View view, String command, Console console)
  52. {
  53. stop();
  54. ConsolePlugin.clearErrors();
  55. // We replace \ with a non-printable char because
  56. // StreamTokenizer handles \ specially, which causes
  57. // problems on Windows as \ is the file separator
  58. // there.
  59. // After parsing is done, the non printable char is
  60. // changed to \ once again.
  61. // StreamTokenizer needs a way to disable backslash
  62. // handling...
  63. String rawCommand = command;
  64. if(appendEXE)
  65. command = rawCommand.replace('\\',winSlash);
  66. StreamTokenizer st = new StreamTokenizer(new StringReader(command));
  67. st.resetSyntax();
  68. st.wordChars('!',255);
  69. st.whitespaceChars(0,' ');
  70. st.quoteChar('"');
  71. st.quoteChar('\'');
  72. Vector args = new Vector();
  73. StringBuffer buf = new StringBuffer();
  74. try
  75. {
  76. loop: for(;;)
  77. {
  78. switch(st.nextToken())
  79. {
  80. case StreamTokenizer.TT_EOF:
  81. break loop;
  82. case StreamTokenizer.TT_WORD:
  83. case '"':
  84. case '\'':
  85. args.addElement(expandVariables(view,
  86. st.sval,buf));
  87. break;
  88. }
  89. }
  90. }
  91. catch(IOException io)
  92. {
  93. String[] pp = { io.getMessage() };
  94. console.printError(jEdit.getProperty("console.shell.ioerror",pp));
  95. }
  96. if(args.size() == 0)
  97. {
  98. exitStatus = false;
  99. return;
  100. }
  101. String executable = (String)args.elementAt(0);
  102. if(executable.equals("pwd"))
  103. {
  104. if(args.size() != 1)
  105. {
  106. console.printError(jEdit.getProperty("console.shell.pwd-usage"));
  107. exitStatus = false;
  108. }
  109. else
  110. {
  111. console.printPlain(dir);
  112. exitStatus = true;
  113. }
  114. return;
  115. }
  116. else if(executable.equals("cd"))
  117. {
  118. if(java13exec == null)
  119. {
  120. console.printError(jEdit.getProperty("console.shell.cd-unsup"));
  121. exitStatus = false;
  122. }
  123. else if(args.size() != 2)
  124. {
  125. console.printError(jEdit.getProperty("console.shell.cd-usage"));
  126. exitStatus = false;
  127. }
  128. else
  129. {
  130. String newDir = (String)args.elementAt(1);
  131. if(newDir.equals(".."))
  132. newDir = MiscUtilities.getParentOfPath(dir);
  133. else
  134. newDir = MiscUtilities.constructPath(dir,newDir);
  135. String[] pp = { newDir };
  136. if(new File(newDir).exists())
  137. {
  138. dir = newDir;
  139. console.printPlain(jEdit.getProperty("console.shell.cd",pp));
  140. exitStatus = true;
  141. }
  142. else
  143. {
  144. console.printError(jEdit.getProperty("console.shell.cd-error",pp));
  145. exitStatus = false;
  146. }
  147. }
  148. return;
  149. }
  150. else if(appendEXE && tableWinBuiltIns.contains(executable))
  151. {
  152. // which command interpreter?
  153. if(System.getProperty("os.name").indexOf("Windows 9") != -1)
  154. args.insertElementAt("command.com",0);
  155. else
  156. args.insertElementAt("cmd.exe",0);
  157. args.insertElementAt("/C",1);
  158. }
  159. String[] extensionsToTry;
  160. if(appendEXE && executable.indexOf('.') == -1)
  161. extensionsToTry = new String[] { ".cmd", ".bat", ".com", ".exe" };
  162. else
  163. extensionsToTry = new String[] { "" };
  164. String[] _args = new String[args.size()];
  165. args.copyInto(_args);
  166. for(int i = 0; i < extensionsToTry.length; i++)
  167. {
  168. _args[0] = executable + extensionsToTry[i];
  169. try
  170. {
  171. process = _exec(_args);
  172. process.getOutputStream().close();
  173. break;
  174. }
  175. catch(IOException io)
  176. {
  177. if(i == extensionsToTry.length - 1)
  178. {
  179. String[] tt = { io.getMessage() };
  180. console.printInfo(jEdit.getProperty("console.shell.ioerror",tt));
  181. exitStatus = false;
  182. return;
  183. }
  184. }
  185. catch(Throwable t)
  186. {
  187. Log.log(Log.ERROR,this,t);
  188. exitStatus = false;
  189. return;
  190. }
  191. }
  192. this.command = rawCommand;
  193. this.console = console;
  194. stdout = new StdoutThread();
  195. stderr = new StderrThread();
  196. }
  197. public synchronized void stop()
  198. {
  199. if(command != null)
  200. {
  201. stdout.stop();
  202. stderr.stop();
  203. process.destroy();
  204. String[] args = { command };
  205. console.printError(jEdit.getProperty("console.shell.killed",args));
  206. exitStatus = false;
  207. commandDone();
  208. }
  209. }
  210. public synchronized boolean waitFor()
  211. {
  212. if(command != null)
  213. {
  214. try
  215. {
  216. wait();
  217. }
  218. catch(InterruptedException ie)
  219. {
  220. return false;
  221. }
  222. }
  223. return exitStatus;
  224. }
  225. // private members
  226. private static final char winSlash = 127;
  227. private String command;
  228. private Console console;
  229. private Process process;
  230. private Thread stdout;
  231. private Thread stderr;
  232. private String dir;
  233. private Method java13exec;
  234. private boolean appendEXE;
  235. private int threadDoneCount;
  236. private boolean exitStatus;
  237. // used to store built-in commands
  238. private Hashtable tableWinBuiltIns;
  239. private String expandVariables(View view, String arg, StringBuffer buf)
  240. {
  241. buf.setLength(0);
  242. for(int i = 0; i < arg.length(); i++)
  243. {
  244. char c = arg.charAt(i);
  245. switch(c)
  246. {
  247. case winSlash:
  248. buf.append('\\');
  249. break;
  250. case '$':
  251. if(i == arg.length() - 1)
  252. buf.append(c);
  253. else
  254. {
  255. Buffer buffer = view.getBuffer();
  256. switch(arg.charAt(++i))
  257. {
  258. case 'd':
  259. String path = MiscUtilities.getParentOfPath(
  260. buffer.getPath());
  261. if(path.endsWith("/")
  262. || path.endsWith(File.separator))
  263. path = path.substring(0,
  264. path.length() - 1);
  265. buf.append(path);
  266. break;
  267. case 'u':
  268. path = buffer.getPath();
  269. if(!MiscUtilities.isURL(path))
  270. path = "file:" + path;
  271. buf.append(path);
  272. break;
  273. case 'f':
  274. buf.append(buffer.getPath());
  275. break;
  276. case 'j':
  277. buf.append(jEdit.getJEditHome());
  278. break;
  279. case 'n':
  280. String name = buffer.getName();
  281. int index = name.lastIndexOf('.');
  282. if(index == -1)
  283. buf.append(name);
  284. else
  285. buf.append(name.substring(0,index));
  286. break;
  287. case '$':
  288. buf.append('$');
  289. break;
  290. }
  291. }
  292. break;
  293. case '~':
  294. // insert the home directory if the tilde
  295. // is the last character on the line, or if
  296. // the character after it is whitespace or
  297. // a path separator.
  298. if(i == arg.length() - 1)
  299. {
  300. buf.append(System.getProperty("user.home"));
  301. break;
  302. }
  303. c = arg.charAt(i + 1);
  304. if(c == '/' || c == ' ' || c == File.separatorChar)
  305. {
  306. buf.append(System.getProperty("user.home"));
  307. break;
  308. }
  309. buf.append('~');
  310. break;
  311. default:
  312. buf.append(c);
  313. break;
  314. }
  315. }
  316. return buf.toString();
  317. }
  318. private void initTableWinBuiltIns()
  319. {
  320. String [] elems = { "md", "rd", "del", "dir", "copy",
  321. "move", "erase", "mkdir", "rmdir", "start",
  322. "path", "ver", "vol", "ren", "type"};
  323. this.tableWinBuiltIns = new Hashtable();
  324. for( int i = 0; i < elems.length; ++i)
  325. {
  326. this.tableWinBuiltIns.put(elems[i], elems[i]);
  327. }
  328. }
  329. private void parseLine(String line)
  330. {
  331. if(console == null)
  332. return;
  333. int type = ConsolePlugin.parseLine(line,dir);
  334. switch(type)
  335. {
  336. case ErrorSource.ERROR:
  337. console.printError(line);
  338. break;
  339. case ErrorSource.WARNING:
  340. console.printWarning(line);
  341. break;
  342. default:
  343. console.printPlain(line);
  344. break;
  345. }
  346. }
  347. private synchronized void threadDone()
  348. {
  349. threadDoneCount++;
  350. if(threadDoneCount == 2)
  351. commandDone();
  352. }
  353. private synchronized void commandDone()
  354. {
  355. if(process != null)
  356. {
  357. int exitCode;
  358. try
  359. {
  360. exitCode = process.waitFor();
  361. }
  362. catch(InterruptedException e)
  363. {
  364. Log.log(Log.ERROR,this,"Yo Flav, what is this?");
  365. return;
  366. }
  367. Object[] args = { command, new Integer(exitCode) };
  368. String msg = jEdit.getProperty("console.shell.exited",args);
  369. if(exitCode == 0)
  370. console.printInfo(msg);
  371. else
  372. console.printError(msg);
  373. exitStatus = (exitCode == 0);
  374. }
  375. threadDoneCount = 0;
  376. command = null;
  377. stdout = null;
  378. stderr = null;
  379. process = null;
  380. console = null;
  381. notify();
  382. }
  383. private Process _exec(String[] args) throws Throwable
  384. {
  385. if(java13exec != null)
  386. {
  387. try
  388. {
  389. Object[] params = { args, null, new File(dir) };
  390. return (Process)java13exec.invoke(Runtime.getRuntime(),params);
  391. }
  392. catch(InvocationTargetException e)
  393. {
  394. throw e.getTargetException();
  395. }
  396. }
  397. else
  398. return Runtime.getRuntime().exec(args);
  399. }
  400. class StdoutThread extends Thread
  401. {
  402. StdoutThread()
  403. {
  404. setName(StdoutThread.class + "[" + command + "]");
  405. start();
  406. }
  407. public void run()
  408. {
  409. try
  410. {
  411. BufferedReader in = new BufferedReader(
  412. new InputStreamReader(process
  413. .getInputStream()));
  414. String line;
  415. while((line = in.readLine()) != null)
  416. {
  417. parseLine(line);
  418. }
  419. in.close();
  420. }
  421. catch(IOException io)
  422. {
  423. String[] args = { io.getMessage() };
  424. console.printError(jEdit.getProperty("console.shell.ioerror",args));
  425. }
  426. finally
  427. {
  428. threadDone();
  429. }
  430. }
  431. }
  432. class StderrThread extends Thread
  433. {
  434. StderrThread()
  435. {
  436. setName(StderrThread.class + "[" + command + "]");
  437. start();
  438. }
  439. public void run()
  440. {
  441. try
  442. {
  443. // If process exits really fast, it could
  444. // be null by now. So check first...
  445. if(process == null)
  446. return;
  447. BufferedReader in = new BufferedReader(
  448. new InputStreamReader(process
  449. .getErrorStream()));
  450. String line;
  451. while((line = in.readLine()) != null)
  452. {
  453. parseLine(line);
  454. }
  455. in.close();
  456. }
  457. catch(IOException io)
  458. {
  459. String[] args = { io.getMessage() };
  460. console.printError(jEdit.getProperty("console.shell.ioerror",args));
  461. }
  462. finally
  463. {
  464. threadDone();
  465. }
  466. }
  467. }
  468. }