001: package tide.execute;
002:
003: import tide.editor.Accelerators;
004: import java.awt.Color;
005: import tide.utils.SyntaxUtils;
006: import snow.utils.gui.Icons;
007: import tide.editor.MainEditorFrame;
008: import java.awt.event.*;
009: import java.util.*;
010: import java.io.*;
011: import javax.swing.*;
012: import tide.sources.*;
013:
014: /** The actions for execution used in the trees popup and in the navigation bar.
015: */
016: public final class ExecuteActions {
017: private ExecuteActions() {
018: }
019:
020: /** Looks in the source code.
021: */
022: public static boolean isExecutable(final FileItem sf) {
023: if (sf == null)
024: return false;
025:
026: boolean hasStaticMain = true;
027: // without this, one didn't see the "new edited version"
028: MainEditorFrame.instance.editorPanel
029: .storeTemporary_ActualEditedSource();
030:
031: // the dependencies are only detected at compilation. Here we may have a new state not yet parsed.
032: try {
033: hasStaticMain = SyntaxUtils.hasStaticMainMethod(sf
034: .getContent());
035: } catch (Exception e) {
036: }
037:
038: /*bad... too complicated, not correct, enums also can be exec
039: if(sf instanceof SourceFile)
040: {
041: SourceFile sfi = (SourceFile) sf;
042:
043: try
044: {
045: if(sfi.sourceFileDependencies.areDependenciesActual())
046: {
047: hasStaticMain = sfi.sourceFileDependencies.hasStaticMain;
048: }
049: else
050: {
051: // maybe not parsed yet =>
052: hasStaticMain = SyntaxUtils.hasStaticMainMethod(sfi.getContent());
053: // helper
054: if(hasStaticMain)
055: {
056: sfi.sourceFileDependencies.hasStaticMain = true;
057: }
058: }
059: } catch(Exception e) {}
060: }
061: else
062: {
063: try {
064: hasStaticMain = SyntaxUtils.hasStaticMainMethod(sf.getContent());
065: } catch(Exception e) {}
066: }*/
067:
068: return hasStaticMain;
069: }
070:
071: /** TODO.
072: */
073: public static JMenuItem createSearchRunActions() {
074: final JMenuItem runs = new JMenuItem(
075: "Search for executable classes");
076: // runs.set Accelerator(Accelerators.searchForRunnables);
077: runs.addActionListener(new ActionListener() {
078: public void actionPerformed(ActionEvent ae) {
079: //...
080: // just loop over src and look for static void main methods (in classes, enums)
081: //MainEditorFrame.instance;
082:
083: }
084: });
085: return runs;
086: }
087:
088: /** Ask if none defined...
089: */
090: public static JMenuItem createProjectRunAction() {
091: JMenuItem run = new JMenuItem("Run project",
092: new Icons.StartIcon(14, 14, true, false, Color.blue
093: .brighter()));
094: // Warning: F10 is already defined as menu open !! (but has been deactivated in MainEditorFrame!)
095: run.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F10, 0,
096: true)); // true is important here...
097:
098: run.addActionListener(new ActionListener() {
099: public void actionPerformed(ActionEvent ae) {
100: String mainClassName = MainEditorFrame.instance
101: .getActualProject().getMainClassJavaName();
102: if (mainClassName == null) {
103: int rep = JOptionPane
104: .showConfirmDialog(
105: MainEditorFrame.instance,
106: "The project doesn't contain a main project class."
107: + "\nYour can define that class in the project settings"
108: + "\nor directly from the sources tree panel context menu."
109: + "\n\nDo you want to select one now ?",
110: "Cannot run the project",
111: JOptionPane.YES_NO_OPTION);
112: if (rep != JOptionPane.YES_OPTION)
113: return;
114:
115: if (!MainEditorFrame.instance.editSettingsDialog(
116: false, false))
117: return;
118:
119: mainClassName = MainEditorFrame.instance
120: .getActualProject().getMainClassJavaName();
121:
122: if (mainClassName == null)
123: return;
124: }
125: //System.out.println("F10 pressed => run project");
126: MainEditorFrame.instance.runAction_queued(
127: mainClassName, false, false, null, null);
128: }
129: });
130:
131: return run;
132: }
133:
134: /** Contains null for separators.
135: */
136: public static List<JMenuItem> createNormalRunActions(
137: final FileItem sf) {
138: List<JMenuItem> acts = new ArrayList<JMenuItem>();
139:
140: JMenuItem execute = new JMenuItem(
141: "Run " + sf.getJavaPartName(), Icons.sharedStart);
142: execute.setAccelerator(Accelerators.runSelected); // just display, mapping occurs in the MainEditorFrame
143: acts.add(execute);
144: execute.addActionListener(new ActionListener() {
145: public void actionPerformed(ActionEvent ae) {
146: MainEditorFrame.instance.execute(sf, false, null, null);
147: }
148: });
149:
150: if (sf instanceof SourceFile) {
151: final SourceFile sfi = (SourceFile) sf;
152: if (!sfi.isProjectMainClass) {
153: JMenuItem defMain = new JMenuItem(
154: "Define as project main class",
155: new Icons.StartIcon(10, 10, true, false,
156: Color.blue.brighter()));
157: acts.add(null);
158: acts.add(defMain);
159: defMain.addActionListener(new ActionListener() {
160: public void actionPerformed(ActionEvent ae) {
161: MainEditorFrame.instance.getActualProject()
162: .setMainSourceFile(sfi.javaFile);
163: MainEditorFrame.instance.sourcesTreePanel
164: .getTreeModel().markMainProjectSource();
165: }
166: });
167: }
168: }
169:
170: return acts;
171: }
172:
173: /** Contains null for separators.
174: */
175: public static List<JMenuItem> createDebugRunActions(
176: final FileItem sf) {
177: List<JMenuItem> acts = new ArrayList<JMenuItem>();
178:
179: if (MainEditorFrame.instance.getActualProject()
180: .isJava5_OrMore()) {
181:
182: JMenuItem executeJMX = new JMenuItem(
183: "Execute with JMX remote enabled",
184: Icons.sharedDebugStart);
185: executeJMX
186: .setToolTipText("<html><body>You can then, from the processes tab, attach jConsole to the running app."
187: + "<br>From Java6, JMX is enabled by default");
188: acts.add(executeJMX);
189: executeJMX.addActionListener(new ActionListener() {
190: public void actionPerformed(ActionEvent ae) {
191: MainEditorFrame.instance.execute(sf, true, null,
192: null);
193: }
194: });
195: }
196:
197: JMenuItem profCPUSampled = new JMenuItem(
198: "Execute with CPU usage sampling (QUICK but inexact)",
199: Icons.sharedDebugStart);
200: profCPUSampled
201: .setToolTipText("When the application normally exits, a new tab with the CPU profiling info will be opened.");
202: acts.add(null);
203: acts.add(profCPUSampled);
204: profCPUSampled.addActionListener(new ActionListener() {
205: public void actionPerformed(ActionEvent ae) {
206: // inexact, each 20ms, but quick
207: File profFolder = MainEditorFrame.instance
208: .getActualProject().getProfilerResultsFolder();
209: if (!profFolder.exists())
210: profFolder.mkdirs();
211: String command = "-agentlib:hprof=cpu=samples,file=../.tide/profiler/"
212: + sf.getJavaName()
213: + ".cpu_samples.hprof,depth="
214: + MainEditorFrame.instance
215: .getActualProject()
216: .getProperty(
217: "Profiler_stacktraceDepth", "5")
218: + ",interval="
219: + MainEditorFrame.instance.getActualProject()
220: .getProperty(
221: "Profiler_samplingInterval",
222: "30")
223: + ",cutoff="
224: + MainEditorFrame.instance.getActualProject()
225: .getProperty("Profiler_cutoff",
226: "0.0001");
227: //+",monitor=y";
228: MainEditorFrame.instance.execute(sf, false, command,
229: null);
230: }
231: });
232:
233: // CPU usage time profiling (cpu=times) slow but exact
234: JMenuItem cpuTimeProf = new JMenuItem(
235: "Execute with exact CPU time profiling (VERY SLOW)",
236: Icons.sharedDebugStart);
237: cpuTimeProf
238: .setToolTipText("When the application normally exits, a new tab with the CPU profiling info will be opened.");
239: acts.add(cpuTimeProf);
240: cpuTimeProf.addActionListener(new ActionListener() {
241: public void actionPerformed(ActionEvent ae) {
242: // LARGE OUTPUTS !
243: File profFolder = MainEditorFrame.instance
244: .getActualProject().getProfilerResultsFolder();
245: if (!profFolder.exists())
246: profFolder.mkdirs();
247: String command = "-agentlib:hprof=cpu=times,lineno=y,file=../.tide/profiler/"
248: + sf.getJavaName()
249: + ".cpu_times.hprof,depth="
250: + MainEditorFrame.instance
251: .getActualProject()
252: .getProperty(
253: "Profiler_stacktraceDepth", "5")
254: + ",cutoff="
255: + MainEditorFrame.instance.getActualProject()
256: .getProperty("Profiler_cutoff",
257: "0.0001");
258: //lineno=y don't work ??? there are no line number !!
259: MainEditorFrame.instance.execute(sf, false, command,
260: null);
261: }
262: });
263:
264: JMenuItem profHeapAlloc = new JMenuItem(
265: "Execute with heap allocation profiling (SLOW)",
266: Icons.sharedDebugStart);
267: profHeapAlloc
268: .setToolTipText("When the application exits, a new tab with the Memory profiling info will be opened.");
269: //menuProfile.addSeparator();
270: acts.add(profHeapAlloc);
271: profHeapAlloc.addActionListener(new ActionListener() {
272: public void actionPerformed(ActionEvent ae) {
273: // LARGE OUTPUTS !
274: // reveals whichs methods performs heap allocation
275: // allow to see which methods are ultimatively responsible for making calls that resulted in memory allocation !
276: File profFolder = MainEditorFrame.instance
277: .getActualProject().getProfilerResultsFolder();
278: if (!profFolder.exists())
279: profFolder.mkdirs();
280: String command = "-agentlib:hprof=heap=sites,file=../.tide/profiler/"
281: + sf.getJavaName()
282: + ".heap_sites.hprof,depth="
283: + MainEditorFrame.instance
284: .getActualProject()
285: .getProperty(
286: "Profiler_stacktraceDepth", "5")
287: + ",cutoff="
288: + MainEditorFrame.instance.getActualProject()
289: .getProperty("Profiler_cutoff",
290: "0.0001");
291: MainEditorFrame.instance.execute(sf, false, command,
292: null);
293: }
294: });
295:
296: // heap=dump (VERY LARGE OUTPUTS) (can be browsed with HAT)
297: JMenuItem profHeapDump = new JMenuItem(
298: "Execute with heap dump (BIG FILES, use jHAT to analyse)",
299: Icons.sharedDebugStart);
300: profHeapDump
301: .setToolTipText("At application exit, a big file containing the head dump will be created.");
302: //menuProfile.addSeparator();
303: acts.add(profHeapDump);
304: profHeapDump.addActionListener(new ActionListener() {
305: public void actionPerformed(ActionEvent ae) {
306: // LARGE OUTPUTS !
307: File profFolder = MainEditorFrame.instance
308: .getActualProject().getProfilerResultsFolder();
309: if (!profFolder.exists())
310: profFolder.mkdirs();
311:
312: // depth ?? cutoff ??
313: // format=b is required by HAT
314: String command = "-agentlib:hprof=heap=dump,format=b,file=../.tide/profiler/"
315: + sf.getJavaName() + ".heap_dump.hprof";
316: MainEditorFrame.instance.execute(sf, false, command,
317: null);
318:
319: }
320: });
321: /* }
322: else
323: {
324: menuProfile.add("SORRY: Profiling and JMX management only since 1.5");
325: }*/
326:
327: if (MainEditorFrame.enableExperimental) {
328: JMenuItem debugTool = new JMenuItem(
329: "Execute with the JDA debugger",
330: Icons.sharedDebugStart);
331: debugTool
332: .setToolTipText("<html><body>The application is started and a JDA debug console is attached."
333: + "<br>Please read the docs at technotes/tools/windows/jdb.html");
334: acts.add(null);
335: acts.add(debugTool);
336: debugTool.addActionListener(new ActionListener() {
337: public void actionPerformed(ActionEvent ae) {
338: MainEditorFrame.instance.execute(sf, true, true,
339: null, null);
340: }
341: });
342: }
343:
344: return acts;
345: }
346:
347: /** Also updates the project ran list (removes old entries).
348: */
349: public static List<JMenuItem> createRunActionsForAlreadyRan() {
350: List<JMenuItem> acts = new ArrayList<JMenuItem>();
351:
352: Set<String> rem = new HashSet<String>();
353: for (Iterator<String> its = MainEditorFrame.instance
354: .getActualProject().getAllAlreadyRanJavaNames()
355: .iterator(); its.hasNext();) {
356: final String in = its.next();
357: if (in.trim().length() == 0)
358: continue;
359:
360: final FileItem fi = MainEditorFrame.instance.getFileItem(
361: in, "");
362: if (fi == null) {
363: System.out.println("Cannot find " + in
364: + " for execution");
365: rem.add(in);
366: continue;
367: }
368:
369: JMenuItem ex = new JMenuItem("" + in,
370: Icons.sharedSmallStart);
371: ex.addActionListener(new ActionListener() {
372: public void actionPerformed(ActionEvent ae) {
373: FileItem fi = MainEditorFrame.instance.getFileItem(
374: in, "");
375: if (fi == null) {
376: System.out.println("Cannot find " + in
377: + " for execution");
378: return;
379: }
380: MainEditorFrame.instance.execute(fi, false, null,
381: null);
382: }
383: });
384:
385: acts.add(ex);
386: }
387: MainEditorFrame.instance.getActualProject()
388: .getAllAlreadyRanJavaNames().removeAll(rem);
389:
390: return acts;
391: }
392:
393: /** The 10 most ran, sorted */
394: public static List<JMenuItem> createRunActionsForMostRan() {
395: List<JMenuItem> acts = new ArrayList<JMenuItem>();
396: Map<String, Integer> rac = MainEditorFrame.instance
397: .getActualProject().getRanCount();
398: List<Object[]> tos = new ArrayList<Object[]>();
399: for (String jni : rac.keySet()) {
400: tos.add(new Object[] { jni, rac.get(jni) });
401: }
402: Collections.sort(tos, new Comparator<Object[]>() {
403: public int compare(Object[] o1, Object[] o2) {
404: return ((Integer) o2[1]).compareTo((Integer) o1[1]);
405: }
406: });
407:
408: for (int i = 0; i < tos.size(); i++) {
409: if (i > 10)
410: break;
411: final String in = "" + tos.get(i)[0];
412:
413: JMenuItem ex = new JMenuItem("" + in + " ("
414: + tos.get(i)[1] + ")", Icons.sharedSmallStart);
415: ex.addActionListener(new ActionListener() {
416: public void actionPerformed(ActionEvent ae) {
417: FileItem fi = MainEditorFrame.instance.getFileItem(
418: in, "");
419: if (fi == null) {
420: System.out.println("Cannot find " + in
421: + " for execution");
422: return;
423: }
424: MainEditorFrame.instance.execute(fi, false, null,
425: null);
426: }
427: });
428: acts.add(ex);
429: }
430:
431: return acts;
432: }
433:
434: }
|