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, logTable ) );
    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 	/*
    251
    252 	private class SelectStepFilterAction extends AbstractAction
    253 	{
    254 		private final String filter;
    255
    256 		public SelectStepFilterAction(String name, String filter)
    257 		{
    258 			super(name);
    259 			this.filter = filter;
    260 		}
    261
    262 		public void actionPerformed(ActionEvent e)
    263 		{
    264 			stepFilter.setPattern( filter, 0 );
    265 		}
    266 	}
    267
    268 	private class SelectTypeFilterAction extends AbstractAction
    269 	{
    270 		private final String filter;
    271
    272 		public SelectTypeFilterAction(String name, String filter)
    273 		{
    274 			super(name);
    275 			this.filter = filter;
    276 		}
    277
    278 		public void actionPerformed(ActionEvent e)
    279 		{
    280 			typeFilter.setPattern( filter, 0 );
    281 		}
    282 	}
    283 	*/
    284
    285 	private class LoadTestLogTableModel extends AbstractTableModel implements ListDataListener
    286 	{
    287 		public LoadTestLogTableModel()
    288 		{
    289 		}
    290
    291 		public int getRowCount()
    292 		{
    293 			return loadTestLog.getSize();
    294 		}
    295
    296 		public int getColumnCount()
    297 		{
    298 			return 5;
    299 		}
    300
    301 		public Class<?> getColumnClass(int columnIndex)
    302 		{
    303 			switch( columnIndex )
    304 			{
    305 			case 0 : return ImageIcon.class;
    306 			case 1 : return Date.class;
    307 			default : return String.class;
    308 			}
    309 		}
    310
    311 		public String getColumnName(int column)
    312 		{
    313 			switch( column )
    314 			{
    315 			case 0 : return " ";
    316 			case 1 : return "time";
    317 			case 2 : return "type";
    318 			case 3 : return "step";
    319 			case 4 : return "message";
    320 			}
    321
    322 			return null;
    323 		}
    324
    325 		public Object getValueAt(int rowIndex, int columnIndex)
    326 		{
    327 			if( rowIndex == -1 )
    328 				return null;
    329
    330 			LoadTestLogEntry entry = (LoadTestLogEntry) loadTestLog.getElementAt( rowIndex );
    331
    332 			switch( columnIndex )
    333 			{
    334 				case 0 : return entry.getIcon();
    335 				case 1 : return entry.getTimeStamp();
    336 				case 2 : return entry.getType();
    337 				case 3 : return entry.getTargetStepName();
    338 				case 4 : return entry.getMessage();
    339 			}
    340
    341 			return null;
    342 		}
    343
    344 		public void intervalAdded(ListDataEvent e)
    345 		{
    346 			fireTableRowsInserted( e.getIndex0(), e.getIndex1() );
    347 		}
    348
    349 		public void intervalRemoved(ListDataEvent e)
    350 		{
    351 			fireTableRowsDeleted( e.getIndex0(), e.getIndex1() );
    352 		}
    353
    354 		public void contentsChanged(ListDataEvent e)
    355 		{
    356 			fireTableDataChanged();
    357 		}}
    358
    359 	private static final class IconTableCellRenderer extends DefaultTableCellRenderer
    360 	{
    361 		public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
    362 		{
    363 			if( value != null )
    364 				setIcon( (Icon) value );
    365
    366 			if (isSelected)
    367          {
    368             setBackground(table.getSelectionBackground());
    369             setForeground(table.getSelectionForeground());
    370          }
    371          else
    372          {
    373             setBackground(table.getBackground());
    374             setForeground(table.getForeground());
    375          }
    376
    377 			return this;
    378 		}
    379 	}
    380
    381 	private static final class TimestampTableCellRenderer extends DefaultTableCellRenderer
    382 	{
    383 		private SimpleDateFormat sdf;
    384
    385       private TimestampTableCellRenderer()
    386       {
    387          sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS");
    388       }
    389
    390 		public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
    391 		{
    392 			if( value != null )
    393 				setText( sdf.format( new Date( (Long)value )));
    394
    395 			if (isSelected)
    396          {
    397             setBackground(table.getSelectionBackground());
    398             setForeground(table.getSelectionForeground());
    399          }
    400          else
    401          {
    402             setBackground(table.getBackground());
    403             setForeground(table.getForeground());
    404          }
    405
    406 			return this;
    407 		}
    408 	}
    409
    410    public class ClearErrorsAction extends AbstractAction
    411    {
    412 		public ClearErrorsAction()
    413       {
    414          putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/clear_errors.gif"));
    415          putValue( Action.SHORT_DESCRIPTION, "Removes all errors from the LoadTest log" );
    416       }
    417
    418 		public void actionPerformed(ActionEvent e)
    419 		{
    420 			loadTestLog.clearErrors();
    421 		}
    422    }
    423
    424    private final class LoadTestLogTableMouseListener extends MouseAdapter
    425 	{
    426    	public void mouseClicked(MouseEvent e)
    427 		{
    428 			if( e.getClickCount() > 1 )
    429 			{
    430 				int selectedRow = logTable.getSelectedRow();
    431 				if( selectedRow < 0 )
    432 					return;
    433
    434 				int row = logTable.convertRowIndexToModel( selectedRow );
    435 				if( row < 0 )
    436 					return;
    437
    438 				LoadTestLogEntry entry = (LoadTestLogEntry) loadTestLog.getElementAt( row );
    439 				ActionList actions = entry.getActions();
    440 				if( actions != null )
    441 					actions.performDefaultAction( new ActionEvent( logTable, 0, null ));
    442 			}
    443 		}
    444
    445 		public void mousePressed(MouseEvent e)
    446 		{
    447 			if( e.isPopupTrigger() )
    448 			{
    449 				showPopup( e );
    450 			}
    451 		}
    452
    453 		public void mouseReleased(MouseEvent e)
    454 		{
    455 			if( e.isPopupTrigger() )
    456 			{
    457 				showPopup( e );
    458 			}
    459 		}
    460 	}
    461
    462    public void showPopup(MouseEvent e)
    463 	{
    464 		int selectedRow = logTable.rowAtPoint( e.getPoint() );
    465 		if( selectedRow == -1 )
    466 			return;
    467
    468 		if( logTable.getSelectedRow() != selectedRow )
    469 		{
    470 			logTable.getSelectionModel().setSelectionInterval( selectedRow, selectedRow );
    471 		}
    472
    473 		int row = logTable.convertRowIndexToModel( selectedRow );
    474 		if( row < 0 )
    475 			return;
    476
    477 		LoadTestLogEntry entry = (LoadTestLogEntry) loadTestLog.getElementAt( row );
    478 		ActionList actions = entry.getActions();
    479
    480 		if( actions == null || actions.getActionCount() == 0 )
    481 			return;
    482
    483 		JPopupMenu popup = ActionSupport.buildPopup( actions );
    484 		popup.setInvoker( logTable );
    485
    486 		popup.setLocation( (int)(logTable.getLocationOnScreen().getX() + e.getPoint().getX()),
    487 				(int)(logTable.getLocationOnScreen().getY() + e.getPoint().getY()));
    488 		popup.setVisible( true );
    489 	}
    490 }