001: package tide.execute;
002:
003: import java.awt.Dimension;
004: import snow.utils.DateUtils;
005: import tide.profiler.*;
006: import tide.project.*;
007: import tide.editor.MainEditorFrame;
008: import snow.utils.storage.*;
009: import snow.utils.ProcessUtils;
010: import snow.texteditor.SimpleDocument;
011: import snow.sortabletable.*;
012: import snow.utils.gui.Icons;
013: import java.util.concurrent.*;
014: import javax.swing.*;
015: import java.awt.BorderLayout;
016: import java.awt.Insets;
017: import java.awt.EventQueue;
018: import java.awt.event.*;
019: import javax.swing.border.*;
020: import javax.swing.event.*;
021: import javax.swing.text.*;
022: import java.util.*;
023: import java.io.*;
024: import java.text.*;
025:
026: /** Represents the running processes and allow to kill them and access several JMX operations (jmap, jstack, jconsole, ...)
027: *
028: * TODO?: windbg, userdump, drwtsn32 launch (but they must b downloaded from "Debugging tools for Windows")
029: * tasklist /svc, taskkill, shutdown
030: */
031: public class ProcessesManager extends JPanel {
032: final private ProcessesModel processesModel = new ProcessesModel();
033: final private SortableTableModel stm = new SortableTableModel(
034: processesModel, 2, true); // sorts the start date (robust)
035: final private JTable table = new JTable(stm);
036:
037: public ProcessesManager() {
038: super (new BorderLayout(0, 0));
039: setBorder(null);
040:
041: JScrollPane sp = new JScrollPane(table);
042: add(sp, BorderLayout.CENTER);
043: stm.installGUI(table);
044:
045: JPanel northPanel = new JPanel(new BorderLayout());
046: add(northPanel, BorderLayout.NORTH);
047:
048: JPanel controlPanel = new JPanel();
049: northPanel.add(controlPanel, BorderLayout.NORTH);
050: controlPanel.setBorder(new EmptyBorder(2, 5, 2, 0));
051: controlPanel.setLayout(new BoxLayout(controlPanel,
052: BoxLayout.X_AXIS));
053: final JButton kill = new JButton("Kill selected processes",
054: Icons.sharedStop);
055: kill.setDisabledIcon(new Icons.StopIcon(11, 11, false));
056: controlPanel.add(kill);
057: controlPanel.add(Box.createHorizontalStrut(5));
058:
059: kill.setMargin(new Insets(0, 2, 0, 2));
060: kill.setFocusPainted(false);
061: kill.setEnabled(false);
062: kill.addActionListener(new ActionListener() {
063: public void actionPerformed(ActionEvent ae) {
064: List<ProcessItem> sp = new ArrayList<ProcessItem>();
065: for (int sel : table.getSelectedRows()) {
066: int ind = stm.getIndexInUnsortedFromTablePos(sel);
067: if (ind >= 0) {
068: sp.add(processesModel.getProcessAt(ind));
069: }
070: }
071: processesModel.killProcesses(sp);
072: }
073: });
074:
075: final JButton clear = new JButton("Clear");
076: clear
077: .setToolTipText("<html><body>Remove the processes that are terminated");
078: controlPanel.add(clear);
079: controlPanel.add(Box.createHorizontalStrut(5));
080: clear.setMargin(new Insets(0, 2, 0, 2));
081: clear.setFocusPainted(false);
082: clear.addActionListener(new ActionListener() {
083: public void actionPerformed(ActionEvent ae) {
084: processesModel.removeTerminatedProcesses();
085: }
086: });
087:
088: final JButton jconsole = new JButton("Launch JConsole");
089: jconsole
090: .setToolTipText("<html><body>Instrumented JVM as Java6, or Java5 started with the JVM argument <pre>"
091: + JavaExecutor.JMX_ENABLE_JVM_ARG
092: + "</pre> can be monitored during runtime with jconsole.");
093: controlPanel.add(jconsole);
094: controlPanel.add(Box.createHorizontalStrut(5));
095: jconsole.setMargin(new Insets(0, 2, 0, 2));
096: jconsole.setFocusPainted(false);
097: jconsole.setEnabled(true);
098: jconsole.addActionListener(new ActionListener() {
099: public void actionPerformed(ActionEvent ae) {
100: File cons = MainEditorFrame.instance.getActualProject()
101: .getJConsole_TOOL();
102: if (cons.exists()) {
103: /*ProcessItem proc = null;
104: if(table.getSelectedRowCount()==1)
105: {
106: int pos = stm.getIndexInUnsortedFromTablePos( table.getSelectedRow() );
107: if(pos>=0)
108: {
109: // this returns empty if not running anymore.
110: proc = processesModel.getProcessAt(pos);
111: }
112: }*/
113: launchJConsole(null);
114: }
115:
116: }
117: });
118:
119: final JButton osTools = new JButton("OS tools");
120: osTools
121: .setToolTipText("<html><body>Some operating system tools.");
122: controlPanel.add(osTools);
123: controlPanel.add(Box.createHorizontalStrut(5));
124: osTools.setMargin(new Insets(0, 2, 0, 2));
125: osTools.setFocusPainted(false);
126: osTools.setEnabled(true);
127: osTools.addActionListener(new ActionListener() {
128: public void actionPerformed(ActionEvent ae) {
129: JPopupMenu pop = new JPopupMenu();
130: OSProcUtils.createOSMenu(pop, ProcessesManager.this );
131: pop.show(osTools, 0, osTools.getHeight());
132: }
133: });
134:
135: controlPanel
136: .add(new JLabel(
137: " Right click on a process below to access some analysis tools"));
138: controlPanel.setMinimumSize(new Dimension(100, 35)); // to allow "split bar freedom"
139:
140: MultiSearchPanel multiSearchPanel = new MultiSearchPanel(
141: "Filter", null, stm);
142: northPanel.add(multiSearchPanel);
143:
144: table.getSelectionModel().addListSelectionListener(
145: new ListSelectionListener() {
146: public void valueChanged(ListSelectionEvent lse) {
147: kill
148: .setEnabled(table.getSelectedRows().length > 0);
149: }
150: });
151:
152: table.addMouseListener(new MouseAdapter() {
153: @Override
154: public void mousePressed(MouseEvent me) {
155: if (me.isPopupTrigger()) {
156: showTablePopup(me);
157: return;
158: }
159: }
160:
161: @Override
162: public void mouseReleased(MouseEvent me) {
163: if (me.isPopupTrigger()) {
164: showTablePopup(me);
165: return;
166: }
167: }
168: });
169:
170: } // Constructor
171:
172: /** Writes the number of processes.
173: */
174: void updateProcessTabString() {
175: int count = processesModel.getNumberOfRunningProcesses();
176: MainEditorFrame.instance.outputPanels
177: .setNumberOfRunningProcesses(count);
178: }
179:
180: private void showTablePopup(MouseEvent me) {
181: JPopupMenu popup = new JPopupMenu();
182:
183: if (table.getSelectedRowCount() == 1) {
184: int pos = stm.getIndexInUnsortedFromTablePos(table
185: .getSelectedRow());
186: if (pos < 0)
187: return;
188:
189: // this returns empty if not running anymore.
190: final ProcessItem pi = processesModel.getProcessAt(pos);
191: popup.add((pi.isTerminated() ? "(Terminated) " : "")
192: + "Process \"" + pi.name + "\"");
193:
194: if (!pi.isTerminated()) {
195: popup.addSeparator();
196: JMenuItem kk = new JMenuItem("Kill process",
197: Icons.sharedStop);
198: popup.add(kk);
199: kk.addActionListener(new ActionListener() {
200: public void actionPerformed(ActionEvent ae) {
201: processesModel.killProcesses(Arrays.asList(pi));
202: }
203: });
204: }
205:
206: final String pid = processesModel.getProcessPIDAt(pos);
207: final ProjectSettings proj = MainEditorFrame.instance
208: .getActualProject();
209:
210: if (pi.isJavaProcess) {
211: popup.addSeparator();
212: final JMenuItem jc = new JMenuItem("Connect jConsole");
213: popup.add(jc);
214: jc.addActionListener(new ActionListener() {
215: public void actionPerformed(ActionEvent ae) {
216: launchJConsole(pi);
217: }
218: });
219:
220: popup.addSeparator();
221: final File jstack = proj.getJDK_Tool("jstack");
222: if (jstack.exists()) {
223: // WARNING: only since 1.6 (unsupported and experimental !!, may disapear)
224:
225: final JMenuItem ps = new JMenuItem(
226: "Show actual stacktrace (jstack)");
227: popup.add(ps);
228: ps.addActionListener(new ActionListener() {
229: public void actionPerformed(ActionEvent ae) {
230: SimpleDocument doc = MainEditorFrame.instance.outputPanels
231: .getExecutionOutputDoc();
232: MainEditorFrame.instance.outputPanels
233: .selectOutputTab(true);
234: doc.append("\r\nStacktrace of process "
235: + pid + " (" + pi.name + ")\r\n");
236: try {
237: String stack = ProcessUtils
238: .readWholeProcessStack(Arrays
239: .asList(
240: jstack
241: .getAbsolutePath(),
242: pid))
243: + "\r\n";
244: int pos = doc.getLength(); // so we can place the caret later where the stacktrace begins
245:
246: doc.appendNamed(stack, pid + "> ");
247:
248: MainEditorFrame.instance.outputPanels.executionOutputPanel
249: .setCaretPosition(pos);
250: } catch (Exception e) {
251: e.printStackTrace();
252: doc.appendError("\r\nERROR: "
253: + e.getMessage());
254: }
255: }
256: });
257: } // if jstack exists
258:
259: final File jmap = proj.getJDK_Tool("jmap");
260: if (jmap.exists()) {
261: // WARNING: only since 1.6 (unsupported and experimental !!, may disapear)
262: JMenuItem psf = new JMenuItem(
263: "Show actual objects in memory (jmap)");
264: popup.add(psf);
265: psf.addActionListener(new ActionListener() {
266: public void actionPerformed(ActionEvent ae) {
267: // quick=> no need to thread...
268: SimpleDocument doc = MainEditorFrame.instance.outputPanels
269: .getExecutionOutputDoc();
270: try {
271: Process p = Runtime.getRuntime().exec(
272: new String[] {
273: jmap.getAbsolutePath(),
274: "-histo", pid });
275: JMapReader reader = new JMapReader(p);
276: p.waitFor();
277: JMapViewer viewer = new JMapViewer(
278: reader, pi, jmap);
279: viewer.installAsTab();
280: } catch (Exception e) {
281: e.printStackTrace();
282: doc.appendError("\r\nERROR: "
283: + e.getMessage());
284: }
285: }
286: });
287:
288: JMenuItem ps2 = new JMenuItem(
289: "Dump the Java heap to file (jmap)");
290: ps2
291: .setToolTipText("TIP: use the SAP Memory Analyser free tool to analyse this heap dump.");
292: popup.addSeparator();
293: popup.add(ps2);
294: ps2.addActionListener(new ActionListener() {
295: public void actionPerformed(ActionEvent ae) {
296: ProfilerUtils.dumpToFileWithJMap(pi, null);
297: }
298: });
299:
300: JMenuItem ps3 = new JMenuItem(
301: "Dump the Java heap and browse it (jhat)");
302: popup.add(ps3);
303: ps3.addActionListener(new ActionListener() {
304: public void actionPerformed(ActionEvent ae) {
305: File f = ProfilerUtils.dumpToFileWithJMap(
306: pi, null);
307: if (f != null) {
308: try {
309: ProfilerUtils
310: .analyseProfilerResultWithJHatTool(
311: f, null);
312: } catch (Exception e) {
313: MainEditorFrame.instance.outputPanels
314: .getExecutionOutputDoc()
315: .appendErrorLine(
316: "" + e.getMessage()); // ToolsDoc ?
317: }
318: }
319: }
320: });
321:
322: JMenu redumpDiff = new JMenu(
323: "Dump again and show differences with a previous dump");
324: JMenu browseDump = new JMenu(
325: "Browse a previous dump");
326:
327: List<File> allPreviousDumps = pi.getAllDumps();
328: for (int i = allPreviousDumps.size() - 1; i >= 0; i--) // reverse
329: {
330: final File previousDump = allPreviousDumps
331: .get(i);
332: if (!previousDump.exists())
333: continue;
334:
335: String age = DateUtils
336: .formatTimeDifference(System
337: .currentTimeMillis()
338: - previousDump.lastModified());
339: JMenuItem ps4 = new JMenuItem(
340: "Differences with "
341: + previousDump.getName()
342: + ", made " + age + " ago");
343: redumpDiff.add(ps4);
344: ps4.addActionListener(new ActionListener() {
345: public void actionPerformed(ActionEvent ae) {
346:
347: File newDump = ProfilerUtils
348: .dumpToFileWithJMap(pi,
349: previousDump);
350: if (newDump == null)
351: return;
352: try {
353: System.out
354: .println("Analyse dump differences "
355: + newDump.getName()
356: + ", base="
357: + previousDump
358: .getName());
359: ProfilerUtils
360: .analyseProfilerResultWithJHatTool(
361: newDump,
362: previousDump);
363:
364: } catch (Exception e) {
365: MainEditorFrame.instance.outputPanels
366: .getExecutionOutputDoc()
367: .appendErrorLine(
368: "" + e.getMessage());
369: }
370: }
371: });
372:
373: JMenuItem ps5 = new JMenuItem("Browse "
374: + previousDump.getName() + ", made "
375: + age + " ago");
376: browseDump.add(ps5);
377: ps5.addActionListener(new ActionListener() {
378: public void actionPerformed(ActionEvent ae) {
379: try {
380: ProfilerUtils
381: .analyseProfilerResultWithJHatTool(
382: previousDump, null);
383: } catch (Exception e) {
384: MainEditorFrame.instance.outputPanels
385: .getExecutionOutputDoc()
386: .appendErrorLine(
387: "" + e.getMessage()); // ToolsDoc ?
388: }
389:
390: }
391: });
392:
393: }
394:
395: if (redumpDiff.getItemCount() > 0) {
396: popup.addSeparator();
397: popup.add(redumpDiff);
398: }
399:
400: if (browseDump.getItemCount() > 0) {
401: popup.add(browseDump);
402: }
403:
404: }
405: }
406:
407: } else {
408: popup.add("" + table.getSelectedRowCount()
409: + " selected processes");
410: }
411:
412: popup.show(table, me.getX(), me.getY());
413: }
414:
415: /** Adds a process to this manager.
416: */
417: public void addProcess(String name, final JProcess proc,
418: boolean removeFromViewWhenFinished) {
419: final ProcessItem pi = new ProcessItem(name, proc);
420: pi.autoRemoveFromViewWhenTerminated = removeFromViewWhenFinished;
421: processesModel.add(pi);
422:
423: if (proc.process != null) {
424: // wait for the end in a thread
425: Thread t = new Thread() {
426: public void run() {
427: try {
428: proc.process.waitFor();
429: } catch (Exception e) {
430: e.printStackTrace();
431: } finally {
432: processesModel.setTerminated(pi);
433: }
434:
435: }
436: };
437: t.setPriority(Thread.MIN_PRIORITY);
438: t.start();
439: } // else when popupated with jps
440: }
441:
442: /** Adds a process to this manager.
443: */
444: public void addProcess(String name, final Process proc,
445: boolean removeFromViewWhenFinished) {
446: final ProcessItem pi = new ProcessItem(name, proc);
447: pi.autoRemoveFromViewWhenTerminated = removeFromViewWhenFinished;
448: processesModel.add(pi);
449:
450: // wait for the end in a thread
451: // TODO:
452: Thread t = new Thread() {
453: public void run() {
454: try {
455: proc.waitFor();
456: } catch (Exception e) {
457: e.printStackTrace();
458: } finally {
459: processesModel.setTerminated(pi);
460: }
461:
462: }
463: };
464: t.setPriority(Thread.MIN_PRIORITY);
465: t.start();
466: }
467:
468: /** Adds a process to this manager
469: */
470: public void addProcess(SProcess proc) {
471: final ProcessItem pi = new ProcessItem(proc);
472: //pi.autoRemoveFromViewWhenTerminated = removeFromViewWhenFinished;
473: processesModel.add(pi);
474: }
475:
476: /** Adds a process to this manager.
477: */
478: public void addProcess(final String name, final Thread proc,
479: final boolean removeFromViewWhenFinished) {
480: final ProcessItem pi = new ProcessItem(name, proc);
481: pi.autoRemoveFromViewWhenTerminated = removeFromViewWhenFinished;
482: processesModel.add(pi);
483:
484: // wait for the end in a thread
485: Thread t = new Thread() {
486: public void run() {
487: try {
488: proc.join();
489: } catch (Exception e) {
490: e.printStackTrace();
491: } finally {
492: processesModel.setTerminated(pi);
493: }
494:
495: }
496: };
497: t.setPriority(Thread.MIN_PRIORITY);
498: t.start();
499: }
500:
501: /** Adds a process to this manager.
502: * Future items are returned for example by executors
503: */
504: public void addProcess(final String name, final Future proc,
505: boolean removeFromViewWhenFinished) {
506: final ProcessItem pi = new ProcessItem(name, proc);
507: pi.autoRemoveFromViewWhenTerminated = removeFromViewWhenFinished;
508: processesModel.add(pi);
509:
510: // wait for the end in a thread
511: // TODO:
512: Thread t = new Thread() {
513: public void run() {
514: try {
515: while (!proc.isDone()) {
516: Thread.sleep(50);
517: }
518: } catch (Exception e) {
519: e.printStackTrace();
520: } finally {
521: processesModel.setTerminated(pi);
522: }
523:
524: }
525: };
526: t.setPriority(Thread.MIN_PRIORITY);
527: t.start();
528: }
529:
530: /** @return null if not found.
531: */
532: public ProcessItem getProcess(final String pid) {
533: return processesModel.getProcess(pid);
534: }
535:
536: public ProcessItem getProcess(final JProcess pid) {
537: return processesModel.getProcess(pid);
538: }
539:
540: public void removeNonTIDEProcs() {
541: processesModel.removeNonTIDEProcs();
542: }
543:
544: public void refreshALL(final List<SProcess> allJPs) {
545: processesModel.refreshALL(allJPs);
546: }
547:
548: public void refreshALLJavaProcesses(List<JProcess> allJPs) {
549: processesModel.refreshALLJavaProcesses(allJPs);
550: }
551:
552: public void refresh() {
553: processesModel.update();
554: }
555:
556: public List<ProcessItem> getRunningJHatServers() {
557: List<ProcessItem> rl = new ArrayList<ProcessItem>();
558: for (ProcessItem pi : processesModel.processes) {
559: if (pi.state == ProcessItem.State.Running
560: && pi.name
561: .startsWith(ProfilerUtils.hatServerProcessStartWithName)) {
562: rl.add(pi);
563: }
564: }
565: return rl;
566: }
567:
568: /** null => no direct connection to some process, but jConsole shows various available.
569: */
570: public void launchJConsole(final ProcessItem proc) {
571: final File cons = MainEditorFrame.instance.getActualProject()
572: .getJConsole_TOOL();
573: if (cons.exists()) {
574: try {
575: // problem: if bad ID or syntax, silently crash...
576: String pid = "";
577: if (proc != null) {
578: if (proc.isJavaProcess) //.guessedJMX)
579: {
580: pid = proc.pid;
581: } // otherwise let the user select the pid itself, it may work...
582: // but do not directly start jconsole with that potential invalid pid, because it will end silently
583: }
584:
585: List<String> args = new ArrayList<String>();
586: args.add(cons.getAbsolutePath());
587:
588: File tt = new File(MainEditorFrame.instance
589: .getActualProject().getProperty("TDA_EXT_TOOL",
590: "C:/java/tools/tda/tda.jar"));
591: if (tt.exists()) {
592: args.add("-pluginpath");
593: args.add(tt.getAbsolutePath());
594: }
595:
596: if (pid.length() > 0) {
597: args.add(pid);
598: }
599: //System.out.println("JCons: "+args);
600: Process p = ProcessUtils
601: .executeProcessAndGobbleToConsole(
602: "Execute JConsole", null,
603: args.toArray(new String[args.size()]));
604: //not necessary... ProcessUtils.drainProcess(p, false);
605:
606: //debug... System.out.println(ProcessUtils.readWholeProcessStack(p, -1));
607:
608: } catch (Exception ex) {
609: JOptionPane.showMessageDialog(MainEditorFrame.instance,
610: "Error: " + ex.getMessage(),
611: "Cannot launch jConsole",
612: JOptionPane.ERROR_MESSAGE);
613: ex.printStackTrace();
614: }
615: } else {
616: JOptionPane
617: .showMessageDialog(MainEditorFrame.instance,
618: "JDK jconsole tool not found. Use a 1.5+ JDK for your project.");
619: }
620: }
621:
622: // TODO: store selection
623: class ProcessesModel extends FineGrainTableModel {
624: private final Vector<ProcessItem> processes = new Vector<ProcessItem>();
625: private final String[] COLUMN_NAMES = new String[] { "State",
626: "Process Name", "Start", "Duration", "Mem", "PID" };
627: private final int[] COLUMN_PREFERED_SIZES = new int[] { 4, 23,
628: 6, 6, 3, 3 };
629: final private SimpleDateFormat hourAndMinutesFormat = new SimpleDateFormat(
630: "HH:mm");
631:
632: @Override
633: public int getPreferredColumnWidth(int column) {
634: if (column >= 0 && column < COLUMN_PREFERED_SIZES.length)
635: return COLUMN_PREFERED_SIZES[column];
636: return -1;
637: }
638:
639: @Override
640: public String getColumnName(int column) {
641: if (column >= 0 && column < COLUMN_NAMES.length)
642: return COLUMN_NAMES[column];
643: return "Bad column " + column;
644: }
645:
646: public void add(final ProcessItem proc) {
647: EventQueue.invokeLater(new Runnable() {
648: public void run() {
649: fireTableModelWillChange();
650: processes.add(0, proc);
651: fireTableDataChanged();
652: fireTableModelHasChanged();
653:
654: updateProcessTabString();
655: }
656: });
657: }
658:
659: public void setTerminated(final ProcessItem proc) {
660: proc.endTime = System.currentTimeMillis();
661: proc.state = ProcessItem.State.Done;
662:
663: EventQueue.invokeLater(new Runnable() {
664: public void run() {
665: // update in each case, even if not removed, cause the state changes...
666: fireTableModelWillChange();
667:
668: if (proc.autoRemoveFromViewWhenTerminated) {
669: processes.remove(proc);
670: }
671:
672: fireTableDataChanged();
673: fireTableModelHasChanged();
674:
675: updateProcessTabString();
676: }
677: });
678: }
679:
680: public int getRowCount() {
681: return processes.size();
682: }
683:
684: public int getColumnCount() {
685: return COLUMN_NAMES.length;
686: }
687:
688: public void removeTerminatedProcesses() {
689: fireTableModelWillChange();
690: for (int i = processes.size() - 1; i >= 0; i--) {
691: ProcessItem pi = processes.get(i);
692: if (pi.isTerminated()) {
693: processes.remove(pi);
694: }
695: }
696: fireTableDataChanged();
697: fireTableModelHasChanged();
698: }
699:
700: public ProcessItem getProcess(final String pid) {
701: for (ProcessItem processItem : processes) {
702: if (pid.equals(processItem.pid)) {
703: return processItem;
704: }
705: }
706: return null;
707: }
708:
709: public ProcessItem getProcess(final JProcess pid) {
710: for (ProcessItem processItem : processes) {
711: if (pid == processItem.jproc) {
712: return processItem;
713: }
714: }
715: return null;
716: }
717:
718: public void removeNonTIDEProcs() {
719: List<ProcessItem> toRem = new ArrayList<ProcessItem>();
720: for (ProcessItem pi : processes) {
721: if (pi.isNonTIDE) {
722: toRem.add(pi);
723: }
724: }
725:
726: if (toRem.size() > 0) {
727: fireTableModelWillChange();
728:
729: processes.removeAll(toRem);
730:
731: fireTableDataChanged();
732: fireTableModelHasChanged();
733: }
734: }
735:
736: /** @return empty if killed or done, because it makes no sense !
737: */
738: public String getProcessPIDAt(int row) {
739: ProcessItem pi = processes.get(row);
740: if (pi.isTerminated())
741: return "";
742: return pi.pid;
743: }
744:
745: public int getNumberOfRunningProcesses() {
746: int count = 0;
747: for (ProcessItem pi : processes) {
748: if (pi.state == ProcessItem.State.Running)
749: count++;
750: }
751: return count;
752: }
753:
754: public ProcessItem getProcessAt(int row) {
755: return processes.get(row);
756: }
757:
758: public void killProcesses(List<ProcessItem> pl) {
759: fireTableModelWillChange();
760:
761: for (ProcessItem proc : pl) {
762: proc.kill();
763: }
764:
765: fireTableDataChanged();
766: fireTableModelHasChanged();
767:
768: updateProcessTabString();
769: }
770:
771: /** Should only be called with all procs. Mark as "Done" the no more present.
772: */
773: public void refreshALLJavaProcesses(final List<JProcess> allJPs) {
774: fireTableModelWillChange();
775:
776: for (ProcessItem proc : processes) {
777: if (proc.isJavaProcess) {
778: proc.visited = false;
779: }
780: }
781:
782: for (JProcess pr : allJPs) {
783: ProcessItem already = getProcess(pr.pid);
784: if (already == null) {
785: pr.externalNotTide = true;
786: final ProcessItem pi = new ProcessItem(
787: "EXTERNAL jps: " + pr.javaName + " ("
788: + pr.arguments + ")", pr);
789: pi.autoRemoveFromViewWhenTerminated = false;
790: processes.add(pi);
791: } else {
792: // already there.
793: already.visited = true;
794: }
795: }
796:
797: for (ProcessItem proc : processes) {
798: if (proc.isJavaProcess && !proc.visited) {
799: proc.state = ProcessItem.State.Done;
800: }
801: }
802:
803: fireTableDataChanged();
804: fireTableModelHasChanged();
805: }
806:
807: // EDT !
808: public void update() {
809: fireTableModelWillChange();
810: fireTableDataChanged();
811: fireTableModelHasChanged();
812: }
813:
814: /** Should only be called with all procs. Mark as "Done" the no more present.
815: */
816: public void refreshALL(List<SProcess> allJPs) {
817: fireTableModelWillChange();
818:
819: for (ProcessItem proc : processes) {
820: proc.visited = false;
821: }
822:
823: for (SProcess pr : allJPs) {
824: ProcessItem already = getProcess(pr.pid);
825: if (already == null) {
826: addProcess(pr);
827: } else {
828: already.visited = true;
829: already.name = pr.getName();
830: already.memoryBytes = pr.memory;
831: }
832: }
833:
834: for (ProcessItem proc : processes) {
835: if (!proc.visited && !proc.isTerminated()) {
836: proc.state = ProcessItem.State.Done;
837: }
838: }
839:
840: fireTableDataChanged();
841: fireTableModelHasChanged();
842: }
843:
844: public Object getValueAt(int row, int col) {
845: ProcessItem proc = processes.get(row);
846: if (col == 0)
847: return proc.state;
848: if (col == 1)
849: return proc.name;
850: if (col == 2)
851: return hourAndMinutesFormat.format(new Date(
852: proc.startTime));
853: if (col == 3) {
854: if (proc.endTime < 0)
855: return "";
856: return DateUtils.formatTimeDifference(proc.endTime
857: - proc.startTime);
858: }
859: if (col == 4) {
860: if (proc.memoryBytes <= 0)
861: return "";
862: return FileUtils.formatSize(proc.memoryBytes);
863: }
864: if (col == 5) {
865: if (proc.isTerminated())
866: return "";
867: return proc.pid
868: + (proc.pid.length() > 0 && proc.guessedJMX ? " (JMX)"
869: : "");
870: }
871:
872: return "?";
873: }
874:
875: @Override
876: public int compareForColumnSort(int pos1, int pos2, int col) {
877: if (col == 2) {
878: ProcessItem proc1 = processes.get(pos1);
879: ProcessItem proc2 = processes.get(pos2);
880: return Long.valueOf(proc1.startTime).compareTo(
881: proc2.startTime);
882: } else if (col == 3) {
883: ProcessItem proc1 = processes.get(pos1);
884: ProcessItem proc2 = processes.get(pos2);
885: return Long.valueOf(proc2.endTime - proc2.startTime)
886: .compareTo(proc2.endTime - proc2.startTime);
887: } else if (col == 4) {
888: ProcessItem proc1 = processes.get(pos1);
889: ProcessItem proc2 = processes.get(pos2);
890: return Long.valueOf(proc1.memoryBytes).compareTo(
891: proc2.memoryBytes);
892: } else if (col == 5) {
893: ProcessItem proc1 = processes.get(pos1);
894: ProcessItem proc2 = processes.get(pos2);
895: return Integer.valueOf(Integer.parseInt(proc1.pid))
896: .compareTo(Integer.parseInt(proc2.pid));
897: }
898:
899: else {
900: return super.compareForColumnSort(pos1, pos2, col);
901: }
902: }
903:
904: }
905:
906: }
|