io.github.tavernaextras.biocatalogue.integration.config.BioCataloguePluginConfigurationPanel.java Source code

Java tutorial

Introduction

Here is the source code for io.github.tavernaextras.biocatalogue.integration.config.BioCataloguePluginConfigurationPanel.java

Source

package io.github.tavernaextras.biocatalogue.integration.config;
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

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 io.github.tavernaextras.biocatalogue.model.connectivity.BioCatalogueClient;
import io.github.tavernaextras.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());
    }

}