com.atlassian.launchpad.jira.whiteboard.WhiteboardTabPanel.java Source code

Java tutorial

Introduction

Here is the source code for com.atlassian.launchpad.jira.whiteboard.WhiteboardTabPanel.java

Source

//   Copyright 2014 Rackspace Hosting
//
//   Licensed 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.

package com.atlassian.launchpad.jira.whiteboard;

import static org.apache.commons.lang.StringEscapeUtils.escapeHtml;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

import com.atlassian.crowd.embedded.api.User;
import com.atlassian.jira.component.ComponentAccessor;
import com.atlassian.jira.issue.Issue;
import com.atlassian.jira.issue.fields.CustomField;
import com.atlassian.jira.issue.tabpanels.GenericMessageAction;
import com.atlassian.jira.plugin.issuetabpanel.AbstractIssueTabPanel;
import com.atlassian.jira.plugin.issuetabpanel.IssueAction;
import com.atlassian.jira.plugin.issuetabpanel.IssueTabPanel;
import com.atlassian.jira.util.json.JSONException;
import com.atlassian.jira.util.json.JSONObject;
import com.atlassian.jira.util.json.JSONTokener;

/**
 * @author marc7279
 * WhiteboardTabPanel creates the "Whiteboard" tab in Jira. For a given Launchpad
 * blueprint URL, the tab will retrieve and display the related whiteboard.
 */
public class WhiteboardTabPanel extends AbstractIssueTabPanel implements IssueTabPanel {

    private final String BASE_LAUNCHPAD_API_URL = "https://api.launchpad.net/";
    private final String API_VERSION = "devel"; // currently devel level of the api is the only means of accessing the whiteboard data
    private final String BASE_LAUNCHPAD_BLUEPRINT_HOST = "blueprints.launchpad.net";
    private final String URL_REGEX = "\\b(https?|http)://blueprints.launchpad.net/[-a-zA-Z0-9+&@#%?=~_|!:,.;]*/[+]spec/[-a-zA-Z0-9+&@#%=~_|]*[-a-zA-Z0-9+&@#/%=~_|]";
    private final String WHITEBOARD = "whiteboard";
    private final String LAUNCHPAD_URL_FIELD_NAME = "Launchpad Blueprint URL";

    /* (non-Javadoc)
     * @see com.atlassian.jira.plugin.issuetabpanel.IssueTabPanel#getActions(com.atlassian.jira.issue.Issue, com.atlassian.crowd.embedded.api.User)
     */
    @Override
    public List<IssueAction> getActions(Issue issue, User remoteUser) {
        List<IssueAction> messages = new ArrayList<IssueAction>();

        //retrieve and validate url from custom field
        CustomField bpLinkField = ComponentAccessor.getCustomFieldManager()
                .getCustomFieldObjectByName(LAUNCHPAD_URL_FIELD_NAME);

        if (bpLinkField == null) {
            messages.add(new GenericMessageAction("\"" + LAUNCHPAD_URL_FIELD_NAME
                    + "\" custom field not available. Cannot process Gerrit Review comments"));
            return messages;
        }

        Object bpURLFieldObj = issue.getCustomFieldValue(bpLinkField);
        if (bpURLFieldObj == null) {
            messages.add(new GenericMessageAction("\"" + LAUNCHPAD_URL_FIELD_NAME
                    + "\" not provided. Please provide the Launchpad URL to view the whiteboard for this issue."));
            return messages;
        }

        String bpURL = bpURLFieldObj.toString().trim();

        if (bpURL.length() == 0) {
            messages.add(
                    new GenericMessageAction("To view the Launchpad Blueprint for this issue please provide the "
                            + LAUNCHPAD_URL_FIELD_NAME));
            return messages;
        }

        if (!bpURL.matches(URL_REGEX)) {
            messages.add(new GenericMessageAction(
                    "Launchpad URL not properly formatted. Please provide URL that appears as follows:<br/> https://blueprints.launchpad.net/devel/PROJECT NAME/+spec/BLUEPRINT NAME"));
            return messages;
        }

        String apiQuery = bpURL.substring(
                (bpURL.lastIndexOf(BASE_LAUNCHPAD_BLUEPRINT_HOST) + BASE_LAUNCHPAD_BLUEPRINT_HOST.length()));

        String url = BASE_LAUNCHPAD_API_URL + API_VERSION + apiQuery;

        try {
            //establish api connection
            URL obj = new URL(url);
            HttpURLConnection conn = (HttpURLConnection) obj.openConnection();

            boolean redirect = false;

            // normally, 3xx is redirect
            int status = conn.getResponseCode();
            if (status != HttpURLConnection.HTTP_OK) {
                if (status == HttpURLConnection.HTTP_MOVED_TEMP || status == HttpURLConnection.HTTP_MOVED_PERM
                        || status == HttpURLConnection.HTTP_SEE_OTHER)
                    redirect = true;
            }

            if (redirect) {
                // get redirect url from "location" header field
                String newUrl = conn.getHeaderField("Location");

                // open the new connection
                conn = (HttpURLConnection) new URL(newUrl).openConnection();
            }

            //parse returned json
            BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
            String inputLine;
            StringBuffer json = new StringBuffer();

            while ((inputLine = in.readLine()) != null) {
                json.append(inputLine);
            }
            in.close();

            //generate tab content
            JSONTokener tokener = new JSONTokener(json.toString());
            JSONObject finalResult = new JSONObject(tokener);
            if (finalResult.has(WHITEBOARD) && finalResult.getString(WHITEBOARD).length() > 0) {
                messages.add(new GenericMessageAction(
                        escapeHtml(finalResult.getString(WHITEBOARD)).replaceAll("\n", "<br/>")));
            } else {
                messages.add(new GenericMessageAction("No whiteboard for this blueprint."));
            }

        } catch (JSONException e) {
            // whiteboard JSON key not found
            e.printStackTrace();
        } catch (FileNotFoundException e) {
            //unable to find the requested whiteboard
            messages.add(new GenericMessageAction(
                    "Unable to find desired blueprint. Please check that the URL references the correct blueprint."));
            return messages;
        } catch (IOException e) {
            // Exception in attempting to read from Launchpad API
            e.printStackTrace();
        }

        return messages;
    }

    /* (non-Javadoc)
     * @see com.atlassian.jira.plugin.issuetabpanel.IssueTabPanel#showPanel(com.atlassian.jira.issue.Issue, com.atlassian.crowd.embedded.api.User)
     */
    @Override
    public boolean showPanel(Issue issue, User remoteUser) {
        return true;
    }
}