View Javadoc

    1   /*
    2    *  soapUI, copyright (C) 2004-2007 eviware.com
    3    *
    4    *  soapUI is free software; you can redistribute it and/or modify it under the
    5    *  terms of version 2.1 of the GNU Lesser General Public License as published by
    6    *  the Free Software Foundation.
    7    *
    8    *  soapUI is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
    9    *  even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    10   *  See the GNU Lesser General Public License for more details at gnu.org.
    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,    // regex, matchflags, column
    116 		      stepFilter    // regex, matchflags, column
    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; //builder.getPanel();
    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 }