001: package tide.execute;
002:
003: import java.awt.EventQueue;
004: import tide.editor.MainEditorFrame;
005: import snow.utils.ProcessUtils;
006: import java.util.*;
007: import java.io.File;
008:
009: /** Wraps potentially processes with JVM instrumentation availability.
010:
011: JVM6 or JVM5 started with -Dcom.sun.management.jmxremote, allows
012: connection (localhost without password) with jconsole.
013:
014: A JProcess may also wrap a normal process, without pid (no connect possible)...
015: be careful, if user name contains "_" char, pid cannot be listed.
016: */
017: public class JProcess //implements Comparable<JProcess>
018: {
019: public String javaName;
020: public String pid = ""; // not found
021: public String arguments = ""; // no args
022: public boolean guessedJMXMode = false; // detected when present in JVM execution args
023:
024: // external means: not in tIDE.
025: public boolean externalNotTide = false;
026:
027: public Process process = null;
028:
029: private JProcess(String javaName) {
030: this .javaName = javaName;
031: }
032:
033: private static JProcess scan(String line) {
034: JProcess p = new JProcess("unknown");
035:
036: Scanner sl = new Scanner(line);
037: sl.useDelimiter("\\s+");
038: p.pid = sl.next();
039: p.javaName = sl.next();
040:
041: sl.useDelimiter("$");
042: if (sl.hasNext()) {
043: p.arguments = sl.next();
044: }
045:
046: // rest are args...
047: return p;
048: }
049:
050: @Override
051: public boolean equals(Object anotherprocess) {
052: if (!(anotherprocess instanceof JProcess))
053: throw new ClassCastException("Bad class "
054: + anotherprocess.getClass());
055: JProcess ap = (JProcess) anotherprocess;
056: if (ap.javaName.equals(javaName) && ap.pid.equals(pid)
057: && ap.arguments.equals(arguments)) {
058: return true;
059: }
060: return false;
061: }
062:
063: /** TODO: also look at arguments, not only at javaName
064: * always completes, also on errors.
065: * If not found with jps Returns a dummy JProcess with associated process and name.
066: */
067: public static JProcess recognizeRunningProcess(final Process proc,
068: final String javaName, final boolean jmxMode,
069: final List<JProcess> processesBefore, final File jpsTool) {
070: try {
071: if (jpsTool.exists()) {
072: // actual
073: List<JProcess> nowProcs = getAllRunningJavaProcesses(jpsTool);
074: List<JProcess> allCache = new ArrayList<JProcess>(
075: nowProcs);
076:
077: // remove from now all processes that are already in the before list
078: if (processesBefore != null) {
079: nowProcs.removeAll(processesBefore);
080: }
081:
082: // look if one corresponds !
083: for (JProcess p : nowProcs) {
084: if (p.javaName.equals(javaName)) {
085: p.process = proc;
086: p.guessedJMXMode = jmxMode;
087: return p;
088: }
089: }
090: System.out.println("No " + javaName + " found in "
091: + nowProcs);
092: System.out.println("All: " + allCache);
093: }
094: } catch (Exception e) {
095: e.printStackTrace();
096: }
097:
098: // not found => create an empty one (without proc number)
099: final JProcess p = new JProcess(javaName);
100: p.process = proc;
101: p.guessedJMXMode = jmxMode;
102:
103: // [Oct2007]: look in 5 secs.
104: if (jpsTool.exists()) {
105: Thread t = new Thread() {
106: public void run() {
107: try {
108: Thread.sleep(5000);
109: List<JProcess> nowProcs = getAllRunningJavaProcesses(jpsTool);
110:
111: // remove from now all processes that are already in the before list
112: if (processesBefore != null) {
113: nowProcs.removeAll(processesBefore);
114: }
115:
116: // look if one corresponds !
117: for (JProcess pi : nowProcs) {
118: if (pi.javaName.equals(javaName)) {
119:
120: p.pid = pi.pid;
121:
122: // must be searched in the wrapper !
123: ProcessItem pit = MainEditorFrame.instance.outputPanels.processesManager
124: .getProcess(p);
125: if (pit != null) // may have been terminated !
126: {
127: pit.pid = p.pid;
128: }
129:
130: //System.out.println("PID FOUND AFTER 5 SEC: "+p.pid);
131: //System.out.println("From "+nowProcs);
132:
133: EventQueue.invokeLater(new Runnable() {
134: public void run() {
135: MainEditorFrame.instance.outputPanels.processesManager
136: .refresh();
137: }
138: });
139:
140: return; // OK, yeaah.
141: }
142: }
143: System.out
144: .println("PID NOT FOUND AFTER 5 sec.");
145:
146: } catch (Exception e) {
147: e.printStackTrace();
148: }
149: }
150: };
151: t.setPriority(Thread.MIN_PRIORITY);
152: t.start();
153: }
154:
155: return p;
156: }
157:
158: /** Invokes jps and return the actual running java processes with their pid and main class
159: always complete. on errors, return an empty list !
160: */
161: public static List<JProcess> getAllRunningJavaProcesses(
162: final File jps) {
163: final List<JProcess> vp = new ArrayList<JProcess>();
164: try {
165: final String ans = ProcessUtils
166: .readWholeProcessStack(Arrays.asList(jps
167: .getAbsolutePath(), "-lm"));
168: //System.out.println(ans);
169: Scanner s = new Scanner(ans);
170:
171: while (s.hasNextLine()) {
172: JProcess p = scan(s.nextLine());
173: if (!"sun.tools.jps.Jps".equals(p.javaName)) // ignores jps itself !!
174: {
175: vp.add(p);
176: }
177: }
178: } catch (Exception e) {
179: e.printStackTrace();
180: }
181: return vp;
182: }
183:
184: @Override
185: public String toString() {
186: return "JProcess " + pid + ": " + javaName + " (" + arguments
187: + ")";
188: }
189:
190: /*test
191: public static void main(String[] args)
192: {
193: try
194: {
195: System.out.println( getAllRunningJavaProcesses(new File("c:/java/jdk1.6.0_05/bin/jps.exe") ));
196: }
197: catch(Exception e)
198: {
199: e.printStackTrace();
200: }
201: }*/
202:
203: }
|