/* * SoapUI, Copyright (C) 2004-2016 SmartBear Software * * Licensed under the EUPL, Version 1.1 or - as soon as they will be approved by the European Commission - subsequent * versions of the EUPL (the "Licence"); * You may not use this work except in compliance with the Licence. * You may obtain a copy of the Licence at: * * http://ec.europa.eu/idabc/eupl * * Unless required by applicable law or agreed to in writing, software distributed under the Licence is * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either * express or implied. See the Licence for the specific language governing permissions and limitations * under the Licence. */ package com.eviware.soapui.impl.wsdl.panels.testcase; import com.eviware.soapui.impl.wsdl.testcase.TestCaseLogItem; import com.eviware.soapui.impl.wsdl.testcase.TestCaseLogModel; import com.eviware.soapui.model.settings.Settings; import com.eviware.soapui.model.testsuite.TestStepResult; import com.eviware.soapui.model.testsuite.TestStepResult.TestStepStatus; import com.eviware.soapui.support.StringUtils; 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.AField.AFieldType; import com.eviware.x.form.support.AForm; 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 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; /** * Panel for displaying TestStepResults * * @author Ole.Matzura */ public class JTestRunLog extends JPanel implements TestRunLog { private TestCaseLogModel 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; public JTestRunLog(Settings settings) { super(new BorderLayout()); this.settings = settings; errorsOnly = settings.getBoolean(OptionsForm.class.getName() + "@errors_only"); buildUI(); } private void buildUI() { logListModel = new TestCaseLogModel(); logListModel.setMaxSize((int) settings.getLong(OptionsForm.class.getName() + "@max_rows", 1000)); testLogList = new JList(logListModel); testLogList.setCellRenderer(new TestLogCellRenderer()); testLogList.setPrototypeCellValue("Testing 123"); testLogList.setFixedCellWidth(-1); 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())); } private final class TestLogCellRenderer extends JLabel implements ListCellRenderer { private Font boldFont; private Font normalFont; private JHyperlinkLabel hyperlinkLabel = new JHyperlinkLabel(""); public TestLogCellRenderer() { 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); } TestStepResult result = logListModel.getResultAt(index); if (result != null && !getText().startsWith(" ->")) { hyperlinkLabel.setText(getText()); hyperlinkLabel.setBackground(getBackground()); hyperlinkLabel.setEnabled(list.isEnabled()); if (result.getStatus() == TestStepStatus.OK) { hyperlinkLabel.setIcon(UISupport.createImageIcon("/valid_assertion.gif")); } else if (result.getStatus() == TestStepStatus.FAILED) { hyperlinkLabel.setIcon(UISupport.createImageIcon("/failed_assertion.gif")); } else { hyperlinkLabel.setIcon(UISupport.createImageIcon("/unknown_assertion.png")); } return hyperlinkLabel; } setEnabled(list.isEnabled()); if (boldTexts.contains(getText())) { setFont(boldFont); } else { setFont(normalFont); } return this; } } /** * 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)) { TestStepResult result = logListModel.getResultAt(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); } TestStepResult result = logListModel.getResultAt(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()); } } /* * (non-Javadoc) * * @see com.eviware.soapui.impl.wsdl.panels.testcase.TestRunLog#clear() */ public synchronized void clear() { logListModel.clear(); boldTexts.clear(); } /* * (non-Javadoc) * * @see * com.eviware.soapui.impl.wsdl.panels.testcase.TestRunLog#addText(java.lang * .String) */ public synchronized void addText(String string) { logListModel.addText(string); if (follow) { testLogList.ensureIndexIsVisible(logListModel.getSize() - 1); } } /* * (non-Javadoc) * * @see * com.eviware.soapui.impl.wsdl.panels.testcase.TestRunLog#addTestStepResult * (com.eviware.soapui.model.testsuite.TestStepResult) */ public synchronized void addTestStepResult(TestStepResult stepResult) { if (errorsOnly && stepResult.getStatus() != TestStepResult.TestStepStatus.FAILED) { return; } logListModel.addTestStepResult(stepResult); if (follow) { try { testLogList.ensureIndexIsVisible(logListModel.getSize() - 1); } catch (RuntimeException e) { } } } public TestCaseLogModel getLogListModel() { return logListModel; } public void setLogListModel(TestCaseLogModel logListModel) { this.logListModel = logListModel; testLogList.setModel(logListModel); } private class SetLogOptionsAction extends AbstractAction { public SetLogOptionsAction() { putValue(Action.SMALL_ICON, UISupport.createImageIcon("/preferences.png")); 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") 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 = "Errors Only", description = "Logs only TestStep errors in the log", type = AFieldType.BOOLEAN) public static final String ERRORSONLY = "Errors 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.png")); 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.png")); 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 setStepIndex(int i) { logListModel.setStepIndex(i); } public synchronized void addBoldText(String string) { boldTexts.add(string); addText(string); } 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()); } else if (value instanceof TestCaseLogItem) { TestCaseLogItem logItem = (TestCaseLogItem) value; String msg = logItem.getMsg(); if (StringUtils.hasContent(msg)) { out.println(msg); } } } } }