1 19 package org.netbeans.modules.ruby.rubyproject.execution; 20 21 import java.awt.event.ActionEvent ; 22 import java.io.File ; 23 import java.io.IOException ; 24 import java.lang.InterruptedException ; 25 import java.util.HashSet ; 26 import java.util.List ; 27 import java.util.Map ; 28 import java.util.Set ; 29 import java.util.WeakHashMap ; 30 import javax.swing.AbstractAction ; 31 import javax.swing.Action ; 32 import org.netbeans.api.progress.ProgressHandle; 33 import org.netbeans.api.progress.ProgressHandleFactory; 34 import org.netbeans.modules.ruby.rubyproject.api.RubyInstallation; 35 import org.openide.ErrorManager; 36 import org.openide.execution.ExecutionEngine; 37 import org.openide.execution.ExecutorTask; 38 import org.openide.util.Cancellable; 39 import org.openide.util.Exceptions; 40 import org.openide.util.NbBundle; 41 import org.openide.util.RequestProcessor; 42 import org.openide.util.Task; 43 import org.openide.util.TaskListener; 44 import org.openide.util.Utilities; 45 import org.openide.windows.IOProvider; 46 import org.openide.windows.InputOutput; 47 48 49 62 public class ExecutionService { 63 static { 64 Thread t = 65 new Thread () { 66 public void run() { 67 ExecutionService.killAll(); 68 } 69 }; 70 71 Runtime.getRuntime().addShutdownHook(t); 72 } 73 76 private static final Set <String > activeDisplayNames = new HashSet <String >(); 77 78 84 private static final Map <ExecutionService, String > freeTabs = 85 new WeakHashMap <ExecutionService, String >(); 86 private static Set <ExecutionService> runningProcesses = new HashSet <ExecutionService>(); 87 88 private Task currentTask; 90 private InputOutput io; 91 private StopAction stopAction; 92 private RerunAction rerunAction; 93 private ExecutionDescriptor descriptor; 94 private String displayName; 96 public ExecutionService(ExecutionDescriptor descriptor) { 97 this.descriptor = descriptor; 98 99 } 100 101 104 public static void setupEnvironment(ProcessBuilder pb, String path) { 105 Map <String , String > env = pb.environment(); 107 108 String pathName = "PATH"; 112 if (Utilities.isWindows()) { 113 pathName = "Path"; 115 for (String key : env.keySet()) { 116 if ("PATH".equals(key.toUpperCase())) { pathName = key; 118 119 break; 120 } 121 } 122 } 123 124 String currentPath = env.get(pathName); 125 126 if (currentPath == null) { 127 currentPath = ""; 128 } 129 130 if (!Utilities.isWindows()) { 131 path = path.replace(" ", "\\ "); } 133 134 currentPath = path + File.pathSeparator + currentPath; 135 env.put(pathName, currentPath); 137 String jrubyHome = RubyInstallation.getInstance().getJRubyHome(); 139 env.put("JRUBY_HOME", jrubyHome); env.put("JRUBY_BASE", jrubyHome); env.put("JAVA_HOME", System.getProperty("java.home")); } 143 144 public static void killAll() { 145 for (ExecutionService service : runningProcesses) { 146 StopAction sa = service.stopAction; 147 148 if (sa != null) { 149 sa.actionPerformed(null); 150 151 if (sa.process != null) { 152 sa.process.destroy(); 153 } 154 } 155 } 156 } 157 158 Task rerun() { 159 io = null; 160 stopAction = null; 161 rerunAction = null; 162 return run(); 163 } 164 165 public Task run() { 166 String dn = descriptor.displayName; 167 168 if (activeDisplayNames.contains(dn)) { 169 int i = 2; 171 String testdn; 172 173 do { 174 testdn = NbBundle.getMessage(ExecutionService.class, "Uniquified", dn, i++); 175 } while (activeDisplayNames.contains(testdn)); 176 177 dn = testdn; 178 } 179 assert !activeDisplayNames.contains(dn); 180 displayName = dn; 181 activeDisplayNames.add(displayName); 182 183 synchronized (this) { 185 synchronized (freeTabs) { 188 for (Map.Entry <ExecutionService, String > entry : freeTabs.entrySet()) { 189 ExecutionService free = entry.getKey(); 190 191 String freeName = entry.getValue(); 193 194 if (free != this && (io == null) && freeName.equals(displayName)) { 195 io = free.io; 197 stopAction = free.stopAction; 198 rerunAction = free.rerunAction; 199 200 try { 201 io.getOut().reset(); 202 } catch (IOException ioe) { 203 Exceptions.printStackTrace(ioe); 204 } 205 206 io.setInputVisible(descriptor.inputVisible); 207 208 io.select(); 211 } else { 212 } 217 } 218 219 freeTabs.clear(); 221 } 222 223 if ((io == null) || (stopAction == null)) { 225 stopAction = new StopAction(); 226 rerunAction = new RerunAction(this, descriptor.fileObject); 227 228 if (io == null) { 229 io = IOProvider.getDefault() 230 .getIO(displayName, new Action [] { rerunAction, stopAction }); 231 232 try { 233 io.getOut().reset(); 234 } catch (IOException exc) { 235 ErrorManager.getDefault().notify(exc); 236 } 237 238 io.setInputVisible(descriptor.inputVisible); 240 io.setErrSeparated(false); 241 242 io.select(); 244 } 245 } 246 } 247 248 Runnable runnable = 250 new Runnable () { 251 public void run() { 252 File cmd = descriptor.cmd; 253 if (cmd == null) { 254 cmd = new File (RubyInstallation.getInstance().getRuby()); 255 } 256 257 String [] applicationArgs = null; 258 259 if (descriptor.additionalArgs != null) { 260 applicationArgs = org.openide.util.Utilities.parseParameters(descriptor.additionalArgs); 261 } 262 263 String [] applicationFlags = null; 264 265 if (descriptor.initialArgs != null) { 266 applicationFlags = org.openide.util.Utilities.parseParameters(descriptor.initialArgs); 267 } 268 269 int argvSize = 270 1 + ((descriptor.args != null) ? descriptor.args.length : 0) + 271 ((applicationArgs != null) ? applicationArgs.length : 0) + 272 ((applicationFlags != null) ? applicationFlags.length : 0); 273 String [] argv = new String [argvSize]; 274 argv[0] = cmd.getPath(); 275 276 int destPos = 1; 277 278 if (applicationFlags != null) { 279 System.arraycopy(applicationFlags, 0, argv, destPos, applicationFlags.length); 280 destPos += applicationFlags.length; 281 } 282 283 if ((descriptor.args != null) && (descriptor.args.length > 0)) { 284 System.arraycopy(descriptor.args, 0, argv, destPos, descriptor.args.length); 285 destPos += descriptor.args.length; 286 } 287 288 if (applicationArgs != null) { 289 System.arraycopy(applicationArgs, 0, argv, destPos, applicationArgs.length); 290 destPos += applicationArgs.length; 291 } 292 293 if ((argv != null) && Utilities.isWindows()) { 294 for (int i = 0; i < argv.length; i++) { 295 if ((argv[i] != null) && (argv[i].indexOf(' ') != -1) && 296 (argv[i].indexOf('"') == -1)) { 297 argv[i] = '"' + argv[i] + '"'; 298 } 299 } 300 } 301 302 ProcessBuilder pb = new ProcessBuilder (argv); 303 pb.directory(descriptor.pwd); 304 305 setupEnvironment(pb, cmd.getParent()); 306 307 try { 308 Process process = pb.start(); 309 runningProcesses.add(ExecutionService.this); 310 stopAction.process = process; 311 runIO(stopAction, process, io, descriptor.fileLocator, descriptor.outputRecognizers); 312 313 int retcode = process.waitFor(); 314 } catch (IOException ex) { 315 ErrorManager.getDefault().notify(ex); 316 } catch (InterruptedException ex) { 317 ErrorManager.getDefault().notify(ex); 318 } 319 } 320 }; 321 322 final ProgressHandle handle; 323 324 if (descriptor.showProgress || descriptor.showSuspended) { 325 handle = 326 ProgressHandleFactory.createHandle(displayName, 327 new Cancellable() { 328 public boolean cancel() { 329 stopAction.actionPerformed(null); 330 331 return true; 332 } 333 }, 334 new AbstractAction () { 335 public void actionPerformed(ActionEvent e) { 336 io.select(); 337 } 338 }); 339 handle.start(); 340 handle.switchToIndeterminate(); 341 342 if (descriptor.showSuspended) { 343 handle.suspend(NbBundle.getMessage(ExecutionService.class, "Running")); 344 } 345 } else { 346 handle = null; 347 } 348 349 stopAction.setEnabled(true); 350 rerunAction.setEnabled(false); 351 352 ExecutorTask task = ExecutionEngine.getDefault().execute(null, runnable, InputOutput.NULL); 353 355 currentTask = task; 357 task.addTaskListener(new TaskListener() { 358 public void taskFinished(Task task) { 359 int result = 0; 360 361 runningProcesses.remove(ExecutionService.this); 362 363 if (io != null) { 364 synchronized (freeTabs) { 365 freeTabs.put(ExecutionService.this, displayName); 366 } 367 } 368 369 activeDisplayNames.remove(displayName); 370 371 if (task instanceof ExecutorTask) { 372 result = ((ExecutorTask)task).result(); 373 } 374 375 if (descriptor.postBuildAction != null) { 383 descriptor.postBuildAction.run(); 384 } 385 386 if (handle != null) { 387 handle.finish(); 388 } 389 390 stopAction.setEnabled(false); 391 rerunAction.setEnabled(true); 392 393 if (stopAction.process != null) { 394 stopAction.process.destroy(); 395 stopAction.process = null; 396 } 397 398 currentTask = null; 399 } 400 }); 401 402 return task; 403 } 404 405 private void runIO(final StopAction sa, Process process, InputOutput ioput, 406 FileLocator fileLocator, List <OutputRecognizer> recognizers) { 407 try { 408 InputForwarder in = new InputForwarder(process.getOutputStream(), ioput.getIn()); 409 OutputForwarder out = 410 new OutputForwarder(process.getInputStream(), ioput.getOut(), fileLocator, 411 recognizers, sa, "Output"); OutputForwarder err = 413 new OutputForwarder(process.getErrorStream(), ioput.getErr(), fileLocator, 414 recognizers, sa, "Error"); 416 RequestProcessor PROCESSOR = new RequestProcessor("Process Execution Stream Handler", 3, true); 418 TaskListener tl = 419 new TaskListener() { 420 public void taskFinished(Task task) { 421 sa.notifyDone((RequestProcessor.Task)task); 422 } 423 }; 424 425 RequestProcessor.Task outTask = PROCESSOR.post(out); 426 RequestProcessor.Task errTask = PROCESSOR.post(err); 427 RequestProcessor.Task inTask = PROCESSOR.post(in); 428 429 outTask.addTaskListener(tl); 430 errTask.addTaskListener(tl); 431 inTask.addTaskListener(tl); 432 433 sa.processorTasks.add(outTask); 434 sa.processorTasks.add(errTask); 435 sa.processorTasks.add(inTask); 436 437 process.waitFor(); 438 sa.process = null; 439 440 in.cancel(); 441 outTask.waitFinished(); 442 errTask.waitFinished(); 443 inTask.waitFinished(); 444 445 PROCESSOR.stop(); 446 } catch (InterruptedException exc) { 447 ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, exc); 450 } 451 } 452 } 453 | Popular Tags |