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.visualizers;
020:
021: import java.awt.BorderLayout;
022: import java.awt.Color;
023: import java.awt.FlowLayout;
024: import java.text.Format;
025: import java.text.SimpleDateFormat;
026:
027: import javax.swing.BorderFactory;
028: import javax.swing.ImageIcon;
029: import javax.swing.JLabel;
030: import javax.swing.JPanel;
031: import javax.swing.JScrollPane;
032: import javax.swing.JTable;
033: import javax.swing.JTextField;
034: import javax.swing.border.Border;
035: import javax.swing.border.EmptyBorder;
036: import javax.swing.table.TableCellRenderer;
037:
038: import org.apache.jmeter.samplers.Clearable;
039: import org.apache.jmeter.samplers.SampleResult;
040: import org.apache.jmeter.util.Calculator;
041: import org.apache.jmeter.util.JMeterUtils;
042: import org.apache.jmeter.visualizers.gui.AbstractVisualizer;
043: import org.apache.jorphan.gui.ObjectTableModel;
044: import org.apache.jorphan.gui.RendererUtils;
045: import org.apache.jorphan.gui.RightAlignRenderer;
046: import org.apache.jorphan.gui.layout.VerticalLayout;
047: import org.apache.jorphan.logging.LoggingManager;
048: import org.apache.jorphan.reflect.Functor;
049: import org.apache.log.Logger;
050:
051: /**
052: * This class implements a statistical analyser that calculates both the average
053: * and the standard deviation of the sampling process. The samples are displayed
054: * in a JTable, and the statistics are displayed at the bottom of the table.
055: *
056: * created March 10, 2002
057: *
058: */
059: public class TableVisualizer extends AbstractVisualizer implements
060: Clearable {
061: private static final Logger log = LoggingManager
062: .getLoggerForClass();
063:
064: private static final ImageIcon imageSuccess = JMeterUtils.getImage(
065: JMeterUtils.getPropDefault("viewResultsTree.success", //$NON-NLS-1$
066: "icon_success_sml.gif"), //$NON-NLS-1$
067: JMeterUtils.getResString("table_visualizer_success")); //$NON-NLS-1$
068:
069: private static final ImageIcon imageFailure = JMeterUtils.getImage(
070: JMeterUtils.getPropDefault("viewResultsTree.failure", //$NON-NLS-1$
071: "icon_warning_sml.gif"), //$NON-NLS-1$
072: JMeterUtils.getResString("table_visualizer_warning")); //$NON-NLS-1$
073:
074: private final String[] COLUMNS = new String[] {
075: JMeterUtils.getResString("table_visualizer_sample_num"), // $NON-NLS-1$
076: JMeterUtils.getResString("table_visualizer_start_time"), // $NON-NLS-1$
077: JMeterUtils.getResString("table_visualizer_thread_name"),// $NON-NLS-1$
078: JMeterUtils.getResString("sampler_label"), // $NON-NLS-1$
079: JMeterUtils.getResString("table_visualizer_sample_time"), // $NON-NLS-1$
080: JMeterUtils.getResString("table_visualizer_status"), // $NON-NLS-1$
081: JMeterUtils.getResString("table_visualizer_bytes") }; // $NON-NLS-1$
082:
083: private ObjectTableModel model = null;
084:
085: private JTable table = null;
086:
087: private JTextField dataField = null;
088:
089: private JTextField averageField = null;
090:
091: private JTextField deviationField = null;
092:
093: private JTextField noSamplesField = null;
094:
095: private JScrollPane tableScrollPanel = null;
096:
097: private transient Calculator calc = new Calculator();
098:
099: private long currentData = 0;
100:
101: private Format format = new SimpleDateFormat("HH:mm:ss.SSS"); //$NON-NLS-1$
102:
103: // Column renderers
104: private static final TableCellRenderer[] RENDERERS = new TableCellRenderer[] {
105: null, // Count
106: new RightAlignRenderer(), // Start Time
107: null, // Thread Name
108: null, // Label
109: null, // Sample Time
110: null, // Status
111: null, // Bytes
112: };
113:
114: /**
115: * Constructor for the TableVisualizer object.
116: */
117: public TableVisualizer() {
118: super ();
119: model = new ObjectTableModel(COLUMNS, Sample.class, // The object used for each row
120: new Functor[] {
121: new Functor("getCount"), // $NON-NLS-1$
122: new Functor("getStartTimeFormatted", // $NON-NLS-1$
123: new Object[] { format }),
124: new Functor("getThreadName"), // $NON-NLS-1$
125: new Functor("getLabel"), // $NON-NLS-1$
126: new Functor("getData"), // $NON-NLS-1$
127: new SampleSuccessFunctor("isSuccess"), // $NON-NLS-1$
128: new Functor("getBytes") }, // $NON-NLS-1$
129: new Functor[] { null, null, null, null, null, null,
130: null }, new Class[] { Long.class, String.class,
131: String.class, String.class, Long.class,
132: ImageIcon.class, Integer.class });
133: init();
134: }
135:
136: public static boolean testFunctors() {
137: TableVisualizer instance = new TableVisualizer();
138: return instance.model.checkFunctors(null, instance.getClass());
139: }
140:
141: public String getLabelResource() {
142: return "view_results_in_table"; // $NON-NLS-1$
143: }
144:
145: protected synchronized void updateTextFields() {
146: noSamplesField.setText(Long.toString(calc.getCount()));
147: dataField.setText(Long.toString(currentData));
148: averageField.setText(Long.toString((long) calc.getMean()));
149: deviationField.setText(Long.toString((long) calc
150: .getStandardDeviation()));
151: }
152:
153: public void add(SampleResult res) {
154: currentData = res.getTime();
155: synchronized (calc) {
156: calc.addValue(currentData);
157: int count = calc.getCount();
158: Sample newS = new Sample(res.getSampleLabel(), res
159: .getTime(), 0, 0, 0, 0, 0, 0, res.isSuccessful(),
160: count, res.getEndTime(), res.getBytes(), res
161: .getThreadName());
162: model.addRow(newS);
163: }
164: updateTextFields();
165: }
166:
167: public synchronized void clearData() {
168: model.clearData();
169: currentData = 0;
170: calc.clear();
171: noSamplesField.setText("0"); // $NON-NLS-1$
172: dataField.setText("0"); // $NON-NLS-1$
173: averageField.setText("0"); // $NON-NLS-1$
174: deviationField.setText("0"); // $NON-NLS-1$
175: repaint();
176: }
177:
178: public String toString() {
179: return "Show the samples in a table";
180: }
181:
182: private void init() {
183: this .setLayout(new BorderLayout());
184:
185: // MAIN PANEL
186: JPanel mainPanel = new JPanel();
187: Border margin = new EmptyBorder(10, 10, 5, 10);
188:
189: mainPanel.setBorder(margin);
190: mainPanel.setLayout(new VerticalLayout(5, VerticalLayout.BOTH));
191:
192: // NAME
193: mainPanel.add(makeTitlePanel());
194:
195: // Set up the table itself
196: table = new JTable(model);
197: // table.getTableHeader().setReorderingAllowed(false);
198: RendererUtils.applyRenderers(table, RENDERERS);
199:
200: tableScrollPanel = new JScrollPane(table);
201: tableScrollPanel.setViewportBorder(BorderFactory
202: .createEmptyBorder(2, 2, 2, 2));
203:
204: // Set up footer of table which displays numerics of the graphs
205: JPanel dataPanel = new JPanel();
206: JLabel dataLabel = new JLabel(JMeterUtils
207: .getResString("graph_results_latest_sample")); // $NON-NLS-1$
208: dataLabel.setForeground(Color.black);
209: dataField = new JTextField(5);
210: dataField
211: .setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
212: dataField.setEditable(false);
213: dataField.setForeground(Color.black);
214: dataField.setBackground(getBackground());
215: dataPanel.add(dataLabel);
216: dataPanel.add(dataField);
217:
218: JPanel averagePanel = new JPanel();
219: JLabel averageLabel = new JLabel(JMeterUtils
220: .getResString("graph_results_average")); // $NON-NLS-1$
221: averageLabel.setForeground(Color.blue);
222: averageField = new JTextField(5);
223: averageField.setBorder(BorderFactory.createEmptyBorder(0, 0, 0,
224: 0));
225: averageField.setEditable(false);
226: averageField.setForeground(Color.blue);
227: averageField.setBackground(getBackground());
228: averagePanel.add(averageLabel);
229: averagePanel.add(averageField);
230:
231: JPanel deviationPanel = new JPanel();
232: JLabel deviationLabel = new JLabel(JMeterUtils
233: .getResString("graph_results_deviation")); // $NON-NLS-1$
234: deviationLabel.setForeground(Color.red);
235: deviationField = new JTextField(5);
236: deviationField.setBorder(BorderFactory.createEmptyBorder(0, 0,
237: 0, 0));
238: deviationField.setEditable(false);
239: deviationField.setForeground(Color.red);
240: deviationField.setBackground(getBackground());
241: deviationPanel.add(deviationLabel);
242: deviationPanel.add(deviationField);
243:
244: JPanel noSamplesPanel = new JPanel();
245: JLabel noSamplesLabel = new JLabel(JMeterUtils
246: .getResString("graph_results_no_samples")); // $NON-NLS-1$
247:
248: noSamplesField = new JTextField(10);
249: noSamplesField.setBorder(BorderFactory.createEmptyBorder(0, 0,
250: 0, 0));
251: noSamplesField.setEditable(false);
252: noSamplesField.setForeground(Color.black);
253: noSamplesField.setBackground(getBackground());
254: noSamplesPanel.add(noSamplesLabel);
255: noSamplesPanel.add(noSamplesField);
256:
257: JPanel tableInfoPanel = new JPanel();
258: tableInfoPanel.setLayout(new FlowLayout());
259: tableInfoPanel.setBorder(BorderFactory.createEmptyBorder(0, 0,
260: 0, 0));
261:
262: tableInfoPanel.add(noSamplesPanel);
263: tableInfoPanel.add(dataPanel);
264: tableInfoPanel.add(averagePanel);
265: tableInfoPanel.add(deviationPanel);
266:
267: // Set up the table with footer
268: JPanel tablePanel = new JPanel();
269:
270: tablePanel.setLayout(new BorderLayout());
271: tablePanel.add(tableScrollPanel, BorderLayout.CENTER);
272: tablePanel.add(tableInfoPanel, BorderLayout.SOUTH);
273:
274: // Add the main panel and the graph
275: this .add(mainPanel, BorderLayout.NORTH);
276: this .add(tablePanel, BorderLayout.CENTER);
277: }
278:
279: public static class SampleSuccessFunctor extends Functor {
280: public SampleSuccessFunctor(String methodName) {
281: super (methodName);
282: }
283:
284: public Object invoke(Object p_invokee) {
285: Boolean success = (Boolean) super.invoke(p_invokee);
286:
287: if (success != null) {
288: if (success.booleanValue()) {
289: return imageSuccess;
290: } else {
291: return imageFailure;
292: }
293: } else {
294: return null;
295: }
296: }
297: }
298: }
|