View Javadoc

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                 // Remove the title line.
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                         // Status
129                         tokenizer.nextToken();
130                         // Time
131                         tokenizer.nextToken();
132                         // SL
133                         tokenizer.nextToken();
134                         // RE
135                         tokenizer.nextToken();
136                         // PAGEIN
137                         tokenizer.nextToken();
138                         // VSZ
139                         tokenizer.nextToken();
140                         // RSS
141                         tokenizer.nextToken();
142                         // LIM
143                         tokenizer.nextToken();
144                         // TSIZ
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 }