001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: *
017: */
018:
019: package org.apache.jmeter.reporters;
020:
021: import java.awt.BorderLayout;
022: import java.awt.Color;
023: import java.awt.Graphics;
024: import java.awt.GridBagConstraints;
025: import java.awt.GridBagLayout;
026: import java.awt.Insets;
027: import java.io.BufferedReader;
028: import java.io.File;
029: import java.io.FileReader;
030: import java.io.IOException;
031: import java.text.DecimalFormat;
032: import java.util.Enumeration;
033: import java.util.Hashtable;
034: import java.util.Vector;
035:
036: import javax.swing.JFrame;
037: import javax.swing.JLabel;
038: import javax.swing.JOptionPane;
039: import javax.swing.JPanel;
040:
041: import org.apache.jorphan.logging.LoggingManager;
042: import org.apache.log.Logger;
043:
044: /**
045: * This class loads data from a saved file and displays statistics about it.
046: *
047: *
048: * @author Tom Schneider
049: * @version $Revision: 493779 $
050: */
051: public class FileReporter extends JPanel {
052: private static final Logger log = LoggingManager
053: .getLoggerForClass();
054:
055: private Hashtable data = new Hashtable();
056:
057: /** initalize a file reporter from a file */
058: public void init(String file) throws IOException {
059: File datafile = new File(file);
060: BufferedReader reader = null;
061:
062: try {
063: if (datafile.canRead()) {
064: reader = new BufferedReader(new FileReader(datafile));
065: } else {
066: JOptionPane.showMessageDialog(null,
067: "The file you specified cannot be read.",
068: "Information", JOptionPane.INFORMATION_MESSAGE);
069: return;
070: }
071: String line;
072:
073: while ((line = reader.readLine()) != null) {
074: try {
075: line = line.trim();
076: if (line.startsWith("#") || line.length() == 0) {
077: continue;
078: }
079: int splitter = line.lastIndexOf(' ');
080: String key = line.substring(0, splitter);
081: int len = line.length() - 1;
082: Integer value = null;
083:
084: if (line.charAt(len) == ',') {
085: value = new Integer(line.substring(
086: splitter + 1, len));
087: } else {
088: value = new Integer(line
089: .substring(splitter + 1));
090: }
091: Vector v = getData(key);
092:
093: if (v == null) {
094: v = new Vector();
095: this .data.put(key, v);
096: }
097: v.addElement(value);
098: } catch (NumberFormatException nfe) {
099: log.error("This line could not be parsed: " + line,
100: nfe);
101: } catch (Exception e) {
102: log.error("This line caused a problem: " + line, e);
103: }
104: }
105: } finally {
106: if (reader != null)
107: reader.close();
108: }
109: showPanel();
110: }
111:
112: public Vector getData(String key) {
113: return (Vector) data.get(key);
114: }
115:
116: /**
117: * Show main panel with length, graph, and stats.
118: */
119: public void showPanel() {
120: JFrame f = new JFrame("Data File Report");
121:
122: setLayout(new BorderLayout());
123: GraphPanel gp = new GraphPanel(data);
124:
125: add(gp, "Center");
126: add(gp.getStats(), BorderLayout.EAST);
127: add(gp.getLegend(), BorderLayout.NORTH);
128: f.setSize(500, 300);
129: f.getContentPane().add(this );
130: f.show();
131: }
132:
133: /**
134: * Graph panel generates all the panels for this reporter. Data is organized
135: * based on thread name in a hashtable. The data itself is a Vector of Integer
136: * objects
137: */
138: private static class GraphPanel extends JPanel {
139: // boolean autoScale = true;
140: Hashtable data;
141:
142: Vector keys = new Vector();
143:
144: Vector colorList = new Vector();
145:
146: private GraphPanel() {
147: }
148:
149: public GraphPanel(Hashtable data) {
150: this .data = data;
151: Enumeration e = data.keys();
152:
153: while (e.hasMoreElements()) {
154: String key = (String) e.nextElement();
155:
156: keys.addElement(key);
157: }
158: for (int a = 0x33; a < 0xFF; a += 0x66) {
159: for (int b = 0x33; b < 0xFF; b += 0x66) {
160: for (int c = 0x33; c < 0xFF; c += 0x66) {
161: colorList.addElement(new Color(a, b, c));
162: }
163: }
164: }
165: }
166:
167: /**
168: * Get the maximum for all the data.
169: */
170: public float getMax() {
171: float maxValue = 0;
172:
173: for (int t = 0; t < keys.size(); t++) {
174: String key = (String) keys.elementAt(t);
175: Vector temp = (Vector) data.get(key);
176:
177: for (int j = 0; j < temp.size(); j++) {
178: float f = ((Integer) temp.elementAt(j)).intValue();
179:
180: maxValue = Math.max(f, maxValue);
181: }
182: }
183: return (float) (maxValue + maxValue * 0.1);
184: }
185:
186: /**
187: * Get the minimum for all the data.
188: */
189: public float getMin() {
190: float minValue = 9999999;
191:
192: for (int t = 0; t < keys.size(); t++) {
193: String key = (String) keys.elementAt(t);
194: Vector temp = (Vector) data.get(key);
195:
196: for (int j = 0; j < temp.size(); j++) {
197: float f = ((Integer) temp.elementAt(j)).intValue();
198:
199: minValue = Math.min(f, minValue);
200: }
201: }
202: return (float) (minValue - minValue * 0.1);
203: }
204:
205: /**
206: * Get the legend panel.
207: */
208: public JPanel getLegend() {
209: JPanel main = new JPanel();
210: GridBagLayout g = new GridBagLayout();
211:
212: main.setLayout(g);
213: GridBagConstraints c = new GridBagConstraints();
214:
215: c.insets = new Insets(3, 3, 3, 3);
216: c.fill = GridBagConstraints.BOTH;
217: c.gridwidth = 1;
218: c.gridheight = 1;
219: for (int t = 0; t < keys.size(); t++) {
220: String key = (String) keys.elementAt(t);
221: JLabel colorSwatch = new JLabel(" ");
222:
223: colorSwatch.setBackground((Color) colorList.elementAt(t
224: % colorList.size()));
225: colorSwatch.setOpaque(true);
226: c.gridx = 1;
227: c.gridy = t;
228: g.setConstraints(colorSwatch, c);
229: main.add(colorSwatch);
230: JLabel name = new JLabel(key);
231:
232: c.gridx = 2;
233: c.gridy = t;
234: g.setConstraints(name, c);
235: main.add(name);
236: }
237: return main;
238: }
239:
240: /**
241: * Get the stats panel.
242: */
243: public JPanel getStats() {
244: int total = 0;
245: float totalValue = 0;
246: float maxValue = 0;
247: float minValue = 999999;
248:
249: for (int t = 0; t < keys.size(); t++) {
250: String key = (String) keys.elementAt(t);
251: Vector temp = (Vector) data.get(key);
252:
253: for (int j = 0; j < temp.size(); j++) {
254: float f = ((Integer) temp.elementAt(j)).intValue();
255:
256: minValue = Math.min(f, minValue);
257: maxValue = Math.max(f, maxValue);
258: totalValue += f;
259: total++;
260: }
261: }
262: float averageValue = totalValue / total;
263: JPanel main = new JPanel();
264: GridBagLayout g = new GridBagLayout();
265:
266: main.setLayout(g);
267: DecimalFormat df = new DecimalFormat("#0.0");
268: GridBagConstraints c = new GridBagConstraints();
269:
270: c.insets = new Insets(3, 6, 3, 6);
271: c.fill = GridBagConstraints.BOTH;
272: c.gridwidth = 1;
273: c.gridheight = 1;
274: JLabel count = new JLabel("Count: " + total);
275:
276: c.gridx = 1;
277: c.gridy = 1;
278: g.setConstraints(count, c);
279: JLabel min = new JLabel("Min: "
280: + df.format(new Float(minValue)));
281:
282: c.gridx = 1;
283: c.gridy = 2;
284: g.setConstraints(min, c);
285: JLabel max = new JLabel("Max: "
286: + df.format(new Float(maxValue)));
287:
288: c.gridx = 1;
289: c.gridy = 3;
290: g.setConstraints(max, c);
291: JLabel average = new JLabel("Average: "
292: + df.format(new Float(averageValue)));
293:
294: c.gridx = 1;
295: c.gridy = 4;
296: g.setConstraints(average, c);
297: main.add(count);
298: main.add(min);
299: main.add(max);
300: main.add(average);
301: return main;
302: }
303:
304: /**
305: * Gets the size of the biggest Vector.
306: */
307: public int getDataWidth() {
308: int size = 0;
309:
310: for (int t = 0; t < keys.size(); t++) {
311: String key = (String) keys.elementAt(t);
312: Vector v = (Vector) data.get(key);
313:
314: size = Math.max(size, v.size());
315: }
316: return size;
317: }
318:
319: /**
320: * Draws the graph.
321: */
322: public void update(Graphics g) {
323: // setup drawing area
324: int base = 10;
325:
326: g.setColor(Color.white);
327: g.fillRect(0, 0, getSize().width, getSize().height);
328: int width = getSize().width;
329: int height = getSize().height;
330: float maxValue = getMax();
331: float minValue = getMin();
332:
333: // draw grid
334: g.setColor(Color.gray);
335: int dataWidth = getDataWidth();
336: int increment = Math.round((float) (width - 1)
337: / (dataWidth - 1));
338:
339: /*
340: * for (int t = 0; t < dataWidth; t++) { g.drawLine(t * increment, 0, t *
341: * increment, height); }
342: */
343: int yIncrement = Math.round(((float) height - (1 + base))
344: / (10 - 1));
345:
346: /*
347: * for (int t = 0; t < 10; t++) { g.drawLine(0, height - t * yIncrement,
348: * width, height - t * yIncrement); }
349: */
350: // draw axis
351: for (int t = 1; t < dataWidth; t += (dataWidth / 25 + 1)) {
352: g.drawString((new Integer(t)).toString(), t * increment
353: + 2, height - 2);
354: }
355: float incrementValue = (maxValue - minValue) / (10 - 1);
356:
357: for (int t = 0; t < 10; t++) {
358: g.drawString(new Integer(Math.round(minValue
359: + (t * incrementValue))).toString(), 2, height
360: - t * yIncrement - 2 - base);
361: }
362: // draw data lines
363: int start = 0;
364:
365: for (int t = 0; t < keys.size(); t++) {
366: String key = (String) keys.elementAt(t);
367: Vector v = (Vector) data.get(key);
368:
369: start = 0;
370: g.setColor((Color) colorList.elementAt(t
371: % colorList.size()));
372: for (int i = 0; i < v.size() - 1; i++) {
373: float y1 = ((Integer) v.elementAt(i)).intValue();
374: float y2 = ((Integer) v.elementAt(i + 1))
375: .intValue();
376:
377: y1 = y1 - minValue;
378: y2 = y2 - minValue;
379: int Y1 = Math.round((height * y1)
380: / (maxValue - minValue));
381: int Y2 = Math.round((height * y2)
382: / (maxValue - minValue));
383:
384: Y1 = height - Y1 - base;
385: Y2 = height - Y2 - base;
386: g.drawLine(start, Y1, start + increment, Y2);
387:
388: start += increment;
389: }
390: }
391: }
392:
393: public void paint(Graphics g) {
394: update(g);
395: }
396: }
397: }
|