/*
* soapUI, copyright (C) 2004-2011 eviware.com
*
* soapUI is free software; you can redistribute it and/or modify it under the
* terms of version 2.1 of the GNU Lesser General Public License as published by
* the Free Software Foundation.
*
* soapUI is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details at gnu.org.
*/
package com.eviware.soapui.security.log;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.util.HashSet;
import java.util.Set;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.BorderFactory;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.ListCellRenderer;
import org.apache.log4j.Logger;
import com.eviware.soapui.impl.wsdl.support.HelpUrls;
import com.eviware.soapui.impl.wsdl.testcase.TestCaseLogItem;
import com.eviware.soapui.model.security.SecurityScan;
import com.eviware.soapui.model.settings.Settings;
import com.eviware.soapui.model.testsuite.TestStep;
import com.eviware.soapui.security.SecurityTest;
import com.eviware.soapui.security.result.SecurityScanRequestResult;
import com.eviware.soapui.security.result.SecurityScanResult;
import com.eviware.soapui.security.result.SecurityResult;
import com.eviware.soapui.security.result.SecurityTestStepResult;
import com.eviware.soapui.security.result.SecurityResult.ResultStatus;
import com.eviware.soapui.support.UISupport;
import com.eviware.soapui.support.action.swing.ActionList;
import com.eviware.soapui.support.action.swing.ActionSupport;
import com.eviware.soapui.support.components.JHyperlinkLabel;
import com.eviware.soapui.support.components.JXToolBar;
import com.eviware.x.form.XFormDialog;
import com.eviware.x.form.support.ADialogBuilder;
import com.eviware.x.form.support.AField;
import com.eviware.x.form.support.AForm;
import com.eviware.x.form.support.AField.AFieldType;
/**
* Panel for displaying SecurityScan Results
*
* @author dragica.soldo
*/
public class JSecurityTestRunLog extends JPanel
{
private SecurityTestLogModel logListModel;
private JList testLogList;
private boolean errorsOnly = false;
private final Settings settings;
private Set<String> boldTexts = new HashSet<String>();
private boolean follow = true;
protected int selectedIndex;
private XFormDialog optionsDialog;
private Logger log = Logger.getLogger( JSecurityTestRunLog.class );
public JSecurityTestRunLog( SecurityTest securityTest )
{
super( new BorderLayout() );
this.settings = securityTest.getSettings();
logListModel = new SecurityTestLogModel();
errorsOnly = settings.getBoolean( OptionsForm.class.getName() + "@errors_only" );
buildUI();
}
private void buildUI()
{
logListModel = new SecurityTestLogModel();
logListModel.setMaxSize( ( int )settings.getLong( OptionsForm.class.getName() + "@max_rows", 1000 ) );
testLogList = new JList( logListModel );
testLogList.setCellRenderer( new SecurityTestLogCellRenderer() );
testLogList.addMouseListener( new LogListMouseListener() );
JScrollPane scrollPane = new JScrollPane( testLogList );
add( scrollPane, BorderLayout.CENTER );
add( buildToolbar(), BorderLayout.NORTH );
}
private Component buildToolbar()
{
JXToolBar toolbar = UISupport.createSmallToolbar();
addToolbarButtons( toolbar );
return toolbar;
}
protected JList getTestLogList()
{
return testLogList;
}
public boolean isErrorsOnly()
{
return errorsOnly;
}
public boolean isFollow()
{
return follow;
}
protected void addToolbarButtons( JXToolBar toolbar )
{
toolbar.addFixed( UISupport.createToolbarButton( new ClearLogAction() ) );
toolbar.addFixed( UISupport.createToolbarButton( new SetLogOptionsAction() ) );
toolbar.addFixed( UISupport.createToolbarButton( new ExportLogAction() ) );
}
/*
* (non-Javadoc)
*
* @see com.eviware.soapui.impl.wsdl.panels.testcase.TestRunLog#clear()
*/
public synchronized void clear()
{
logListModel.clear();
boldTexts.clear();
}
public synchronized void locateSecurityScan( SecurityScan check )
{
try
{
int idx = logListModel.getIndexOfSecurityScan( check );
if( idx != -1 )
{
testLogList.ensureIndexIsVisible( idx );
}
}
catch( RuntimeException e )
{
}
}
public synchronized boolean addSecurityTestStepResult( TestStep testStep )
{
boolean added = logListModel.addSecurityTestStepResult( testStep );
if( follow )
{
try
{
testLogList.ensureIndexIsVisible( logListModel.getSize() - 1 );
}
catch( RuntimeException e )
{
log.error( e.getMessage() );
}
}
return added;
}
public synchronized void updateSecurityTestStepResult( SecurityTestStepResult testStepResult,
boolean hasChecksToProcess, boolean startStepLogEntryAdded )
{
logListModel
.updateSecurityTestStepResult( testStepResult, errorsOnly, hasChecksToProcess, startStepLogEntryAdded );
if( follow )
{
try
{
testLogList.ensureIndexIsVisible( logListModel.getSize() - 1 );
}
catch( RuntimeException e )
{
log.error( e.getMessage() );
}
}
}
public synchronized void addSecurityScanResult( SecurityScan securityCheck )
{
logListModel.addSecurityScanResult( securityCheck );
if( follow )
{
try
{
testLogList.ensureIndexIsVisible( logListModel.getSize() - 1 );
}
catch( RuntimeException e )
{
log.error( e.getMessage() );
}
}
}
public synchronized void updateSecurityScanResult( SecurityScanResult checkResult )
{
logListModel.updateSecurityScanResult( checkResult, errorsOnly );
if( follow )
{
try
{
testLogList.ensureIndexIsVisible( logListModel.getSize() - 1 );
}
catch( RuntimeException e )
{
log.error( e.getMessage() );
}
}
}
public synchronized void addSecurityScanRequestResult( SecurityScanRequestResult checkRequestResult )
{
if( errorsOnly && checkRequestResult.getStatus() != SecurityScanRequestResult.ResultStatus.FAILED )
return;
logListModel.addSecurityScanRequestResult( checkRequestResult );
if( follow )
{
try
{
testLogList.ensureIndexIsVisible( logListModel.getSize() - 1 );
}
catch( RuntimeException e )
{
log.error( e.getMessage() );
}
}
}
private class SetLogOptionsAction extends AbstractAction
{
public SetLogOptionsAction()
{
putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/options.gif" ) );
putValue( Action.SHORT_DESCRIPTION, "Sets TestCase Log Options" );
}
public void actionPerformed( ActionEvent e )
{
if( optionsDialog == null )
optionsDialog = ADialogBuilder.buildDialog( OptionsForm.class );
optionsDialog.setIntValue( OptionsForm.MAXROWS,
( int )settings.getLong( OptionsForm.class.getName() + "@max_rows", 1000 ) );
optionsDialog.setBooleanValue( OptionsForm.ERRORSONLY,
settings.getBoolean( OptionsForm.class.getName() + "@errors_only" ) );
optionsDialog.setBooleanValue( OptionsForm.FOLLOW, follow );
if( optionsDialog.show() )
{
int maxRows = optionsDialog.getIntValue( OptionsForm.MAXROWS, 1000 );
logListModel.setMaxSize( maxRows );
settings.setLong( OptionsForm.class.getName() + "@max_rows", maxRows );
errorsOnly = optionsDialog.getBooleanValue( OptionsForm.ERRORSONLY );
settings.setBoolean( OptionsForm.class.getName() + "@errors_only", errorsOnly );
follow = optionsDialog.getBooleanValue( OptionsForm.FOLLOW );
}
}
}
@AForm( name = "Log Options", description = "Set options for the run log below", helpUrl = HelpUrls.SECURITY_SCANS_OVERVIEW )
private static interface OptionsForm
{
@AField( name = "Max Rows", description = "Sets the maximum number of rows to keep in the log", type = AFieldType.INT )
public static final String MAXROWS = "Max Rows";
@AField( name = "Warnings Only", description = "Logs only TestStep warnings in the log", type = AFieldType.BOOLEAN )
public static final String ERRORSONLY = "Warnings Only";
@AField( name = "Follow", description = "Follow log content", type = AFieldType.BOOLEAN )
public static final String FOLLOW = "Follow";
}
private class ClearLogAction extends AbstractAction
{
public ClearLogAction()
{
putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/clear_loadtest.gif" ) );
putValue( Action.SHORT_DESCRIPTION, "Clears the log" );
}
public void actionPerformed( ActionEvent e )
{
logListModel.clear();
}
}
private class ExportLogAction extends AbstractAction
{
public ExportLogAction()
{
putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/export.gif" ) );
putValue( Action.SHORT_DESCRIPTION, "Exports this log to a file" );
}
public void actionPerformed( ActionEvent e )
{
File file = UISupport.getFileDialogs().saveAs( this, "Save Log" );
if( file != null )
{
try
{
PrintWriter out = new PrintWriter( file );
printLog( out );
out.close();
}
catch( FileNotFoundException e1 )
{
UISupport.showErrorMessage( e1 );
}
}
}
}
public void release()
{
if( optionsDialog != null )
{
optionsDialog.release();
optionsDialog = null;
}
}
public void printLog( PrintWriter out )
{
for( int c = 0; c < logListModel.getSize(); c++ )
{
Object value = logListModel.getElementAt( c );
if( value instanceof String )
{
out.println( value.toString() );
}
}
}
/**
* Mouse Listener for triggering default action and showing popup for log
* list items
*
* @author Ole.Matzura
*/
private final class LogListMouseListener extends MouseAdapter
{
public void mouseClicked( MouseEvent e )
{
int index = testLogList.getSelectedIndex();
if( index != -1 && ( index == selectedIndex || e.getClickCount() > 1 ) )
{
SecurityResult result = logListModel.getTestStepResultAt( index );
if( result != null && result.getActions() != null )
result.getActions().performDefaultAction( new ActionEvent( this, 0, null ) );
}
selectedIndex = index;
}
public void mousePressed( MouseEvent e )
{
if( e.isPopupTrigger() )
showPopup( e );
}
public void mouseReleased( MouseEvent e )
{
if( e.isPopupTrigger() )
showPopup( e );
}
public void showPopup( MouseEvent e )
{
int row = testLogList.locationToIndex( e.getPoint() );
if( row == -1 )
return;
if( testLogList.getSelectedIndex() != row )
{
testLogList.setSelectedIndex( row );
}
SecurityResult result = logListModel.getTestStepResultAt( row );
if( result == null )
return;
ActionList actions = result.getActions();
if( actions == null || actions.getActionCount() == 0 )
return;
JPopupMenu popup = ActionSupport.buildPopup( actions );
UISupport.showPopup( popup, testLogList, e.getPoint() );
}
}
public synchronized void addText( String string )
{
logListModel.addText( string );
if( follow )
testLogList.ensureIndexIsVisible( logListModel.getSize() - 1 );
}
private final class SecurityTestLogCellRenderer extends JLabel implements ListCellRenderer
{
private Font boldFont;
private Font normalFont;
private JHyperlinkLabel hyperlinkLabel = new JHyperlinkLabel( "" );
public SecurityTestLogCellRenderer()
{
setOpaque( true );
setBorder( BorderFactory.createEmptyBorder( 3, 3, 3, 3 ) );
setIcon( null );
boldFont = getFont().deriveFont( Font.BOLD );
normalFont = getFont();
hyperlinkLabel.setOpaque( true );
hyperlinkLabel.setForeground( Color.BLUE.darker().darker().darker() );
hyperlinkLabel.setUnderlineColor( Color.GRAY );
hyperlinkLabel.setBorder( BorderFactory.createEmptyBorder( 0, 4, 3, 3 ) );
}
public Component getListCellRendererComponent( JList list, Object value, int index, boolean isSelected,
boolean cellHasFocus )
{
if( isSelected )
{
setBackground( list.getSelectionBackground() );
setForeground( list.getSelectionForeground() );
}
else
{
setBackground( list.getBackground() );
setForeground( list.getForeground() );
}
if( value instanceof String )
{
setText( value.toString() );
}
else if( value instanceof TestCaseLogItem )
{
TestCaseLogItem logItem = ( TestCaseLogItem )value;
String msg = logItem.getMsg();
setText( msg == null ? "" : msg );
}
SecurityResult result = logListModel.getTestStepResultAt( index );
if( result != null )
{
if( result.getResultType().equals( SecurityScanRequestResult.TYPE ) )
{
hyperlinkLabel.setText( getText() );
hyperlinkLabel.setBackground( getBackground() );
hyperlinkLabel.setEnabled( list.isEnabled() );
hyperlinkLabel.setUnderlineColor( Color.WHITE );
hyperlinkLabel.setIcon( null );
hyperlinkLabel.setBorder( BorderFactory.createEmptyBorder( 0, 24, 3, 3 ) );
}
else if( result.getResultType().equals( SecurityScanResult.TYPE ) )
{
hyperlinkLabel.setText( getText() );
hyperlinkLabel.setBackground( getBackground() );
hyperlinkLabel.setEnabled( list.isEnabled() );
hyperlinkLabel.setBorder( BorderFactory.createEmptyBorder( 0, 16, 3, 3 ) );
hyperlinkLabel.setUnderlineColor( Color.WHITE );
hyperlinkLabel.setIcon( null );
// if( getText().startsWith( "SecurityScan" ) &&
// !getText().startsWith( " ->" ) )
// if( result.getStatus() != SecurityStatus.INITIALIZED )
// {
hyperlinkLabel.setUnderlineColor( Color.GRAY );
setStatusIcon( result );
// }
}
else if( result.getResultType().equals( SecurityTestStepResult.TYPE ) )
{
SecurityTestStepResult securitytestStepresult = ( SecurityTestStepResult )result;
hyperlinkLabel.setText( getText() );
hyperlinkLabel.setBackground( getBackground() );
hyperlinkLabel.setEnabled( list.isEnabled() );
hyperlinkLabel.setBorder( BorderFactory.createEmptyBorder( 0, 4, 3, 3 ) );
hyperlinkLabel.setUnderlineColor( Color.GRAY );
setStatusIcon( securitytestStepresult );
}
return hyperlinkLabel;
}
setEnabled( list.isEnabled() );
if( boldTexts.contains( getText() ) )
{
setFont( boldFont );
}
else
{
setFont( normalFont );
}
return this;
}
private void setStatusIcon( SecurityResult securityResult )
{
if( securityResult.getLogIconStatus() == ResultStatus.OK )
{
hyperlinkLabel.setIcon( UISupport.createImageIcon( "/valid_assertion.gif" ) );
}
else if( securityResult.getLogIconStatus() == ResultStatus.FAILED )
{
hyperlinkLabel.setIcon( UISupport.createImageIcon( "/failed_assertion.gif" ) );
}
else if( securityResult.getLogIconStatus() == ResultStatus.MISSING_ASSERTIONS
|| securityResult.getLogIconStatus() == ResultStatus.MISSING_PARAMETERS )
{
hyperlinkLabel.setIcon( UISupport.createImageIcon( "/missing_assertion.gif" ) );
}
else
{
hyperlinkLabel.setIcon( UISupport.createImageIcon( "/unknown_assertion.gif" ) );
}
}
}
}