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

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

#
Java | 504 lines | 427 code | 49 blank | 28 comment | 64 complexity | 16b0e9aff9bdcc1be6f2eb9f79478da8 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. boolean 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. StreamTokenizer st = new StreamTokenizer(new StringReader(command));
  56. st.resetSyntax();
  57. st.wordChars('!',255);
  58. st.whitespaceChars(0,' ');
  59. st.quoteChar('"');
  60. st.quoteChar('\'');
  61. Vector args = new Vector();
  62. StringBuffer buf = new StringBuffer();
  63. try
  64. {
  65. loop: for(;;)
  66. {
  67. switch(st.nextToken())
  68. {
  69. case StreamTokenizer.TT_EOF:
  70. break loop;
  71. case StreamTokenizer.TT_WORD:
  72. case '"':
  73. case '\'':
  74. args.addElement(expandVariables(view,
  75. st.sval,buf));
  76. break;
  77. }
  78. }
  79. }
  80. catch(IOException io)
  81. {
  82. String[] pp = { io.getMessage() };
  83. console.printError(jEdit.getProperty("console.shell.ioerror",pp));
  84. }
  85. if(args.size() == 0)
  86. {
  87. exitStatus = false;
  88. return;
  89. }
  90. String executable = (String)args.elementAt(0);
  91. if(executable.equals("pwd"))
  92. {
  93. if(args.size() != 1)
  94. {
  95. console.printError(jEdit.getProperty("console.shell.pwd-usage"));
  96. exitStatus = false;
  97. }
  98. else
  99. {
  100. console.printPlain(dir);
  101. exitStatus = true;
  102. }
  103. return;
  104. }
  105. else if(executable.equals("cd"))
  106. {
  107. if(java13exec == null)
  108. {
  109. console.printError(jEdit.getProperty("console.shell.cd-unsup"));
  110. exitStatus = false;
  111. }
  112. else if(args.size() != 2)
  113. {
  114. console.printError(jEdit.getProperty("console.shell.cd-usage"));
  115. exitStatus = false;
  116. }
  117. else
  118. {
  119. String newDir = (String)args.elementAt(1);
  120. if(newDir.equals(".."))
  121. newDir = MiscUtilities.getParentOfPath(dir);
  122. else
  123. newDir = MiscUtilities.constructPath(dir,newDir);
  124. String[] pp = { newDir };
  125. if(new File(newDir).exists())
  126. {
  127. dir = newDir;
  128. console.printPlain(jEdit.getProperty("console.shell.cd",pp));
  129. exitStatus = true;
  130. }
  131. else
  132. {
  133. console.printError(jEdit.getProperty("console.shell.cd-error",pp));
  134. exitStatus = false;
  135. }
  136. }
  137. return;
  138. }
  139. else if(appendEXE && tableWinBuiltIns.contains(executable))
  140. {
  141. // which command interpreter?
  142. if(System.getProperty("os.name").indexOf("Windows 9") != -1)
  143. args.insertElementAt("command.com",0);
  144. else
  145. args.insertElementAt("cmd.exe",0);
  146. args.insertElementAt("/C",1);
  147. }
  148. String[] extensionsToTry;
  149. if(appendEXE && executable.indexOf('.') == -1)
  150. extensionsToTry = new String[] { ".cmd", ".bat", ".com", ".exe" };
  151. else
  152. extensionsToTry = new String[] { "" };
  153. String[] _args = new String[args.size()];
  154. args.copyInto(_args);
  155. for(int i = 0; i < extensionsToTry.length; i++)
  156. {
  157. _args[0] = executable + extensionsToTry[i];
  158. try
  159. {
  160. process = _exec(_args);
  161. process.getOutputStream().close();
  162. break;
  163. }
  164. catch(IOException io)
  165. {
  166. if(i == extensionsToTry.length - 1)
  167. {
  168. String[] tt = { io.getMessage() };
  169. console.printInfo(jEdit.getProperty("console.shell.ioerror",tt));
  170. exitStatus = false;
  171. return;
  172. }
  173. }
  174. catch(Throwable t)
  175. {
  176. Log.log(Log.ERROR,this,t);
  177. exitStatus = false;
  178. return;
  179. }
  180. }
  181. this.command = command;
  182. this.console = console;
  183. stdout = new StdoutThread();
  184. stderr = new StderrThread();
  185. }
  186. public synchronized void stop()
  187. {
  188. if(command != null)
  189. {
  190. stdout.stop();
  191. stderr.stop();
  192. process.destroy();
  193. String[] args = { command };
  194. console.printError(jEdit.getProperty("console.shell.killed",args));
  195. exitStatus = false;
  196. commandDone();
  197. }
  198. }
  199. public synchronized boolean waitFor()
  200. {
  201. if(command != null)
  202. {
  203. try
  204. {
  205. wait();
  206. }
  207. catch(InterruptedException ie)
  208. {
  209. return false;
  210. }
  211. }
  212. return exitStatus;
  213. }
  214. // private members
  215. private String command;
  216. private Console console;
  217. private Process process;
  218. private Thread stdout;
  219. private Thread stderr;
  220. private String dir;
  221. private Method java13exec;
  222. private boolean appendEXE;
  223. private int threadDoneCount;
  224. private boolean exitStatus;
  225. // used to store built-in commands
  226. private Hashtable tableWinBuiltIns;
  227. private String expandVariables(View view, String arg, StringBuffer buf)
  228. {
  229. buf.setLength(0);
  230. for(int i = 0; i < arg.length(); i++)
  231. {
  232. char c = arg.charAt(i);
  233. switch(c)
  234. {
  235. case '$':
  236. if(i == arg.length() - 1)
  237. buf.append(c);
  238. else
  239. {
  240. Buffer buffer = view.getBuffer();
  241. switch(arg.charAt(++i))
  242. {
  243. case 'd':
  244. String path = MiscUtilities.getParentOfPath(
  245. buffer.getPath());
  246. if(path.endsWith("/")
  247. || path.endsWith(File.separator))
  248. path = path.substring(0,
  249. path.length() - 1);
  250. buf.append(path);
  251. break;
  252. case 'u':
  253. path = buffer.getPath();
  254. if(!MiscUtilities.isURL(path))
  255. path = "file:" + path;
  256. buf.append(path);
  257. break;
  258. case 'f':
  259. buf.append(buffer.getPath());
  260. break;
  261. case 'j':
  262. buf.append(jEdit.getJEditHome());
  263. break;
  264. case 'n':
  265. String name = buffer.getName();
  266. int index = name.lastIndexOf('.');
  267. if(index == -1)
  268. buf.append(name);
  269. else
  270. buf.append(name.substring(0,index));
  271. break;
  272. case '$':
  273. buf.append('$');
  274. break;
  275. }
  276. }
  277. break;
  278. case '~':
  279. // insert the home directory if the tilde
  280. // is the last character on the line, or if
  281. // the character after it is whitespace or
  282. // a path separator.
  283. if(i == arg.length() - 1)
  284. {
  285. buf.append(System.getProperty("user.home"));
  286. break;
  287. }
  288. c = arg.charAt(i + 1);
  289. if(c == '/' || c == ' ' || c == File.separatorChar)
  290. {
  291. buf.append(System.getProperty("user.home"));
  292. break;
  293. }
  294. buf.append('~');
  295. break;
  296. default:
  297. buf.append(c);
  298. break;
  299. }
  300. }
  301. return buf.toString();
  302. }
  303. private void initTableWinBuiltIns()
  304. {
  305. String [] elems = { "md", "rd", "del", "dir", "copy",
  306. "move", "erase", "mkdir", "rmdir", "start",
  307. "path", "ver", "vol", "ren", "type"};
  308. this.tableWinBuiltIns = new Hashtable();
  309. for( int i = 0; i < elems.length; ++i)
  310. {
  311. this.tableWinBuiltIns.put(elems[i], elems[i]);
  312. }
  313. }
  314. private void parseLine(String line)
  315. {
  316. if(console == null)
  317. return;
  318. int type = ConsolePlugin.parseLine(line,dir);
  319. switch(type)
  320. {
  321. case ErrorSource.ERROR:
  322. console.printError(line);
  323. break;
  324. case ErrorSource.WARNING:
  325. console.printWarning(line);
  326. break;
  327. default:
  328. console.printPlain(line);
  329. break;
  330. }
  331. }
  332. private synchronized void threadDone()
  333. {
  334. threadDoneCount++;
  335. if(threadDoneCount == 2)
  336. commandDone();
  337. }
  338. private synchronized void commandDone()
  339. {
  340. if(process != null)
  341. {
  342. int exitCode;
  343. try
  344. {
  345. exitCode = process.waitFor();
  346. }
  347. catch(InterruptedException e)
  348. {
  349. Log.log(Log.ERROR,this,"Yo Flav, what is this?");
  350. return;
  351. }
  352. Object[] args = { command, new Integer(exitCode) };
  353. String msg = jEdit.getProperty("console.shell.exited",args);
  354. if(exitCode == 0)
  355. console.printInfo(msg);
  356. else
  357. console.printError(msg);
  358. exitStatus = (exitCode == 0);
  359. }
  360. threadDoneCount = 0;
  361. command = null;
  362. stdout = null;
  363. stderr = null;
  364. process = null;
  365. console = null;
  366. notify();
  367. }
  368. private Process _exec(String[] args) throws Throwable
  369. {
  370. if(java13exec != null)
  371. {
  372. try
  373. {
  374. Object[] params = { args, null, new File(dir) };
  375. return (Process)java13exec.invoke(Runtime.getRuntime(),params);
  376. }
  377. catch(InvocationTargetException e)
  378. {
  379. throw e.getTargetException();
  380. }
  381. }
  382. else
  383. return Runtime.getRuntime().exec(args);
  384. }
  385. class StdoutThread extends Thread
  386. {
  387. StdoutThread()
  388. {
  389. setName(StdoutThread.class + "[" + command + "]");
  390. start();
  391. }
  392. public void run()
  393. {
  394. try
  395. {
  396. BufferedReader in = new BufferedReader(
  397. new InputStreamReader(process
  398. .getInputStream()));
  399. String line;
  400. while((line = in.readLine()) != null)
  401. {
  402. parseLine(line);
  403. }
  404. in.close();
  405. }
  406. catch(IOException io)
  407. {
  408. String[] args = { io.getMessage() };
  409. console.printError(jEdit.getProperty("console.shell.ioerror",args));
  410. }
  411. finally
  412. {
  413. threadDone();
  414. }
  415. }
  416. }
  417. class StderrThread extends Thread
  418. {
  419. StderrThread()
  420. {
  421. setName(StderrThread.class + "[" + command + "]");
  422. start();
  423. }
  424. public void run()
  425. {
  426. try
  427. {
  428. // If process exits really fast, it could
  429. // be null by now. So check first...
  430. if(process == null)
  431. return;
  432. BufferedReader in = new BufferedReader(
  433. new InputStreamReader(process
  434. .getErrorStream()));
  435. String line;
  436. while((line = in.readLine()) != null)
  437. {
  438. parseLine(line);
  439. }
  440. in.close();
  441. }
  442. catch(IOException io)
  443. {
  444. String[] args = { io.getMessage() };
  445. console.printError(jEdit.getProperty("console.shell.ioerror",args));
  446. }
  447. finally
  448. {
  449. threadDone();
  450. }
  451. }
  452. }
  453. }