1 21 22 package org.armedbear.j; 23 24 import java.io.IOException ; 25 import java.io.InputStream ; 26 import java.util.List ; 27 import javax.swing.SwingUtilities ; 28 29 public final class AsynchronousShellCommand implements Constants, Runnable  30 { 31 private final String command; 32 private final File directory; 33 private final String cmdline; 34 private final ShellCommandOutputBuffer outputBuffer; 35 private final Position posEndOfBuffer; 36 37 private Process process; 38 private Thread thread; 39 private ProcessTable processTable; 40 41 public AsynchronousShellCommand(String command, File directory, 42 ShellCommandOutputBuffer buf) 43 { 44 this.command = command; 45 this.directory = directory; 46 cmdline = "(\\cd " + directory.canonicalPath() + " && " + command + ")"; 47 this.outputBuffer = buf; 48 this.posEndOfBuffer = new Position(buf.getFirstLine(), 0); 49 buf.setShellCommand(this); 50 } 51 52 private void start() 53 { 54 thread = new Thread (this); 55 thread.start(); 56 } 57 58 public void run() 59 { 60 if (!Platform.isPlatformUnix()) { 61 Debug.bug(); 62 return; 63 } 64 try { 65 if (cmdline != null) { 66 String [] cmdarray = {"/bin/sh", "-c", cmdline}; 67 process = Runtime.getRuntime().exec(cmdarray); 68 } 69 } 70 catch (IOException e) { 71 Log.error(e); 72 } 73 if (process != null) { 74 ShellCommandReaderThread stdoutThread = 75 new ShellCommandReaderThread(process.getInputStream()); 76 stdoutThread.start(); 77 ShellCommandReaderThread stderrThread = 78 new ShellCommandReaderThread(process.getErrorStream()); 79 stderrThread.start(); 80 processTable = ProcessTable.getProcessTable(); 81 try { 82 process.waitFor(); 83 } 84 catch (InterruptedException e) { 85 killProcess(); 87 } 88 } 89 } 90 91 private void interrupt() 92 { 93 if (thread != null) 94 thread.interrupt(); 95 } 96 97 private void killProcess() 98 { 99 if (processTable != null) { 100 List entries = processTable.findMatchingEntries(cmdline); 101 if (entries != null && entries.size() > 0) { 102 ProcessTableEntry parent = 104 (ProcessTableEntry) entries.get(entries.size()-1); 105 if (parent != null) { 106 List children = processTable.findChildren(parent.pid); 107 if (children != null) { 108 for (int i = 0; i < children.size(); i++) { 109 ProcessTableEntry entry = 110 (ProcessTableEntry) children.get(i); 111 Utilities.kill(entry.pid); 112 } 113 } 114 } 115 } 116 try { 117 process.waitFor(); 118 } 119 catch (InterruptedException e) { 120 Log.debug(e); 121 } 122 } 123 } 124 125 private void appendLater(final String s) 126 { 127 Runnable runnable = new Runnable () { 128 public void run() 129 { 130 outputBuffer.insertString(posEndOfBuffer, s); 131 if (outputBuffer.needsRenumbering()) 132 outputBuffer.renumber(); 133 outputBuffer.enforceOutputLimit(Property.SHELL_OUTPUT_LIMIT); 134 for (EditorIterator it = new EditorIterator(); it.hasNext();) { 135 Editor ed = it.nextEditor(); 136 if (ed.getBuffer() == outputBuffer) { 137 ed.eob(); 138 ed.getDisplay().setReframe(-2); 139 ed.setUpdateFlag(REPAINT); 140 ed.updateDisplay(); 141 } 142 } 143 } 144 }; 145 SwingUtilities.invokeLater(runnable); 146 } 147 148 private class ShellCommandReaderThread extends ReaderThread 149 { 150 public ShellCommandReaderThread(InputStream inputStream) 151 { 152 super(inputStream); 153 } 154 155 public void update(final String s) 156 { 157 appendLater(s); 158 } 159 } 160 161 private static class ShellCommandOutputBuffer extends Buffer 162 { 163 private AsynchronousShellCommand shellCommand; 164 165 public ShellCommandOutputBuffer() 166 { 167 supportsUndo = false; 168 type = TYPE_OUTPUT; 169 mode = PlainTextMode.getMode(); 170 formatter = new PlainTextFormatter(this); 171 lineSeparator = System.getProperty("line.separator"); 172 readOnly = true; 173 setTransient(true); 174 setProperty(Property.VERTICAL_RULE, 0); 175 setProperty(Property.SHOW_CHANGE_MARKS, false); 176 setProperty(Property.SHOW_LINE_NUMBERS, false); 177 setProperty(Property.HIGHLIGHT_MATCHING_BRACKET, false); 178 setProperty(Property.HIGHLIGHT_BRACKETS, false); 179 try { 180 lockWrite(); 181 } 182 catch (InterruptedException e) { 183 Log.debug(e); 184 return; 185 } 186 try { 187 appendLine(""); 188 renumber(); 189 } 190 finally { 191 unlockWrite(); 192 } 193 setInitialized(true); 194 } 195 196 public void setShellCommand(AsynchronousShellCommand shellCommand) 197 { 198 this.shellCommand = shellCommand; 199 } 200 201 public int load() 202 { 203 return LOAD_COMPLETED; 204 } 205 206 public String getFileNameForDisplay() 207 { 208 return title != null ? title : ""; 209 } 210 211 public boolean isModified() 212 { 213 return false; 214 } 215 216 public void dispose() 217 { 218 if (shellCommand != null) 219 shellCommand.interrupt(); 220 } 221 } 222 223 public static void startShellCommand(Editor editor, String command) 224 { 225 final File dir = editor.getCurrentDirectory(); 226 if (dir == null || !dir.isDirectory()) 227 return; 228 ShellCommandOutputBuffer buf = new ShellCommandOutputBuffer(); 229 buf.setTitle(command); 230 editor.makeNext(buf); 231 editor.activateInOtherWindow(buf); 232 AsynchronousShellCommand shellCommand = 233 new AsynchronousShellCommand(command, dir, buf); 234 shellCommand.start(); 235 } 236 } 237 | Popular Tags |