KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > tools > ant > module > run > TargetExecutor


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.apache.tools.ant.module.run;
21
22 import java.awt.event.ActionEvent JavaDoc;
23 import java.io.File JavaDoc;
24 import java.io.IOException JavaDoc;
25 import java.io.InputStream JavaDoc;
26 import java.io.OutputStream JavaDoc;
27 import java.util.Arrays JavaDoc;
28 import java.util.HashMap JavaDoc;
29 import java.util.HashSet JavaDoc;
30 import java.util.Iterator JavaDoc;
31 import java.util.List JavaDoc;
32 import java.util.Map JavaDoc;
33 import java.util.Set JavaDoc;
34 import java.util.WeakHashMap JavaDoc;
35 import java.util.logging.Level JavaDoc;
36 import java.util.logging.Logger JavaDoc;
37 import javax.swing.AbstractAction JavaDoc;
38 import javax.swing.Action JavaDoc;
39 import javax.swing.ImageIcon JavaDoc;
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 JavaDoc;
65
66 /** Executes an Ant Target asynchronously in the IDE.
67  */

68 public final class TargetExecutor implements Runnable JavaDoc {
69
70     /**
71      * All tabs which were used for some process which has now ended.
72      * These are closed when you start a fresh process.
73      * Map from tab to tab display name.
74      * @see "#43001"
75      */

76     private static final Map JavaDoc<InputOutput,String JavaDoc> freeTabs = new WeakHashMap JavaDoc<InputOutput,String JavaDoc>();
77     
78     /**
79      * Display names of currently active processes.
80      */

81     private static final Set JavaDoc<String JavaDoc> activeDisplayNames = new HashSet JavaDoc<String JavaDoc>();
82     
83     private AntProjectCookie pcookie;
84     private InputOutput io;
85     private OutputStream JavaDoc outputStream;
86     private boolean ok = false;
87     private int verbosity = AntSettings.getVerbosity ();
88     private Map JavaDoc<String JavaDoc,String JavaDoc> properties = AntSettings.getProperties();
89     private List JavaDoc<String JavaDoc> targetNames;
90     /** used for the tab etc. */
91     private String JavaDoc displayName;
92
93     /** targets may be null to indicate default target */
94     public TargetExecutor (AntProjectCookie pcookie, String JavaDoc[] 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 JavaDoc<String JavaDoc,String JavaDoc> p) {
104         properties = new HashMap JavaDoc<String JavaDoc,String JavaDoc>(p);
105     }
106     
107     static String JavaDoc getProcessDisplayName(AntProjectCookie pcookie, List JavaDoc<String JavaDoc> targetNames) {
108         Element JavaDoc projel = pcookie.getProjectElement();
109         String JavaDoc projectName;
110         if (projel != null) {
111             // remove & if available.
112
projectName = Actions.cutAmpersand(projel.getAttribute("name")); // NOI18N
113
} else {
114             projectName = NbBundle.getMessage(TargetExecutor.class, "LBL_unparseable_proj_name");
115         }
116         String JavaDoc 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 = ""; // last resort for #84874
123
}
124         if (projectName.equals("")) { // NOI18N
125
// No name="..." given, so try the file name instead.
126
projectName = fileName;
127         }
128         if (targetNames != null) {
129             StringBuffer JavaDoc targetList = new StringBuffer JavaDoc();
130             Iterator JavaDoc<String JavaDoc> 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 JavaDoc<InputOutput,StopAction> stopActions = new HashMap JavaDoc<InputOutput,StopAction>();
145     private static final Map JavaDoc<InputOutput,RerunAction> rerunActions = new HashMap JavaDoc<InputOutput,RerunAction>();
146
147     private static final class StopAction extends AbstractAction JavaDoc {
148
149         public Thread JavaDoc t;
150
151         public StopAction() {
152             setEnabled(false); // initially, until ready
153
}
154
155         @Override JavaDoc
156         public Object JavaDoc getValue(String JavaDoc key) {
157             if (key.equals(Action.SMALL_ICON)) {
158                 return new ImageIcon JavaDoc(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 JavaDoc e) {
167             setEnabled(false); // discourage repeated clicking
168
if (t != null) { // #84688
169
stopProcess(t);
170             }
171         }
172
173     }
174
175     private static final class RerunAction extends AbstractAction JavaDoc implements FileChangeListener {
176
177         private final AntProjectCookie pcookie;
178         private final List JavaDoc<String JavaDoc> targetNames;
179         private final int verbosity;
180         private final Map JavaDoc<String JavaDoc,String JavaDoc> 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); // initially, until ready
188
FileObject script = pcookie.getFileObject();
189             if (script != null) {
190                 script.addFileChangeListener(FileUtil.weakFileChangeListener(this, script));
191             }
192         }
193
194         @Override JavaDoc
195         public Object JavaDoc getValue(String JavaDoc key) {
196             if (key.equals(Action.SMALL_ICON)) {
197                 return new ImageIcon JavaDoc(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 JavaDoc e) {
206             setEnabled(false);
207             try {
208                 TargetExecutor exec = new TargetExecutor(pcookie,
209                         targetNames != null ? targetNames.toArray(new String JavaDoc[targetNames.size()]) : null);
210                 exec.setVerbosity(verbosity);
211                 exec.setProperties(properties);
212                 exec.execute();
213             } catch (IOException JavaDoc 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); // NOI18N
220
}
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             // #84874: should be disabled in case the original Ant script is now gone.
234
return super.isEnabled() && pcookie.getFileObject() != null && pcookie.getFileObject().isValid();
235         }
236
237     }
238
239     /**
240      * Actually start the process.
241      */

242     public ExecutorTask execute () throws IOException JavaDoc {
243         String JavaDoc dn = getProcessDisplayName(pcookie, targetNames);
244         if (activeDisplayNames.contains(dn)) {
245             // Uniquify: "prj (targ) #2", "prj (targ) #3", etc.
246
int i = 2;
247             String JavaDoc 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             // OutputWindow
260
if (AntSettings.getAutoCloseTabs()) { // #47753
261
synchronized (freeTabs) {
262                 for (Map.Entry JavaDoc<InputOutput,String JavaDoc> entry : freeTabs.entrySet()) {
263                     InputOutput free = entry.getKey();
264                     String JavaDoc freeName = entry.getValue();
265                     if (io == null && freeName.equals(displayName)) {
266                         // Reuse it.
267
io = free;
268                         io.getOut().reset();
269                         // Apparently useless and just prints warning: io.getErr().reset();
270
// useless: io.flushReader();
271
} else {
272                         // Discard it.
273
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 JavaDoc[] {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 JavaDoc outputStream) throws IOException JavaDoc {
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 JavaDoc
310         public void stop () {
311             StopAction sa = stopActions.get(io);
312             if (sa != null) {
313                 sa.actionPerformed(null);
314             } else { // just in case
315
task.stop();
316             }
317         }
318         @Override JavaDoc
319         public int result () {
320             return task.result () + (ok ? 0 : 1);
321         }
322         @Override JavaDoc
323         public InputOutput getInputOutput () {
324             return io;
325         }
326     }
327     private static class WrapperRunnable implements Runnable JavaDoc {
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     /** Call execute(), not this method directly!
338      */

339     synchronized public void run () {
340         final Thread JavaDoc[] thisProcess = new Thread JavaDoc[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 JavaDoc("XXX No support for outputStream currently!"); // NOI18N
366
}
367         
368         File JavaDoc 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 JavaDoc[targetNames.size()]) : null, properties);
375         
376         // Don't hog the CPU, the build might take a while:
377
Thread.currentThread().setPriority((Thread.MIN_PRIORITY + Thread.NORM_PRIORITY) / 2);
378         
379         final Runnable JavaDoc interestingOutputCallback = new Runnable JavaDoc() {
380             public void run() {
381                 // #58513: display output now.
382
if (!displayed[0]) {
383                     displayed[0] = true;
384                     io.select();
385                 }
386             }
387         };
388         
389         InputStream JavaDoc in = null;
390         if (outputStream == null) { // #43043
391
try {
392                 in = new ReaderInputStream(io.getIn()) {
393                     // Show the output when an input field is displayed, if it hasn't already.
394
@Override JavaDoc
395                     public int read() throws IOException JavaDoc {
396                         interestingOutputCallback.run();
397                         return super.read();
398                     }
399                     @Override JavaDoc
400                     public int read(byte[] b) throws IOException JavaDoc {
401                         interestingOutputCallback.run();
402                         return super.read(b);
403                     }
404                     @Override JavaDoc
405                     public int read(byte[] b, int off, int len) throws IOException JavaDoc {
406                         interestingOutputCallback.run();
407                         return super.read(b, off, len);
408                     }
409                     @Override JavaDoc
410                     public long skip(long n) throws IOException JavaDoc {
411                         interestingOutputCallback.run();
412                         return super.skip(n);
413                     }
414                 };
415             } catch (IOException JavaDoc 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         // #58513, #87801: register a progress handle for the task too.
424
ProgressHandle handle = ProgressHandleFactory.createHandle(displayName, new Cancellable() {
425             public boolean cancel() {
426                 sa.actionPerformed(null);
427                 return true;
428             }
429         }, new AbstractAction JavaDoc() {
430             public void actionPerformed(ActionEvent JavaDoc e) {
431                 io.select();
432             }
433         });
434         handle.setInitialDelay(0); // #92436
435
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     /** Try to stop a build. */
457     static void stopProcess(Thread JavaDoc t) {
458         AntBridge.getInterface().stop(t);
459     }
460
461 }
462
Popular Tags