1
2
3
4
5
6
7
8
9
10
11
12
13 package com.eviware.soapui.impl.wsdl.panels.loadtest;
14
15 import java.awt.BorderLayout;
16 import java.awt.Component;
17 import java.awt.event.ActionEvent;
18 import java.awt.event.ItemEvent;
19 import java.awt.event.ItemListener;
20 import java.awt.event.MouseAdapter;
21 import java.awt.event.MouseEvent;
22 import java.text.SimpleDateFormat;
23 import java.util.ArrayList;
24 import java.util.Date;
25 import java.util.List;
26
27 import javax.swing.AbstractAction;
28 import javax.swing.Action;
29 import javax.swing.BorderFactory;
30 import javax.swing.Icon;
31 import javax.swing.ImageIcon;
32 import javax.swing.JButton;
33 import javax.swing.JComboBox;
34 import javax.swing.JComponent;
35 import javax.swing.JLabel;
36 import javax.swing.JPanel;
37 import javax.swing.JPopupMenu;
38 import javax.swing.JScrollPane;
39 import javax.swing.JTable;
40 import javax.swing.event.ListDataEvent;
41 import javax.swing.event.ListDataListener;
42 import javax.swing.event.TableModelEvent;
43 import javax.swing.event.TableModelListener;
44 import javax.swing.table.AbstractTableModel;
45 import javax.swing.table.DefaultTableCellRenderer;
46 import javax.swing.table.TableColumnModel;
47
48 import org.jdesktop.swingx.JXTable;
49 import org.jdesktop.swingx.decorator.Filter;
50 import org.jdesktop.swingx.decorator.FilterPipeline;
51 import org.jdesktop.swingx.decorator.PatternFilter;
52 import org.jdesktop.swingx.decorator.SortOrder;
53
54 import com.eviware.soapui.impl.wsdl.loadtest.LoadTestAssertion;
55 import com.eviware.soapui.impl.wsdl.loadtest.data.actions.ExportLoadTestLogAction;
56 import com.eviware.soapui.impl.wsdl.loadtest.log.LoadTestLog;
57 import com.eviware.soapui.impl.wsdl.loadtest.log.LoadTestLogEntry;
58 import com.eviware.soapui.model.testsuite.TestStep;
59 import com.eviware.soapui.support.UISupport;
60 import com.eviware.soapui.support.action.swing.ActionList;
61 import com.eviware.soapui.support.action.swing.ActionSupport;
62 import com.eviware.soapui.support.components.JXToolBar;
63 import com.jgoodies.forms.builder.ButtonBarBuilder;
64
65 /***
66 * Compound component for showing a LoadTestLog
67 *
68 * @author Ole.Matzura
69 */
70
71 public class JLoadTestLogTable extends JPanel
72 {
73 private final LoadTestLog loadTestLog;
74 private JXTable logTable;
75 private PatternFilter stepFilter;
76 private PatternFilter typeFilter;
77 private JComboBox typesFilterComboBox;
78 private JComboBox stepsFilterComboBox;
79 private JButton clearErrorsButton;
80 private JLabel rowCountLabel;
81 @SuppressWarnings("unused")
82 private JPopupMenu popup;
83 private LoadTestLogTableModel logTableModel;
84 private JButton exportButton;
85 private LogTableModelListener logTableModelListener;
86
87 public JLoadTestLogTable( LoadTestLog log )
88 {
89 super( new BorderLayout() );
90
91 loadTestLog = log;
92
93 logTableModel = new LoadTestLogTableModel();
94 logTable = new JXTable( logTableModel );
95 logTable.setHorizontalScrollEnabled( true );
96 logTable.addMouseListener( new LoadTestLogTableMouseListener() );
97
98 TableColumnModel columnModel = logTable.getColumnModel();
99 columnModel.getColumn( 0 ).setMaxWidth( 5 );
100 columnModel.getColumn( 0 ).setCellRenderer( new IconTableCellRenderer() );
101
102 columnModel.getColumn( 1 ).setPreferredWidth( 120 );
103 columnModel.getColumn( 1 ).setCellRenderer( new TimestampTableCellRenderer() );
104
105 columnModel.getColumn( 2 ).setPreferredWidth( 110 );
106 columnModel.getColumn( 3 ).setPreferredWidth( 110 );
107 columnModel.getColumn( 4 ).setPreferredWidth( 250 );
108
109 typeFilter = new PatternFilter(".*", 0, 2);
110 typeFilter.setAcceptNull( true );
111 stepFilter = new PatternFilter(".*", 0, 3);
112 stepFilter.setAcceptNull( true );
113
114 Filter[] filters = new Filter[] {
115 typeFilter,
116 stepFilter
117 };
118
119 FilterPipeline pipeline = new FilterPipeline(filters);
120 logTable.setFilters( pipeline );
121
122 JScrollPane scrollPane = new JScrollPane(logTable);
123 add( scrollPane, BorderLayout.CENTER );
124 add( buildToolbar(), BorderLayout.NORTH );
125 add( buildStatus(), BorderLayout.SOUTH );
126
127 logTableModelListener = new LogTableModelListener();
128 logTable.getModel().addTableModelListener( logTableModelListener );
129
130 logTable.setSortOrder( 1, SortOrder.ASCENDING );
131 }
132
133 public void addNotify()
134 {
135 super.addNotify();
136 if( logTableModelListener != null )
137 logTableModel.addTableModelListener( logTableModelListener );
138
139 loadTestLog.addListDataListener( logTableModel );
140 }
141
142 public void removeNotify()
143 {
144 super.removeNotify();
145 logTableModel.removeTableModelListener( logTableModelListener );
146 loadTestLog.removeListDataListener( logTableModel );
147 }
148
149 private JComponent buildStatus()
150 {
151 ButtonBarBuilder builder = new ButtonBarBuilder();
152 rowCountLabel = new JLabel( "0 entries" );
153 builder.addFixed( rowCountLabel );
154 builder.addGlue();
155 builder.setBorder( BorderFactory.createEmptyBorder( 3, 3, 3, 3 ));
156 return builder.getPanel();
157 }
158
159 protected void updateRowCountLabel()
160 {
161 int c = logTableModel.getRowCount();
162 rowCountLabel.setText( c == 1 ? "1 entry" : c + " entries" );
163 }
164
165 private JComponent buildToolbar()
166 {
167 JXToolBar toolbar = UISupport.createToolbar();
168
169 clearErrorsButton = UISupport.createToolbarButton( new ClearErrorsAction() );
170 exportButton = UISupport.createToolbarButton( new ExportLoadTestLogAction( loadTestLog ) );
171
172 toolbar.add( clearErrorsButton );
173 toolbar.add( exportButton );
174 toolbar.addGlue();
175
176 List<Object> steps = new ArrayList<Object>();
177 steps.add( "- All -" );
178 steps.add( "Message" );
179 for( LoadTestAssertion assertion : loadTestLog.getLoadTest().getAssertionList() )
180 {
181 steps.add( assertion.getName() );
182 }
183
184 toolbar.add( new JLabel( "Show Types:"));
185 toolbar.addSeparator();
186 typesFilterComboBox = new JComboBox( steps.toArray() );
187 typesFilterComboBox.addItemListener( new ItemListener() {
188
189 public void itemStateChanged(ItemEvent e)
190 {
191 int ix = typesFilterComboBox.getSelectedIndex();
192 if( ix == -1 )
193 return;
194
195 typeFilter.setAcceptNull( ix == 0 );
196
197 if( ix == 0 )
198 typeFilter.setPattern( ".*", 0 );
199 else
200 typeFilter.setPattern( typesFilterComboBox.getSelectedItem().toString(), 0 );
201
202 updateRowCountLabel();
203 }} );
204
205 toolbar.add( typesFilterComboBox );
206 toolbar.addSeparator();
207
208 List<Object> types = new ArrayList<Object>();
209 types.add( "- All -" );
210 for( TestStep testStep : loadTestLog.getLoadTest().getTestCase().getTestStepList() )
211 {
212 types.add( testStep.getName() );
213 }
214
215 toolbar.addFixed( new JLabel( "Show Steps:"));
216 toolbar.addSeparator();
217 stepsFilterComboBox = new JComboBox( types.toArray() );
218 stepsFilterComboBox.addItemListener( new ItemListener() {
219
220 public void itemStateChanged(ItemEvent e)
221 {
222 int ix = stepsFilterComboBox.getSelectedIndex();
223 if( ix == -1 )
224 return;
225
226 stepFilter.setAcceptNull( ix == 0 );
227
228 if( ix == 0 )
229 stepFilter.setPattern( ".*", 0 );
230 else
231 stepFilter.setPattern( stepsFilterComboBox.getSelectedItem().toString(), 0 );
232
233 updateRowCountLabel();
234 }} );
235
236 toolbar.addFixed( stepsFilterComboBox );
237 toolbar.setBorder( BorderFactory.createEmptyBorder( 0, 0, 2, 0 ));
238
239 return toolbar;
240 }
241
242 private final class LogTableModelListener implements TableModelListener
243 {
244 public void tableChanged(TableModelEvent e)
245 {
246 updateRowCountLabel();
247 }
248 }
249
250 private class SelectStepFilterAction extends AbstractAction
251 {
252 private final String filter;
253
254 public SelectStepFilterAction(String name, String filter)
255 {
256 super(name);
257 this.filter = filter;
258 }
259
260 public void actionPerformed(ActionEvent e)
261 {
262 stepFilter.setPattern( filter, 0 );
263 }
264 }
265
266 private class SelectTypeFilterAction extends AbstractAction
267 {
268 private final String filter;
269
270 public SelectTypeFilterAction(String name, String filter)
271 {
272 super(name);
273 this.filter = filter;
274 }
275
276 public void actionPerformed(ActionEvent e)
277 {
278 typeFilter.setPattern( filter, 0 );
279 }
280 }
281
282 private class LoadTestLogTableModel extends AbstractTableModel implements ListDataListener
283 {
284 public LoadTestLogTableModel()
285 {
286 }
287
288 public int getRowCount()
289 {
290 return loadTestLog.getSize();
291 }
292
293 public int getColumnCount()
294 {
295 return 5;
296 }
297
298 public Class<?> getColumnClass(int columnIndex)
299 {
300 switch( columnIndex )
301 {
302 case 0 : return ImageIcon.class;
303 case 1 : return Date.class;
304 default : return String.class;
305 }
306 }
307
308 public String getColumnName(int column)
309 {
310 switch( column )
311 {
312 case 0 : return " ";
313 case 1 : return "time";
314 case 2 : return "type";
315 case 3 : return "step";
316 case 4 : return "message";
317 }
318
319 return null;
320 }
321
322 public Object getValueAt(int rowIndex, int columnIndex)
323 {
324 if( rowIndex == -1 )
325 return null;
326
327 LoadTestLogEntry entry = (LoadTestLogEntry) loadTestLog.getElementAt( rowIndex );
328
329 switch( columnIndex )
330 {
331 case 0 : return entry.getIcon();
332 case 1 : return entry.getTimeStamp();
333 case 2 : return entry.getType();
334 case 3 : return entry.getTargetStep() == null ? entry.isError() ? "- Total - " : null : entry.getTargetStep().getName();
335 case 4 : return entry.getMessage();
336 }
337
338 return null;
339 }
340
341 public void intervalAdded(ListDataEvent e)
342 {
343 fireTableRowsInserted( e.getIndex0(), e.getIndex1() );
344 }
345
346 public void intervalRemoved(ListDataEvent e)
347 {
348 fireTableRowsDeleted( e.getIndex0(), e.getIndex1() );
349 }
350
351 public void contentsChanged(ListDataEvent e)
352 {
353 fireTableDataChanged();
354 }}
355
356 private static final class IconTableCellRenderer extends DefaultTableCellRenderer
357 {
358 public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
359 {
360 if( value != null )
361 setIcon( (Icon) value );
362
363 if (isSelected)
364 {
365 setBackground(table.getSelectionBackground());
366 setForeground(table.getSelectionForeground());
367 }
368 else
369 {
370 setBackground(table.getBackground());
371 setForeground(table.getForeground());
372 }
373
374 return this;
375 }
376 }
377
378 private static final class TimestampTableCellRenderer extends DefaultTableCellRenderer
379 {
380 private SimpleDateFormat sdf;
381
382 private TimestampTableCellRenderer()
383 {
384 sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS");
385 }
386
387 public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
388 {
389 if( value != null )
390 setText( sdf.format( new Date( (Long)value )));
391
392 if (isSelected)
393 {
394 setBackground(table.getSelectionBackground());
395 setForeground(table.getSelectionForeground());
396 }
397 else
398 {
399 setBackground(table.getBackground());
400 setForeground(table.getForeground());
401 }
402
403 return this;
404 }
405 }
406
407 public class ClearErrorsAction extends AbstractAction
408 {
409 public ClearErrorsAction()
410 {
411 putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/clear_errors.gif"));
412 putValue( Action.SHORT_DESCRIPTION, "Removes all errors from the LoadTest log" );
413 }
414
415 public void actionPerformed(ActionEvent e)
416 {
417 loadTestLog.clearErrors();
418 }
419 }
420
421 private final class LoadTestLogTableMouseListener extends MouseAdapter
422 {
423 public void mouseClicked(MouseEvent e)
424 {
425 if( e.getClickCount() > 1 )
426 {
427 int selectedRow = logTable.getSelectedRow();
428 if( selectedRow < 0 )
429 return;
430
431 int row = logTable.convertRowIndexToModel( selectedRow );
432 if( row < 0 )
433 return;
434
435 LoadTestLogEntry entry = (LoadTestLogEntry) loadTestLog.getElementAt( row );
436 ActionList actions = entry.getActions();
437 if( actions != null )
438 actions.performDefaultAction( new ActionEvent( logTable, 0, null ));
439 }
440 }
441
442 public void mousePressed(MouseEvent e)
443 {
444 if( e.isPopupTrigger() )
445 {
446 showPopup( e );
447 }
448 }
449
450 public void mouseReleased(MouseEvent e)
451 {
452 if( e.isPopupTrigger() )
453 {
454 showPopup( e );
455 }
456 }
457 }
458
459 public void showPopup(MouseEvent e)
460 {
461 int selectedRow = logTable.rowAtPoint( e.getPoint() );
462 if( selectedRow == -1 )
463 return;
464
465 if( logTable.getSelectedRow() != selectedRow )
466 {
467 logTable.getSelectionModel().setSelectionInterval( selectedRow, selectedRow );
468 }
469
470 int row = logTable.convertRowIndexToModel( selectedRow );
471 if( row < 0 )
472 return;
473
474 LoadTestLogEntry entry = (LoadTestLogEntry) loadTestLog.getElementAt( row );
475 ActionList actions = entry.getActions();
476
477 if( actions == null || actions.getActionCount() == 0 )
478 return;
479
480 JPopupMenu popup = ActionSupport.buildPopup( actions );
481 popup.setInvoker( logTable );
482
483 popup.setLocation( (int)(logTable.getLocationOnScreen().getX() + e.getPoint().getX()),
484 (int)(logTable.getLocationOnScreen().getY() + e.getPoint().getY()));
485 popup.setVisible( true );
486 }
487 }