/*
* 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.SoapUI;
import com.eviware.soapui.SoapUISystemProperties;
import com.eviware.soapui.analytics.Analytics;
import com.eviware.soapui.analytics.SoapUIActions;
import com.eviware.soapui.impl.support.actions.ShowOnlineHelpAction;
import com.eviware.soapui.impl.wsdl.support.HelpUrls;
import com.eviware.soapui.impl.wsdl.testcase.WsdlTestCase;
import com.eviware.soapui.support.Tools;
import com.eviware.soapui.support.UISupport;
import com.eviware.soapui.support.components.JXToolBar;
import com.eviware.soapui.support.components.WebViewBasedBrowserComponent;
import com.eviware.soapui.support.components.WebViewBasedBrowserComponentFactory;
import com.eviware.soapui.testondemand.DependencyValidator;
import com.eviware.soapui.testondemand.Location;
import com.eviware.soapui.testondemand.TestOnDemandCaller;
import com.eviware.x.dialogs.Worker.WorkerAdapter;
import com.eviware.x.dialogs.XProgressDialog;
import com.eviware.x.dialogs.XProgressMonitor;
import com.google.common.base.Joiner;
import com.google.common.base.Strings;
import javax.annotation.Nonnull;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
/**
* Panel for displaying a Test On Demand report
*/
public class TestOnDemandPanel extends JPanel {
// FIXME This should be a URL on our servers. Replace with the real URL when it has been developed by our web dev team.
private static final String FIRST_PAGE_URL = "http://www.soapui.org/Appindex/test-on-demand.html";
private static final String GET_MORE_LOCATIONS_URL = "http://www2.smartbear.com/AlertSite_Monitor_APIs_Learn_More.html";
private static final String GET_MORE_LOCATIONS_MESSAGE = "More locations trial";
private static final String INITIALIZING_MESSAGE = "Initializing...";
private static final String NO_LOCATIONS_FOUND_MESSAGE = "No locations found";
private static final String COULD_NOT_GET_LOCATIONS_MESSAGE = "Could not get Test On Demand Locations. Check your network connection.";
private static final String COULD_NOT_UPLOAD_MESSAGE = "Could not upload TestCase to the selected location";
private static final String UPLOAD_TEST_CASE_HEADING = "Upload TestCase";
private static final String UPLOADING_TEST_CASE_MESSAGE = "Uploading TestCase..";
private static final String SERVER_IP_ADDRESSES_PREFIX = "IP: ";
private static final String SERVER_IP_ADDRESSES_DELIMETER = ", ";
private static final String NO_SERVER_IP_ADDRESSES_MESSAGE = "<No IP addresses found>";
// FIXME This suggest using a Java 7 feature, Fix compiler level!
@Nonnull
private JComboBox locationsComboBox;
private WebViewBasedBrowserComponent browser;
@Nonnull
private Action sendTestCaseAction;
@Nonnull
private static List<Location> locationsCache = new ArrayList<Location>();
@Nonnull
JLabel serverIPAddressesLabel = new JLabel();
@Nonnull
TestOnDemandCaller caller;
private final WsdlTestCase testCase;
protected DependencyValidator validator;
public TestOnDemandPanel(WsdlTestCase testCase) {
super(new BorderLayout());
this.testCase = testCase;
setBackground(Color.WHITE);
setOpaque(true);
setValidator();
setCaller();
add(buildToolbar(), BorderLayout.NORTH);
}
protected void setValidator() {
validator = new DependencyValidator();
}
protected void setCaller() {
caller = new TestOnDemandCaller();
}
public void release() {
if (browser != null) {
browser.close(true);
}
}
private Component buildToolbar() {
JXToolBar toolbar = UISupport.createToolbar();
sendTestCaseAction = new SendTestCaseAction();
sendTestCaseAction.setEnabled(false);
locationsComboBox = buildInitializingLocationsComboBox();
locationsComboBox.addActionListener(new LocationComboBoxAction());
// FIXME Is there a way to make this fill a the rest of the X space?
serverIPAddressesLabel.setPreferredSize(new Dimension(1000, 10));
serverIPAddressesLabel.setForeground(Color.GRAY);
toolbar.addFixed(UISupport.createToolbarButton(sendTestCaseAction));
toolbar.addRelatedGap();
toolbar.addFixed(locationsComboBox);
toolbar.addSpace(10);
toolbar.addFixed(serverIPAddressesLabel);
toolbar.addGlue();
toolbar.addFixed(UISupport.createToolbarButton(new ShowOnlineHelpAction(HelpUrls.ALERT_SITE_HELP_URL)));
return toolbar;
}
private JComboBox buildInitializingLocationsComboBox() {
JComboBox initLocationsComboBox = new JComboBox();
// FIXME This should be dynamic
initLocationsComboBox.setPreferredSize(new Dimension(170, 10));
initLocationsComboBox.addItem(INITIALIZING_MESSAGE);
initLocationsComboBox.setEnabled(false);
return initLocationsComboBox;
}
public void initializeLocationsCache() {
if (locationsCache.isEmpty()) {
new TestOnDemandCallerThread().start();
} else {
populateLocationsComboBox();
}
}
private void populateLocationsComboBox() {
locationsComboBox.removeAllItems();
if (locationsCache.isEmpty()) {
locationsComboBox.addItem(NO_LOCATIONS_FOUND_MESSAGE);
openInInternalBrowser(SoapUI.STARTER_PAGE_ERROR_URL);
} else {
for (Location location : locationsCache) {
locationsComboBox.addItem(location);
}
locationsComboBox.addItem(GET_MORE_LOCATIONS_MESSAGE);
locationsComboBox.setEnabled(true);
sendTestCaseAction.setEnabled(true);
}
invalidate();
}
private void openInInternalBrowser(String url) {
if (!SoapUI.isBrowserDisabled()) {
browser.navigate(url);
}
}
private void openInExternalBrowser(String url) {
Tools.openURL(url);
}
private String getFirstPageURL() {
return System.getProperty(SoapUISystemProperties.TEST_ON_DEMAND_FIRST_PAGE_URL, FIRST_PAGE_URL);
}
private String getMoreLocationsURL() {
return System.getProperty(SoapUISystemProperties.TEST_ON_DEMAND_GET_LOCATIONS_URL, GET_MORE_LOCATIONS_URL);
}
public void ensureBrowserIsInitialized() {
if (browser == null) {
browser = WebViewBasedBrowserComponentFactory.createBrowserComponent(false);
add(browser.getComponent(), BorderLayout.CENTER);
openInInternalBrowser(FIRST_PAGE_URL);
}
}
private class SendTestCaseAction extends AbstractAction {
public SendTestCaseAction() {
putValue(SMALL_ICON, UISupport.createImageIcon("/run.png"));
putValue(Action.SHORT_DESCRIPTION, "Run Test On Demand report");
}
public void actionPerformed(ActionEvent arg0) {
if (validator != null && !validator.isValid(testCase)) {
UISupport.showErrorMessage("Your project contains external dependencies that "
+ "are not supported by the Test-On-Demand functionality at this point.");
return;
}
if (locationsComboBox != null) {
Location selectedLocation = (Location) locationsComboBox.getSelectedItem();
XProgressDialog progressDialog = UISupport.getDialogs().createProgressDialog(UPLOAD_TEST_CASE_HEADING, 3,
UPLOADING_TEST_CASE_MESSAGE, false);
SendTestCaseWorker sendTestCaseWorker = new SendTestCaseWorker(testCase, selectedLocation);
try {
progressDialog.run(sendTestCaseWorker);
} catch (Exception e) {
SoapUI.logError(e);
}
String redirectUrl = sendTestCaseWorker.getResult();
if (!Strings.isNullOrEmpty(redirectUrl)) {
openURLSafely(redirectUrl);
}
Analytics.trackAction(SoapUIActions.TEST_ON_DEMAND.getActionName());
}
}
}
private void openURLSafely(String url)
{
if (SoapUI.isBrowserDisabled()) {
Tools.openURL(url);
} else {
if (browser != null) {
browser.navigate(url);
}
}
}
private class LocationComboBoxAction implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
Object selectedItem = locationsComboBox.getSelectedItem();
if (selectedItem != null) {
if (locationsComboBox.getSelectedItem().equals(GET_MORE_LOCATIONS_MESSAGE)) {
openInExternalBrowser(getMoreLocationsURL());
sendTestCaseAction.setEnabled(false);
serverIPAddressesLabel.setText(null);
} else {
if (locationsComboBox.isEnabled() && !sendTestCaseAction.isEnabled()) {
openInInternalBrowser(getFirstPageURL());
sendTestCaseAction.setEnabled(true);
}
if (selectedItem instanceof Location) {
String[] serverIPAddresses = ((Location) selectedItem).getServerIPAddresses();
if (serverIPAddresses != null && serverIPAddresses.length > 0) {
String severIpAddressList = Joiner.on(SERVER_IP_ADDRESSES_DELIMETER).join(serverIPAddresses);
serverIPAddressesLabel.setText(SERVER_IP_ADDRESSES_PREFIX + severIpAddressList);
} else {
serverIPAddressesLabel.setText(SERVER_IP_ADDRESSES_PREFIX + NO_SERVER_IP_ADDRESSES_MESSAGE);
// FIXME: Log errors aswell?
}
invalidate();
}
}
}
}
}
private class SendTestCaseWorker extends WorkerAdapter {
private final WsdlTestCase testCase;
private final Location selectedLocation;
private String result = null;
public SendTestCaseWorker(WsdlTestCase testCase, Location selectedLocation) {
this.testCase = testCase;
this.selectedLocation = selectedLocation;
}
public Object construct(XProgressMonitor monitor) {
try {
result = caller.sendTestCase(testCase, selectedLocation);
} catch (Exception e) {
SoapUI.logError(e);
UISupport.showErrorMessage(COULD_NOT_UPLOAD_MESSAGE);
}
return result;
}
public String getResult() {
return result;
}
}
// Used to prevent soapUI from halting while waiting for the Test On Demand server to respond
private class TestOnDemandCallerThread extends Thread {
@Override
public void run() {
try {
locationsCache = caller.getLocations();
} catch (Exception e) {
SoapUI.logError(e, COULD_NOT_GET_LOCATIONS_MESSAGE);
} finally {
populateLocationsComboBox();
}
}
}
}