1 /***
2 * ProcessInfoSource.java
3 *
4 * This file is part of the creme library.
5 * The creme library intends to ease the development effort of large
6 * applications by providing easy to use support classes.
7 *
8 * Copyright (C) 2003 Denis Bregeon
9 *
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
14 *
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
19 *
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 *
24 * contact information: dbregeon@sourceforge.net
25 */
26 package org.jcreme.tutorial;
27
28 import java.io.IOException;
29 import java.util.HashSet;
30 import java.util.Hashtable;
31 import java.util.Iterator;
32 import java.util.StringTokenizer;
33 import java.util.Timer;
34 import java.util.TimerTask;
35
36 import org.jcreme.reporting.DataChangeEvent;
37 import org.jcreme.reporting.DataChangeListener;
38 import org.jcreme.reporting.DataSource;
39
40 /***
41 *
42 * @author $Author: dbregeon $
43 * @version $Revision: 1.1 $
44 */
45 public class ProcessInfoSource implements DataSource {
46 protected Hashtable processes = new Hashtable();
47
48 protected HashSet listeners = new HashSet();
49
50 protected Timer refreshTimer = null;
51
52 /***
53 * @see org.jcreme.reporting.DataSource#addDataChangeListener(org.jcreme.reporting.DataChangeListener)
54 */
55 public void addDataChangeListener(DataChangeListener listener) {
56 if (listener != null) {
57 synchronized (this.listeners) {
58 this.listeners.add(listener);
59 }
60 }
61
62 }
63
64 /***
65 * @see org.jcreme.reporting.DataSource#removeDataChangeListener(org.jcreme.reporting.DataChangeListener)
66 */
67 public void removeDataChangeListener(DataChangeListener listener) {
68 if (listener != null) {
69 synchronized (this.listeners) {
70 this.listeners.remove(listener);
71 }
72 }
73 }
74
75 /***
76 *
77 * @return the processes detected.
78 */
79 public ProcessInfo[] getProcessInfos() {
80 updateProcesses();
81 return (ProcessInfo[]) this.processes.values().toArray(
82 new ProcessInfo[0]);
83 }
84
85 /***
86 *
87 *
88 */
89 public void updateProcesses() {
90 HashSet changed = new HashSet();
91 Hashtable oldValues = null;
92 synchronized (this.processes) {
93 oldValues = (Hashtable) this.processes.clone();
94 this.processes.clear();
95
96 System.err.println("Refreshing.");
97 Process proc = null;
98 try {
99 proc = Runtime.getRuntime().exec("/bin/ps -eavwx");
100 StringBuffer text = new StringBuffer();
101 int next = proc.getInputStream().read();
102 while (next != -1) {
103 text.append((char) next);
104 next = proc.getInputStream().read();
105 }
106 StringTokenizer tokenizer = new StringTokenizer(
107 text.toString(), "\n", false);
108
109 tokenizer.nextToken();
110 tokenizer.nextToken(" ");
111 Integer pid = null;
112 Double cpuUsage = null;
113 Double memoryUsage = null;
114 String processName = null;
115 ProcessInfo processInfo = null;
116 while (tokenizer.hasMoreTokens()) {
117 try {
118 pid = Integer.valueOf(tokenizer.nextToken(" ").trim());
119 processInfo = (ProcessInfo) this.processes.get(pid);
120 if (processInfo == null) {
121 processInfo = (ProcessInfo) oldValues.get(pid);
122 if (processInfo == null) {
123 processInfo = new ProcessInfo(pid);
124 changed.add(processInfo);
125 }
126 this.processes.put(pid, processInfo);
127 }
128
129 tokenizer.nextToken();
130
131 tokenizer.nextToken();
132
133 tokenizer.nextToken();
134
135 tokenizer.nextToken();
136
137 tokenizer.nextToken();
138
139 tokenizer.nextToken();
140
141 tokenizer.nextToken();
142
143 tokenizer.nextToken();
144
145 tokenizer.nextToken();
146 try {
147 cpuUsage = Double.valueOf(tokenizer.nextToken());
148 if (!cpuUsage.equals(processInfo.getCPUUsage())) {
149 processInfo.setCPUUsage(cpuUsage);
150 changed.add(processInfo);
151 }
152 } catch (NumberFormatException e) {
153 e.printStackTrace();
154 }
155 try {
156 memoryUsage = Double.valueOf(tokenizer.nextToken());
157 if (!memoryUsage.equals(processInfo
158 .getMemoryUsage())) {
159 processInfo.setMemoryUsage(memoryUsage);
160 changed.add(processInfo);
161 }
162 } catch (NumberFormatException e) {
163 e.printStackTrace();
164 }
165 processName = tokenizer.nextToken("\n");
166 if (!processName.equals(processInfo.getProcessName())) {
167 processInfo.setProcessName(processName);
168 changed.add(processInfo);
169 }
170 } catch (NumberFormatException e) {
171 e.printStackTrace();
172 tokenizer.nextToken("\n");
173 } catch (IllegalArgumentException e) {
174 e.printStackTrace();
175 tokenizer.nextToken("\n");
176 }
177 tokenizer.nextToken(" ");
178 }
179 } catch (IOException e) {
180 e.printStackTrace();
181 } finally {
182 proc.destroy();
183 }
184 Iterator iter = oldValues.keySet().iterator();
185 Object currentKey = null;
186 while (iter.hasNext()) {
187 currentKey = iter.next();
188 if (this.processes.get(currentKey) == null) {
189 changed.add(oldValues.get(currentKey));
190 }
191 }
192 }
193 Iterator iter = changed.iterator();
194 while (iter.hasNext()) {
195 fireDataChangeEvent(this, iter.next());
196 }
197 }
198
199 protected void fireDataChangeEvent(Object source, Object data) {
200 synchronized (this.listeners) {
201 DataChangeEvent dataChangeEvent = new DataChangeEvent(source, data);
202 Iterator iter = this.listeners.iterator();
203 while (iter.hasNext()) {
204 ((DataChangeListener) iter.next()).dataChanged(dataChangeEvent);
205 }
206 }
207 }
208
209 /***
210 *
211 * @param timer
212 */
213 public void setRefreshTimer(long timer) {
214 if (timer > 0) {
215 removeRefreshTimer();
216 this.refreshTimer = new Timer();
217 this.refreshTimer.scheduleAtFixedRate(new TimerTask() {
218 protected volatile boolean isRunning = false;
219
220 public void run() {
221 if (!this.isRunning) {
222 this.isRunning = true;
223 updateProcesses();
224 this.isRunning = false;
225 }
226 }
227 }, 0, timer);
228 }
229 }
230
231 /***
232 *
233 *
234 */
235 public void removeRefreshTimer() {
236 if (this.refreshTimer != null) {
237 this.refreshTimer.cancel();
238 this.refreshTimer = null;
239 }
240 }
241
242 /***
243 *
244 * @param info
245 * @return true if the ProcessInfo is valid.
246 */
247 public boolean isValid(ProcessInfo info) {
248 return (info != null)
249 && (this.processes.get(info.getProcessId()) != null);
250 }
251
252 }