KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > armedbear > lisp > ShellCommand


1 /*
2  * ShellCommand.java
3  *
4  * Copyright (C) 2000-2004 Peter Graves
5  * $Id: ShellCommand.java,v 1.2 2004/02/23 00:09:55 piso Exp $
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20  */

21
22 package org.armedbear.lisp;
23
24 import java.io.BufferedReader JavaDoc;
25 import java.io.IOException JavaDoc;
26 import java.io.InputStream JavaDoc;
27 import java.io.InputStreamReader JavaDoc;
28 import java.util.ArrayList JavaDoc;
29 import java.util.List JavaDoc;
30
31 public final class ShellCommand extends Lisp implements Runnable JavaDoc
32 {
33     private final String JavaDoc command;
34     private final String JavaDoc directory;
35     private final StringBuffer JavaDoc output = new StringBuffer JavaDoc();
36
37     private int exitValue = -1;
38
39     private ShellCommand(String JavaDoc command, String JavaDoc directory)
40         throws ConditionThrowable
41     {
42         this.command = command;
43         this.directory = directory;
44     }
45
46     private final String JavaDoc getOutput()
47     {
48         return output.toString();
49     }
50
51     private final int exitValue()
52     {
53         return exitValue;
54     }
55
56     private void appendOutput(String JavaDoc s)
57     {
58         output.append(s);
59     }
60
61     public void run()
62     {
63         Process JavaDoc process = null;
64         try {
65             if (command != null) {
66                 if (Utilities.isPlatformUnix()) {
67                     if (directory != null) {
68                         StringBuffer JavaDoc sb = new StringBuffer JavaDoc("\\cd \"");
69                         sb.append(directory);
70                         sb.append("\" && ");
71                         sb.append(command);
72                         String JavaDoc[] cmdarray = {"/bin/sh", "-c", sb.toString()};
73                         process = Runtime.getRuntime().exec(cmdarray);
74                     } else {
75                         String JavaDoc[] cmdarray = {"/bin/sh", "-c", command};
76                         process = Runtime.getRuntime().exec(cmdarray);
77                     }
78                 } else if (Utilities.isPlatformWindows()) {
79                     ArrayList JavaDoc list = new ArrayList JavaDoc();
80                     list.add("cmd.exe");
81                     list.add("/c");
82                     if (directory != null) {
83                         StringBuffer JavaDoc sb = new StringBuffer JavaDoc("cd /d \"");
84                         sb.append(directory);
85                         sb.append("\" && ");
86                         sb.append(command);
87                         list.addAll(tokenize(sb.toString()));
88                     } else
89                         list.addAll(tokenize(command));
90                     final int size = list.size();
91                     String JavaDoc[] cmdarray = new String JavaDoc[size];
92                     for (int i = 0; i < size; i++)
93                         cmdarray[i] = (String JavaDoc) list.get(i);
94                     process = Runtime.getRuntime().exec(cmdarray);
95                 }
96             }
97         }
98         catch (IOException JavaDoc e) {
99             Debug.trace(e);
100         }
101         if (process != null) {
102             ReaderThread stdoutThread =
103                 new ReaderThread(process.getInputStream());
104             stdoutThread.start();
105             ReaderThread stderrThread =
106                 new ReaderThread(process.getErrorStream());
107             stderrThread.start();
108             try {
109                 exitValue = process.waitFor();
110             }
111             catch (InterruptedException JavaDoc e) {
112                 Debug.trace(e);
113             }
114             try {
115                 stdoutThread.join();
116             }
117             catch (InterruptedException JavaDoc e) {
118                 Debug.trace(e);
119             }
120             try {
121                 stderrThread.join();
122             }
123             catch (InterruptedException JavaDoc e) {
124                 Debug.trace(e);
125             }
126         }
127     }
128
129     // Does not handle embedded single-quoted strings.
130
private static List JavaDoc tokenize(String JavaDoc s)
131     {
132         ArrayList JavaDoc list = new ArrayList JavaDoc();
133         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
134         boolean inQuote = false;
135         final int limit = s.length();
136         for (int i = 0; i < limit; i++) {
137             char c = s.charAt(i);
138             switch (c) {
139                 case ' ':
140                     if (inQuote)
141                         sb.append(c);
142                     else if (sb.length() > 0) {
143                         list.add(sb.toString());
144                         sb.setLength(0);
145                     }
146                     break;
147                 case '"':
148                     if (inQuote) {
149                         if (sb.length() > 0) {
150                             list.add(sb.toString());
151                             sb.setLength(0);
152                         }
153                         inQuote = false;
154                     } else
155                         inQuote = true;
156                     break;
157                 default:
158                     sb.append(c);
159                     break;
160             }
161         }
162         if (sb.length() > 0)
163             list.add(sb.toString());
164         return list;
165     }
166
167     private class ReaderThread extends Thread JavaDoc
168     {
169         private char[] buf = new char[4096];
170         private final InputStream JavaDoc inputStream;
171         private final BufferedReader JavaDoc reader;
172         private boolean done = false;
173
174         public ReaderThread(InputStream JavaDoc inputStream)
175         {
176             this.inputStream = inputStream;
177             reader = new BufferedReader JavaDoc(new InputStreamReader JavaDoc(inputStream));
178         }
179
180         public void run()
181         {
182             while (!done) {
183                 String JavaDoc s = read();
184                 if (s == null)
185                     return;
186                 appendOutput(s);
187             }
188         }
189
190         private String JavaDoc read()
191         {
192             StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
193             try {
194                 do {
195                     int numChars = reader.read(buf, 0, buf.length); // Blocks.
196
if (numChars < 0) {
197                         done = true;
198                         break;
199                     }
200                     if (numChars > 0)
201                         sb.append(buf, 0, numChars);
202                     Thread.sleep(10);
203                 } while (reader.ready());
204             }
205             catch (IOException JavaDoc e) {
206                 return null;
207             }
208             catch (InterruptedException JavaDoc e) {
209                 return null;
210             }
211             catch (Throwable JavaDoc t) {
212                 return null;
213             }
214             return sb.toString();
215         }
216     }
217
218     // run-shell-command command &key :output
219
// ### %run-shell-command command directory output => exit-code
220
private static final Primitive _RUN_SHELL_COMMAND =
221         new Primitive("%run-shell-command", PACKAGE_SYS, false)
222     {
223         public LispObject execute(LispObject[] args) throws ConditionThrowable
224         {
225             if (args.length != 3)
226                 signal(new WrongNumberOfArgumentsException(this));
227             String JavaDoc command = args[0].getStringValue();
228             LispObject directory = args[1];
229             LispObject output = args[2];
230             String JavaDoc namestring = null;
231             Stream outputStream = null;
232             if (directory != NIL) {
233                 Pathname pathname = Pathname.coerceToPathname(directory);
234                 namestring = pathname.getNamestring();
235                 if (namestring == null) {
236                     return signal(new SimpleError("Pathname has no namestring: " +
237                                                   pathname));
238                 }
239             }
240             if (output != NIL)
241                 outputStream = checkStream(output);
242             ShellCommand shellCommand = new ShellCommand(command, namestring);
243             shellCommand.run();
244             if (outputStream != null)
245                 outputStream._writeString(shellCommand.getOutput());
246             return number(shellCommand.exitValue());
247         }
248     };
249 }
250
Popular Tags