blob: a83a2238b65bc05dcf3bad1dcba1f060d2e0a946 [file] [log] [blame]
package net.sf.taverna.t2.ui.perspectives.biocatalogue.integration.config;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.ProxySelector;
import java.net.URL;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
//import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.ProxySelectorRoutePlanner;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.HttpContext;
import org.apache.log4j.Logger;
import org.jdom.Attribute;
import org.jdom.Document;
import org.jdom.input.SAXBuilder;
import net.sf.taverna.biocatalogue.model.connectivity.BioCatalogueClient;
import net.sf.taverna.t2.ui.perspectives.biocatalogue.MainComponentFactory;
/**
*
* @author Sergejs Aleksejevs
*/
@SuppressWarnings("serial")
public class BioCataloguePluginConfigurationPanel extends JPanel
{
public static final String APPLICATION_XML_MIME_TYPE = "application/xml";
public static String PROXY_HOST = "http.proxyHost";
public static String PROXY_PORT = "http.proxyPort";
public static String PROXY_USERNAME = "http.proxyUser";
public static String PROXY_PASSWORD = "http.proxyPassword";
// 1.0.0b and higher until the first digit changes, as according to "Semantic Versioning"
// from http://www.biocatalogue.org/wiki/doku.php?id=public:api:changelog
// "Major version X (X.y.z | X > 0) MUST be incremented if any backwards
// incompatible changes are introduced to the public API. It MAY include minor and patch level changes."
public static String[] MIN_SUPPORTED_BIOCATALOGUE_API_VERSION = {"1", "1", "0"}; // major, minor and patch versions
public static String API_VERSION = "apiVersion";
private BioCataloguePluginConfiguration configuration =
BioCataloguePluginConfiguration.getInstance();
// UI elements
JTextField tfBioCatalogueAPIBaseURL;
private Logger logger = Logger.getLogger(BioCataloguePluginConfigurationPanel.class);
public BioCataloguePluginConfigurationPanel() {
initialiseUI();
resetFields();
}
private void initialiseUI()
{
this.setLayout(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
c.fill = GridBagConstraints.HORIZONTAL;
c.anchor = GridBagConstraints.NORTHWEST;
c.weightx = 1.0;
c.gridx = 0;
c.gridy = 0;
JTextArea taDescription = new JTextArea("Configure the Service Catalogue integration functionality");
taDescription.setFont(taDescription.getFont().deriveFont(Font.PLAIN, 11));
taDescription.setLineWrap(true);
taDescription.setWrapStyleWord(true);
taDescription.setEditable(false);
taDescription.setFocusable(false);
taDescription.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
this.add(taDescription, c);
c.gridy++;
c.insets = new Insets(20, 0, 0, 0);
JLabel jlBioCatalogueAPIBaseURL = new JLabel("Base URL of the Service Catalogue instance to connect to:");
this.add(jlBioCatalogueAPIBaseURL, c);
c.gridy++;
c.insets = new Insets(0, 0, 0, 0);
tfBioCatalogueAPIBaseURL = new JTextField();
this.add(tfBioCatalogueAPIBaseURL, c);
c.gridy++;
c.insets = new Insets(30, 0, 0, 0);
// We are not removing BioCatalogue services from its config panel any more -
// they are being handled by the Taverna's Service Registry
// JButton bForgetStoredServices = new JButton("Forget services added to Service Panel by BioCatalogue Plugin");
// bForgetStoredServices.addActionListener(new ActionListener() {
// public void actionPerformed(ActionEvent e)
// {
// int response = JOptionPane.showConfirmDialog(null, // no way T2ConfigurationFrame instance can be obtained to be used as a parent...
// "Are you sure you want to clear all SOAP operations and REST methods\n" +
// "that were added to the Service Panel by the BioCatalogue Plugin?\n\n" +
// "This action is permanent is cannot be undone.\n\n" +
// "Do you want to proceed?", "BioCatalogue Plugin", JOptionPane.YES_NO_OPTION);
//
// if (response == JOptionPane.YES_OPTION)
// {
// BioCatalogueServiceProvider.clearRegisteredServices();
// JOptionPane.showMessageDialog(null, // no way T2ConfigurationFrame instance can be obtained to be used as a parent...
// "Stored services have been successfully cleared, but will remain\n" +
// "being shown in Service Panel during this session.\n\n" +
// "They will not appear in the Service Panel after you restart Taverna.",
// "BioCatalogue Plugin", JOptionPane.INFORMATION_MESSAGE);
// }
// }
// });
// this.add(bForgetStoredServices, c);
JButton bLoadDefaults = new JButton("Load Defaults");
bLoadDefaults.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
loadDefaults();
}
});
JButton bReset = new JButton("Reset");
bReset.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
resetFields();
}
});
JButton bApply = new JButton("Apply");
bApply.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
applyChanges();
}
});
JPanel jpActionButtons = new JPanel();
jpActionButtons.add(bLoadDefaults);
jpActionButtons.add(bReset);
jpActionButtons.add(bApply);
c.insets = new Insets(30, 0, 0, 0);
c.gridy++;
c.weighty = 1.0;
this.add(jpActionButtons, c);
}
/**
* Resets all fields to the last saved configuration.
*/
private void resetFields() {
tfBioCatalogueAPIBaseURL.setText(configuration.getProperty(BioCataloguePluginConfiguration.SERVICE_CATALOGUE_BASE_URL));
}
/**
* Resets all fields to the default values.
*/
private void loadDefaults() {
tfBioCatalogueAPIBaseURL.setText(configuration.getDefaultProperty(BioCataloguePluginConfiguration.SERVICE_CATALOGUE_BASE_URL));
}
/**
* Saves recent changes to the configuration parameter map.
* Some input validation is performed as well.
*/
private void applyChanges() {
// --- BioCatalogue BASE URL ---
String candidateBaseURL = tfBioCatalogueAPIBaseURL.getText();
if (candidateBaseURL.length() == 0) {
JOptionPane.showMessageDialog(this,
"Service Catalogue base URL must not be blank",
"Service Catalogue Configuration", JOptionPane.WARNING_MESSAGE);
tfBioCatalogueAPIBaseURL.requestFocusInWindow();
return;
} else {
try {
new URL(candidateBaseURL);
} catch (MalformedURLException e) {
JOptionPane
.showMessageDialog(
this,
"Currently set Service Catalogue instance URL is not valid\n." +
"Please check the URL and try again.",
"Service Catalogue Configuration",
JOptionPane.WARNING_MESSAGE);
tfBioCatalogueAPIBaseURL.selectAll();
tfBioCatalogueAPIBaseURL.requestFocusInWindow();
return;
}
// check if the base URL has changed from the last saved state
if (!candidateBaseURL
.equals(configuration
.getProperty(BioCataloguePluginConfiguration.SERVICE_CATALOGUE_BASE_URL))) {
// Perform various checks on the new URL
// Do a GET with "Accept" header set to "application/xml"
// We are expecting a 200 OK and an XML doc in return that
// contains the BioCataogue version number element.
DefaultHttpClient httpClient = new DefaultHttpClient();
// Set the proxy settings, if any
if (System.getProperty(PROXY_HOST) != null
&& !System.getProperty(PROXY_HOST).equals("")) {
// Instruct HttpClient to use the standard
// JRE proxy selector to obtain proxy information
ProxySelectorRoutePlanner routePlanner = new ProxySelectorRoutePlanner(
httpClient.getConnectionManager().getSchemeRegistry(), ProxySelector
.getDefault());
httpClient.setRoutePlanner(routePlanner);
// Do we need to authenticate the user to the proxy?
if (System.getProperty(PROXY_USERNAME) != null
&& !System.getProperty(PROXY_USERNAME).equals("")) {
// Add the proxy username and password to the list of credentials
httpClient.getCredentialsProvider().setCredentials(
new AuthScope(System.getProperty(PROXY_HOST),Integer.parseInt(System.getProperty(PROXY_PORT))),
new UsernamePasswordCredentials(System.getProperty(PROXY_USERNAME), System.getProperty(PROXY_PASSWORD)));
}
}
HttpGet httpGet = new HttpGet(candidateBaseURL);
httpGet.setHeader("Accept", APPLICATION_XML_MIME_TYPE);
// Execute the request
HttpContext localContext = new BasicHttpContext();
HttpResponse httpResponse;
try {
httpResponse = httpClient.execute(httpGet, localContext);
} catch (Exception ex1) {
logger.error("Service Catalogue preferences configuration: Failed to do "
+ httpGet.getRequestLine(), ex1);
// Warn the user
JOptionPane.showMessageDialog(this,
"Failed to connect to the URL of the Service Catalogue instance.\n"
+ "Please check the URL and try again.",
"Service Catalogue Configuration",
JOptionPane.INFORMATION_MESSAGE);
// Release resource
httpClient.getConnectionManager().shutdown();
tfBioCatalogueAPIBaseURL.requestFocusInWindow();
return;
}
if (httpResponse.getStatusLine().getStatusCode() == HttpURLConnection.HTTP_OK) { // HTTP/1.1 200 OK
HttpEntity httpEntity = httpResponse.getEntity();
String contentType = httpEntity.getContentType().getValue()
.toLowerCase().trim();
logger
.info("Service Catalogue preferences configuration: Got 200 OK when testing the Service Catalogue instance by doing "
+ httpResponse.getStatusLine()
+ ". Content type of response "
+ contentType);
if (contentType.startsWith(APPLICATION_XML_MIME_TYPE)) {
String value = null;
Document doc = null;
try {
value = readResponseBodyAsString(httpEntity)
.trim();
// Try to read this string into an XML document
SAXBuilder builder = new SAXBuilder();
byte[] bytes = value.getBytes("UTF-8");
doc = builder.build(new ByteArrayInputStream(bytes));
} catch (Exception ex2) {
logger.error("Service Catalogue preferences configuration: Failed to build an XML document from the response.", ex2);
// Warn the user
JOptionPane.showMessageDialog(this,
"Failed to get the expected response body when testing the Service Catalogue instance.\n"
+ "The URL is probably wrong. Please check it and try again.",
"Service Catalogue Configuration",
JOptionPane.INFORMATION_MESSAGE);
tfBioCatalogueAPIBaseURL.requestFocusInWindow();
return;
}
finally{
// Release resource
httpClient.getConnectionManager().shutdown();
}
// Get the version element from the XML document
Attribute apiVersionAttribute = doc.getRootElement().getAttribute(API_VERSION);
if (apiVersionAttribute != null){
String apiVersion = apiVersionAttribute.getValue();
String versions[] = apiVersion.split("[.]");
String majorVersion = versions[0];
String minorVersion = versions[1];
try {
//String patchVersion = versions[2]; // we are not comparing the patch versions
String supportedMajorVersion = MIN_SUPPORTED_BIOCATALOGUE_API_VERSION[0];
String supportedMinorVersion = MIN_SUPPORTED_BIOCATALOGUE_API_VERSION[1];
Integer iSupportedMajorVersion = Integer.parseInt(supportedMajorVersion);
Integer iMajorVersion = Integer.parseInt(majorVersion);
Integer iSupportedMinorVersion = Integer.parseInt(supportedMinorVersion);
Integer iMinorVersion = Integer.parseInt(minorVersion);
if (!(iSupportedMajorVersion == iMajorVersion &&
iSupportedMinorVersion <= iMinorVersion)){
// Warn the user
JOptionPane
.showMessageDialog(
this,
"The version of the Service Catalogue instance you are trying to connect to is not supported.\n"
+ "Please change the URL and try again.",
"Service Catalogue Configuration",
JOptionPane.INFORMATION_MESSAGE);
tfBioCatalogueAPIBaseURL.requestFocusInWindow();
return;
}
} catch (Exception e) {
logger.error(e);
}
} // if null - we'll try to do our best to connect to BioCatalogue anyway
} else {
logger
.error("Service Catalogue preferences configuration: Failed to get the expected response content type when testing the Service Catalogue instance. "
+ httpGet.getRequestLine()
+ " returned content type '"
+ contentType
+ "'; expected response content type is 'application/xml'.");
// Warn the user
JOptionPane
.showMessageDialog(
this,
"Failed to get the expected response content type when testing the Service Catalogue instance.\n"
+ "The URL is probably wrong. Please check it and try again.",
"Service Catalogue Plugin",
JOptionPane.INFORMATION_MESSAGE);
tfBioCatalogueAPIBaseURL.requestFocusInWindow();
return;
}
}
else{
logger
.error("Service Catalogue preferences configuration: Failed to get the expected response status code when testing the Service Catalogue instance. "
+ httpGet.getRequestLine()
+ " returned the status code "
+ httpResponse.getStatusLine()
.getStatusCode() + "; expected status code is 200 OK.");
// Warn the user
JOptionPane
.showMessageDialog(
this,
"Failed to get the expected response status code when testing the Service Catalogue instance.\n"
+ "The URL is probably wrong. Please check it and try again.",
"Service Catalogue Configuration",
JOptionPane.INFORMATION_MESSAGE);
tfBioCatalogueAPIBaseURL.requestFocusInWindow();
return;
}
// Warn the user of the changes in the BioCatalogue base URL
JOptionPane
.showMessageDialog(
this,
"You have updated the Service Catalogue base URL.\n"
+ "This does not take effect until you restart Taverna.",
"Service catalogue Configuration",
JOptionPane.INFORMATION_MESSAGE);
}
// the new base URL seems to be valid - can save it into config
// settings
configuration.setProperty(
BioCataloguePluginConfiguration.SERVICE_CATALOGUE_BASE_URL,
candidateBaseURL);
/* // also update the base URL in the BioCatalogueClient
BioCatalogueClient.getInstance()
.setBaseURL(candidateBaseURL);*/
}
}
/**
* For testing only.
*/
public static void main(String[] args) {
JFrame theFrame = new JFrame();
theFrame.add(new BioCataloguePluginConfigurationPanel());
theFrame.pack();
theFrame.setLocationRelativeTo(null);
theFrame.setVisible(true);
}
/**
* Worker method that extracts the content of the received HTTP message as a
* string. It also makes use of the charset that is specified in the
* Content-Type header of the received data to read it appropriately.
*
* @param entity
* @return
* @throws IOException
*/
// Taken from HTTPRequestHandler in rest-activity by Sergejs Aleksejevs
private static String readResponseBodyAsString(HttpEntity entity)
throws IOException {
// get charset name
String charset = null;
String contentType = entity.getContentType().getValue().toLowerCase();
String[] contentTypeParts = contentType.split(";");
for (String contentTypePart : contentTypeParts) {
contentTypePart = contentTypePart.trim();
if (contentTypePart.startsWith("charset=")) {
charset = contentTypePart.substring("charset=".length());
}
}
// read the data line by line
StringBuilder responseBodyString = new StringBuilder();
BufferedReader reader = new BufferedReader(new InputStreamReader(entity
.getContent(), charset));
String str;
while ((str = reader.readLine()) != null) {
responseBodyString.append(str + "\n");
}
return (responseBodyString.toString());
}
}