1 19 20 package org.apache.tools.ant.module.run; 21 22 import java.awt.event.ActionEvent ; 23 import java.io.File ; 24 import java.io.IOException ; 25 import java.io.InputStream ; 26 import java.io.OutputStream ; 27 import java.util.Arrays ; 28 import java.util.HashMap ; 29 import java.util.HashSet ; 30 import java.util.Iterator ; 31 import java.util.List ; 32 import java.util.Map ; 33 import java.util.Set ; 34 import java.util.WeakHashMap ; 35 import java.util.logging.Level ; 36 import java.util.logging.Logger ; 37 import javax.swing.AbstractAction ; 38 import javax.swing.Action ; 39 import javax.swing.ImageIcon ; 40 import org.apache.tools.ant.module.AntModule; 41 import org.apache.tools.ant.module.AntSettings; 42 import org.apache.tools.ant.module.api.AntProjectCookie; 43 import org.apache.tools.ant.module.bridge.AntBridge; 44 import org.netbeans.api.progress.ProgressHandle; 45 import org.netbeans.api.progress.ProgressHandleFactory; 46 import org.openide.ErrorManager; 47 import org.openide.LifecycleManager; 48 import org.openide.awt.Actions; 49 import org.openide.execution.ExecutionEngine; 50 import org.openide.execution.ExecutorTask; 51 import org.openide.filesystems.FileAttributeEvent; 52 import org.openide.filesystems.FileChangeListener; 53 import org.openide.filesystems.FileEvent; 54 import org.openide.filesystems.FileObject; 55 import org.openide.filesystems.FileRenameEvent; 56 import org.openide.filesystems.FileUtil; 57 import org.openide.util.Cancellable; 58 import org.openide.util.NbBundle; 59 import org.openide.util.RequestProcessor; 60 import org.openide.util.io.ReaderInputStream; 61 import org.openide.windows.IOProvider; 62 import org.openide.windows.InputOutput; 63 import org.openide.windows.OutputWriter; 64 import org.w3c.dom.Element ; 65 66 68 public final class TargetExecutor implements Runnable { 69 70 76 private static final Map <InputOutput,String > freeTabs = new WeakHashMap <InputOutput,String >(); 77 78 81 private static final Set <String > activeDisplayNames = new HashSet <String >(); 82 83 private AntProjectCookie pcookie; 84 private InputOutput io; 85 private OutputStream outputStream; 86 private boolean ok = false; 87 private int verbosity = AntSettings.getVerbosity (); 88 private Map <String ,String > properties = AntSettings.getProperties(); 89 private List <String > targetNames; 90 91 private String displayName; 92 93 94 public TargetExecutor (AntProjectCookie pcookie, String [] targets) { 95 this.pcookie = pcookie; 96 targetNames = ((targets == null) ? null : Arrays.asList(targets)); 97 } 98 99 public void setVerbosity (int v) { 100 verbosity = v; 101 } 102 103 public synchronized void setProperties(Map <String ,String > p) { 104 properties = new HashMap <String ,String >(p); 105 } 106 107 static String getProcessDisplayName(AntProjectCookie pcookie, List <String > targetNames) { 108 Element projel = pcookie.getProjectElement(); 109 String projectName; 110 if (projel != null) { 111 projectName = Actions.cutAmpersand(projel.getAttribute("name")); } else { 114 projectName = NbBundle.getMessage(TargetExecutor.class, "LBL_unparseable_proj_name"); 115 } 116 String fileName; 117 if (pcookie.getFileObject() != null) { 118 fileName = pcookie.getFileObject().getNameExt(); 119 } else if (pcookie.getFile() != null) { 120 fileName = pcookie.getFile().getName(); 121 } else { 122 fileName = ""; } 124 if (projectName.equals("")) { projectName = fileName; 127 } 128 if (targetNames != null) { 129 StringBuffer targetList = new StringBuffer (); 130 Iterator <String > it = targetNames.iterator(); 131 if (it.hasNext()) { 132 targetList.append(it.next()); 133 } 134 while (it.hasNext()) { 135 targetList.append(NbBundle.getMessage(TargetExecutor.class, "SEP_output_target")); 136 targetList.append(it.next()); 137 } 138 return NbBundle.getMessage(TargetExecutor.class, "TITLE_output_target", projectName, fileName, targetList); 139 } else { 140 return NbBundle.getMessage(TargetExecutor.class, "TITLE_output_notarget", projectName, fileName); 141 } 142 } 143 144 private static final Map <InputOutput,StopAction> stopActions = new HashMap <InputOutput,StopAction>(); 145 private static final Map <InputOutput,RerunAction> rerunActions = new HashMap <InputOutput,RerunAction>(); 146 147 private static final class StopAction extends AbstractAction { 148 149 public Thread t; 150 151 public StopAction() { 152 setEnabled(false); } 154 155 @Override 156 public Object getValue(String key) { 157 if (key.equals(Action.SMALL_ICON)) { 158 return new ImageIcon (TargetExecutor.class.getResource("/org/apache/tools/ant/module/resources/stop.gif")); 159 } else if (key.equals(Action.SHORT_DESCRIPTION)) { 160 return NbBundle.getMessage(TargetExecutor.class, "TargetExecutor.StopAction.stop"); 161 } else { 162 return super.getValue(key); 163 } 164 } 165 166 public void actionPerformed(ActionEvent e) { 167 setEnabled(false); if (t != null) { stopProcess(t); 170 } 171 } 172 173 } 174 175 private static final class RerunAction extends AbstractAction implements FileChangeListener { 176 177 private final AntProjectCookie pcookie; 178 private final List <String > targetNames; 179 private final int verbosity; 180 private final Map <String ,String > properties; 181 182 public RerunAction(TargetExecutor prototype) { 183 pcookie = prototype.pcookie; 184 targetNames = prototype.targetNames; 185 verbosity = prototype.verbosity; 186 properties = prototype.properties; 187 setEnabled(false); FileObject script = pcookie.getFileObject(); 189 if (script != null) { 190 script.addFileChangeListener(FileUtil.weakFileChangeListener(this, script)); 191 } 192 } 193 194 @Override 195 public Object getValue(String key) { 196 if (key.equals(Action.SMALL_ICON)) { 197 return new ImageIcon (TargetExecutor.class.getResource("/org/apache/tools/ant/module/resources/rerun.png")); 198 } else if (key.equals(Action.SHORT_DESCRIPTION)) { 199 return NbBundle.getMessage(TargetExecutor.class, "TargetExecutor.RerunAction.rerun"); 200 } else { 201 return super.getValue(key); 202 } 203 } 204 205 public void actionPerformed(ActionEvent e) { 206 setEnabled(false); 207 try { 208 TargetExecutor exec = new TargetExecutor(pcookie, 209 targetNames != null ? targetNames.toArray(new String [targetNames.size()]) : null); 210 exec.setVerbosity(verbosity); 211 exec.setProperties(properties); 212 exec.execute(); 213 } catch (IOException x) { 214 Logger.getLogger(TargetExecutor.class.getName()).log(Level.INFO, null, x); 215 } 216 } 217 218 public void fileDeleted(FileEvent fe) { 219 firePropertyChange("enabled", null, false); } 221 222 public void fileFolderCreated(FileEvent fe) {} 223 224 public void fileDataCreated(FileEvent fe) {} 225 226 public void fileChanged(FileEvent fe) {} 227 228 public void fileRenamed(FileRenameEvent fe) {} 229 230 public void fileAttributeChanged(FileAttributeEvent fe) {} 231 232 public boolean isEnabled() { 233 return super.isEnabled() && pcookie.getFileObject() != null && pcookie.getFileObject().isValid(); 235 } 236 237 } 238 239 242 public ExecutorTask execute () throws IOException { 243 String dn = getProcessDisplayName(pcookie, targetNames); 244 if (activeDisplayNames.contains(dn)) { 245 int i = 2; 247 String testdn; 248 do { 249 testdn = NbBundle.getMessage(TargetExecutor.class, "TargetExecutor.uniquified", dn, i++); 250 } while (activeDisplayNames.contains(testdn)); 251 dn = testdn; 252 } 253 assert !activeDisplayNames.contains(dn); 254 displayName = dn; 255 activeDisplayNames.add(displayName); 256 257 final ExecutorTask task; 258 synchronized (this) { 259 if (AntSettings.getAutoCloseTabs()) { synchronized (freeTabs) { 262 for (Map.Entry <InputOutput,String > entry : freeTabs.entrySet()) { 263 InputOutput free = entry.getKey(); 264 String freeName = entry.getValue(); 265 if (io == null && freeName.equals(displayName)) { 266 io = free; 268 io.getOut().reset(); 269 } else { 272 free.closeInputOutput(); 274 stopActions.remove(free); 275 rerunActions.remove(free); 276 } 277 } 278 freeTabs.clear(); 279 } 280 } 281 if (io == null) { 282 StopAction sa = new StopAction(); 283 RerunAction ra = new RerunAction(this); 284 io = IOProvider.getDefault().getIO(displayName, new Action [] {ra, sa}); 285 stopActions.put(io, sa); 286 rerunActions.put(io, ra); 287 } 288 task = ExecutionEngine.getDefault().execute(null, this, InputOutput.NULL); 289 } 290 WrapperExecutorTask wrapper = new WrapperExecutorTask(task, io); 291 RequestProcessor.getDefault().post(wrapper); 292 return wrapper; 293 } 294 295 public ExecutorTask execute(OutputStream outputStream) throws IOException { 296 this.outputStream = outputStream; 297 ExecutorTask task = ExecutionEngine.getDefault().execute(null, this, InputOutput.NULL); 298 return new WrapperExecutorTask(task, null); 299 } 300 301 private class WrapperExecutorTask extends ExecutorTask { 302 private ExecutorTask task; 303 private InputOutput io; 304 public WrapperExecutorTask(ExecutorTask task, InputOutput io) { 305 super(new WrapperRunnable(task)); 306 this.task = task; 307 this.io = io; 308 } 309 @Override 310 public void stop () { 311 StopAction sa = stopActions.get(io); 312 if (sa != null) { 313 sa.actionPerformed(null); 314 } else { task.stop(); 316 } 317 } 318 @Override 319 public int result () { 320 return task.result () + (ok ? 0 : 1); 321 } 322 @Override 323 public InputOutput getInputOutput () { 324 return io; 325 } 326 } 327 private static class WrapperRunnable implements Runnable { 328 private final ExecutorTask task; 329 public WrapperRunnable(ExecutorTask task) { 330 this.task = task; 331 } 332 public void run () { 333 task.waitFinished (); 334 } 335 } 336 337 339 synchronized public void run () { 340 final Thread [] thisProcess = new Thread [1]; 341 final StopAction sa = stopActions.get(io); 342 assert sa != null; 343 RerunAction ra = rerunActions.get(io); 344 assert ra != null; 345 try { 346 347 final boolean[] displayed = new boolean[] {AntSettings.getAlwaysShowOutput()}; 348 349 if (outputStream == null) { 350 if (displayed[0]) { 351 io.select(); 352 } 353 } 354 355 if (AntSettings.getSaveAll()) { 356 LifecycleManager.getDefault ().saveAll (); 357 } 358 359 OutputWriter out; 360 OutputWriter err; 361 if (outputStream == null) { 362 out = io.getOut(); 363 err = io.getErr(); 364 } else { 365 throw new RuntimeException ("XXX No support for outputStream currently!"); } 367 368 File buildFile = pcookie.getFile (); 369 if (buildFile == null) { 370 err.println(NbBundle.getMessage(TargetExecutor.class, "EXC_non_local_proj_file")); 371 return; 372 } 373 374 LastTargetExecuted.record(buildFile, verbosity, targetNames != null ? targetNames.toArray(new String [targetNames.size()]) : null, properties); 375 376 Thread.currentThread().setPriority((Thread.MIN_PRIORITY + Thread.NORM_PRIORITY) / 2); 378 379 final Runnable interestingOutputCallback = new Runnable () { 380 public void run() { 381 if (!displayed[0]) { 383 displayed[0] = true; 384 io.select(); 385 } 386 } 387 }; 388 389 InputStream in = null; 390 if (outputStream == null) { try { 392 in = new ReaderInputStream(io.getIn()) { 393 @Override 395 public int read() throws IOException { 396 interestingOutputCallback.run(); 397 return super.read(); 398 } 399 @Override 400 public int read(byte[] b) throws IOException { 401 interestingOutputCallback.run(); 402 return super.read(b); 403 } 404 @Override 405 public int read(byte[] b, int off, int len) throws IOException { 406 interestingOutputCallback.run(); 407 return super.read(b, off, len); 408 } 409 @Override 410 public long skip(long n) throws IOException { 411 interestingOutputCallback.run(); 412 return super.skip(n); 413 } 414 }; 415 } catch (IOException e) { 416 AntModule.err.notify(ErrorManager.INFORMATIONAL, e); 417 } 418 } 419 420 thisProcess[0] = Thread.currentThread(); 421 StopBuildingAction.registerProcess(thisProcess[0], displayName); 422 sa.t = thisProcess[0]; 423 ProgressHandle handle = ProgressHandleFactory.createHandle(displayName, new Cancellable() { 425 public boolean cancel() { 426 sa.actionPerformed(null); 427 return true; 428 } 429 }, new AbstractAction () { 430 public void actionPerformed(ActionEvent e) { 431 io.select(); 432 } 433 }); 434 handle.setInitialDelay(0); handle.start(); 436 sa.setEnabled(true); 437 ra.setEnabled(false); 438 ok = AntBridge.getInterface().run(buildFile, targetNames, in, out, err, properties, verbosity, displayName, interestingOutputCallback, handle); 439 440 } finally { 441 if (io != null) { 442 synchronized (freeTabs) { 443 freeTabs.put(io, displayName); 444 } 445 } 446 if (thisProcess[0] != null) { 447 StopBuildingAction.unregisterProcess(thisProcess[0]); 448 } 449 sa.t = null; 450 sa.setEnabled(false); 451 ra.setEnabled(true); 452 activeDisplayNames.remove(displayName); 453 } 454 } 455 456 457 static void stopProcess(Thread t) { 458 AntBridge.getInterface().stop(t); 459 } 460 461 } 462 | Popular Tags |