/* * 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.monitor; import com.eviware.soapui.SoapUI; import com.eviware.soapui.impl.support.AbstractInterface; import com.eviware.soapui.impl.wsdl.WsdlInterface; import com.eviware.soapui.impl.wsdl.WsdlProject; import com.eviware.soapui.impl.wsdl.WsdlRequest; import com.eviware.soapui.impl.wsdl.WsdlTestSuite; import com.eviware.soapui.impl.wsdl.actions.monitor.SoapMonitorAction; import com.eviware.soapui.impl.wsdl.actions.monitor.SoapMonitorAction.LaunchForm; import com.eviware.soapui.impl.wsdl.mock.WsdlMockOperation; import com.eviware.soapui.impl.wsdl.mock.WsdlMockResponse; import com.eviware.soapui.impl.wsdl.mock.WsdlMockService; import com.eviware.soapui.impl.wsdl.support.HelpUrls; import com.eviware.soapui.impl.wsdl.support.MessageExchangeModelItem; import com.eviware.soapui.impl.wsdl.support.MessageExchangeRequestMessageEditor; import com.eviware.soapui.impl.wsdl.support.MessageExchangeResponseMessageEditor; import com.eviware.soapui.impl.wsdl.testcase.WsdlTestCase; import com.eviware.soapui.impl.wsdl.teststeps.HttpTestRequest; import com.eviware.soapui.impl.wsdl.teststeps.HttpTestRequestStep; import com.eviware.soapui.impl.wsdl.teststeps.WsdlTestRequest; import com.eviware.soapui.impl.wsdl.teststeps.WsdlTestRequestStep; import com.eviware.soapui.impl.wsdl.teststeps.registry.HttpRequestStepFactory; import com.eviware.soapui.impl.wsdl.teststeps.registry.WsdlTestRequestStepFactory; import com.eviware.soapui.model.iface.Attachment; import com.eviware.soapui.model.iface.Interface; import com.eviware.soapui.model.settings.Settings; import com.eviware.soapui.model.support.ModelSupport; import com.eviware.soapui.model.testsuite.TestSuite; import com.eviware.soapui.settings.ProxySettings; import com.eviware.soapui.support.DateUtil; import com.eviware.soapui.support.StringUtils; import com.eviware.soapui.support.UISupport; import com.eviware.soapui.support.components.JComponentInspector; import com.eviware.soapui.support.components.JInspectorPanel; import com.eviware.soapui.support.components.JInspectorPanelFactory; import com.eviware.soapui.support.components.JXToolBar; import com.eviware.soapui.support.types.StringList; import com.eviware.soapui.support.types.StringToStringsMap; import com.eviware.x.form.XFormDialog; import com.eviware.x.form.XFormField; import com.eviware.x.form.XFormFieldListener; 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 com.jgoodies.forms.builder.ButtonBarBuilder; import org.apache.commons.collections.list.TreeList; import org.jdesktop.swingx.JXTable; import org.jdesktop.swingx.decorator.Filter; import org.jdesktop.swingx.decorator.FilterPipeline; import org.jdesktop.swingx.decorator.PatternFilter; import javax.swing.AbstractAction; import javax.swing.BorderFactory; import javax.swing.DefaultComboBoxModel; import javax.swing.JButton; import javax.swing.JComboBox; import javax.swing.JComponent; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JProgressBar; import javax.swing.JScrollPane; import javax.swing.ListSelectionModel; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import javax.swing.table.AbstractTableModel; import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.net.MalformedURLException; import java.net.URL; import java.util.Date; import java.util.List; import java.util.Map; import java.util.Stack; /** * A SOAP Monitor.. */ @SuppressWarnings("serial") public class SoapMonitor extends JPanel { private static final String ALL_FILTER_OPTION = "- all -"; private JProgressBar progressBar; private JButton stopButton = null; private JXTable logTable = null; private MonitorLogTableModel tableModel = null; private String httpProxyHost = null; private int httpProxyPort = 80; private JButton startButton; private final WsdlProject project; private MessageExchangeRequestMessageEditor requestViewer; private MessageExchangeResponseMessageEditor responseViewer; private MessageExchangeModelItem requestModelItem; private JButton optionsButton; private int listenPort; private String targetEndpoint; private JButton clearButton; private int maxRows; private JButton addToTestCaseButton; // private JButton addToRestTestCaseButton; private JButton createRequestButton; private JButton addToMockServiceButton; private Stack<WsdlMonitorMessageExchange> messageExchangeStack = new Stack<WsdlMonitorMessageExchange>(); private StackProcessor stackProcessor = new StackProcessor(); private PatternFilter operationFilter; private PatternFilter interfaceFilter; private PatternFilter targetHostFilter; private JLabel infoLabel; private PatternFilter requestHostFilter; private JComboBox requestHostFilterCombo; private JComboBox targetHostFilterCombo; private JComboBox interfaceFilterCombo; private JComboBox operationFilterCombo; private DefaultComboBoxModel operationFilterModel; private DefaultComboBoxModel requestFilterModel; private DefaultComboBoxModel targetHostFilterModel; private JLabel rowCountLabel = new JLabel(); private Map<AbstractInterface<?>, String> addedEndpoints; private JXToolBar toolbar; private String incomingRequestWss; private String incomingResponseWss; private boolean setAsProxy; private XFormDialog optionsDialog; private SoapMonitorEngine monitorEngine; private String oldProxyHost; private String oldProxyPort; private boolean oldProxyEnabled; private boolean oldProxyAuto; private String sslEndpoint; private JInspectorPanel inspectorPanel; private SoapMonitorListenerCallBack listenerCallBack; public SoapMonitor(WsdlProject project, int listenPort, String incomingRequestWss, String incomingResponseWss, JXToolBar mainToolbar, boolean setAsProxy, String sslEndpoint) { super(new BorderLayout()); this.project = project; this.listenPort = listenPort; this.incomingRequestWss = incomingRequestWss; this.incomingResponseWss = incomingResponseWss; this.setAsProxy = setAsProxy; this.maxRows = 100; this.sslEndpoint = sslEndpoint; // set the slow link to the passed down link this.setLayout(new BorderLayout()); add(buildToolbars(mainToolbar), BorderLayout.NORTH); add(buildContent(), BorderLayout.CENTER); start(); } public SoapMonitor(WsdlProject project, int sourcePort, String incomingRequestWss, String incomingResponseWss, JXToolBar toolbar, boolean setAsProxy) { this(project, sourcePort, incomingRequestWss, incomingResponseWss, toolbar, setAsProxy, null); } private JComponent buildContent() { inspectorPanel = JInspectorPanelFactory.build(buildLog()); JComponentInspector<JComponent> viewInspector = new JComponentInspector<JComponent>(buildViewer(), "Message Content", "Shows message content", true); inspectorPanel.addInspector(viewInspector); return inspectorPanel.getComponent(); } private JComponent buildLog() { tableModel = new MonitorLogTableModel(); logTable = new JXTable(1, 2); logTable.setColumnControlVisible(true); logTable.setModel(tableModel); logTable.setHorizontalScrollEnabled(true); logTable.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); operationFilter = new PatternFilter(".*", 0, 4); operationFilter.setAcceptNull(true); interfaceFilter = new PatternFilter(".*", 0, 3); interfaceFilter.setAcceptNull(true); targetHostFilter = new PatternFilter(".*", 0, 2); targetHostFilter.setAcceptNull(true); requestHostFilter = new PatternFilter(".*", 0, 1); requestHostFilter.setAcceptNull(true); Filter[] filters = new Filter[]{requestHostFilter, targetHostFilter, interfaceFilter, operationFilter}; FilterPipeline pipeline = new FilterPipeline(filters); logTable.setFilters(pipeline); ListSelectionModel sel = logTable.getSelectionModel(); sel.addListSelectionListener(new ListSelectionListener() { public void valueChanged(ListSelectionEvent event) { int row = logTable.getSelectedRow(); if (row == -1) { requestModelItem.setMessageExchange(null); } else { WsdlMonitorMessageExchange exchange = tableModel.getMessageExchangeAt(row); requestModelItem.setMessageExchange(exchange); } addToMockServiceButton.setEnabled(row != -1); addToTestCaseButton.setEnabled(row != -1); // addToRestTestCaseButton.setEnabled( row != -1 ); createRequestButton.setEnabled(row != -1); } }); JPanel tablePane = new JPanel(); tablePane.setLayout(new BorderLayout()); toolbar.addGlue(); tablePane.add(buildFilterBar(), BorderLayout.NORTH); tablePane.add(new JScrollPane(logTable), BorderLayout.CENTER); return tablePane; } private JPanel buildFilterBar() { requestFilterModel = new DefaultComboBoxModel(new String[]{ALL_FILTER_OPTION}); targetHostFilterModel = new DefaultComboBoxModel(new String[]{ALL_FILTER_OPTION}); Dimension comboBoxSize = new Dimension(90, 18); requestHostFilterCombo = UISupport.setFixedSize(new JComboBox(requestFilterModel), comboBoxSize); // toolbar.addFixed( new JLabel( "<html><b>Filter:</b></html>")); // toolbar.addUnrelatedGap(); ButtonBarBuilder toolbar = new ButtonBarBuilder(); toolbar.addFixed(new JLabel("Request Host")); toolbar.addRelatedGap(); toolbar.addFixed(requestHostFilterCombo); toolbar.addUnrelatedGap(); requestHostFilterCombo.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { int ix = requestHostFilterCombo.getSelectedIndex(); if (ix == -1) { return; } requestHostFilter.setAcceptNull(ix == 0); if (ix == 0) { requestHostFilter.setPattern(".*", 0); } else { requestHostFilter.setPattern(requestHostFilterCombo.getSelectedItem().toString(), 0); } updateRowCountLabel(); } }); toolbar.addFixed(new JLabel("Target Host")); toolbar.addRelatedGap(); targetHostFilterCombo = UISupport.setFixedSize(new JComboBox(targetHostFilterModel), comboBoxSize); toolbar.addFixed(targetHostFilterCombo); toolbar.addUnrelatedGap(); targetHostFilterCombo.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { int ix = targetHostFilterCombo.getSelectedIndex(); if (ix == -1) { return; } targetHostFilter.setAcceptNull(ix == 0); if (ix == 0) { targetHostFilter.setPattern(".*", 0); } else { targetHostFilter.setPattern(targetHostFilterCombo.getSelectedItem().toString(), 0); } updateRowCountLabel(); } }); String[] interfaceNames = ModelSupport.getNames(new String[]{ALL_FILTER_OPTION}, ModelSupport.getChildren(getProject(), WsdlInterface.class)); toolbar.addFixed(new JLabel("Interface")); toolbar.addRelatedGap(); interfaceFilterCombo = UISupport.setFixedSize(new JComboBox(interfaceNames), comboBoxSize); toolbar.addFixed(interfaceFilterCombo); toolbar.addUnrelatedGap(); operationFilterModel = new DefaultComboBoxModel(new String[]{ALL_FILTER_OPTION}); interfaceFilterCombo.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { String item = (String) interfaceFilterCombo.getSelectedItem(); operationFilterModel.removeAllElements(); if (item == null || getProject().getInterfaceByName(item) == null) { operationFilterModel.addElement(ALL_FILTER_OPTION); interfaceFilter.setPattern(".*", 0); } else if (getProject().getInterfaceByName(item) != null) { WsdlInterface iface = (WsdlInterface) getProject().getInterfaceByName(item); String[] operationNames = ModelSupport.getNames(new String[]{ALL_FILTER_OPTION}, iface.getOperationList()); for (String s : operationNames) { operationFilterModel.addElement(s); } interfaceFilter.setPattern(iface.getName(), 0); } } }); toolbar.addFixed(new JLabel("Operation")); toolbar.addRelatedGap(); operationFilterCombo = UISupport.setFixedSize(new JComboBox(operationFilterModel), comboBoxSize); toolbar.addFixed(operationFilterCombo); operationFilterCombo.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { int ix = operationFilterCombo.getSelectedIndex(); if (ix == -1) { operationFilter.setPattern(".*", 0); updateRowCountLabel(); return; } operationFilter.setAcceptNull(ix == 0); if (ix == 0) { operationFilter.setPattern(".*", 0); } else { operationFilter.setPattern(operationFilterCombo.getSelectedItem().toString(), 0); } updateRowCountLabel(); } }); toolbar.setBorder(BorderFactory.createEmptyBorder(3, 2, 3, 0)); return toolbar.getPanel(); } protected void updateRowCountLabel() { rowCountLabel.setText(logTable.getRowCount() + "/" + tableModel.getRowCount() + " entries"); } private JComponent buildViewer() { requestModelItem = new MessageExchangeModelItem("monitor message exchange", null) { @Override public boolean hasRawData() { return true; } }; requestViewer = new MessageExchangeRequestMessageEditor(requestModelItem); responseViewer = new MessageExchangeResponseMessageEditor(requestModelItem); return UISupport.createHorizontalSplit(requestViewer, responseViewer); } private JComponent buildToolbars(JXToolBar mainToolbar) { toolbar = UISupport.createSmallToolbar(); mainToolbar.addFixed(startButton = UISupport.createToolbarButton(UISupport .createImageIcon("/start.png"))); mainToolbar.addFixed(stopButton = UISupport.createToolbarButton(UISupport .createImageIcon("/stop.png"))); mainToolbar.addFixed(optionsButton = UISupport.createToolbarButton(new SoapMonitorOptionsAction())); toolbar .addFixed(createRequestButton = UISupport.createToolbarButton(UISupport.createImageIcon("/soap_request.png"))); toolbar.addFixed(addToTestCaseButton = UISupport.createToolbarButton(UISupport .createImageIcon("/testcase.png"))); // toolbar.addFixed( addToRestTestCaseButton = // UISupport.createToolbarButton( UISupport // .createImageIcon( "/testcase.png" ) ) ); toolbar.addFixed(addToMockServiceButton = UISupport.createToolbarButton(UISupport .createImageIcon("/soap_virt.png"))); toolbar .addFixed(clearButton = UISupport.createToolbarButton(UISupport.createImageIcon("/clear.png"))); startButton.setToolTipText("Starts the HTTP Monitor as configured"); stopButton.setToolTipText("Stops the HTTP Monitor"); optionsButton.setToolTipText("Sets Monitor Options"); clearButton.setToolTipText("Clear all/selected messages from the log"); createRequestButton.setToolTipText("Creates requests from selected messages"); addToTestCaseButton.setToolTipText("Adds selected requests to a test case"); // addToRestTestCaseButton.setToolTipText( // "Adds selected REST requests to a TestCase" ); addToMockServiceButton.setToolTipText("Adds selected responses to a mock service"); createRequestButton.setEnabled(false); addToMockServiceButton.setEnabled(false); addToTestCaseButton.setEnabled(false); // addToRestTestCaseButton.setEnabled( false ); startButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { start(); } }); stopButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { stop(); } }); clearButton.addActionListener(new ClearAction()); createRequestButton.addActionListener(new CreateRequestsAction()); addToTestCaseButton.addActionListener(new AddToTestCaseAction()); // addToRestTestCaseButton.addActionListener( new // AddToRESTTestCaseAction() ); addToMockServiceButton.addActionListener(new AddToMockServiceAction()); mainToolbar.addGlue(); infoLabel = new JLabel(); infoLabel.setPreferredSize(new Dimension(150, 20)); infoLabel.setOpaque(false); mainToolbar.addFixed(infoLabel); progressBar = new JProgressBar(); JPanel progressBarPanel = UISupport.createProgressBarPanel(progressBar, 2, false); progressBarPanel.setPreferredSize(new Dimension(60, 20)); mainToolbar.addFixed(progressBarPanel); return toolbar; } /** * Method start */ public void start() { int localPort = getLocalPort(); listenerCallBack = new SoapMonitorListenerCallBack() { @Override public void fireAddMessageExchange(WsdlMonitorMessageExchange messageExchange) { addMessageExchange(messageExchange); } }; monitorEngine = new SoapMonitorEngineImpl(sslEndpoint); monitorEngine.setIncludedContentTypes(ContentTypes.of(project.getSettings() .getString(SoapMonitorAction.LaunchForm.SET_CONTENT_TYPES, SoapMonitorAction.defaultContentTypes().toString()))); monitorEngine.start(this.getProject(), localPort, listenerCallBack); if (monitorEngine.isRunning()) { stopButton.setEnabled(true); startButton.setEnabled(false); optionsButton.setEnabled(false); infoLabel.setText((monitorEngine.isProxy() ? "HTTP Proxy " : "SSL Tunnel ") + "on port " + localPort); progressBar.setIndeterminate(true); if (setAsProxy) { oldProxyHost = SoapUI.getSettings().getString(ProxySettings.HOST, ""); oldProxyPort = SoapUI.getSettings().getString(ProxySettings.PORT, ""); oldProxyEnabled = SoapUI.getSettings().getBoolean(ProxySettings.ENABLE_PROXY); oldProxyAuto = SoapUI.getSettings().getBoolean(ProxySettings.AUTO_PROXY); SoapUI.getSettings().setString(ProxySettings.HOST, "127.0.0.1"); SoapUI.getSettings().setString(ProxySettings.PORT, String.valueOf(localPort)); SoapUI.getSettings().setBoolean(ProxySettings.ENABLE_PROXY, true); SoapUI.getSettings().setBoolean(ProxySettings.AUTO_PROXY, false); SoapUI.updateProxyFromSettings(); } SoapUI.log.info("Started HTTP Monitor on local port " + localPort); } else { stopButton.setEnabled(false); startButton.setEnabled(true); optionsButton.setEnabled(true); infoLabel.setText("Stopped"); progressBar.setIndeterminate(false); SoapUI.log.info("Could not start HTTP Monitor on local port " + localPort); } } /** * Method close */ public void close() { stop(); } /** * Method stop */ public void stop() { monitorEngine.stop(); if (addedEndpoints != null) { for (Interface iface : addedEndpoints.keySet()) { iface.removeEndpoint(addedEndpoints.get(iface)); } addedEndpoints.clear(); } stopButton.setEnabled(false); startButton.setEnabled(true); optionsButton.setEnabled(true); progressBar.setIndeterminate(false); infoLabel.setText("Stopped"); if (setAsProxy) { SoapUI.getSettings().setString(ProxySettings.HOST, oldProxyHost); SoapUI.getSettings().setString(ProxySettings.PORT, oldProxyPort); SoapUI.getSettings().setBoolean(ProxySettings.ENABLE_PROXY, oldProxyEnabled); SoapUI.getSettings().setBoolean(ProxySettings.AUTO_PROXY, oldProxyAuto); SoapUI.updateProxyFromSettings(); } } @AForm(description = "Set options for adding selected requests to a MockService", name = "Add To MockService") private final class AddToMockServiceAction implements ActionListener { private static final String CREATE_NEW_OPTION = "<Create New>"; private XFormDialog dialog; @AField(name = "Target MockService", description = "The target TestSuite", type = AFieldType.ENUMERATION) public final static String MOCKSERVICE = "Target MockService"; @AField(name = "Open Editor", description = "Open the created MockService", type = AFieldType.BOOLEAN) public final static String OPENEDITOR = "Open Editor"; public void actionPerformed(ActionEvent e) { int[] rows = logTable.getSelectedRows(); if (rows.length == 0) { return; } if (dialog == null) { dialog = ADialogBuilder.buildDialog(this.getClass()); } String[] testSuiteNames = ModelSupport.getNames(new String[]{CREATE_NEW_OPTION}, getProject() .getMockServiceList()); dialog.setOptions(MOCKSERVICE, testSuiteNames); if (dialog.show()) { int withoutOperation = 0; for (int row : rows) { WsdlMonitorMessageExchange me = tableModel.getMessageExchangeAt(row); if (me.getOperation() == null) { withoutOperation++; } } if (withoutOperation == rows.length) { UISupport.showInfoMessage("No SOAP requests selected!"); return; } String targetMockServiceName = dialog.getValue(MOCKSERVICE); WsdlMockService mockService = getProject().getMockServiceByName(targetMockServiceName); if (mockService == null) { targetMockServiceName = ModelSupport.promptForUniqueName("MockService", getProject(), ""); if (targetMockServiceName == null) { return; } mockService = getProject().addNewMockService(targetMockServiceName); mockService.setIncomingWss(incomingResponseWss); } int cnt = 0; for (int row : rows) { WsdlMonitorMessageExchange me = tableModel.getMessageExchangeAt(row); if (me.getOperation() == null) { continue; } WsdlMockOperation mockOperation = mockService.getMockOperation(me.getOperation()); if (mockOperation == null) { mockOperation = (WsdlMockOperation) mockService.addNewMockOperation(me.getOperation()); } WsdlMockResponse mockResponse = mockOperation .addNewMockResponse("Monitor Response " + (++cnt), false); mockResponse.setResponseContent(me.getResponseContent()); Attachment[] requestAttachments = me.getResponseAttachments(); if (requestAttachments != null) { for (Attachment attachment : requestAttachments) { mockResponse.addAttachment(attachment); } } } if (cnt == 0) { UISupport.showInfoMessage("No response messages found"); } else { UISupport.showInfoMessage("Added " + cnt + " MockResponses to MockService"); if (dialog.getBooleanValue(OPENEDITOR)) { UISupport.selectAndShow(mockService); } } } } } @AForm(description = "Set options for adding selected requests to a TestCase", name = "Add To TestCase") private final class AddToTestCaseAction implements ActionListener { private static final String CREATE_NEW_OPTION = "<Create New>"; private XFormDialog dialog; @AField(name = "Target TestSuite", description = "The target TestSuite", type = AFieldType.ENUMERATION) public final static String TESTSUITE = "Target TestSuite"; @AField(name = "Target TestCase", description = "The target TestCase for the requests", type = AFieldType.ENUMERATION) public final static String TESTCASE = "Target TestCase"; @AField(name = "Open Editor", description = "Open the created TestCase", type = AFieldType.BOOLEAN) public final static String OPENEDITOR = "Open Editor"; TestSuite testSuite; public void actionPerformed(ActionEvent e) { int[] rows = logTable.getSelectedRows(); if (rows.length == 0) { return; } if (dialog == null) { dialog = ADialogBuilder.buildDialog(this.getClass()); dialog.getFormField(TESTSUITE).addFormFieldListener(new XFormFieldListener() { public void valueChanged(XFormField sourceField, String newValue, String oldValue) { if (newValue.equals(CREATE_NEW_OPTION)) { dialog.setOptions(TESTCASE, new String[]{CREATE_NEW_OPTION}); } else { testSuite = getProject().getTestSuiteByName(newValue); dialog.setOptions( TESTCASE, testSuite == null ? new String[]{CREATE_NEW_OPTION} : ModelSupport.getNames( testSuite.getTestCaseList(), new String[]{CREATE_NEW_OPTION})); } } }); } String[] testSuiteNames = ModelSupport.getNames(new String[]{CREATE_NEW_OPTION}, getProject() .getTestSuiteList()); dialog.setOptions(TESTSUITE, testSuiteNames); testSuite = getProject().getTestSuiteByName(dialog.getValue(TESTSUITE)); dialog.setOptions( TESTCASE, testSuite == null ? new String[]{CREATE_NEW_OPTION} : ModelSupport.getNames( testSuite.getTestCaseList(), new String[]{CREATE_NEW_OPTION})); if (dialog.show()) { String targetTestSuiteName = dialog.getValue(TESTSUITE); String targetTestCaseName = dialog.getValue(TESTCASE); WsdlTestSuite testSuite = getProject().getTestSuiteByName(targetTestSuiteName); if (testSuite == null) { targetTestSuiteName = ModelSupport.promptForUniqueName("TestSuite", getProject(), ""); if (targetTestSuiteName == null) { return; } testSuite = getProject().addNewTestSuite(targetTestSuiteName); } WsdlTestCase testCase = testSuite.getTestCaseByName(targetTestCaseName); if (testCase == null) { targetTestCaseName = ModelSupport.promptForUniqueName("TestCase", testSuite, ""); if (targetTestCaseName == null) { return; } testCase = testSuite.addNewTestCase(targetTestCaseName); } for (int row : rows) { WsdlMonitorMessageExchange me = tableModel.getMessageExchangeAt(row); if (me.getOperation() != null) { WsdlTestRequestStep test = (WsdlTestRequestStep) testCase.insertTestStep( WsdlTestRequestStepFactory.createConfig(me.getOperation(), "Monitor Request " + (row + 1)), -1); WsdlTestRequest request = test.getTestRequest(); request.setRequestContent(me.getRequestContent()); request.setEndpoint(me.getTargetUrl().toString()); request.setIncomingWss(incomingRequestWss); Attachment[] requestAttachments = me.getRequestAttachments(); if (requestAttachments != null) { for (Attachment attachment : requestAttachments) { request.importAttachment(attachment); } } } else { HttpRequestStepFactory httpRequestStepFactory = new HttpRequestStepFactory(); HttpTestRequestStep test = (HttpTestRequestStep) testCase.insertTestStep( httpRequestStepFactory.createConfig(me, "Monitor Request " + (row + 1)), -1); test.getTestRequest().setRequestHeaders(excludeProxyHeaders(me.getRequestHeaders())); HttpTestRequest request = (HttpTestRequest) test.getHttpRequest(); request.setEndpoint(me.getTargetUrl().toString()); // request.setIncomingWss( incomingRequestWss ); String existingMediaType = me.getResponseHeaders().get("Content-Type", ""); if (!StringUtils.isNullOrEmpty(existingMediaType)) { request.setMediaType(existingMediaType); } if ("application/octet-stream".equals(existingMediaType) || "application/x-amf".equals(existingMediaType)) { request.attachBinaryData(me.getRequestContent().getBytes(), existingMediaType); } else { request.setRequestContent(me.getRequestContent()); test.getTestRequest().setRequestContent(me.getRequestContent()); } Attachment[] requestAttachments = me.getRequestAttachments(); if (requestAttachments != null) { for (Attachment attachment : requestAttachments) { request.importAttachment(attachment); } } // } } } if (dialog.getBooleanValue(OPENEDITOR)) { UISupport.selectAndShow(testCase); } } } } private final class CreateRequestsAction implements ActionListener { public void actionPerformed(ActionEvent e) { int[] rows = logTable.getSelectedRows(); if (rows.length == 0) { return; } if (UISupport.confirm("Create " + rows.length + " requests", "Create Request")) { int withoutOperation = 0; for (int row : rows) { WsdlMonitorMessageExchange me = tableModel.getMessageExchangeAt(row); if (me.getOperation() == null) { withoutOperation++; continue; } WsdlRequest request = me.getOperation().addNewRequest("Monitor Request " + (row + 1)); request.setRequestContent(me.getRequestContent()); request.setEndpoint(me.getTargetUrl().toString()); Attachment[] requestAttachments = me.getRequestAttachments(); if (requestAttachments != null) { for (Attachment attachment : requestAttachments) { request.importAttachment(attachment); } } } if (withoutOperation > 0) { UISupport.showInfoMessage("For " + withoutOperation + "request(s) there are no operations", "Create Request"); } } } } private final class ClearAction implements ActionListener { public void actionPerformed(ActionEvent e) { if (logTable.getRowCount() == 0) { return; } int[] rows = logTable.getSelectedRows(); if (rows.length == 0) { if (UISupport.confirm("Clear monitor log?", "Clear Log")) { tableModel.clear(); } } else if (UISupport.confirm("Clear " + rows.length + " rows from monitor log?", "Clear Log")) { tableModel.clearRows(rows); } } } @SuppressWarnings("unchecked") public class MonitorLogTableModel extends AbstractTableModel { private List<WsdlMonitorMessageExchange> exchanges = new TreeList(); public MonitorLogTableModel() { } public synchronized void clear() { int sz = exchanges.size(); while (exchanges.size() > 0) { WsdlMonitorMessageExchange removed = exchanges.remove(0); removed.discard(); } fireTableRowsDeleted(0, sz); while (requestFilterModel.getSize() > 1) { requestFilterModel.removeElementAt(1); } while (targetHostFilterModel.getSize() > 1) { targetHostFilterModel.removeElementAt(1); } updateRowCountLabel(); } public synchronized void clearRows(int[] indices) { for (int c = indices.length; c > 0; c--) { int index = indices[c - 1]; WsdlMonitorMessageExchange removed = exchanges.remove(logTable.convertRowIndexToModel(index)); removed.discard(); fireTableRowsDeleted(index, index); updateRowCountLabel(); } } public int getColumnCount() { return 12; } public WsdlMonitorMessageExchange getMessageExchangeAt(int tableRow) { return exchanges.get(logTable.convertRowIndexToModel(tableRow)); } @Override public String getColumnName(int column) { switch (column) { case 0: return "Count."; case 1: return "Time"; case 2: return "Request Host"; case 3: return "Target Host"; case 4: return "Interface"; case 5: return "Operation"; case 6: return "Time Taken"; case 7: return "Req Sz"; case 8: return "Resp Sz"; case 9: return "Method"; case 10: return "Path"; case 11: return "Content-Type"; } return null; } public int getRowCount() { return exchanges.size(); } public Object getValueAt(int rowIndex, int columnIndex) { if (rowIndex < 0 || rowIndex >= exchanges.size()) { return null; } WsdlMonitorMessageExchange exchange = exchanges.get(rowIndex); if (exchange == null) { return null; } switch (columnIndex) { case 0: return rowIndex; case 1: return DateUtil.formatFull(new Date(exchange.getTimestamp())); case 2: return exchange.getRequestHost(); case 3: return exchange.getTargetUrl().getHost(); case 4: return exchange.getOperation() == null ? "- unknown -" : exchange.getOperation().getInterface().getName(); case 5: return exchange.getOperation() == null ? "- unknown -" : exchange.getOperation().getName(); case 6: return String.valueOf(exchange.getTimeTaken()); case 7: return String.valueOf(exchange.getRequestContentLength()); case 8: return String.valueOf(exchange.getResponseContentLength()); case 9: return String.valueOf(exchange.getRequestMethod()); case 10: return exchange.getTargetUrl().getPath(); case 11: return String.valueOf(exchange.getResponseContentType()); } return null; } public synchronized void addMessageExchange(WsdlMonitorMessageExchange exchange) { exchanges.add(exchange); int size = exchanges.size(); fireTableRowsInserted(size - 1, size - 1); fitSizeToMaxRows(); String requestHost = exchange.getRequestHost(); if (requestFilterModel.getIndexOf(requestHost) == -1) { requestFilterModel.addElement(requestHost); } String host = exchange.getTargetUrl().getHost(); if (targetHostFilterModel.getIndexOf(host) == -1) { targetHostFilterModel.addElement(host); } updateRowCountLabel(); } public void fitSizeToMaxRows() { int removeCnt = 0; while (exchanges.size() > maxRows) { WsdlMonitorMessageExchange removed = exchanges.remove(0); removed.discard(); removeCnt++; } if (removeCnt > 0) { fireTableDataChanged(); updateRowCountLabel(); } } } protected String getHttpProxyHost() { return httpProxyHost; } /** * Excludes proxy headers * * @param requestHeaders * @return */ private StringToStringsMap excludeProxyHeaders(StringToStringsMap requestHeaders) { StringToStringsMap stsmap = new StringToStringsMap(); for (String key : requestHeaders.getKeys()) { if (!(key.contains("Proxy") || key.contains("Content"))) { stsmap.add(key, requestHeaders.get(key, "")); } } return stsmap; } protected void setHttpProxyHost(String proxyHost) { httpProxyHost = proxyHost; } protected int getHttpProxyPort() { return httpProxyPort; } protected void setHttpProxyPort(int proxyPort) { httpProxyPort = proxyPort; } // protected SlowLinkSimulator getSlowLink() // { // return slowLink; // } public String getTargetHost() { String host = targetEndpoint; try { URL url = new URL(host); return url.getHost(); } catch (MalformedURLException e) { return host; } } public String getTargetEndpoint() { return targetEndpoint; } public int getTargetPort() { try { URL url = new URL(targetEndpoint); return url.getPort() == -1 ? 80 : url.getPort(); } catch (MalformedURLException e) { return 80; } } public int getLocalPort() { return listenPort; } public synchronized void addMessageExchange(WsdlMonitorMessageExchange messageExchange) { messageExchangeStack.push(messageExchange); if (!stackProcessor.isRunning()) { new Thread(stackProcessor, "SoapMonitor StackProcessor for project [" + getProject().getName() + "]") .start(); } } private class StackProcessor implements Runnable { private boolean canceled; private boolean running; public void run() { running = true; SoapUI.log.info("Started stackprocessor for soapmonitor in project [" + getProject().getName() + "]"); while (!canceled && messageExchangeStack.size() > 0) { WsdlMonitorMessageExchange messageExchange = messageExchangeStack.pop(); if (messageExchange != null) { processMessage(messageExchange); } try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } running = false; } private synchronized void processMessage(WsdlMonitorMessageExchange messageExchange) { messageExchange.prepare(project.getWssContainer().getIncomingWssByName(incomingRequestWss), project .getWssContainer().getIncomingWssByName(incomingResponseWss)); tableModel.addMessageExchange(messageExchange); listenerCallBack.fireOnMessageExchange(messageExchange); } @SuppressWarnings("unused") public void cancel() { canceled = true; } @SuppressWarnings("unused") protected boolean isCanceled() { return canceled; } protected boolean isRunning() { return running; } } public MonitorLogTableModel getLogModel() { return tableModel; } public void addSoapMonitorListener(MonitorListener listener) { listenerCallBack.addSoapMonitorListener(listener); } public void removeSoapMonitorListener(MonitorListener listener) { listenerCallBack.removeSoapMonitorListener(listener); } public WsdlProject getProject() { return project; } public class SoapMonitorOptionsAction extends AbstractAction { public SoapMonitorOptionsAction() { putValue(SMALL_ICON, UISupport.createImageIcon("/preferences.png")); } public void actionPerformed(ActionEvent e) { if (optionsDialog == null) { optionsDialog = ADialogBuilder.buildDialog(OptionsForm.class); } StringList endpoints = new StringList(); endpoints.add(null); for (WsdlInterface iface : ModelSupport.getChildren(getProject(), WsdlInterface.class)) { endpoints.addAll(iface.getEndpoints()); } optionsDialog.setIntValue(OptionsForm.PORT, listenPort); optionsDialog.setIntValue(OptionsForm.MAXROWS, maxRows); optionsDialog.setOptions(OptionsForm.REQUEST_WSS, StringUtils.merge(project.getWssContainer().getIncomingWssNames(), "<none>")); optionsDialog.setOptions(OptionsForm.RESPONSE_WSS, StringUtils.merge(project.getWssContainer().getIncomingWssNames(), "<none>")); optionsDialog.setValue(OptionsForm.REQUEST_WSS, incomingRequestWss); optionsDialog.setValue(OptionsForm.RESPONSE_WSS, incomingResponseWss); optionsDialog .setValue( LaunchForm.SET_CONTENT_TYPES, project.getSettings().getString(LaunchForm.SET_CONTENT_TYPES, SoapMonitorAction.defaultContentTypes().toString())); if (optionsDialog.show()) { Settings settings = getProject().getSettings(); settings.setLong(OptionsForm.PORT, listenPort = optionsDialog.getIntValue(OptionsForm.PORT, listenPort)); settings.setLong(OptionsForm.MAXROWS, maxRows = optionsDialog.getIntValue(OptionsForm.MAXROWS, maxRows)); settings.setString(LaunchForm.SET_CONTENT_TYPES, optionsDialog.getValue(LaunchForm.SET_CONTENT_TYPES)); incomingRequestWss = optionsDialog.getValue(OptionsForm.REQUEST_WSS); incomingResponseWss = optionsDialog.getValue(OptionsForm.RESPONSE_WSS); tableModel.fitSizeToMaxRows(); } } @AForm(name = "HTTP Monitor Options", description = "Set options for HTTP Monitor", helpUrl = HelpUrls.SOAPMONITOR_MONITOR_OPTIONS, icon = UISupport.OPTIONS_ICON_PATH) private class OptionsForm { @AField(description = "The local port to listen on", name = "Port", type = AFieldType.INT) public final static String PORT = "Port"; @AField(description = "The maximum number of exchanges to log", name = "Max Log", type = AFieldType.INT) public final static String MAXROWS = "Max Log"; @AField(description = "The Incoming WSS configuration to use for processing requests", name = "Incoming Request WSS", type = AFieldType.ENUMERATION) public final static String REQUEST_WSS = "Incoming Request WSS"; @AField(description = "The Outgoing WSS configuration to use for processing responses", name = "Incoming Response WSS", type = AFieldType.ENUMERATION) public final static String RESPONSE_WSS = "Incoming Response WSS"; @AField(description = "Content types to monitor", name = "Content types to monitor", type = AFieldType.STRINGAREA) public final static String SET_CONTENT_TYPES = "Content types to monitor"; } } public void release() { requestViewer.release(); responseViewer.release(); if (optionsDialog != null) { optionsDialog.release(); optionsDialog = null; } inspectorPanel.release(); } public boolean isRunning() { return monitorEngine.isRunning(); } public MessageExchangeModelItem getRequestModelItem() { return requestModelItem; } }